mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 20:51:44 +00:00
ASoC: nau8825: Add TDM support
Support TDM format for NAU88L25. Signed-off-by: David Lin <CTLIN0@nuvoton.com> Link: https://lore.kernel.org/r/20220930072804.2524352-1-CTLIN0@nuvoton.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
d488b28502
commit
dacdef1bd2
@ -1425,10 +1425,107 @@ static int nau8825_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* nau8825_set_tdm_slot - configure DAI TDM.
|
||||
* @dai: DAI
|
||||
* @tx_mask: bitmask representing active TX slots.
|
||||
* @rx_mask: bitmask representing active RX slots.
|
||||
* @slots: Number of slots in use.
|
||||
* @slot_width: Width in bits for each slot.
|
||||
*
|
||||
* Configures a DAI for TDM operation. Support TDM 4/8 slots.
|
||||
* The limitation is DAC and ADC need shift 4 slots at 8 slots mode.
|
||||
*/
|
||||
static int nau8825_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;
|
||||
struct nau8825 *nau8825 = snd_soc_component_get_drvdata(component);
|
||||
unsigned int ctrl_val = 0, ctrl_offset = 0, value = 0, dac_s, adc_s;
|
||||
|
||||
if (slots != 4 && slots != 8) {
|
||||
dev_err(nau8825->dev, "Only support 4 or 8 slots!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* The driver is limited to 1-channel for ADC, and 2-channel for DAC on TDM mode */
|
||||
if (hweight_long((unsigned long) tx_mask) != 1 ||
|
||||
hweight_long((unsigned long) rx_mask) != 2) {
|
||||
dev_err(nau8825->dev,
|
||||
"The limitation is 1-channel for ADC, and 2-channel for DAC on TDM mode.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (((tx_mask & 0xf) && (tx_mask & 0xf0)) ||
|
||||
((rx_mask & 0xf) && (rx_mask & 0xf0)) ||
|
||||
((tx_mask & 0xf) && (rx_mask & 0xf0)) ||
|
||||
((rx_mask & 0xf) && (tx_mask & 0xf0))) {
|
||||
dev_err(nau8825->dev,
|
||||
"Slot assignment of DAC and ADC need to set same interval.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* The offset of fixed 4 slots for 8 slots support */
|
||||
if (rx_mask & 0xf0) {
|
||||
regmap_update_bits(nau8825->regmap, NAU8825_REG_I2S_PCM_CTRL2,
|
||||
NAU8825_I2S_PCM_TS_EN_MASK, NAU8825_I2S_PCM_TS_EN);
|
||||
regmap_read(nau8825->regmap, NAU8825_REG_I2S_PCM_CTRL1, &value);
|
||||
ctrl_val |= NAU8825_TDM_OFFSET_EN;
|
||||
ctrl_offset = 4 * slot_width;
|
||||
if (!(value & NAU8825_I2S_PCMB_MASK))
|
||||
ctrl_offset += 1;
|
||||
dac_s = (rx_mask & 0xf0) >> 4;
|
||||
adc_s = fls((tx_mask & 0xf0) >> 4);
|
||||
} else {
|
||||
dac_s = rx_mask & 0xf;
|
||||
adc_s = fls(tx_mask & 0xf);
|
||||
}
|
||||
|
||||
ctrl_val |= NAU8825_TDM_MODE;
|
||||
|
||||
switch (dac_s) {
|
||||
case 0x3:
|
||||
ctrl_val |= 1 << NAU8825_TDM_DACR_RX_SFT;
|
||||
break;
|
||||
case 0x5:
|
||||
ctrl_val |= 2 << NAU8825_TDM_DACR_RX_SFT;
|
||||
break;
|
||||
case 0x6:
|
||||
ctrl_val |= 1 << NAU8825_TDM_DACL_RX_SFT;
|
||||
ctrl_val |= 2 << NAU8825_TDM_DACR_RX_SFT;
|
||||
break;
|
||||
case 0x9:
|
||||
ctrl_val |= 3 << NAU8825_TDM_DACR_RX_SFT;
|
||||
break;
|
||||
case 0xa:
|
||||
ctrl_val |= 1 << NAU8825_TDM_DACL_RX_SFT;
|
||||
ctrl_val |= 3 << NAU8825_TDM_DACR_RX_SFT;
|
||||
break;
|
||||
case 0xc:
|
||||
ctrl_val |= 2 << NAU8825_TDM_DACL_RX_SFT;
|
||||
ctrl_val |= 3 << NAU8825_TDM_DACR_RX_SFT;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ctrl_val |= adc_s - 1;
|
||||
|
||||
regmap_update_bits(nau8825->regmap, NAU8825_REG_TDM_CTRL,
|
||||
NAU8825_TDM_MODE | NAU8825_TDM_OFFSET_EN |
|
||||
NAU8825_TDM_DACL_RX_MASK | NAU8825_TDM_DACR_RX_MASK |
|
||||
NAU8825_TDM_TX_MASK, ctrl_val);
|
||||
regmap_update_bits(nau8825->regmap, NAU8825_REG_LEFT_TIME_SLOT,
|
||||
NAU8825_TSLOT_L0_MASK, ctrl_offset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_soc_dai_ops nau8825_dai_ops = {
|
||||
.startup = nau8825_dai_startup,
|
||||
.hw_params = nau8825_hw_params,
|
||||
.set_fmt = nau8825_set_dai_fmt,
|
||||
.set_tdm_slot = nau8825_set_tdm_slot,
|
||||
};
|
||||
|
||||
#define NAU8825_RATES SNDRV_PCM_RATE_8000_192000
|
||||
|
@ -225,6 +225,15 @@
|
||||
#define NAU8825_JKDET_PULL_EN (1 << 9) /* 0 - enable pull, 1 - disable */
|
||||
#define NAU8825_JKDET_OUTPUT_EN (1 << 8) /* 0 - enable input, 1 - enable output */
|
||||
|
||||
/* TDM_CTRL (0x1b) */
|
||||
#define NAU8825_TDM_MODE (0x1 << 15)
|
||||
#define NAU8825_TDM_OFFSET_EN (0x1 << 14)
|
||||
#define NAU8825_TDM_DACL_RX_SFT 6
|
||||
#define NAU8825_TDM_DACL_RX_MASK (0x3 << NAU8825_TDM_DACL_RX_SFT)
|
||||
#define NAU8825_TDM_DACR_RX_SFT 4
|
||||
#define NAU8825_TDM_DACR_RX_MASK (0x3 << NAU8825_TDM_DACR_RX_SFT)
|
||||
#define NAU8825_TDM_TX_MASK 0x3
|
||||
|
||||
/* I2S_PCM_CTRL1 (0x1c) */
|
||||
#define NAU8825_I2S_BP_SFT 7
|
||||
#define NAU8825_I2S_BP_MASK (1 << NAU8825_I2S_BP_SFT)
|
||||
@ -249,6 +258,9 @@
|
||||
#define NAU8825_I2S_TRISTATE (1 << 15) /* 0 - normal mode, 1 - Hi-Z output */
|
||||
#define NAU8825_I2S_LRC_DIV_SFT 12
|
||||
#define NAU8825_I2S_LRC_DIV_MASK (0x3 << NAU8825_I2S_LRC_DIV_SFT)
|
||||
#define NAU8825_I2S_PCM_TS_EN_SFT 10
|
||||
#define NAU8825_I2S_PCM_TS_EN_MASK (1 << NAU8825_I2S_PCM_TS_EN_SFT)
|
||||
#define NAU8825_I2S_PCM_TS_EN (1 << NAU8825_I2S_PCM_TS_EN_SFT)
|
||||
#define NAU8825_I2S_MS_SFT 3
|
||||
#define NAU8825_I2S_MS_MASK (1 << NAU8825_I2S_MS_SFT)
|
||||
#define NAU8825_I2S_MS_MASTER (1 << NAU8825_I2S_MS_SFT)
|
||||
@ -259,6 +271,8 @@
|
||||
#define NAU8825_FS_ERR_CMP_SEL_SFT 14
|
||||
#define NAU8825_FS_ERR_CMP_SEL_MASK (0x3 << NAU8825_FS_ERR_CMP_SEL_SFT)
|
||||
#define NAU8825_DIS_FS_SHORT_DET (1 << 13)
|
||||
#define NAU8825_TSLOT_L0_MASK 0x3ff
|
||||
#define NAU8825_TSLOT_R0_MASK 0x3ff
|
||||
|
||||
/* BIQ_CTRL (0x20) */
|
||||
#define NAU8825_BIQ_WRT_SFT 4
|
||||
|
Loading…
Reference in New Issue
Block a user