2
0
mirror of https://github.com/edk2-porting/linux-next.git synced 2024-12-25 13:43:55 +08:00

ASoC: fsl_esai: refine esai for TDM support

Original driver didn't store the number of slots, just fix the slot number
to 2, use this default number to calculate bclk and pins for TX/RX.
In this patch, add one parameter for slots, and update the calculation of
bclk and pins of TX/RX. Then driver will be compatible with slots > 2 in
TDM mode.

Signed-off-by: Shengjiu Wang <shengjiu.wang@freescale.com>
Acked-by: Nicolin Chen <nicoleotsuka@gmail.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
This commit is contained in:
Shengjiu Wang 2014-08-08 14:47:21 +08:00 committed by Mark Brown
parent ae34a78c43
commit d177143c36
2 changed files with 15 additions and 7 deletions

View File

@ -38,6 +38,7 @@
* @fsysclk: system clock source to derive HCK, SCK and FS * @fsysclk: system clock source to derive HCK, SCK and FS
* @fifo_depth: depth of tx/rx FIFO * @fifo_depth: depth of tx/rx FIFO
* @slot_width: width of each DAI slot * @slot_width: width of each DAI slot
* @slots: number of slots
* @hck_rate: clock rate of desired HCKx clock * @hck_rate: clock rate of desired HCKx clock
* @sck_rate: clock rate of desired SCKx clock * @sck_rate: clock rate of desired SCKx clock
* @hck_dir: the direction of HCKx pads * @hck_dir: the direction of HCKx pads
@ -56,6 +57,7 @@ struct fsl_esai {
struct clk *fsysclk; struct clk *fsysclk;
u32 fifo_depth; u32 fifo_depth;
u32 slot_width; u32 slot_width;
u32 slots;
u32 hck_rate[2]; u32 hck_rate[2];
u32 sck_rate[2]; u32 sck_rate[2];
bool hck_dir[2]; bool hck_dir[2];
@ -363,6 +365,7 @@ static int fsl_esai_set_dai_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask,
ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(rx_mask)); ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(rx_mask));
esai_priv->slot_width = slot_width; esai_priv->slot_width = slot_width;
esai_priv->slots = slots;
return 0; return 0;
} }
@ -510,10 +513,11 @@ static int fsl_esai_hw_params(struct snd_pcm_substream *substream,
bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
u32 width = snd_pcm_format_width(params_format(params)); u32 width = snd_pcm_format_width(params_format(params));
u32 channels = params_channels(params); u32 channels = params_channels(params);
u32 pins = DIV_ROUND_UP(channels, esai_priv->slots);
u32 bclk, mask, val; u32 bclk, mask, val;
int ret; int ret;
bclk = params_rate(params) * esai_priv->slot_width * 2; bclk = params_rate(params) * esai_priv->slot_width * esai_priv->slots;
ret = fsl_esai_set_bclk(dai, tx, bclk); ret = fsl_esai_set_bclk(dai, tx, bclk);
if (ret) if (ret)
@ -530,7 +534,7 @@ static int fsl_esai_hw_params(struct snd_pcm_substream *substream,
mask = ESAI_xFCR_xFR_MASK | ESAI_xFCR_xWA_MASK | ESAI_xFCR_xFWM_MASK | mask = ESAI_xFCR_xFR_MASK | ESAI_xFCR_xWA_MASK | ESAI_xFCR_xFWM_MASK |
(tx ? ESAI_xFCR_TE_MASK | ESAI_xFCR_TIEN : ESAI_xFCR_RE_MASK); (tx ? ESAI_xFCR_TE_MASK | ESAI_xFCR_TIEN : ESAI_xFCR_RE_MASK);
val = ESAI_xFCR_xWA(width) | ESAI_xFCR_xFWM(esai_priv->fifo_depth) | val = ESAI_xFCR_xWA(width) | ESAI_xFCR_xFWM(esai_priv->fifo_depth) |
(tx ? ESAI_xFCR_TE(channels) | ESAI_xFCR_TIEN : ESAI_xFCR_RE(channels)); (tx ? ESAI_xFCR_TE(pins) | ESAI_xFCR_TIEN : ESAI_xFCR_RE(pins));
regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), mask, val); regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), mask, val);
@ -565,6 +569,7 @@ static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd,
struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai); struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
u8 i, channels = substream->runtime->channels; u8 i, channels = substream->runtime->channels;
u32 pins = DIV_ROUND_UP(channels, esai_priv->slots);
switch (cmd) { switch (cmd) {
case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_START:
@ -579,7 +584,7 @@ static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd,
regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx),
tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK, tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK,
tx ? ESAI_xCR_TE(channels) : ESAI_xCR_RE(channels)); tx ? ESAI_xCR_TE(pins) : ESAI_xCR_RE(pins));
break; break;
case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_STOP:
@ -783,6 +788,9 @@ static int fsl_esai_probe(struct platform_device *pdev)
/* Set a default slot size */ /* Set a default slot size */
esai_priv->slot_width = 32; esai_priv->slot_width = 32;
/* Set a default slot number */
esai_priv->slots = 2;
/* Set a default master/slave state */ /* Set a default master/slave state */
esai_priv->slave_mode = true; esai_priv->slave_mode = true;

