mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 19:08:57 +09:00
ASoC: rockchip: i2s_tdm: add support for tdm mode
Change-Id: Id99c14a1f49796107186405b8b73bffcc49143e8 Signed-off-by: Sugar Zhang <sugar.zhang@rock-chips.com>
This commit is contained in:
@@ -65,6 +65,7 @@ struct rk_i2s_tdm_dev {
|
||||
void __iomem *cru_base;
|
||||
bool is_master_mode;
|
||||
bool mclk_calibrate;
|
||||
bool tdm_mode;
|
||||
unsigned int mclk_rx_freq;
|
||||
unsigned int mclk_tx_freq;
|
||||
unsigned int bclk_fs;
|
||||
@@ -387,8 +388,9 @@ static int rockchip_i2s_tdm_set_fmt(struct snd_soc_dai *cpu_dai,
|
||||
unsigned int fmt)
|
||||
{
|
||||
struct rk_i2s_tdm_dev *i2s_tdm = to_info(cpu_dai);
|
||||
unsigned int mask = 0, val = 0;
|
||||
unsigned int mask = 0, val = 0, tdm_val = 0;
|
||||
int ret = 0;
|
||||
bool is_tdm = i2s_tdm->tdm_mode;
|
||||
|
||||
pm_runtime_get_sync(cpu_dai->dev);
|
||||
mask = I2S_CKR_MSS_MASK;
|
||||
@@ -472,6 +474,48 @@ static int rockchip_i2s_tdm_set_fmt(struct snd_soc_dai *cpu_dai,
|
||||
|
||||
regmap_update_bits(i2s_tdm->regmap, I2S_RXCR, mask, val);
|
||||
|
||||
if (is_tdm) {
|
||||
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
|
||||
case SND_SOC_DAIFMT_RIGHT_J:
|
||||
val = I2S_TXCR_TFS_TDM_I2S;
|
||||
tdm_val = TDM_SHIFT_CTRL(2);
|
||||
break;
|
||||
case SND_SOC_DAIFMT_LEFT_J:
|
||||
val = I2S_TXCR_TFS_TDM_I2S;
|
||||
tdm_val = TDM_SHIFT_CTRL(1);
|
||||
break;
|
||||
case SND_SOC_DAIFMT_I2S:
|
||||
val = I2S_TXCR_TFS_TDM_I2S;
|
||||
tdm_val = TDM_SHIFT_CTRL(0);
|
||||
break;
|
||||
case SND_SOC_DAIFMT_DSP_A:
|
||||
val = I2S_TXCR_TFS_TDM_PCM;
|
||||
tdm_val = TDM_SHIFT_CTRL(0);
|
||||
break;
|
||||
case SND_SOC_DAIFMT_DSP_B:
|
||||
val = I2S_TXCR_TFS_TDM_PCM;
|
||||
tdm_val = TDM_SHIFT_CTRL(2);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
goto err_pm_put;
|
||||
}
|
||||
|
||||
tdm_val |= TDM_FSYNC_WIDTH_SEL1(1);
|
||||
tdm_val |= TDM_FSYNC_WIDTH_ONE_FRAME;
|
||||
|
||||
mask = I2S_TXCR_TFS_MASK;
|
||||
regmap_update_bits(i2s_tdm->regmap, I2S_TXCR, mask, val);
|
||||
regmap_update_bits(i2s_tdm->regmap, I2S_RXCR, mask, val);
|
||||
|
||||
mask = TDM_FSYNC_WIDTH_SEL1_MSK | TDM_FSYNC_WIDTH_SEL0_MSK |
|
||||
TDM_SHIFT_CTRL_MSK;
|
||||
regmap_update_bits(i2s_tdm->regmap, I2S_TDM_TXCR,
|
||||
mask, tdm_val);
|
||||
regmap_update_bits(i2s_tdm->regmap, I2S_TDM_RXCR,
|
||||
mask, tdm_val);
|
||||
}
|
||||
|
||||
err_pm_put:
|
||||
pm_runtime_put(cpu_dai->dev);
|
||||
|
||||
@@ -858,10 +902,31 @@ static int rockchip_i2s_tdm_dai_probe(struct snd_soc_dai *dai)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_dai_tdm_slot(struct snd_soc_dai *dai,
|
||||
unsigned int tx_mask, unsigned int rx_mask,
|
||||
int slots, int slot_width)
|
||||
{
|
||||
struct rk_i2s_tdm_dev *i2s_tdm = snd_soc_dai_get_drvdata(dai);
|
||||
unsigned int mask, val;
|
||||
|
||||
i2s_tdm->tdm_mode = true;
|
||||
i2s_tdm->bclk_fs = slots * slot_width;
|
||||
mask = TDM_SLOT_BIT_WIDTH_MSK | TDM_FRAME_WIDTH_MSK;
|
||||
val = TDM_SLOT_BIT_WIDTH(slot_width) |
|
||||
TDM_FRAME_WIDTH(slots * slot_width);
|
||||
regmap_update_bits(i2s_tdm->regmap, I2S_TDM_TXCR,
|
||||
mask, val);
|
||||
regmap_update_bits(i2s_tdm->regmap, I2S_TDM_RXCR,
|
||||
mask, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_soc_dai_ops rockchip_i2s_tdm_dai_ops = {
|
||||
.hw_params = rockchip_i2s_tdm_hw_params,
|
||||
.set_sysclk = rockchip_i2s_tdm_set_sysclk,
|
||||
.set_fmt = rockchip_i2s_tdm_set_fmt,
|
||||
.set_tdm_slot = rockchip_dai_tdm_slot,
|
||||
.trigger = rockchip_i2s_tdm_trigger,
|
||||
};
|
||||
|
||||
|
||||
@@ -41,7 +41,9 @@
|
||||
#define I2S_TXCR_TFS_SHIFT 5
|
||||
#define I2S_TXCR_TFS_I2S (0 << I2S_TXCR_TFS_SHIFT)
|
||||
#define I2S_TXCR_TFS_PCM (1 << I2S_TXCR_TFS_SHIFT)
|
||||
#define I2S_TXCR_TFS_MASK (1 << I2S_TXCR_TFS_SHIFT)
|
||||
#define I2S_TXCR_TFS_TDM_PCM (2 << I2S_TXCR_TFS_SHIFT)
|
||||
#define I2S_TXCR_TFS_TDM_I2S (3 << I2S_TXCR_TFS_SHIFT)
|
||||
#define I2S_TXCR_TFS_MASK (3 << I2S_TXCR_TFS_SHIFT)
|
||||
#define I2S_TXCR_VDW_SHIFT 0
|
||||
#define I2S_TXCR_VDW(x) ((x - 1) << I2S_TXCR_VDW_SHIFT)
|
||||
#define I2S_TXCR_VDW_MASK (0x1f << I2S_TXCR_VDW_SHIFT)
|
||||
@@ -71,7 +73,9 @@
|
||||
#define I2S_RXCR_TFS_SHIFT 5
|
||||
#define I2S_RXCR_TFS_I2S (0 << I2S_RXCR_TFS_SHIFT)
|
||||
#define I2S_RXCR_TFS_PCM (1 << I2S_RXCR_TFS_SHIFT)
|
||||
#define I2S_RXCR_TFS_MASK (1 << I2S_RXCR_TFS_SHIFT)
|
||||
#define I2S_RXCR_TFS_TDM_PCM (2 << I2S_RXCR_TFS_SHIFT)
|
||||
#define I2S_RXCR_TFS_TDM_I2S (3 << I2S_RXCR_TFS_SHIFT)
|
||||
#define I2S_RXCR_TFS_MASK (3 << I2S_RXCR_TFS_SHIFT)
|
||||
#define I2S_RXCR_VDW_SHIFT 0
|
||||
#define I2S_RXCR_VDW(x) ((x - 1) << I2S_RXCR_VDW_SHIFT)
|
||||
#define I2S_RXCR_VDW_MASK (0x1f << I2S_RXCR_VDW_SHIFT)
|
||||
@@ -213,6 +217,22 @@
|
||||
*/
|
||||
#define I2S_RXDR_MASK (0xff)
|
||||
|
||||
/*
|
||||
* TDM_CTRL
|
||||
* TDM ctrl register
|
||||
*/
|
||||
#define TDM_FSYNC_WIDTH_SEL1_MSK GENMASK(20, 18)
|
||||
#define TDM_FSYNC_WIDTH_SEL1(x) ((x - 1) << 18)
|
||||
#define TDM_FSYNC_WIDTH_SEL0_MSK BIT(17)
|
||||
#define TDM_FSYNC_WIDTH_HALF_FRAME 0
|
||||
#define TDM_FSYNC_WIDTH_ONE_FRAME BIT(17)
|
||||
#define TDM_SHIFT_CTRL_MSK GENMASK(16, 14)
|
||||
#define TDM_SHIFT_CTRL(x) ((x) << 14)
|
||||
#define TDM_SLOT_BIT_WIDTH_MSK GENMASK(13, 9)
|
||||
#define TDM_SLOT_BIT_WIDTH(x) ((x - 1) << 9)
|
||||
#define TDM_FRAME_WIDTH_MSK GENMASK(8, 0)
|
||||
#define TDM_FRAME_WIDTH(x) ((x - 1) << 0)
|
||||
|
||||
/*
|
||||
* CLKDIV
|
||||
* Mclk div register
|
||||
|
||||
Reference in New Issue
Block a user