ASoC: Codec: rt565x: derive proper dmic clk rate
Sameer Pujar [Tue, 2 Aug 2016 11:03:51 +0000 (16:03 +0530)]
The failure was seen in setting dmic clock when 192KHz HRA playback
was running. Earlier divider factors available were not sufficient
to get the right dmic clock. OSR factor is used now to further divide
the dmic clock to get the rate in required range.
(patch provided by Realtek)

Bug 200223032

Reviewed-on: http://git-master/r/1193642
(cherry picked from commit c30c54ba369e3d42bcb768bc855807455a3dbc61)

Change-Id: Ifed1ef43c96de799bfd9d8de483964a91be73372
Signed-off-by: Sameer Pujar <spujar@nvidia.com>
Reviewed-on: http://git-master/r/1195875
GVS: Gerrit_Virtual_Submit
Reviewed-by: Mohan Kumar D <mkumard@nvidia.com>
Reviewed-by: Viswanath L <viswanathl@nvidia.com>
Reviewed-by: Sumit Bhattacharya <sumitb@nvidia.com>

sound/soc/codecs/rt5659.c

index e6433f2..22c4d88 100644 (file)
@@ -1581,14 +1581,28 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w,
        struct snd_soc_codec *codec = w->codec;
        struct rt5659_priv *rt5659 = snd_soc_codec_get_drvdata(codec);
        int div[] = { 2, 3, 4, 6, 8, 12 }, idx =
-               -EINVAL, i, rate, red, bound, temp;
+               -EINVAL, i, rate, red, bound, temp, osr_rate;
 
        pr_debug("%s\n", __FUNCTION__);
 
+       switch (snd_soc_read(codec, RT5659_ADDA_CLK_1) & RT5659_ADC_OSR_MASK) {
+       case RT5659_ADC_OSR_64:
+               osr_rate = 2;
+               break;
+
+       case RT5659_ADC_OSR_32:
+               osr_rate = 4;
+               break;
+
+       default:
+               osr_rate = 1;
+               break;
+       }
+
        rate = rt5659->lrck[RT5659_AIF1] << 8;
-       red = 3000000 * 12;
+       red = 3000000 * 12 * osr_rate;
        for (i = 0; i < ARRAY_SIZE(div); i++) {
-               bound = div[i] * 3000000;
+               bound = div[i] * 3000000 * osr_rate;
                if (rate > bound)
                        continue;
                temp = bound - rate;
@@ -3356,15 +3370,18 @@ static int rt5659_hw_params(struct snd_pcm_substream *substream,
        switch (rt5659->lrck[dai->id]) {
        case 192000:
                snd_soc_update_bits(codec, RT5659_ADDA_CLK_1,
-                       RT5659_DAC_OSR_MASK, RT5659_DAC_OSR_32);
+                       RT5659_DAC_OSR_MASK | RT5659_ADC_OSR_MASK,
+                       RT5659_DAC_OSR_32 | RT5659_ADC_OSR_32);
                break;
        case 96000:
                snd_soc_update_bits(codec, RT5659_ADDA_CLK_1,
-                       RT5659_DAC_OSR_MASK, RT5659_DAC_OSR_64);
+                       RT5659_DAC_OSR_MASK | RT5659_ADC_OSR_MASK,
+                       RT5659_DAC_OSR_64 | RT5659_ADC_OSR_64);
                break;
        default:
                snd_soc_update_bits(codec, RT5659_ADDA_CLK_1,
-                       RT5659_DAC_OSR_MASK, RT5659_DAC_OSR_128);
+                       RT5659_DAC_OSR_MASK | RT5659_ADC_OSR_MASK,
+                       RT5659_DAC_OSR_128 | RT5659_ADC_OSR_128);
                break;
        }