ASoC: rt5665: enable TDM if more than 2 channels
authorBard Liao <bardliao@realtek.com>
Wed, 8 Mar 2017 11:05:36 +0000 (19:05 +0800)
committerMark Brown <broonie@kernel.org>
Wed, 8 Mar 2017 12:47:53 +0000 (13:47 +0100)
TDM is necessary for more than 2 channels. And there is no control bit
to specify which slots are using. Machine driver will not need to call
snd_soc_dai_set_tdm_slot if we do it in rt5665_hw_params.

Signed-off-by: Bard Liao <bardliao@realtek.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/codecs/rt5665.c

index de2c104bbaf381fd57276f457ff0757e2ca7cf8d..b8c50ed7239628480c76474369943dbdb9061c48 100644 (file)
@@ -3964,6 +3964,62 @@ static const struct snd_soc_dapm_route rt5665_dapm_routes[] = {
        {"PDMR", NULL, "PDM R Playback"},
 };
 
+static int rt5665_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
+                       unsigned int rx_mask, int slots, int slot_width)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       unsigned int val = 0;
+
+       if (rx_mask || tx_mask)
+               val |= RT5665_I2S1_MODE_TDM;
+
+       switch (slots) {
+       case 4:
+               val |= RT5665_TDM_IN_CH_4;
+               val |= RT5665_TDM_OUT_CH_4;
+               break;
+       case 6:
+               val |= RT5665_TDM_IN_CH_6;
+               val |= RT5665_TDM_OUT_CH_6;
+               break;
+       case 8:
+               val |= RT5665_TDM_IN_CH_8;
+               val |= RT5665_TDM_OUT_CH_8;
+               break;
+       case 2:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (slot_width) {
+       case 20:
+               val |= RT5665_TDM_IN_LEN_20;
+               val |= RT5665_TDM_OUT_LEN_20;
+               break;
+       case 24:
+               val |= RT5665_TDM_IN_LEN_24;
+               val |= RT5665_TDM_OUT_LEN_24;
+               break;
+       case 32:
+               val |= RT5665_TDM_IN_LEN_32;
+               val |= RT5665_TDM_OUT_LEN_32;
+               break;
+       case 16:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       snd_soc_update_bits(codec, RT5665_TDM_CTRL_1,
+               RT5665_I2S1_MODE_MASK | RT5665_TDM_IN_CH_MASK |
+               RT5665_TDM_OUT_CH_MASK | RT5665_TDM_IN_LEN_MASK |
+               RT5665_TDM_OUT_LEN_MASK, val);
+
+       return 0;
+}
+
+
 static int rt5665_hw_params(struct snd_pcm_substream *substream,
        struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
 {
@@ -4010,6 +4066,9 @@ static int rt5665_hw_params(struct snd_pcm_substream *substream,
        switch (dai->id) {
        case RT5665_AIF1_1:
        case RT5665_AIF1_2:
+               if (params_channels(params) > 2)
+                       rt5665_set_tdm_slot(dai, 0xf, 0xf,
+                               params_channels(params), params_width(params));
                mask_clk = RT5665_I2S_PD1_MASK;
                val_clk = pre_div << RT5665_I2S_PD1_SFT;
                snd_soc_update_bits(codec, RT5665_I2S1_SDP,
@@ -4227,61 +4286,6 @@ static int rt5665_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int Source,
        return 0;
 }
 
-static int rt5665_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
-                       unsigned int rx_mask, int slots, int slot_width)
-{
-       struct snd_soc_codec *codec = dai->codec;
-       unsigned int val = 0;
-
-       if (rx_mask || tx_mask)
-               val |= RT5665_I2S1_MODE_TDM;
-
-       switch (slots) {
-       case 4:
-               val |= RT5665_TDM_IN_CH_4;
-               val |= RT5665_TDM_OUT_CH_4;
-               break;
-       case 6:
-               val |= RT5665_TDM_IN_CH_6;
-               val |= RT5665_TDM_OUT_CH_6;
-               break;
-       case 8:
-               val |= RT5665_TDM_IN_CH_8;
-               val |= RT5665_TDM_OUT_CH_8;
-               break;
-       case 2:
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       switch (slot_width) {
-       case 20:
-               val |= RT5665_TDM_IN_LEN_20;
-               val |= RT5665_TDM_OUT_LEN_20;
-               break;
-       case 24:
-               val |= RT5665_TDM_IN_LEN_24;
-               val |= RT5665_TDM_OUT_LEN_24;
-               break;
-       case 32:
-               val |= RT5665_TDM_IN_LEN_32;
-               val |= RT5665_TDM_OUT_LEN_32;
-               break;
-       case 16:
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       snd_soc_update_bits(codec, RT5665_TDM_CTRL_1,
-               RT5665_I2S1_MODE_MASK | RT5665_TDM_IN_CH_MASK |
-               RT5665_TDM_OUT_CH_MASK | RT5665_TDM_IN_LEN_MASK |
-               RT5665_TDM_OUT_LEN_MASK, val);
-
-       return 0;
-}
-
 static int rt5665_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio)
 {
        struct snd_soc_codec *codec = dai->codec;