Merge tag 'sound-3.10' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
[firefly-linux-kernel-4.4.55.git] / sound / soc / codecs / wm8994.c
index c9bd445c497628d014a77508e8d37092e4db203e..1eb152cb10970d06a09b98995871581105e6fa51 100644 (file)
@@ -2209,7 +2209,7 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src,
                                vmid_reference(codec);
                                break;
                        case WM8958:
-                               if (wm8994->revision < 1)
+                               if (control->revision < 1)
                                        vmid_reference(codec);
                                break;
                        default:
@@ -2244,7 +2244,7 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src,
                                vmid_dereference(codec);
                                break;
                        case WM8958:
-                               if (wm8994->revision < 1)
+                               if (control->revision < 1)
                                        vmid_dereference(codec);
                                break;
                        default:
@@ -2268,10 +2268,26 @@ out:
         */
        if (max(wm8994->aifclk[0], wm8994->aifclk[1]) < 50000) {
                dev_dbg(codec->dev, "Configuring AIFs for 128fs\n");
+
+               wm8994->aifdiv[0] = snd_soc_read(codec, WM8994_AIF1_RATE)
+                       & WM8994_AIF1CLK_RATE_MASK;
+               wm8994->aifdiv[1] = snd_soc_read(codec, WM8994_AIF2_RATE)
+                       & WM8994_AIF1CLK_RATE_MASK;
+
                snd_soc_update_bits(codec, WM8994_AIF1_RATE,
                                    WM8994_AIF1CLK_RATE_MASK, 0x1);
                snd_soc_update_bits(codec, WM8994_AIF2_RATE,
                                    WM8994_AIF2CLK_RATE_MASK, 0x1);
+       } else if (wm8994->aifdiv[0]) {
+               snd_soc_update_bits(codec, WM8994_AIF1_RATE,
+                                   WM8994_AIF1CLK_RATE_MASK,
+                                   wm8994->aifdiv[0]);
+               snd_soc_update_bits(codec, WM8994_AIF2_RATE,
+                                   WM8994_AIF2CLK_RATE_MASK,
+                                   wm8994->aifdiv[1]);
+
+               wm8994->aifdiv[0] = 0;
+               wm8994->aifdiv[1] = 0;
        }
 
        return 0;
@@ -2368,10 +2384,26 @@ static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai,
         */
        if (max(wm8994->aifclk[0], wm8994->aifclk[1]) < 50000) {
                dev_dbg(codec->dev, "Configuring AIFs for 128fs\n");
+
+               wm8994->aifdiv[0] = snd_soc_read(codec, WM8994_AIF1_RATE)
+                       & WM8994_AIF1CLK_RATE_MASK;
+               wm8994->aifdiv[1] = snd_soc_read(codec, WM8994_AIF2_RATE)
+                       & WM8994_AIF1CLK_RATE_MASK;
+
                snd_soc_update_bits(codec, WM8994_AIF1_RATE,
                                    WM8994_AIF1CLK_RATE_MASK, 0x1);
                snd_soc_update_bits(codec, WM8994_AIF2_RATE,
                                    WM8994_AIF2CLK_RATE_MASK, 0x1);
+       } else if (wm8994->aifdiv[0]) {
+               snd_soc_update_bits(codec, WM8994_AIF1_RATE,
+                                   WM8994_AIF1CLK_RATE_MASK,
+                                   wm8994->aifdiv[0]);
+               snd_soc_update_bits(codec, WM8994_AIF2_RATE,
+                                   WM8994_AIF2CLK_RATE_MASK,
+                                   wm8994->aifdiv[1]);
+
+               wm8994->aifdiv[0] = 0;
+               wm8994->aifdiv[1] = 0;
        }
 
        return 0;
