mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 03:15:31 +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;
|
void __iomem *cru_base;
|
||||||
bool is_master_mode;
|
bool is_master_mode;
|
||||||
bool mclk_calibrate;
|
bool mclk_calibrate;
|
||||||
|
bool tdm_mode;
|
||||||
unsigned int mclk_rx_freq;
|
unsigned int mclk_rx_freq;
|
||||||
unsigned int mclk_tx_freq;
|
unsigned int mclk_tx_freq;
|
||||||
unsigned int bclk_fs;
|
unsigned int bclk_fs;
|
||||||
@@ -387,8 +388,9 @@ static int rockchip_i2s_tdm_set_fmt(struct snd_soc_dai *cpu_dai,
|
|||||||
unsigned int fmt)
|
unsigned int fmt)
|
||||||
{
|
{
|
||||||
struct rk_i2s_tdm_dev *i2s_tdm = to_info(cpu_dai);
|
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;
|
int ret = 0;
|
||||||
|
bool is_tdm = i2s_tdm->tdm_mode;
|
||||||
|
|
||||||
pm_runtime_get_sync(cpu_dai->dev);
|
pm_runtime_get_sync(cpu_dai->dev);
|
||||||
mask = I2S_CKR_MSS_MASK;
|
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);
|
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:
|
err_pm_put:
|
||||||
pm_runtime_put(cpu_dai->dev);
|
pm_runtime_put(cpu_dai->dev);
|
||||||
|
|
||||||
@@ -858,10 +902,31 @@ static int rockchip_i2s_tdm_dai_probe(struct snd_soc_dai *dai)
|
|||||||
return 0;
|
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 = {
|
static const struct snd_soc_dai_ops rockchip_i2s_tdm_dai_ops = {
|
||||||
.hw_params = rockchip_i2s_tdm_hw_params,
|
.hw_params = rockchip_i2s_tdm_hw_params,
|
||||||
.set_sysclk = rockchip_i2s_tdm_set_sysclk,
|
.set_sysclk = rockchip_i2s_tdm_set_sysclk,
|
||||||
.set_fmt = rockchip_i2s_tdm_set_fmt,
|
.set_fmt = rockchip_i2s_tdm_set_fmt,
|
||||||
|
.set_tdm_slot = rockchip_dai_tdm_slot,
|
||||||
.trigger = rockchip_i2s_tdm_trigger,
|
.trigger = rockchip_i2s_tdm_trigger,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,9 @@
|
|||||||
#define I2S_TXCR_TFS_SHIFT 5
|
#define I2S_TXCR_TFS_SHIFT 5
|
||||||
#define I2S_TXCR_TFS_I2S (0 << I2S_TXCR_TFS_SHIFT)
|
#define I2S_TXCR_TFS_I2S (0 << I2S_TXCR_TFS_SHIFT)
|
||||||
#define I2S_TXCR_TFS_PCM (1 << 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_SHIFT 0
|
||||||
#define I2S_TXCR_VDW(x) ((x - 1) << I2S_TXCR_VDW_SHIFT)
|
#define I2S_TXCR_VDW(x) ((x - 1) << I2S_TXCR_VDW_SHIFT)
|
||||||
#define I2S_TXCR_VDW_MASK (0x1f << 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_SHIFT 5
|
||||||
#define I2S_RXCR_TFS_I2S (0 << I2S_RXCR_TFS_SHIFT)
|
#define I2S_RXCR_TFS_I2S (0 << I2S_RXCR_TFS_SHIFT)
|
||||||
#define I2S_RXCR_TFS_PCM (1 << 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_SHIFT 0
|
||||||
#define I2S_RXCR_VDW(x) ((x - 1) << I2S_RXCR_VDW_SHIFT)
|
#define I2S_RXCR_VDW(x) ((x - 1) << I2S_RXCR_VDW_SHIFT)
|
||||||
#define I2S_RXCR_VDW_MASK (0x1f << I2S_RXCR_VDW_SHIFT)
|
#define I2S_RXCR_VDW_MASK (0x1f << I2S_RXCR_VDW_SHIFT)
|
||||||
@@ -213,6 +217,22 @@
|
|||||||
*/
|
*/
|
||||||
#define I2S_RXDR_MASK (0xff)
|
#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
|
* CLKDIV
|
||||||
* Mclk div register
|
* Mclk div register
|
||||||
|
|||||||
Reference in New Issue
Block a user