ASoC: tegra: use regmap more directly
Stop open-coding the caching of the ctrl registers; instead, use regmap_update_bits() to update parts of the register from different places. The removal of the open-coded cache will allow controls to be created which touch registers, which will be necessary if any of these modules are converted to CODECs. Get rid of tegra*_read/write; just call regmap_read/write directly. Signed-off-by: Stephen Warren <swarren@nvidia.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
This commit is contained in:
Родитель
c92a40e3a1
Коммит
0f163546a7
|
@ -46,18 +46,6 @@
|
||||||
|
|
||||||
#define DRV_NAME "tegra20-i2s"
|
#define DRV_NAME "tegra20-i2s"
|
||||||
|
|
||||||
static inline void tegra20_i2s_write(struct tegra20_i2s *i2s, u32 reg, u32 val)
|
|
||||||
{
|
|
||||||
regmap_write(i2s->regmap, reg, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline u32 tegra20_i2s_read(struct tegra20_i2s *i2s, u32 reg)
|
|
||||||
{
|
|
||||||
u32 val;
|
|
||||||
regmap_read(i2s->regmap, reg, &val);
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tegra20_i2s_runtime_suspend(struct device *dev)
|
static int tegra20_i2s_runtime_suspend(struct device *dev)
|
||||||
{
|
{
|
||||||
struct tegra20_i2s *i2s = dev_get_drvdata(dev);
|
struct tegra20_i2s *i2s = dev_get_drvdata(dev);
|
||||||
|
@ -85,6 +73,7 @@ static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai,
|
||||||
unsigned int fmt)
|
unsigned int fmt)
|
||||||
{
|
{
|
||||||
struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai);
|
struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai);
|
||||||
|
unsigned int mask, val;
|
||||||
|
|
||||||
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
|
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
|
||||||
case SND_SOC_DAIFMT_NB_NF:
|
case SND_SOC_DAIFMT_NB_NF:
|
||||||
|
@ -93,10 +82,10 @@ static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
i2s->reg_ctrl &= ~TEGRA20_I2S_CTRL_MASTER_ENABLE;
|
mask = TEGRA20_I2S_CTRL_MASTER_ENABLE;
|
||||||
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
|
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
|
||||||
case SND_SOC_DAIFMT_CBS_CFS:
|
case SND_SOC_DAIFMT_CBS_CFS:
|
||||||
i2s->reg_ctrl |= TEGRA20_I2S_CTRL_MASTER_ENABLE;
|
val = TEGRA20_I2S_CTRL_MASTER_ENABLE;
|
||||||
break;
|
break;
|
||||||
case SND_SOC_DAIFMT_CBM_CFM:
|
case SND_SOC_DAIFMT_CBM_CFM:
|
||||||
break;
|
break;
|
||||||
|
@ -104,33 +93,35 @@ static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
i2s->reg_ctrl &= ~(TEGRA20_I2S_CTRL_BIT_FORMAT_MASK |
|
mask |= TEGRA20_I2S_CTRL_BIT_FORMAT_MASK |
|
||||||
TEGRA20_I2S_CTRL_LRCK_MASK);
|
TEGRA20_I2S_CTRL_LRCK_MASK;
|
||||||
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
|
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
|
||||||
case SND_SOC_DAIFMT_DSP_A:
|
case SND_SOC_DAIFMT_DSP_A:
|
||||||
i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_DSP;
|
val |= TEGRA20_I2S_CTRL_BIT_FORMAT_DSP;
|
||||||
i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_L_LOW;
|
val |= TEGRA20_I2S_CTRL_LRCK_L_LOW;
|
||||||
break;
|
break;
|
||||||
case SND_SOC_DAIFMT_DSP_B:
|
case SND_SOC_DAIFMT_DSP_B:
|
||||||
i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_DSP;
|
val |= TEGRA20_I2S_CTRL_BIT_FORMAT_DSP;
|
||||||
i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_R_LOW;
|
val |= TEGRA20_I2S_CTRL_LRCK_R_LOW;
|
||||||
break;
|
break;
|
||||||
case SND_SOC_DAIFMT_I2S:
|
case SND_SOC_DAIFMT_I2S:
|
||||||
i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_I2S;
|
val |= TEGRA20_I2S_CTRL_BIT_FORMAT_I2S;
|
||||||
i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_L_LOW;
|
val |= TEGRA20_I2S_CTRL_LRCK_L_LOW;
|
||||||
break;
|
break;
|
||||||
case SND_SOC_DAIFMT_RIGHT_J:
|
case SND_SOC_DAIFMT_RIGHT_J:
|
||||||
i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_RJM;
|
val |= TEGRA20_I2S_CTRL_BIT_FORMAT_RJM;
|
||||||
i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_L_LOW;
|
val |= TEGRA20_I2S_CTRL_LRCK_L_LOW;
|
||||||
break;
|
break;
|
||||||
case SND_SOC_DAIFMT_LEFT_J:
|
case SND_SOC_DAIFMT_LEFT_J:
|
||||||
i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_LJM;
|
val |= TEGRA20_I2S_CTRL_BIT_FORMAT_LJM;
|
||||||
i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_L_LOW;
|
val |= TEGRA20_I2S_CTRL_LRCK_L_LOW;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL, mask, val);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,27 +131,32 @@ static int tegra20_i2s_hw_params(struct snd_pcm_substream *substream,
|
||||||
{
|
{
|
||||||
struct device *dev = dai->dev;
|
struct device *dev = dai->dev;
|
||||||
struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai);
|
struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai);
|
||||||
u32 reg;
|
unsigned int mask, val;
|
||||||
int ret, sample_size, srate, i2sclock, bitcnt;
|
int ret, sample_size, srate, i2sclock, bitcnt;
|
||||||
|
|
||||||
i2s->reg_ctrl &= ~TEGRA20_I2S_CTRL_BIT_SIZE_MASK;
|
mask = TEGRA20_I2S_CTRL_BIT_SIZE_MASK;
|
||||||
switch (params_format(params)) {
|
switch (params_format(params)) {
|
||||||
case SNDRV_PCM_FORMAT_S16_LE:
|
case SNDRV_PCM_FORMAT_S16_LE:
|
||||||
i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_SIZE_16;
|
val = TEGRA20_I2S_CTRL_BIT_SIZE_16;
|
||||||
sample_size = 16;
|
sample_size = 16;
|
||||||
break;
|
break;
|
||||||
case SNDRV_PCM_FORMAT_S24_LE:
|
case SNDRV_PCM_FORMAT_S24_LE:
|
||||||
i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_SIZE_24;
|
val = TEGRA20_I2S_CTRL_BIT_SIZE_24;
|
||||||
sample_size = 24;
|
sample_size = 24;
|
||||||
break;
|
break;
|
||||||
case SNDRV_PCM_FORMAT_S32_LE:
|
case SNDRV_PCM_FORMAT_S32_LE:
|
||||||
i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_SIZE_32;
|
val = TEGRA20_I2S_CTRL_BIT_SIZE_32;
|
||||||
sample_size = 32;
|
sample_size = 32;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mask |= TEGRA20_I2S_CTRL_FIFO_FORMAT_MASK;
|
||||||
|
val |= TEGRA20_I2S_CTRL_FIFO_FORMAT_PACKED;
|
||||||
|
|
||||||
|
regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL, mask, val);
|
||||||
|
|
||||||
srate = params_rate(params);
|
srate = params_rate(params);
|
||||||
|
|
||||||
/* Final "* 2" required by Tegra hardware */
|
/* Final "* 2" required by Tegra hardware */
|
||||||
|
@ -175,42 +171,44 @@ static int tegra20_i2s_hw_params(struct snd_pcm_substream *substream,
|
||||||
bitcnt = (i2sclock / (2 * srate)) - 1;
|
bitcnt = (i2sclock / (2 * srate)) - 1;
|
||||||
if (bitcnt < 0 || bitcnt > TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US)
|
if (bitcnt < 0 || bitcnt > TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
reg = bitcnt << TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT;
|
val = bitcnt << TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT;
|
||||||
|
|
||||||
if (i2sclock % (2 * srate))
|
if (i2sclock % (2 * srate))
|
||||||
reg |= TEGRA20_I2S_TIMING_NON_SYM_ENABLE;
|
val |= TEGRA20_I2S_TIMING_NON_SYM_ENABLE;
|
||||||
|
|
||||||
tegra20_i2s_write(i2s, TEGRA20_I2S_TIMING, reg);
|
regmap_write(i2s->regmap, TEGRA20_I2S_TIMING, val);
|
||||||
|
|
||||||
tegra20_i2s_write(i2s, TEGRA20_I2S_FIFO_SCR,
|
regmap_write(i2s->regmap, TEGRA20_I2S_FIFO_SCR,
|
||||||
TEGRA20_I2S_FIFO_SCR_FIFO2_ATN_LVL_FOUR_SLOTS |
|
TEGRA20_I2S_FIFO_SCR_FIFO2_ATN_LVL_FOUR_SLOTS |
|
||||||
TEGRA20_I2S_FIFO_SCR_FIFO1_ATN_LVL_FOUR_SLOTS);
|
TEGRA20_I2S_FIFO_SCR_FIFO1_ATN_LVL_FOUR_SLOTS);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tegra20_i2s_start_playback(struct tegra20_i2s *i2s)
|
static void tegra20_i2s_start_playback(struct tegra20_i2s *i2s)
|
||||||
{
|
{
|
||||||
i2s->reg_ctrl |= TEGRA20_I2S_CTRL_FIFO1_ENABLE;
|
regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL,
|
||||||
tegra20_i2s_write(i2s, TEGRA20_I2S_CTRL, i2s->reg_ctrl);
|
TEGRA20_I2S_CTRL_FIFO1_ENABLE,
|
||||||
|
TEGRA20_I2S_CTRL_FIFO1_ENABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tegra20_i2s_stop_playback(struct tegra20_i2s *i2s)
|
static void tegra20_i2s_stop_playback(struct tegra20_i2s *i2s)
|
||||||
{
|
{
|
||||||
i2s->reg_ctrl &= ~TEGRA20_I2S_CTRL_FIFO1_ENABLE;
|
regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL,
|
||||||
tegra20_i2s_write(i2s, TEGRA20_I2S_CTRL, i2s->reg_ctrl);
|
TEGRA20_I2S_CTRL_FIFO1_ENABLE, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tegra20_i2s_start_capture(struct tegra20_i2s *i2s)
|
static void tegra20_i2s_start_capture(struct tegra20_i2s *i2s)
|
||||||
{
|
{
|
||||||
i2s->reg_ctrl |= TEGRA20_I2S_CTRL_FIFO2_ENABLE;
|
regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL,
|
||||||
tegra20_i2s_write(i2s, TEGRA20_I2S_CTRL, i2s->reg_ctrl);
|
TEGRA20_I2S_CTRL_FIFO2_ENABLE,
|
||||||
|
TEGRA20_I2S_CTRL_FIFO2_ENABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tegra20_i2s_stop_capture(struct tegra20_i2s *i2s)
|
static void tegra20_i2s_stop_capture(struct tegra20_i2s *i2s)
|
||||||
{
|
{
|
||||||
i2s->reg_ctrl &= ~TEGRA20_I2S_CTRL_FIFO2_ENABLE;
|
regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL,
|
||||||
tegra20_i2s_write(i2s, TEGRA20_I2S_CTRL, i2s->reg_ctrl);
|
TEGRA20_I2S_CTRL_FIFO2_ENABLE, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tegra20_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
|
static int tegra20_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
|
||||||
|
@ -414,8 +412,6 @@ static __devinit int tegra20_i2s_platform_probe(struct platform_device *pdev)
|
||||||
i2s->playback_dma_data.width = 32;
|
i2s->playback_dma_data.width = 32;
|
||||||
i2s->playback_dma_data.req_sel = dma_ch;
|
i2s->playback_dma_data.req_sel = dma_ch;
|
||||||
|
|
||||||
i2s->reg_ctrl = TEGRA20_I2S_CTRL_FIFO_FORMAT_PACKED;
|
|
||||||
|
|
||||||
pm_runtime_enable(&pdev->dev);
|
pm_runtime_enable(&pdev->dev);
|
||||||
if (!pm_runtime_enabled(&pdev->dev)) {
|
if (!pm_runtime_enabled(&pdev->dev)) {
|
||||||
ret = tegra20_i2s_runtime_resume(&pdev->dev);
|
ret = tegra20_i2s_runtime_resume(&pdev->dev);
|
||||||
|
|
|
@ -158,7 +158,6 @@ struct tegra20_i2s {
|
||||||
struct tegra_pcm_dma_params capture_dma_data;
|
struct tegra_pcm_dma_params capture_dma_data;
|
||||||
struct tegra_pcm_dma_params playback_dma_data;
|
struct tegra_pcm_dma_params playback_dma_data;
|
||||||
struct regmap *regmap;
|
struct regmap *regmap;
|
||||||
u32 reg_ctrl;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -37,19 +37,6 @@
|
||||||
|
|
||||||
#define DRV_NAME "tegra20-spdif"
|
#define DRV_NAME "tegra20-spdif"
|
||||||
|
|
||||||
static inline void tegra20_spdif_write(struct tegra20_spdif *spdif, u32 reg,
|
|
||||||
u32 val)
|
|
||||||
{
|
|
||||||
regmap_write(spdif->regmap, reg, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline u32 tegra20_spdif_read(struct tegra20_spdif *spdif, u32 reg)
|
|
||||||
{
|
|
||||||
u32 val;
|
|
||||||
regmap_read(spdif->regmap, reg, &val);
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tegra20_spdif_runtime_suspend(struct device *dev)
|
static int tegra20_spdif_runtime_suspend(struct device *dev)
|
||||||
{
|
{
|
||||||
struct tegra20_spdif *spdif = dev_get_drvdata(dev);
|
struct tegra20_spdif *spdif = dev_get_drvdata(dev);
|
||||||
|
@ -79,19 +66,22 @@ static int tegra20_spdif_hw_params(struct snd_pcm_substream *substream,
|
||||||
{
|
{
|
||||||
struct device *dev = dai->dev;
|
struct device *dev = dai->dev;
|
||||||
struct tegra20_spdif *spdif = snd_soc_dai_get_drvdata(dai);
|
struct tegra20_spdif *spdif = snd_soc_dai_get_drvdata(dai);
|
||||||
|
unsigned int mask, val;
|
||||||
int ret, spdifclock;
|
int ret, spdifclock;
|
||||||
|
|
||||||
spdif->reg_ctrl &= ~TEGRA20_SPDIF_CTRL_PACK;
|
mask = TEGRA20_SPDIF_CTRL_PACK |
|
||||||
spdif->reg_ctrl &= ~TEGRA20_SPDIF_CTRL_BIT_MODE_MASK;
|
TEGRA20_SPDIF_CTRL_BIT_MODE_MASK;
|
||||||
switch (params_format(params)) {
|
switch (params_format(params)) {
|
||||||
case SNDRV_PCM_FORMAT_S16_LE:
|
case SNDRV_PCM_FORMAT_S16_LE:
|
||||||
spdif->reg_ctrl |= TEGRA20_SPDIF_CTRL_PACK;
|
val = TEGRA20_SPDIF_CTRL_PACK |
|
||||||
spdif->reg_ctrl |= TEGRA20_SPDIF_CTRL_BIT_MODE_16BIT;
|
TEGRA20_SPDIF_CTRL_BIT_MODE_16BIT;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
regmap_update_bits(spdif->regmap, TEGRA20_SPDIF_CTRL, mask, val);
|
||||||
|
|
||||||
switch (params_rate(params)) {
|
switch (params_rate(params)) {
|
||||||
case 32000:
|
case 32000:
|
||||||
spdifclock = 4096000;
|
spdifclock = 4096000;
|
||||||
|
@ -129,14 +119,15 @@ static int tegra20_spdif_hw_params(struct snd_pcm_substream *substream,
|
||||||
|
|
||||||
static void tegra20_spdif_start_playback(struct tegra20_spdif *spdif)
|
static void tegra20_spdif_start_playback(struct tegra20_spdif *spdif)
|
||||||
{
|
{
|
||||||
spdif->reg_ctrl |= TEGRA20_SPDIF_CTRL_TX_EN;
|
regmap_update_bits(spdif->regmap, TEGRA20_SPDIF_CTRL,
|
||||||
tegra20_spdif_write(spdif, TEGRA20_SPDIF_CTRL, spdif->reg_ctrl);
|
TEGRA20_SPDIF_CTRL_TX_EN,
|
||||||
|
TEGRA20_SPDIF_CTRL_TX_EN);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tegra20_spdif_stop_playback(struct tegra20_spdif *spdif)
|
static void tegra20_spdif_stop_playback(struct tegra20_spdif *spdif)
|
||||||
{
|
{
|
||||||
spdif->reg_ctrl &= ~TEGRA20_SPDIF_CTRL_TX_EN;
|
regmap_update_bits(spdif->regmap, TEGRA20_SPDIF_CTRL,
|
||||||
tegra20_spdif_write(spdif, TEGRA20_SPDIF_CTRL, spdif->reg_ctrl);
|
TEGRA20_SPDIF_CTRL_TX_EN, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tegra20_spdif_trigger(struct snd_pcm_substream *substream, int cmd,
|
static int tegra20_spdif_trigger(struct snd_pcm_substream *substream, int cmd,
|
||||||
|
|
|
@ -465,7 +465,6 @@ struct tegra20_spdif {
|
||||||
struct tegra_pcm_dma_params capture_dma_data;
|
struct tegra_pcm_dma_params capture_dma_data;
|
||||||
struct tegra_pcm_dma_params playback_dma_data;
|
struct tegra_pcm_dma_params playback_dma_data;
|
||||||
struct regmap *regmap;
|
struct regmap *regmap;
|
||||||
u32 reg_ctrl;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -44,18 +44,6 @@
|
||||||
|
|
||||||
#define DRV_NAME "tegra30-i2s"
|
#define DRV_NAME "tegra30-i2s"
|
||||||
|
|
||||||
static inline void tegra30_i2s_write(struct tegra30_i2s *i2s, u32 reg, u32 val)
|
|
||||||
{
|
|
||||||
regmap_write(i2s->regmap, reg, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline u32 tegra30_i2s_read(struct tegra30_i2s *i2s, u32 reg)
|
|
||||||
{
|
|
||||||
u32 val;
|
|
||||||
regmap_read(i2s->regmap, reg, &val);
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tegra30_i2s_runtime_suspend(struct device *dev)
|
static int tegra30_i2s_runtime_suspend(struct device *dev)
|
||||||
{
|
{
|
||||||
struct tegra30_i2s *i2s = dev_get_drvdata(dev);
|
struct tegra30_i2s *i2s = dev_get_drvdata(dev);
|
||||||
|
@ -128,6 +116,7 @@ static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai,
|
||||||
unsigned int fmt)
|
unsigned int fmt)
|
||||||
{
|
{
|
||||||
struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai);
|
struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai);
|
||||||
|
unsigned int mask, val;
|
||||||
|
|
||||||
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
|
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
|
||||||
case SND_SOC_DAIFMT_NB_NF:
|
case SND_SOC_DAIFMT_NB_NF:
|
||||||
|
@ -136,10 +125,10 @@ static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_MASTER_ENABLE;
|
mask = TEGRA30_I2S_CTRL_MASTER_ENABLE;
|
||||||
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
|
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
|
||||||
case SND_SOC_DAIFMT_CBS_CFS:
|
case SND_SOC_DAIFMT_CBS_CFS:
|
||||||
i2s->reg_ctrl |= TEGRA30_I2S_CTRL_MASTER_ENABLE;
|
val = TEGRA30_I2S_CTRL_MASTER_ENABLE;
|
||||||
break;
|
break;
|
||||||
case SND_SOC_DAIFMT_CBM_CFM:
|
case SND_SOC_DAIFMT_CBM_CFM:
|
||||||
break;
|
break;
|
||||||
|
@ -147,33 +136,37 @@ static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
i2s->reg_ctrl &= ~(TEGRA30_I2S_CTRL_FRAME_FORMAT_MASK |
|
mask |= TEGRA30_I2S_CTRL_FRAME_FORMAT_MASK |
|
||||||
TEGRA30_I2S_CTRL_LRCK_MASK);
|
TEGRA30_I2S_CTRL_LRCK_MASK;
|
||||||
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
|
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
|
||||||
case SND_SOC_DAIFMT_DSP_A:
|
case SND_SOC_DAIFMT_DSP_A:
|
||||||
i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC;
|
val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC;
|
||||||
i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_L_LOW;
|
val |= TEGRA30_I2S_CTRL_LRCK_L_LOW;
|
||||||
break;
|
break;
|
||||||
case SND_SOC_DAIFMT_DSP_B:
|
case SND_SOC_DAIFMT_DSP_B:
|
||||||
i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC;
|
val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC;
|
||||||
i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_R_LOW;
|
val |= TEGRA30_I2S_CTRL_LRCK_R_LOW;
|
||||||
break;
|
break;
|
||||||
case SND_SOC_DAIFMT_I2S:
|
case SND_SOC_DAIFMT_I2S:
|
||||||
i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK;
|
val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK;
|
||||||
i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_L_LOW;
|
val |= TEGRA30_I2S_CTRL_LRCK_L_LOW;
|
||||||
break;
|
break;
|
||||||
case SND_SOC_DAIFMT_RIGHT_J:
|
case SND_SOC_DAIFMT_RIGHT_J:
|
||||||
i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK;
|
val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK;
|
||||||
i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_L_LOW;
|
val |= TEGRA30_I2S_CTRL_LRCK_L_LOW;
|
||||||
break;
|
break;
|
||||||
case SND_SOC_DAIFMT_LEFT_J:
|
case SND_SOC_DAIFMT_LEFT_J:
|
||||||
i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK;
|
val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK;
|
||||||
i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_L_LOW;
|
val |= TEGRA30_I2S_CTRL_LRCK_L_LOW;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pm_runtime_get_sync(dai->dev);
|
||||||
|
regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL, mask, val);
|
||||||
|
pm_runtime_put(dai->dev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,22 +176,24 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream,
|
||||||
{
|
{
|
||||||
struct device *dev = dai->dev;
|
struct device *dev = dai->dev;
|
||||||
struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai);
|
struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai);
|
||||||
u32 val;
|
unsigned int mask, val, reg;
|
||||||
int ret, sample_size, srate, i2sclock, bitcnt;
|
int ret, sample_size, srate, i2sclock, bitcnt;
|
||||||
|
|
||||||
if (params_channels(params) != 2)
|
if (params_channels(params) != 2)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_BIT_SIZE_MASK;
|
mask = TEGRA30_I2S_CTRL_BIT_SIZE_MASK;
|
||||||
switch (params_format(params)) {
|
switch (params_format(params)) {
|
||||||
case SNDRV_PCM_FORMAT_S16_LE:
|
case SNDRV_PCM_FORMAT_S16_LE:
|
||||||
i2s->reg_ctrl |= TEGRA30_I2S_CTRL_BIT_SIZE_16;
|
val = TEGRA30_I2S_CTRL_BIT_SIZE_16;
|
||||||
sample_size = 16;
|
sample_size = 16;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL, mask, val);
|
||||||
|
|
||||||
srate = params_rate(params);
|
srate = params_rate(params);
|
||||||
|
|
||||||
/* Final "* 2" required by Tegra hardware */
|
/* Final "* 2" required by Tegra hardware */
|
||||||
|
@ -219,7 +214,7 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream,
|
||||||
if (i2sclock % (2 * srate))
|
if (i2sclock % (2 * srate))
|
||||||
val |= TEGRA30_I2S_TIMING_NON_SYM_ENABLE;
|
val |= TEGRA30_I2S_TIMING_NON_SYM_ENABLE;
|
||||||
|
|
||||||
tegra30_i2s_write(i2s, TEGRA30_I2S_TIMING, val);
|
regmap_write(i2s->regmap, TEGRA30_I2S_TIMING, val);
|
||||||
|
|
||||||
val = (0 << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) |
|
val = (0 << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) |
|
||||||
(1 << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
|
(1 << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
|
||||||
|
@ -229,15 +224,17 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream,
|
||||||
|
|
||||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||||
val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_RX;
|
val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_RX;
|
||||||
tegra30_i2s_write(i2s, TEGRA30_I2S_CIF_RX_CTRL, val);
|
reg = TEGRA30_I2S_CIF_RX_CTRL;
|
||||||
} else {
|
} else {
|
||||||
val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_TX;
|
val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_TX;
|
||||||
tegra30_i2s_write(i2s, TEGRA30_I2S_CIF_TX_CTRL, val);
|
reg = TEGRA30_I2S_CIF_RX_CTRL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
regmap_write(i2s->regmap, reg, val);
|
||||||
|
|
||||||
val = (1 << TEGRA30_I2S_OFFSET_RX_DATA_OFFSET_SHIFT) |
|
val = (1 << TEGRA30_I2S_OFFSET_RX_DATA_OFFSET_SHIFT) |
|
||||||
(1 << TEGRA30_I2S_OFFSET_TX_DATA_OFFSET_SHIFT);
|
(1 << TEGRA30_I2S_OFFSET_TX_DATA_OFFSET_SHIFT);
|
||||||
tegra30_i2s_write(i2s, TEGRA30_I2S_OFFSET, val);
|
regmap_write(i2s->regmap, TEGRA30_I2S_OFFSET, val);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -245,29 +242,31 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream,
|
||||||
static void tegra30_i2s_start_playback(struct tegra30_i2s *i2s)
|
static void tegra30_i2s_start_playback(struct tegra30_i2s *i2s)
|
||||||
{
|
{
|
||||||
tegra30_ahub_enable_tx_fifo(i2s->playback_fifo_cif);
|
tegra30_ahub_enable_tx_fifo(i2s->playback_fifo_cif);
|
||||||
i2s->reg_ctrl |= TEGRA30_I2S_CTRL_XFER_EN_TX;
|
regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL,
|
||||||
tegra30_i2s_write(i2s, TEGRA30_I2S_CTRL, i2s->reg_ctrl);
|
TEGRA30_I2S_CTRL_XFER_EN_TX,
|
||||||
|
TEGRA30_I2S_CTRL_XFER_EN_TX);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tegra30_i2s_stop_playback(struct tegra30_i2s *i2s)
|
static void tegra30_i2s_stop_playback(struct tegra30_i2s *i2s)
|
||||||
{
|
{
|
||||||
tegra30_ahub_disable_tx_fifo(i2s->playback_fifo_cif);
|
tegra30_ahub_disable_tx_fifo(i2s->playback_fifo_cif);
|
||||||
i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_TX;
|
regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL,
|
||||||
tegra30_i2s_write(i2s, TEGRA30_I2S_CTRL, i2s->reg_ctrl);
|
TEGRA30_I2S_CTRL_XFER_EN_TX, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tegra30_i2s_start_capture(struct tegra30_i2s *i2s)
|
static void tegra30_i2s_start_capture(struct tegra30_i2s *i2s)
|
||||||
{
|
{
|
||||||
tegra30_ahub_enable_rx_fifo(i2s->capture_fifo_cif);
|
tegra30_ahub_enable_rx_fifo(i2s->capture_fifo_cif);
|
||||||
i2s->reg_ctrl |= TEGRA30_I2S_CTRL_XFER_EN_RX;
|
regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL,
|
||||||
tegra30_i2s_write(i2s, TEGRA30_I2S_CTRL, i2s->reg_ctrl);
|
TEGRA30_I2S_CTRL_XFER_EN_RX,
|
||||||
|
TEGRA30_I2S_CTRL_XFER_EN_RX);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tegra30_i2s_stop_capture(struct tegra30_i2s *i2s)
|
static void tegra30_i2s_stop_capture(struct tegra30_i2s *i2s)
|
||||||
{
|
{
|
||||||
tegra30_ahub_disable_rx_fifo(i2s->capture_fifo_cif);
|
tegra30_ahub_disable_rx_fifo(i2s->capture_fifo_cif);
|
||||||
i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_RX;
|
regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL,
|
||||||
tegra30_i2s_write(i2s, TEGRA30_I2S_CTRL, i2s->reg_ctrl);
|
TEGRA30_I2S_CTRL_XFER_EN_RX, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tegra30_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
|
static int tegra30_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
|
||||||
|
|
|
@ -236,7 +236,6 @@ struct tegra30_i2s {
|
||||||
enum tegra30_ahub_txcif playback_fifo_cif;
|
enum tegra30_ahub_txcif playback_fifo_cif;
|
||||||
struct tegra_pcm_dma_params playback_dma_data;
|
struct tegra_pcm_dma_params playback_dma_data;
|
||||||
struct regmap *regmap;
|
struct regmap *regmap;
|
||||||
u32 reg_ctrl;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Загрузка…
Ссылка в новой задаче