@@ -2411,7 +2443,7 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec,
                if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
                        switch (control->type) {
                        case WM8958:
-                               if (wm8994->revision == 0) {
+                               if (control->revision == 0) {
                                        /* Optimise performance for rev A */
                                        snd_soc_update_bits(codec,
                                                            WM8958_CHARGE_PUMP_2,
@@ -2656,6 +2688,8 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream,
 {
        struct snd_soc_codec *codec = dai->codec;
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+       struct wm8994 *control = wm8994->wm8994;
+       struct wm8994_pdata *pdata = &control->pdata;
        int aif1_reg;
        int aif2_reg;
        int bclk_reg;
@@ -2723,7 +2757,14 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream,
        }
 
        wm8994->channels[id] = params_channels(params);
-       switch (params_channels(params)) {
+       if (pdata->max_channels_clocked[id] &&
+           wm8994->channels[id] > pdata->max_channels_clocked[id]) {
+               dev_dbg(dai->dev, "Constraining channels to %d from %d\n",
+                       pdata->max_channels_clocked[id], wm8994->channels[id]);
+               wm8994->channels[id] = pdata->max_channels_clocked[id];
+       }
+
+       switch (wm8994->channels[id]) {
        case 1:
        case 2:
                bclk_rate *= 2;
@@ -2745,7 +2786,7 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream,
        dev_dbg(dai->dev, "AIF%dCLK is %dHz, target BCLK %dHz\n",
                dai->id, wm8994->aifclk[id], bclk_rate);
 
-       if (params_channels(params) == 1 &&
+       if (wm8994->channels[id] == 1 &&
            (snd_soc_read(codec, aif1_reg) & 0x18) == 0x18)
                aif2 |= WM8994_AIF1_MONO;
 
@@ -2841,6 +2882,7 @@ static int wm8994_aif3_hw_params(struct snd_pcm_substream *substream,
                default:
                        return 0;
                }
+               break;
        default:
                return 0;
        }
@@ -3053,7 +3095,7 @@ static int wm8994_codec_resume(struct snd_soc_codec *codec)
        int i, ret;
        unsigned int val, mask;
 
-       if (wm8994->revision < 4) {
+       if (control->revision < 4) {
                /* force a HW read */
                ret = regmap_read(control->regmap,
                                  WM8994_POWER_MANAGEMENT_5, &val);
@@ -3870,7 +3912,6 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
        codec->dapm.idle_bias_off = 1;
 
        /* Set revision-specific configuration */
-       wm8994->revision = snd_soc_read(codec, WM8994_CHIP_REVISION);
        switch (control->type) {
        case WM8994:
                /* Single ended line outputs should have VMID on. */
@@ -3878,7 +3919,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
                    !control->pdata.lineout2_diff)
                        codec->dapm.idle_bias_off = 0;
 
-               switch (wm8994->revision) {
+               switch (control->revision) {
                case 2:
                case 3:
                        wm8994->hubs.dcs_codes_l = -5;
@@ -3897,7 +3938,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
                wm8994->hubs.dcs_readback_mode = 1;
                wm8994->hubs.hp_startup_mode = 1;
 
-               switch (wm8994->revision) {
+               switch (control->revision) {
                case 0:
                        break;
                default:
@@ -4000,7 +4041,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
 
        switch (control->type) {
        case WM1811:
-               if (control->cust_id > 1 || wm8994->revision > 1) {
+               if (control->cust_id > 1 || control->revision > 1) {
                        ret = wm8994_request_irq(wm8994->wm8994,
                                                 WM8994_IRQ_GPIO(6),
                                                 wm1811_jackdet_irq, "JACKDET",
@@ -4114,7 +4155,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
        case WM8994:
                snd_soc_dapm_new_controls(dapm, wm8994_specific_dapm_widgets,
                                          ARRAY_SIZE(wm8994_specific_dapm_widgets));
-               if (wm8994->revision < 4) {
+               if (control->revision < 4) {
                        snd_soc_dapm_new_controls(dapm, wm8994_lateclk_revd_widgets,
                                                  ARRAY_SIZE(wm8994_lateclk_revd_widgets));
                        snd_soc_dapm_new_controls(dapm, wm8994_adc_revd_widgets,
@@ -4135,7 +4176,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
                                     ARRAY_SIZE(wm8958_snd_controls));
                snd_soc_dapm_new_controls(dapm, wm8958_dapm_widgets,
                                          ARRAY_SIZE(wm8958_dapm_widgets));
-               if (wm8994->revision < 1) {
+               if (control->revision < 1) {
                        snd_soc_dapm_new_controls(dapm, wm8994_lateclk_revd_widgets,
                                                  ARRAY_SIZE(wm8994_lateclk_revd_widgets));
                        snd_soc_dapm_new_controls(dapm, wm8994_adc_revd_widgets,
@@ -4174,7 +4215,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
                snd_soc_dapm_add_routes(dapm, wm8994_intercon,
                                        ARRAY_SIZE(wm8994_intercon));
 
-               if (wm8994->revision < 4) {
+               if (control->revision < 4) {
                        snd_soc_dapm_add_routes(dapm, wm8994_revd_intercon,
                                                ARRAY_SIZE(wm8994_revd_intercon));
                        snd_soc_dapm_add_routes(dapm, wm8994_lateclk_revd_intercon,
@@ -4185,7 +4226,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
                }
                break;
        case WM8958:
-               if (wm8994->revision < 1) {
+               if (control->revision < 1) {
                        snd_soc_dapm_add_routes(dapm, wm8994_intercon,
                                                ARRAY_SIZE(wm8994_intercon));
                        snd_soc_dapm_add_routes(dapm, wm8994_revd_intercon,