All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2] ASoC: rt1015: support TDM slot configuration
@ 2020-11-03  9:14 shumingf
  2020-11-03 15:47 ` Pierre-Louis Bossart
  0 siblings, 1 reply; 3+ messages in thread
From: shumingf @ 2020-11-03  9:14 UTC (permalink / raw)
  To: broonie, lgirdwood
  Cc: oder_chiou, jack.yu, alsa-devel, lars, kent_chen, Keith.Tzeng,
	derek.fang, Shuming Fan, brent.lu, flove

From: Shuming Fan <shumingf@realtek.com>

Add TDM slot callback function to support TDM configuration

Signed-off-by: Shuming Fan <shumingf@realtek.com>
---
 sound/soc/codecs/rt1015.c | 107 ++++++++++++++++++++++++++++++++++++++
 sound/soc/codecs/rt1015.h |  42 +++++++++++++++
 2 files changed, 149 insertions(+)

diff --git a/sound/soc/codecs/rt1015.c b/sound/soc/codecs/rt1015.c
index 25fe2ddedd54..b067bd175287 100644
--- a/sound/soc/codecs/rt1015.c
+++ b/sound/soc/codecs/rt1015.c
@@ -944,6 +944,112 @@ static int rt1015_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio)
 	return 0;
 }
 
+static int rt1015_set_tdm_slot(struct snd_soc_dai *dai,
+	unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width)
+{
+	struct snd_soc_component *component = dai->component;
+	unsigned int val = 0, rx_slotnum, tx_slotnum;
+	int ret = 0, first_bit;
+
+	switch (slots) {
+	case 2:
+		val |= RT1015_I2S_TX_2CH;
+		break;
+	case 4:
+		val |= RT1015_I2S_TX_4CH;
+		break;
+	case 6:
+		val |= RT1015_I2S_TX_6CH;
+		break;
+	case 8:
+		val |= RT1015_I2S_TX_8CH;
+		break;
+	default:
+		ret = -EINVAL;
+		goto _set_tdm_err_;
+	}
+
+	switch (slot_width) {
+	case 16:
+		val |= RT1015_I2S_CH_TX_LEN_16B;
+		break;
+	case 20:
+		val |= RT1015_I2S_CH_TX_LEN_20B;
+		break;
+	case 24:
+		val |= RT1015_I2S_CH_TX_LEN_24B;
+		break;
+	case 32:
+		val |= RT1015_I2S_CH_TX_LEN_32B;
+		break;
+	default:
+		ret = -EINVAL;
+		goto _set_tdm_err_;
+	}
+
+	/* Rx slot configuration */
+	rx_slotnum = hweight_long(rx_mask);
+	if (rx_slotnum != 1) {
+		ret = -EINVAL;
+		dev_err(component->dev, "too many rx slots or zero slot\n");
+		goto _set_tdm_err_;
+	}
+
+	/* This is an assumption that the system sends stereo audio to the amplifier typically.
+	 * And the stereo audio is placed in slot 0/2/4/6 as the starting slot.
+	 * According to the slot number, we also set the mono LR to select the right slot.
+	 */
+	first_bit = __ffs(rx_mask);
+	switch (first_bit) {
+	case 0:
+	case 2:
+	case 4:
+	case 6:
+		snd_soc_component_update_bits(component,
+			RT1015_PAD_DRV2, RT1015_MONO_LR_SEL_MASK,
+			RT1015_MONO_L_CHANNEL);
+		snd_soc_component_update_bits(component,
+			RT1015_TDM1_4,
+			RT1015_TDM_I2S_TX_L_DAC1_1_MASK |
+			RT1015_TDM_I2S_TX_R_DAC1_1_MASK,
+			(first_bit << RT1015_TDM_I2S_TX_L_DAC1_1_SFT) |
+			((first_bit+1) << RT1015_TDM_I2S_TX_R_DAC1_1_SFT));
+		break;
+	case 1:
+	case 3:
+	case 5:
+	case 7:
+		snd_soc_component_update_bits(component,
+			RT1015_PAD_DRV2, RT1015_MONO_LR_SEL_MASK,
+			RT1015_MONO_R_CHANNEL);
+		snd_soc_component_update_bits(component,
+			RT1015_TDM1_4,
+			RT1015_TDM_I2S_TX_L_DAC1_1_MASK |
+			RT1015_TDM_I2S_TX_R_DAC1_1_MASK,
+			((first_bit-1) << RT1015_TDM_I2S_TX_L_DAC1_1_SFT) |
+			(first_bit << RT1015_TDM_I2S_TX_R_DAC1_1_SFT));
+		break;
+	default:
+		ret = -EINVAL;
+		goto _set_tdm_err_;
+	}
+
+	/* Tx slot configuration */
+	tx_slotnum = hweight_long(tx_mask);
+	if (tx_slotnum) {
+		ret = -EINVAL;
+		dev_err(component->dev, "doesn't need to support tx slots\n");
+		goto _set_tdm_err_;
+	}
+
+	snd_soc_component_update_bits(component, RT1015_TDM1_1,
+		RT1015_I2S_CH_TX_MASK | RT1015_I2S_CH_RX_MASK |
+		RT1015_I2S_CH_TX_LEN_MASK | RT1015_I2S_CH_RX_LEN_MASK, val);
+
+_set_tdm_err_:
+	return ret;
+}
+
 static int rt1015_probe(struct snd_soc_component *component)
 {
 	struct rt1015_priv *rt1015 =
@@ -975,6 +1081,7 @@ static struct snd_soc_dai_ops rt1015_aif_dai_ops = {
 	.hw_params = rt1015_hw_params,
 	.set_fmt = rt1015_set_dai_fmt,
 	.set_bclk_ratio = rt1015_set_bclk_ratio,
+	.set_tdm_slot = rt1015_set_tdm_slot,
 };
 
 static struct snd_soc_dai_driver rt1015_dai[] = {
diff --git a/sound/soc/codecs/rt1015.h b/sound/soc/codecs/rt1015.h
index d3fdd30aca6d..ad8274c80990 100644
--- a/sound/soc/codecs/rt1015.h
+++ b/sound/soc/codecs/rt1015.h
@@ -213,6 +213,12 @@
 #define RT1015_ID_VERA				0x0
 #define RT1015_ID_VERB				0x1
 
+/* 0x00f2 */
+#define RT1015_MONO_LR_SEL_MASK			(0x3 << 4)
+#define RT1015_MONO_L_CHANNEL			(0x0 << 4)
+#define RT1015_MONO_R_CHANNEL			(0x1 << 4)
+#define RT1015_MONO_LR_MIX_CHANNEL			(0x2 << 4)
+
 /* 0x0102 */
 #define RT1015_DAC_VOL_MASK			(0x7f << 9)
 #define RT1015_DAC_VOL_SFT			9
@@ -275,6 +281,42 @@
 #define RT1015_TDM_INV_BCLK_MASK		(0x1 << 15)
 #define RT1015_TDM_INV_BCLK_SFT			15
 #define RT1015_TDM_INV_BCLK			(0x1 << 15)
+#define RT1015_I2S_CH_TX_MASK			(0x3 << 10)
+#define RT1015_I2S_CH_TX_SFT			10
+#define RT1015_I2S_TX_2CH			(0x0 << 10)
+#define RT1015_I2S_TX_4CH			(0x1 << 10)
+#define RT1015_I2S_TX_6CH			(0x2 << 10)
+#define RT1015_I2S_TX_8CH			(0x3 << 10)
+#define RT1015_I2S_CH_RX_MASK			(0x3 << 8)
+#define RT1015_I2S_CH_RX_SFT			8
+#define RT1015_I2S_RX_2CH			(0x0 << 8)
+#define RT1015_I2S_RX_4CH			(0x1 << 8)
+#define RT1015_I2S_RX_6CH			(0x2 << 8)
+#define RT1015_I2S_RX_8CH			(0x3 << 8)
+#define RT1015_I2S_LR_CH_SEL_MASK			(0x1 << 7)
+#define RT1015_I2S_LR_CH_SEL_SFT			7
+#define RT1015_I2S_LEFT_CH_SEL			(0x0 << 7)
+#define RT1015_I2S_RIGHT_CH_SEL			(0x1 << 7)
+#define RT1015_I2S_CH_TX_LEN_MASK			(0x7 << 4)
+#define RT1015_I2S_CH_TX_LEN_SFT			4
+#define RT1015_I2S_CH_TX_LEN_16B			(0x0 << 4)
+#define RT1015_I2S_CH_TX_LEN_20B			(0x1 << 4)
+#define RT1015_I2S_CH_TX_LEN_24B			(0x2 << 4)
+#define RT1015_I2S_CH_TX_LEN_32B			(0x3 << 4)
+#define RT1015_I2S_CH_TX_LEN_8B			(0x4 << 4)
+#define RT1015_I2S_CH_RX_LEN_MASK			(0x7 << 0)
+#define RT1015_I2S_CH_RX_LEN_SFT			0
+#define RT1015_I2S_CH_RX_LEN_16B			(0x0 << 0)
+#define RT1015_I2S_CH_RX_LEN_20B			(0x1 << 0)
+#define RT1015_I2S_CH_RX_LEN_24B			(0x2 << 0)
+#define RT1015_I2S_CH_RX_LEN_32B			(0x3 << 0)
+#define RT1015_I2S_CH_RX_LEN_8B			(0x4 << 0)
+
+/* TDM1 Setting-4 (0x011a) */
+#define RT1015_TDM_I2S_TX_L_DAC1_1_MASK			(0x7 << 12)
+#define RT1015_TDM_I2S_TX_R_DAC1_1_MASK			(0x7 << 8)
+#define RT1015_TDM_I2S_TX_L_DAC1_1_SFT 12
+#define RT1015_TDM_I2S_TX_R_DAC1_1_SFT 8
 
 /* 0x0330 */
 #define RT1015_ABST_AUTO_EN_MASK		(0x1 << 13)
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH v2] ASoC: rt1015: support TDM slot configuration
  2020-11-03  9:14 [PATCH v2] ASoC: rt1015: support TDM slot configuration shumingf
@ 2020-11-03 15:47 ` Pierre-Louis Bossart
  2020-11-04  1:42   ` Shuming [范書銘]
  0 siblings, 1 reply; 3+ messages in thread
From: Pierre-Louis Bossart @ 2020-11-03 15:47 UTC (permalink / raw)
  To: shumingf, broonie, lgirdwood
  Cc: oder_chiou, jack.yu, alsa-devel, lars, kent_chen, Keith.Tzeng,
	derek.fang, brent.lu, flove


> +	/* This is an assumption that the system sends stereo audio to the amplifier typically.
> +	 * And the stereo audio is placed in slot 0/2/4/6 as the starting slot.
> +	 * According to the slot number, we also set the mono LR to select the right slot.
> +	 */
> +	first_bit = __ffs(rx_mask);
> +	switch (first_bit) {
> +	case 0:
> +	case 2:
> +	case 4:
> +	case 6:
> +		snd_soc_component_update_bits(component,
> +			RT1015_PAD_DRV2, RT1015_MONO_LR_SEL_MASK,
> +			RT1015_MONO_L_CHANNEL);
> +		snd_soc_component_update_bits(component,
> +			RT1015_TDM1_4,
> +			RT1015_TDM_I2S_TX_L_DAC1_1_MASK |
> +			RT1015_TDM_I2S_TX_R_DAC1_1_MASK,
> +			(first_bit << RT1015_TDM_I2S_TX_L_DAC1_1_SFT) |
> +			((first_bit+1) << RT1015_TDM_I2S_TX_R_DAC1_1_SFT));
> +		break;
> +	case 1:
> +	case 3:
> +	case 5:
> +	case 7:
> +		snd_soc_component_update_bits(component,
> +			RT1015_PAD_DRV2, RT1015_MONO_LR_SEL_MASK,
> +			RT1015_MONO_R_CHANNEL);
> +		snd_soc_component_update_bits(component,
> +			RT1015_TDM1_4,
> +			RT1015_TDM_I2S_TX_L_DAC1_1_MASK |
> +			RT1015_TDM_I2S_TX_R_DAC1_1_MASK,
> +			((first_bit-1) << RT1015_TDM_I2S_TX_L_DAC1_1_SFT) |
> +			(first_bit << RT1015_TDM_I2S_TX_R_DAC1_1_SFT));
> +		break;

One more question from me: if you have 2 amplifiers on the same link and 
use slot 0 and 1, what would be the rx_mask for each amplifier? If the 
mask is BIT(0) for left and BIT(1) for right, it looks like both would 
render L+R?

Also should the settings and channel selection be modifiable using the 
codec configuration as we've done for RT1308, e.g. rt1015-1 would use LL 
and rt1015-2 would use RR?

Thanks
-Pierre

^ permalink raw reply	[flat|nested] 3+ messages in thread

* RE: [PATCH v2] ASoC: rt1015: support TDM slot configuration
  2020-11-03 15:47 ` Pierre-Louis Bossart
