Message ID | 20201104092005.2227-1-shumingf@realtek.com (mailing list archive) |
---|---|
State | Accepted |
Commit | 7e9a2387c5fdfb3121249b216382ec28e36d5612 |
Headers | show |
Series | [v3] ASoC: rt1015: support TDM slot configuration | expand |
On 11/4/20 3:20 AM, shumingf@realtek.com wrote: > From: Shuming Fan <shumingf@realtek.com> > > Add TDM slot callback function to support TDM configuration > > Signed-off-by: Shuming Fan <shumingf@realtek.com> Thanks Shuming for bearing with my questions. Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@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) >
On Wed, 4 Nov 2020 17:20:05 +0800, shumingf@realtek.com wrote:
> Add TDM slot callback function to support TDM configuration
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
Thanks!
[1/1] ASoC: rt1015: support TDM slot configuration
commit: 7e9a2387c5fdfb3121249b216382ec28e36d5612
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
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)