[PATCH v3] ASoC: rt1015: support TDM slot configuration
Pierre-Louis Bossart
pierre-louis.bossart at linux.intel.com
Wed Nov 4 15:53:01 CET 2020
On 11/4/20 3:20 AM, shumingf at realtek.com wrote:
> From: Shuming Fan <shumingf at realtek.com>
>
> Add TDM slot callback function to support TDM configuration
>
> Signed-off-by: Shuming Fan <shumingf at realtek.com>
Thanks Shuming for bearing with my questions.
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart at linux.intel.com>
> ---
> sound/soc/codecs/rt1015.c | 101 ++++++++++++++++++++++++++++++++++++++
> sound/soc/codecs/rt1015.h | 42 ++++++++++++++++
> 2 files changed, 143 insertions(+)
>
> diff --git a/sound/soc/codecs/rt1015.c b/sound/soc/codecs/rt1015.c
> index 25fe2ddedd54..a9cd6ad0bf5a 100644
> --- a/sound/soc/codecs/rt1015.c
> +++ b/sound/soc/codecs/rt1015.c
> @@ -944,6 +944,106 @@ 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.
> + * The users could select the channel from L/R/L+R by "Mono LR Select" control.
> + */
> + first_bit = __ffs(rx_mask);
> + switch (first_bit) {
> + case 0:
> + case 2:
> + case 4:
> + case 6:
> + 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_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 +1075,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)
>
More information about the Alsa-devel
mailing list