View File

@ -130,8 +130,8 @@
#define ESAI_xFCR_RE_WIDTH 4 #define ESAI_xFCR_RE_WIDTH 4
#define ESAI_xFCR_TE_MASK (((1 << ESAI_xFCR_TE_WIDTH) - 1) << ESAI_xFCR_xE_SHIFT) #define ESAI_xFCR_TE_MASK (((1 << ESAI_xFCR_TE_WIDTH) - 1) << ESAI_xFCR_xE_SHIFT)
#define ESAI_xFCR_RE_MASK (((1 << ESAI_xFCR_RE_WIDTH) - 1) << ESAI_xFCR_xE_SHIFT) #define ESAI_xFCR_RE_MASK (((1 << ESAI_xFCR_RE_WIDTH) - 1) << ESAI_xFCR_xE_SHIFT)
#define ESAI_xFCR_TE(x) ((ESAI_xFCR_TE_MASK >> (ESAI_xFCR_TE_WIDTH - ((x + 1) >> 1))) & ESAI_xFCR_TE_MASK) #define ESAI_xFCR_TE(x) ((ESAI_xFCR_TE_MASK >> (ESAI_xFCR_TE_WIDTH - x)) & ESAI_xFCR_TE_MASK)
#define ESAI_xFCR_RE(x) ((ESAI_xFCR_RE_MASK >> (ESAI_xFCR_RE_WIDTH - ((x + 1) >> 1))) & ESAI_xFCR_RE_MASK) #define ESAI_xFCR_RE(x) ((ESAI_xFCR_RE_MASK >> (ESAI_xFCR_RE_WIDTH - x)) & ESAI_xFCR_RE_MASK)
#define ESAI_xFCR_xFR_SHIFT 1 #define ESAI_xFCR_xFR_SHIFT 1
#define ESAI_xFCR_xFR_MASK (1 << ESAI_xFCR_xFR_SHIFT) #define ESAI_xFCR_xFR_MASK (1 << ESAI_xFCR_xFR_SHIFT)
#define ESAI_xFCR_xFR (1 << ESAI_xFCR_xFR_SHIFT) #define ESAI_xFCR_xFR (1 << ESAI_xFCR_xFR_SHIFT)
@ -272,8 +272,8 @@
#define ESAI_xCR_RE_WIDTH 4 #define ESAI_xCR_RE_WIDTH 4
#define ESAI_xCR_TE_MASK (((1 << ESAI_xCR_TE_WIDTH) - 1) << ESAI_xCR_xE_SHIFT) #define ESAI_xCR_TE_MASK (((1 << ESAI_xCR_TE_WIDTH) - 1) << ESAI_xCR_xE_SHIFT)
#define ESAI_xCR_RE_MASK (((1 << ESAI_xCR_RE_WIDTH) - 1) << ESAI_xCR_xE_SHIFT) #define ESAI_xCR_RE_MASK (((1 << ESAI_xCR_RE_WIDTH) - 1) << ESAI_xCR_xE_SHIFT)
#define ESAI_xCR_TE(x) ((ESAI_xCR_TE_MASK >> (ESAI_xCR_TE_WIDTH - ((x + 1) >> 1))) & ESAI_xCR_TE_MASK) #define ESAI_xCR_TE(x) ((ESAI_xCR_TE_MASK >> (ESAI_xCR_TE_WIDTH - x)) & ESAI_xCR_TE_MASK)
#define ESAI_xCR_RE(x) ((ESAI_xCR_RE_MASK >> (ESAI_xCR_RE_WIDTH - ((x + 1) >> 1))) & ESAI_xCR_RE_MASK) #define ESAI_xCR_RE(x) ((ESAI_xCR_RE_MASK >> (ESAI_xCR_RE_WIDTH - x)) & ESAI_xCR_RE_MASK)
/* /*
* Transmit Clock Control Register -- REG_ESAI_TCCR 0xD8 * Transmit Clock Control Register -- REG_ESAI_TCCR 0xD8