ASoC: wm8994: Support constraining the maximum number of channels clocked
authorMark Brown <broonie@opensource.wolfsonmicro.com>
Wed, 20 Mar 2013 09:12:10 +0000 (10:12 +0100)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Thu, 21 Mar 2013 16:27:32 +0000 (17:27 +0100)
Some systems use the audio CODEC to clock a DAI with multiple data lines
in parallel, meaning that bit clocks are only required for a smaller number
of channels than data is sent for. In some cases providing the extra bit
clocks can take the other devices on the audio bus out of spec.

Support such systems by allowing a maximum number of channels to be
specified.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
include/linux/mfd/wm8994/pdata.h
sound/soc/codecs/wm8994.c

index 8e21a094836d21566bec6f08c027ad5c765fa715..68e77659488950f69df451b04b065eee72c9d144 100644 (file)
@@ -17,6 +17,7 @@
 
 #define WM8994_NUM_LDO   2
 #define WM8994_NUM_GPIO 11
+#define WM8994_NUM_AIF   3
 
 struct wm8994_ldo_pdata {
        /** GPIOs to enable regulator, 0 or less if not available */
@@ -215,6 +216,13 @@ struct wm8994_pdata {
         * system.
         */
        bool spkmode_pu;
+
+       /**
+        * Maximum number of channels clocks will be generated for,
+        * useful for systems where and I2S bus with multiple data
+        * lines is mastered.
+        */
+       int max_channels_clocked[WM8994_NUM_AIF];
 };
 
 #endif
index c9bd445c497628d014a77508e8d37092e4db203e..318ea64b98003cf3f49b3bb225c33b33f8862e5e 100644 (file)
@@ -2656,6 +2656,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 +2725,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 +2754,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;