@ 2020-11-04  1:42   ` Shuming [范書銘]
  0 siblings, 0 replies; 3+ messages in thread
From: Shuming [范書銘] @ 2020-11-04  1:42 UTC (permalink / raw)
  To: Pierre-Louis Bossart, broonie@kernel.org, lgirdwood@gmail.com
  Cc: Oder Chiou, Jack Yu, alsa-devel@alsa-project.org, lars@metafoo.de,
	kent_chen@realtek.com [陳建宏],
	Keith.Tzeng@quantatw.com, Derek [方德義],
	brent.lu@intel.com, Flove(HsinFu)

> > +	/* This is an assumption that the system sends stereo audio to the
> amplifier typically.
> > +	 * And the stereo audio is placed in slot 0/2/4/6 as the starting slot.
> > +	 * According to the slot number, we also set the mono LR to select the
> right slot.
> > +	 */
> > +	first_bit = __ffs(rx_mask);
> > +	switch (first_bit) {
> > +	case 0:
> > +	case 2:
> > +	case 4:
> > +	case 6:
> > +		snd_soc_component_update_bits(component,
> > +			RT1015_PAD_DRV2, RT1015_MONO_LR_SEL_MASK,
> > +			RT1015_MONO_L_CHANNEL);
> > +		snd_soc_component_update_bits(component,
> > +			RT1015_TDM1_4,
> > +			RT1015_TDM_I2S_TX_L_DAC1_1_MASK |
> > +			RT1015_TDM_I2S_TX_R_DAC1_1_MASK,
> > +			(first_bit << RT1015_TDM_I2S_TX_L_DAC1_1_SFT) |
> > +			((first_bit+1) << RT1015_TDM_I2S_TX_R_DAC1_1_SFT));
> > +		break;
> > +	case 1:
> > +	case 3:
> > +	case 5:
> > +	case 7:
> > +		snd_soc_component_update_bits(component,
> > +			RT1015_PAD_DRV2, RT1015_MONO_LR_SEL_MASK,
> > +			RT1015_MONO_R_CHANNEL);
> > +		snd_soc_component_update_bits(component,
> > +			RT1015_TDM1_4,
> > +			RT1015_TDM_I2S_TX_L_DAC1_1_MASK |
> > +			RT1015_TDM_I2S_TX_R_DAC1_1_MASK,
> > +			((first_bit-1) << RT1015_TDM_I2S_TX_L_DAC1_1_SFT) |
> > +			(first_bit << RT1015_TDM_I2S_TX_R_DAC1_1_SFT));
> > +		break;
> 
> One more question from me: if you have 2 amplifiers on the same link and use
> slot 0 and 1, what would be the rx_mask for each amplifier? If the mask is
> BIT(0) for left and BIT(1) for right, it looks like both would render L+R?

Oh, I didn't expect that the customers want to render L+R when using TDM configuration.

> Also should the settings and channel selection be modifiable using the codec
> configuration as we've done for RT1308, e.g. rt1015-1 would use LL and
> rt1015-2 would use RR?

OK, I will remove the mono LR channel selection in rt1015_set_tdm_slot function.
The channel selection setting would be controlled by the application level only.
RT1015 is a mono amplifier, it could select 'Left', 'Right' and 'Left + Right average'.

> 
> Thanks
> -Pierre
> 
> ------Please consider the environment before printing this e-mail.

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2020-11-04  1:43 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-11-03  9:14 [PATCH v2] ASoC: rt1015: support TDM slot configuration shumingf
2020-11-03 15:47 ` Pierre-Louis Bossart
2020-11-04  1:42   ` Shuming [范書銘]

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.