Skip to content
/ linux Public
forked from torvalds/linux

Commit

Permalink
ASoC: rockchip: i2s_tdm: add support for tdm mode
Browse files Browse the repository at this point in the history
Change-Id: Id99c14a1f49796107186405b8b73bffcc49143e8
Signed-off-by: Sugar Zhang <sugar.zhang@rock-chips.com>
  • Loading branch information
Sugar Zhang authored and rkhuangtao committed May 21, 2018
1 parent 5597d4a commit 2b987b2
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 3 deletions.
67 changes: 66 additions & 1 deletion sound/soc/rockchip/rockchip_i2s_tdm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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,
};

Expand Down
24 changes: 22 additions & 2 deletions sound/soc/rockchip/rockchip_i2s_tdm.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 2b987b2

Please sign in to comment.