ASoC: nau8824: TDM support
authorJohn Hsu <supercraig0719@gmail.com>
Tue, 2 May 2017 01:42:58 +0000 (09:42 +0800)
committerMark Brown <broonie@kernel.org>
Sun, 14 May 2017 10:14:10 +0000 (19:14 +0900)
Support TDM format for NAU88L24.

Signed-off-by: John Hsu <KCHSU0@nuvoton.com>
Signed-off-by: John Hsu <supercraig0719@gmail.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/codecs/nau8824.c
sound/soc/codecs/nau8824.h

index cca974d26136fbdaeb46f08aa4f972d1958fa668..3a309b18035e7ab29f5762e8d8331be388ae187e 100644 (file)
@@ -1124,6 +1124,57 @@ static int nau8824_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
        return 0;
 }
 
+/**
+ * nau8824_set_tdm_slot - configure DAI TDM.
+ * @dai: DAI
+ * @tx_mask: Bitmask representing active TX slots. Ex.
+ *                 0xf for normal 4 channel TDM.
+ *                 0xf0 for shifted 4 channel TDM
+ * @rx_mask: Bitmask [0:1] representing active DACR RX slots.
+ *                 Bitmask [2:3] representing active DACL RX slots.
+ *                 00=CH0,01=CH1,10=CH2,11=CH3. Ex.
+ *                 0xf for DACL/R selecting TDM CH3.
+ *                 0xf0 for DACL/R selecting shifted TDM CH3.
+ * @slots: Number of slots in use.
+ * @slot_width: Width in bits for each slot.
+ *
+ * Configures a DAI for TDM operation. Only support 4 slots TDM.
+ */
+static int nau8824_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;
+       struct nau8824 *nau8824 = snd_soc_codec_get_drvdata(codec);
+       unsigned int tslot_l = 0, ctrl_val = 0;
+
+       if (slots > 4 || ((tx_mask & 0xf0) && (tx_mask & 0xf)) ||
+               ((rx_mask & 0xf0) && (rx_mask & 0xf)) ||
+               ((rx_mask & 0xf0) && (tx_mask & 0xf)) ||
+               ((rx_mask & 0xf) && (tx_mask & 0xf0)))
+               return -EINVAL;
+
+       ctrl_val |= (NAU8824_TDM_MODE | NAU8824_TDM_OFFSET_EN);
+       if (tx_mask & 0xf0) {
+               tslot_l = 4 * slot_width;
+               ctrl_val |= (tx_mask >> 4);
+       } else {
+               ctrl_val |= tx_mask;
+       }
+       if (rx_mask & 0xf0)
+               ctrl_val |= ((rx_mask >> 4) << NAU8824_TDM_DACR_RX_SFT);
+       else
+               ctrl_val |= (rx_mask << NAU8824_TDM_DACR_RX_SFT);
+
+       regmap_update_bits(nau8824->regmap, NAU8824_REG_TDM_CTRL,
+               NAU8824_TDM_MODE | NAU8824_TDM_OFFSET_EN |
+               NAU8824_TDM_DACL_RX_MASK | NAU8824_TDM_DACR_RX_MASK |
+               NAU8824_TDM_TX_MASK, ctrl_val);
+       regmap_update_bits(nau8824->regmap, NAU8824_REG_PORT0_LEFT_TIME_SLOT,
+               NAU8824_TSLOT_L_MASK, tslot_l);
+
+       return 0;
+}
+
 /**
  * nau8824_calc_fll_param - Calculate FLL parameters.
  * @fll_in: external clock provided to codec.
@@ -1440,6 +1491,7 @@ static struct snd_soc_codec_driver nau8824_codec_driver = {
 static const struct snd_soc_dai_ops nau8824_dai_ops = {
        .hw_params = nau8824_hw_params,
        .set_fmt = nau8824_set_fmt,
+       .set_tdm_slot = nau8824_set_tdm_slot,
 };
 
 #define NAU8824_RATES SNDRV_PCM_RATE_8000_192000
index 87ac9a382aede5ab898d1a0861751c9d63e70a48..21eae2431c83a4d8db8ffe77761e3a460aa208e7 100644 (file)
 #define NAU8824_I2S_MS_SLAVE           (0 << NAU8824_I2S_MS_SFT)
 #define NAU8824_I2S_BLK_DIV_MASK       0x7
 
+/* PORT0_LEFT_TIME_SLOT (0x1E) */
+#define NAU8824_TSLOT_L_MASK   0x3ff
+
+/* TDM_CTRL (0x20) */
+#define NAU8824_TDM_MODE               (0x1 << 15)
+#define NAU8824_TDM_OFFSET_EN          (0x1 << 14)
+#define NAU8824_TDM_DACL_RX_SFT        6
+#define NAU8824_TDM_DACL_RX_MASK       (0x3 << NAU8824_TDM_DACL_RX_SFT)
+#define NAU8824_TDM_DACR_RX_SFT        4
+#define NAU8824_TDM_DACR_RX_MASK       (0x3 << NAU8824_TDM_DACR_RX_SFT)
+#define NAU8824_TDM_TX_MASK            0xf
+
 /* ADC_FILTER_CTRL (0x24) */
 #define NAU8824_ADC_SYNC_DOWN_MASK     0x3
 #define NAU8824_ADC_SYNC_DOWN_32       0