ASoC: da7213: add support for DSP modes
authorPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Wed, 8 Nov 2017 22:42:31 +0000 (16:42 -0600)
committerMark Brown <broonie@kernel.org>
Thu, 9 Nov 2017 11:42:26 +0000 (11:42 +0000)
DSP modes are documented in the data sheet but not enabled in the driver.
The work-around already implemented for DA7218/9 is also required to
make sure the bit clock handling in DSP modes follows ASoC conventions.

Tested with ARD-AUDIO-DA7212 and Minnowmax Turbot boards

Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Acked-by: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/codecs/da7213.c
sound/soc/codecs/da7213.h

index cc0b2d2..41d9b1d 100644 (file)
@@ -1220,6 +1220,7 @@ static int da7213_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
        struct snd_soc_codec *codec = codec_dai->codec;
        struct da7213_priv *da7213 = snd_soc_codec_get_drvdata(codec);
        u8 dai_clk_mode = 0, dai_ctrl = 0;
+       u8 dai_offset = 0;
 
        /* Set master/slave mode */
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -1234,17 +1235,46 @@ static int da7213_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
        }
 
        /* Set clock normal/inverted */
-       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
-       case SND_SOC_DAIFMT_NB_NF:
-               break;
-       case SND_SOC_DAIFMT_NB_IF:
-               dai_clk_mode |= DA7213_DAI_WCLK_POL_INV;
-               break;
-       case SND_SOC_DAIFMT_IB_NF:
-               dai_clk_mode |= DA7213_DAI_CLK_POL_INV;
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_I2S:
+       case SND_SOC_DAIFMT_LEFT_J:
+       case SND_SOC_DAIFMT_RIGHT_J:
+               switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+               case SND_SOC_DAIFMT_NB_NF:
+                       break;
+               case SND_SOC_DAIFMT_NB_IF:
+                       dai_clk_mode |= DA7213_DAI_WCLK_POL_INV;
+                       break;
+               case SND_SOC_DAIFMT_IB_NF:
+                       dai_clk_mode |= DA7213_DAI_CLK_POL_INV;
+                       break;
+               case SND_SOC_DAIFMT_IB_IF:
+                       dai_clk_mode |= DA7213_DAI_WCLK_POL_INV |
+                                       DA7213_DAI_CLK_POL_INV;
+                       break;
+               default:
+                       return -EINVAL;
+               }
                break;
-       case SND_SOC_DAIFMT_IB_IF:
-               dai_clk_mode |= DA7213_DAI_WCLK_POL_INV | DA7213_DAI_CLK_POL_INV;
+       case SND_SOC_DAI_FORMAT_DSP_A:
+       case SND_SOC_DAI_FORMAT_DSP_B:
+               /* The bclk is inverted wrt ASoC conventions */
+               switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+               case SND_SOC_DAIFMT_NB_NF:
+                       dai_clk_mode |= DA7213_DAI_CLK_POL_INV;
+                       break;
+               case SND_SOC_DAIFMT_NB_IF:
+                       dai_clk_mode |= DA7213_DAI_WCLK_POL_INV |
+                                       DA7213_DAI_CLK_POL_INV;
+                       break;
+               case SND_SOC_DAIFMT_IB_NF:
+                       break;
+               case SND_SOC_DAIFMT_IB_IF:
+                       dai_clk_mode |= DA7213_DAI_WCLK_POL_INV;
+                       break;
+               default:
+                       return -EINVAL;
+               }
                break;
        default:
                return -EINVAL;
@@ -1261,6 +1291,13 @@ static int da7213_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
        case SND_SOC_DAIFMT_RIGHT_J:
                dai_ctrl |= DA7213_DAI_FORMAT_RIGHT_J;
                break;
+       case SND_SOC_DAI_FORMAT_DSP_A: /* L data MSB after FRM LRC */
+               dai_ctrl |= DA7213_DAI_FORMAT_DSP;
+               dai_offset = 1;
+               break;
+       case SND_SOC_DAI_FORMAT_DSP_B: /* L data MSB during FRM LRC */
+               dai_ctrl |= DA7213_DAI_FORMAT_DSP;
+               break;
        default:
                return -EINVAL;
        }
@@ -1271,6 +1308,7 @@ static int da7213_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
        snd_soc_write(codec, DA7213_DAI_CLK_MODE, dai_clk_mode);
        snd_soc_update_bits(codec, DA7213_DAI_CTRL, DA7213_DAI_FORMAT_MASK,
                            dai_ctrl);
+       snd_soc_write(codec, DA7213_DAI_OFFSET, dai_offset);
 
        return 0;
 }
index 16ef56f..5a78dba 100644 (file)
 #define DA7213_DAI_FORMAT_I2S_MODE                             (0x0 << 0)
 #define DA7213_DAI_FORMAT_LEFT_J                               (0x1 << 0)
 #define DA7213_DAI_FORMAT_RIGHT_J                              (0x2 << 0)
+#define DA7213_DAI_FORMAT_DSP                                  (0x3 << 0)
 #define DA7213_DAI_FORMAT_MASK                                 (0x3 << 0)
 #define DA7213_DAI_WORD_LENGTH_S16_LE                          (0x0 << 2)
 #define DA7213_DAI_WORD_LENGTH_S20_LE                          (0x1 << 2)