{"AIFTX", NULL, "Digital CH4 Mux"},
 };
 
-static int nau8540_clock_check(struct nau8540 *nau8540, int rate, int osr)
+static const struct nau8540_osr_attr *
+nau8540_get_osr(struct nau8540 *nau8540)
 {
+       unsigned int osr;
+
+       regmap_read(nau8540->regmap, NAU8540_REG_ADC_SAMPLE_RATE, &osr);
+       osr &= NAU8540_ADC_OSR_MASK;
        if (osr >= ARRAY_SIZE(osr_adc_sel))
-               return -EINVAL;
+               return NULL;
+       return &osr_adc_sel[osr];
+}
+
+static int nau8540_dai_startup(struct snd_pcm_substream *substream,
+                              struct snd_soc_dai *dai)
+{
+       struct snd_soc_component *component = dai->component;
+       struct nau8540 *nau8540 = snd_soc_component_get_drvdata(component);
+       const struct nau8540_osr_attr *osr;
 
-       if (rate * osr > CLK_ADC_MAX) {
-               dev_err(nau8540->dev, "exceed the maximum frequency of CLK_ADC\n");
+       osr = nau8540_get_osr(nau8540);
+       if (!osr || !osr->osr)
                return -EINVAL;
-       }
 
-       return 0;
+       return snd_pcm_hw_constraint_minmax(substream->runtime,
+                                           SNDRV_PCM_HW_PARAM_RATE,
+                                           0, CLK_ADC_MAX / osr->osr);
 }
 
 static int nau8540_hw_params(struct snd_pcm_substream *substream,
 {
        struct snd_soc_component *component = dai->component;
        struct nau8540 *nau8540 = snd_soc_component_get_drvdata(component);
-       unsigned int val_len = 0, osr;
+       unsigned int val_len = 0;
+       const struct nau8540_osr_attr *osr;
 
        /* CLK_ADC = OSR * FS
         * ADC clock frequency is defined as Over Sampling Rate (OSR)
         * values must be selected such that the maximum frequency is less
         * than 6.144 MHz.
         */
-       regmap_read(nau8540->regmap, NAU8540_REG_ADC_SAMPLE_RATE, &osr);
-       osr &= NAU8540_ADC_OSR_MASK;
-       if (nau8540_clock_check(nau8540, params_rate(params), osr))
+       osr = nau8540_get_osr(nau8540);
+       if (!osr || !osr->osr)
+               return -EINVAL;
+       if (params_rate(params) * osr->osr > CLK_ADC_MAX)
                return -EINVAL;
        regmap_update_bits(nau8540->regmap, NAU8540_REG_CLOCK_SRC,
                NAU8540_CLK_ADC_SRC_MASK,
-               osr_adc_sel[osr].clk_src << NAU8540_CLK_ADC_SRC_SFT);
+               osr->clk_src << NAU8540_CLK_ADC_SRC_SFT);
 
        switch (params_width(params)) {
        case 16:
 
 
 static const struct snd_soc_dai_ops nau8540_dai_ops = {
+       .startup = nau8540_dai_startup,
        .hw_params = nau8540_hw_params,
        .set_fmt = nau8540_set_fmt,
        .set_tdm_slot = nau8540_set_tdm_slot,