aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/fsl
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/fsl')
-rw-r--r--sound/soc/fsl/Kconfig6
-rw-r--r--sound/soc/fsl/efika-audio-fabric.c2
-rw-r--r--sound/soc/fsl/mpc5200_dma.c51
-rw-r--r--sound/soc/fsl/mpc5200_dma.h1
-rw-r--r--sound/soc/fsl/mpc5200_psc_ac97.c20
-rw-r--r--sound/soc/fsl/pcm030-audio-fabric.c2
6 files changed, 64 insertions, 18 deletions
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 5dbebf82249c..8cb65ccad35f 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -33,7 +33,7 @@ config SND_SOC_MPC5200_I2S
config SND_SOC_MPC5200_AC97
tristate "Freescale MPC5200 PSC in AC97 mode driver"
depends on PPC_MPC52xx && PPC_BESTCOMM
- select AC97_BUS
+ select SND_SOC_AC97_BUS
select SND_MPC52xx_DMA
select PPC_BESTCOMM_GEN_BD
help
@@ -41,7 +41,7 @@ config SND_SOC_MPC5200_AC97
config SND_MPC52xx_SOC_PCM030
tristate "SoC AC97 Audio support for Phytec pcm030 and WM9712"
- depends on PPC_MPC5200_SIMPLE && BROKEN
+ depends on PPC_MPC5200_SIMPLE
select SND_SOC_MPC5200_AC97
select SND_SOC_WM9712
help
@@ -50,7 +50,7 @@ config SND_MPC52xx_SOC_PCM030
config SND_MPC52xx_SOC_EFIKA
tristate "SoC AC97 Audio support for bbplan Efika and STAC9766"
- depends on PPC_EFIKA && BROKEN
+ depends on PPC_EFIKA
select SND_SOC_MPC5200_AC97
select SND_SOC_STAC9766
help
diff --git a/sound/soc/fsl/efika-audio-fabric.c b/sound/soc/fsl/efika-audio-fabric.c
index 85b0e7569504..3326e2a1e863 100644
--- a/sound/soc/fsl/efika-audio-fabric.c
+++ b/sound/soc/fsl/efika-audio-fabric.c
@@ -30,6 +30,8 @@
#include "mpc5200_psc_ac97.h"
#include "../codecs/stac9766.h"
+#define DRV_NAME "efika-audio-fabric"
+
static struct snd_soc_device device;
static struct snd_soc_card card;
diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c
index efec33a1c5bd..6096d22283e6 100644
--- a/sound/soc/fsl/mpc5200_dma.c
+++ b/sound/soc/fsl/mpc5200_dma.c
@@ -69,6 +69,23 @@ static void psc_dma_bcom_enqueue_next_buffer(struct psc_dma_stream *s)
static void psc_dma_bcom_enqueue_tx(struct psc_dma_stream *s)
{
+ if (s->appl_ptr > s->runtime->control->appl_ptr) {
+ /*
+ * In this case s->runtime->control->appl_ptr has wrapped around.
+ * Play the data to the end of the boundary, then wrap our own
+ * appl_ptr back around.
+ */
+ while (s->appl_ptr < s->runtime->boundary) {
+ if (bcom_queue_full(s->bcom_task))
+ return;
+
+ s->appl_ptr += s->period_size;
+
+ psc_dma_bcom_enqueue_next_buffer(s);
+ }
+ s->appl_ptr -= s->runtime->boundary;
+ }
+
while (s->appl_ptr < s->runtime->control->appl_ptr) {
if (bcom_queue_full(s->bcom_task))
@@ -430,6 +447,7 @@ int mpc5200_audio_dma_create(struct of_device *op)
int size, irq, rc;
const __be32 *prop;
void __iomem *regs;
+ int ret;
/* Fetch the registers and IRQ of the PSC */
irq = irq_of_parse_and_map(op->node, 0);
@@ -446,16 +464,19 @@ int mpc5200_audio_dma_create(struct of_device *op)
/* Allocate and initialize the driver private data */
psc_dma = kzalloc(sizeof *psc_dma, GFP_KERNEL);
if (!psc_dma) {
- iounmap(regs);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto out_unmap;
}
/* Get the PSC ID */
prop = of_get_property(op->node, "cell-index", &size);
- if (!prop || size < sizeof *prop)
- return -ENODEV;
+ if (!prop || size < sizeof *prop) {
+ ret = -ENODEV;
+ goto out_free;
+ }
spin_lock_init(&psc_dma->lock);
+ mutex_init(&psc_dma->mutex);
psc_dma->id = be32_to_cpu(*prop);
psc_dma->irq = irq;
psc_dma->psc_regs = regs;
@@ -475,9 +496,8 @@ int mpc5200_audio_dma_create(struct of_device *op)
if (!psc_dma->capture.bcom_task ||
!psc_dma->playback.bcom_task) {
dev_err(&op->dev, "Could not allocate bestcomm tasks\n");
- iounmap(regs);
- kfree(psc_dma);
- return -ENODEV;
+ ret = -ENODEV;
+ goto out_free;
}
/* Disable all interrupts and reset the PSC */
@@ -519,12 +539,8 @@ int mpc5200_audio_dma_create(struct of_device *op)
&psc_dma_bcom_irq_tx, IRQF_SHARED,
"psc-dma-playback", &psc_dma->playback);
if (rc) {
- free_irq(psc_dma->irq, psc_dma);
- free_irq(psc_dma->capture.irq,
- &psc_dma->capture);
- free_irq(psc_dma->playback.irq,
- &psc_dma->playback);
- return -ENODEV;
+ ret = -ENODEV;
+ goto out_irq;
}
/* Save what we've done so it can be found again later */
@@ -532,6 +548,15 @@ int mpc5200_audio_dma_create(struct of_device *op)
/* Tell the ASoC OF helpers about it */
return snd_soc_register_platform(&mpc5200_audio_dma_platform);
+out_irq:
+ free_irq(psc_dma->irq, psc_dma);
+ free_irq(psc_dma->capture.irq, &psc_dma->capture);
+ free_irq(psc_dma->playback.irq, &psc_dma->playback);
+out_free:
+ kfree(psc_dma);
+out_unmap:
+ iounmap(regs);
+ return ret;
}
EXPORT_SYMBOL_GPL(mpc5200_audio_dma_create);
diff --git a/sound/soc/fsl/mpc5200_dma.h b/sound/soc/fsl/mpc5200_dma.h
index 2000803f06a7..8d396bb9d9fe 100644
--- a/sound/soc/fsl/mpc5200_dma.h
+++ b/sound/soc/fsl/mpc5200_dma.h
@@ -55,6 +55,7 @@ struct psc_dma {
unsigned int irq;
struct device *dev;
spinlock_t lock;
+ struct mutex mutex;
u32 sicr;
uint sysclk;
int imr;
diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c
index 794a247b3eb5..c4ae3e096bb9 100644
--- a/sound/soc/fsl/mpc5200_psc_ac97.c
+++ b/sound/soc/fsl/mpc5200_psc_ac97.c
@@ -12,6 +12,7 @@
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/of_platform.h>
+#include <linux/delay.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -34,13 +35,20 @@ static unsigned short psc_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
int status;
unsigned int val;
+ mutex_lock(&psc_dma->mutex);
+
/* Wait for command send status zero = ready */
status = spin_event_timeout(!(in_be16(&psc_dma->psc_regs->sr_csr.status) &
MPC52xx_PSC_SR_CMDSEND), 100, 0);
if (status == 0) {
pr_err("timeout on ac97 bus (rdy)\n");
+ mutex_unlock(&psc_dma->mutex);
return -ENODEV;
}
+
+ /* Force clear the data valid bit */
+ in_be32(&psc_dma->psc_regs->ac97_data);
+
/* Send the read */
out_be32(&psc_dma->psc_regs->ac97_cmd, (1<<31) | ((reg & 0x7f) << 24));
@@ -50,16 +58,19 @@ static unsigned short psc_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
if (status == 0) {
pr_err("timeout on ac97 read (val) %x\n",
in_be16(&psc_dma->psc_regs->sr_csr.status));
+ mutex_unlock(&psc_dma->mutex);
return -ENODEV;
}
/* Get the data */
val = in_be32(&psc_dma->psc_regs->ac97_data);
if (((val >> 24) & 0x7f) != reg) {
pr_err("reg echo error on ac97 read\n");
+ mutex_unlock(&psc_dma->mutex);
return -ENODEV;
}
val = (val >> 8) & 0xffff;
+ mutex_unlock(&psc_dma->mutex);
return (unsigned short) val;
}
@@ -68,16 +79,21 @@ static void psc_ac97_write(struct snd_ac97 *ac97,
{
int status;
+ mutex_lock(&psc_dma->mutex);
+
/* Wait for command status zero = ready */
status = spin_event_timeout(!(in_be16(&psc_dma->psc_regs->sr_csr.status) &
MPC52xx_PSC_SR_CMDSEND), 100, 0);
if (status == 0) {
pr_err("timeout on ac97 bus (write)\n");
- return;
+ goto out;
}
/* Write data */
out_be32(&psc_dma->psc_regs->ac97_cmd,
((reg & 0x7f) << 24) | (val << 8));
+
+ out:
+ mutex_unlock(&psc_dma->mutex);
}
static void psc_ac97_warm_reset(struct snd_ac97 *ac97)
@@ -97,7 +113,7 @@ static void psc_ac97_cold_reset(struct snd_ac97 *ac97)
out_8(&regs->op1, MPC52xx_PSC_OP_RES);
udelay(10);
out_8(&regs->op0, MPC52xx_PSC_OP_RES);
- udelay(50);
+ msleep(1);
psc_ac97_warm_reset(ac97);
}
diff --git a/sound/soc/fsl/pcm030-audio-fabric.c b/sound/soc/fsl/pcm030-audio-fabric.c
index 8766f7a3893d..b928ef7d28eb 100644
--- a/sound/soc/fsl/pcm030-audio-fabric.c
+++ b/sound/soc/fsl/pcm030-audio-fabric.c
@@ -30,6 +30,8 @@
#include "mpc5200_psc_ac97.h"
#include "../codecs/wm9712.h"
+#define DRV_NAME "pcm030-audio-fabric"
+
static struct snd_soc_device device;
static struct snd_soc_card card;