Skip to content

Commit

Permalink
ASoC/mpc5200: fix enable/disable of AC97 slots
Browse files Browse the repository at this point in the history
The MPC5200 AC97 driver is disabling the slots when a stop
trigger is received, but not reenabling them if the stream
is started again without processing the hw_params again.

This patch fixes the problem by caching the slot enable bit
settings calculated at hw_params time so that they can be
reapplied every time the start trigger is received.

Signed-off-by: Grant Likely <[email protected]>
Acked-by: Liam Girdwood <[email protected]>
Signed-off-by: Mark Brown <[email protected]>
  • Loading branch information
glikely authored and broonie committed Nov 7, 2009
1 parent 1d8222e commit c939e5c
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 18 deletions.
4 changes: 4 additions & 0 deletions sound/soc/fsl/mpc5200_dma.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
* @period_end: physical address of end of DMA region
* @period_next_pt: physical address of next DMA buffer to enqueue
* @period_bytes: size of DMA period in bytes
* @ac97_slot_bits: Enable bits for turning on the correct AC97 slot
*/
struct psc_dma_stream {
struct snd_pcm_runtime *runtime;
Expand All @@ -28,6 +29,9 @@ struct psc_dma_stream {
int period_current;
int period_bytes;
int period_count;

/* AC97 state */
u32 ac97_slot_bits;
};

/**
Expand Down
39 changes: 21 additions & 18 deletions sound/soc/fsl/mpc5200_psc_ac97.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ static int psc_ac97_hw_analog_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai)
{
struct psc_dma *psc_dma = cpu_dai->private_data;
struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma);

dev_dbg(psc_dma->dev, "%s(substream=%p) p_size=%i p_bytes=%i"
" periods=%i buffer_size=%i buffer_bytes=%i channels=%i"
Expand All @@ -140,20 +141,10 @@ static int psc_ac97_hw_analog_params(struct snd_pcm_substream *substream,
params_channels(params), params_rate(params),
params_format(params));


if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) {
if (params_channels(params) == 1)
psc_dma->slots |= 0x00000100;
else
psc_dma->slots |= 0x00000300;
} else {
if (params_channels(params) == 1)
psc_dma->slots |= 0x01000000;
else
psc_dma->slots |= 0x03000000;
}
out_be32(&psc_dma->psc_regs->ac97_slots, psc_dma->slots);

/* Determine the set of enable bits to turn on */
s->ac97_slot_bits = (params_channels(params) == 1) ? 0x100 : 0x300;
if (substream->pstr->stream != SNDRV_PCM_STREAM_CAPTURE)
s->ac97_slot_bits <<= 16;
return 0;
}

Expand All @@ -163,6 +154,8 @@ static int psc_ac97_hw_digital_params(struct snd_pcm_substream *substream,
{
struct psc_dma *psc_dma = cpu_dai->private_data;

dev_dbg(psc_dma->dev, "%s(substream=%p)\n", __func__, substream);

if (params_channels(params) == 1)
out_be32(&psc_dma->psc_regs->ac97_slots, 0x01000000);
else
Expand All @@ -176,14 +169,24 @@ static int psc_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data;
struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma);

switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
dev_dbg(psc_dma->dev, "AC97 START: stream=%i\n",
substream->pstr->stream);

/* Set the slot enable bits */
psc_dma->slots |= s->ac97_slot_bits;
out_be32(&psc_dma->psc_regs->ac97_slots, psc_dma->slots);
break;

case SNDRV_PCM_TRIGGER_STOP:
if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
psc_dma->slots &= 0xFFFF0000;
else
psc_dma->slots &= 0x0000FFFF;
dev_dbg(psc_dma->dev, "AC97 STOP: stream=%i\n",
substream->pstr->stream);

/* Clear the slot enable bits */
psc_dma->slots &= ~(s->ac97_slot_bits);
out_be32(&psc_dma->psc_regs->ac97_slots, psc_dma->slots);
break;
}
Expand Down

0 comments on commit c939e5c

Please sign in to comment.