ASoC/mpc5200: fix enable/disable of AC97 slots
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 <grant.likely@secretlab.ca> Acked-by: Liam Girdwood <lrg@slimlogic.co.uk> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
This commit is contained in:
parent
1d8222e8df
commit
c939e5c821
|
@ -16,6 +16,7 @@
|
||||||
* @period_end: physical address of end of DMA region
|
* @period_end: physical address of end of DMA region
|
||||||
* @period_next_pt: physical address of next DMA buffer to enqueue
|
* @period_next_pt: physical address of next DMA buffer to enqueue
|
||||||
* @period_bytes: size of DMA period in bytes
|
* @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 psc_dma_stream {
|
||||||
struct snd_pcm_runtime *runtime;
|
struct snd_pcm_runtime *runtime;
|
||||||
|
@ -28,6 +29,9 @@ struct psc_dma_stream {
|
||||||
int period_current;
|
int period_current;
|
||||||
int period_bytes;
|
int period_bytes;
|
||||||
int period_count;
|
int period_count;
|
||||||
|
|
||||||
|
/* AC97 state */
|
||||||
|
u32 ac97_slot_bits;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -130,6 +130,7 @@ static int psc_ac97_hw_analog_params(struct snd_pcm_substream *substream,
|
||||||
struct snd_soc_dai *cpu_dai)
|
struct snd_soc_dai *cpu_dai)
|
||||||
{
|
{
|
||||||
struct psc_dma *psc_dma = cpu_dai->private_data;
|
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"
|
dev_dbg(psc_dma->dev, "%s(substream=%p) p_size=%i p_bytes=%i"
|
||||||
" periods=%i buffer_size=%i buffer_bytes=%i channels=%i"
|
" periods=%i buffer_size=%i buffer_bytes=%i channels=%i"
|
||||||
|
@ -140,20 +141,10 @@ static int psc_ac97_hw_analog_params(struct snd_pcm_substream *substream,
|
||||||
params_channels(params), params_rate(params),
|
params_channels(params), params_rate(params),
|
||||||
params_format(params));
|
params_format(params));
|
||||||
|
|
||||||
|
/* Determine the set of enable bits to turn on */
|
||||||
if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) {
|
s->ac97_slot_bits = (params_channels(params) == 1) ? 0x100 : 0x300;
|
||||||
if (params_channels(params) == 1)
|
if (substream->pstr->stream != SNDRV_PCM_STREAM_CAPTURE)
|
||||||
psc_dma->slots |= 0x00000100;
|
s->ac97_slot_bits <<= 16;
|
||||||
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);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
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)
|
if (params_channels(params) == 1)
|
||||||
out_be32(&psc_dma->psc_regs->ac97_slots, 0x01000000);
|
out_be32(&psc_dma->psc_regs->ac97_slots, 0x01000000);
|
||||||
else
|
else
|
||||||
|
@ -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 snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||||
struct psc_dma *psc_dma = rtd->dai->cpu_dai->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) {
|
switch (cmd) {
|
||||||
case SNDRV_PCM_TRIGGER_STOP:
|
case SNDRV_PCM_TRIGGER_START:
|
||||||
if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
|
dev_dbg(psc_dma->dev, "AC97 START: stream=%i\n",
|
||||||
psc_dma->slots &= 0xFFFF0000;
|
substream->pstr->stream);
|
||||||
else
|
|
||||||
psc_dma->slots &= 0x0000FFFF;
|
|
||||||
|
|
||||||
|
/* 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:
|
||||||
|
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);
|
out_be32(&psc_dma->psc_regs->ac97_slots, psc_dma->slots);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue