提交 0827d6ba 编写于 作者: G Grant Likely 提交者: Mark Brown

ASoC: add locking to mpc5200-psc-ac97 driver

AC97 bus register read/write hooks need to provide locking, but the
mpc5200-psc-ac97 driver does not.  This patch adds a mutex around
the register access routines.
Signed-off-by: NGrant Likely <grant.likely@secretlab.ca>
Acked-by: NJon Smirl <jonsmirl@gmail.com>
Signed-off-by: NMark Brown <broonie@opensource.wolfsonmicro.com>
上级 07573534
...@@ -456,6 +456,7 @@ int mpc5200_audio_dma_create(struct of_device *op) ...@@ -456,6 +456,7 @@ int mpc5200_audio_dma_create(struct of_device *op)
return -ENODEV; return -ENODEV;
spin_lock_init(&psc_dma->lock); spin_lock_init(&psc_dma->lock);
mutex_init(&psc_dma->mutex);
psc_dma->id = be32_to_cpu(*prop); psc_dma->id = be32_to_cpu(*prop);
psc_dma->irq = irq; psc_dma->irq = irq;
psc_dma->psc_regs = regs; psc_dma->psc_regs = regs;
......
...@@ -55,6 +55,7 @@ struct psc_dma { ...@@ -55,6 +55,7 @@ struct psc_dma {
unsigned int irq; unsigned int irq;
struct device *dev; struct device *dev;
spinlock_t lock; spinlock_t lock;
struct mutex mutex;
u32 sicr; u32 sicr;
uint sysclk; uint sysclk;
int imr; int imr;
......
...@@ -34,11 +34,14 @@ static unsigned short psc_ac97_read(struct snd_ac97 *ac97, unsigned short reg) ...@@ -34,11 +34,14 @@ static unsigned short psc_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
int status; int status;
unsigned int val; unsigned int val;
mutex_lock(&psc_dma->mutex);
/* Wait for command send status zero = ready */ /* Wait for command send status zero = ready */
status = spin_event_timeout(!(in_be16(&psc_dma->psc_regs->sr_csr.status) & status = spin_event_timeout(!(in_be16(&psc_dma->psc_regs->sr_csr.status) &
MPC52xx_PSC_SR_CMDSEND), 100, 0); MPC52xx_PSC_SR_CMDSEND), 100, 0);
if (status == 0) { if (status == 0) {
pr_err("timeout on ac97 bus (rdy)\n"); pr_err("timeout on ac97 bus (rdy)\n");
mutex_unlock(&psc_dma->mutex);
return -ENODEV; return -ENODEV;
} }
...@@ -54,16 +57,19 @@ static unsigned short psc_ac97_read(struct snd_ac97 *ac97, unsigned short reg) ...@@ -54,16 +57,19 @@ static unsigned short psc_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
if (status == 0) { if (status == 0) {
pr_err("timeout on ac97 read (val) %x\n", pr_err("timeout on ac97 read (val) %x\n",
in_be16(&psc_dma->psc_regs->sr_csr.status)); in_be16(&psc_dma->psc_regs->sr_csr.status));
mutex_unlock(&psc_dma->mutex);
return -ENODEV; return -ENODEV;
} }
/* Get the data */ /* Get the data */
val = in_be32(&psc_dma->psc_regs->ac97_data); val = in_be32(&psc_dma->psc_regs->ac97_data);
if (((val >> 24) & 0x7f) != reg) { if (((val >> 24) & 0x7f) != reg) {
pr_err("reg echo error on ac97 read\n"); pr_err("reg echo error on ac97 read\n");
mutex_unlock(&psc_dma->mutex);
return -ENODEV; return -ENODEV;
} }
val = (val >> 8) & 0xffff; val = (val >> 8) & 0xffff;
mutex_unlock(&psc_dma->mutex);
return (unsigned short) val; return (unsigned short) val;
} }
...@@ -72,16 +78,21 @@ static void psc_ac97_write(struct snd_ac97 *ac97, ...@@ -72,16 +78,21 @@ static void psc_ac97_write(struct snd_ac97 *ac97,
{ {
int status; int status;
mutex_lock(&psc_dma->mutex);
/* Wait for command status zero = ready */ /* Wait for command status zero = ready */
status = spin_event_timeout(!(in_be16(&psc_dma->psc_regs->sr_csr.status) & status = spin_event_timeout(!(in_be16(&psc_dma->psc_regs->sr_csr.status) &
MPC52xx_PSC_SR_CMDSEND), 100, 0); MPC52xx_PSC_SR_CMDSEND), 100, 0);
if (status == 0) { if (status == 0) {
pr_err("timeout on ac97 bus (write)\n"); pr_err("timeout on ac97 bus (write)\n");
return; goto out;
} }
/* Write data */ /* Write data */
out_be32(&psc_dma->psc_regs->ac97_cmd, out_be32(&psc_dma->psc_regs->ac97_cmd,
((reg & 0x7f) << 24) | (val << 8)); ((reg & 0x7f) << 24) | (val << 8));
out:
mutex_unlock(&psc_dma->mutex);
} }
static void psc_ac97_warm_reset(struct snd_ac97 *ac97) static void psc_ac97_warm_reset(struct snd_ac97 *ac97)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册