|
@@ -166,6 +166,65 @@ static inline void aaci_chan_wait_ready(struct aaci_runtime *aacirun)
|
|
*/
|
|
*/
|
|
static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask)
|
|
static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask)
|
|
{
|
|
{
|
|
|
|
+ if (mask & ISR_ORINTR) {
|
|
|
|
+ dev_warn(&aaci->dev->dev, "RX overrun on chan %d\n", channel);
|
|
|
|
+ writel(ICLR_RXOEC1 << channel, aaci->base + AACI_INTCLR);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (mask & ISR_RXTOINTR) {
|
|
|
|
+ dev_warn(&aaci->dev->dev, "RX timeout on chan %d\n", channel);
|
|
|
|
+ writel(ICLR_RXTOFEC1 << channel, aaci->base + AACI_INTCLR);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (mask & ISR_RXINTR) {
|
|
|
|
+ struct aaci_runtime *aacirun = &aaci->capture;
|
|
|
|
+ void *ptr;
|
|
|
|
+
|
|
|
|
+ if (!aacirun->substream || !aacirun->start) {
|
|
|
|
+ dev_warn(&aaci->dev->dev, "RX interrupt???");
|
|
|
|
+ writel(0, aacirun->base + AACI_IE);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ ptr = aacirun->ptr;
|
|
|
|
+
|
|
|
|
+ do {
|
|
|
|
+ unsigned int len = aacirun->fifosz;
|
|
|
|
+ u32 val;
|
|
|
|
+
|
|
|
|
+ if (aacirun->bytes <= 0) {
|
|
|
|
+ aacirun->bytes += aacirun->period;
|
|
|
|
+ aacirun->ptr = ptr;
|
|
|
|
+ spin_unlock(&aaci->lock);
|
|
|
|
+ snd_pcm_period_elapsed(aacirun->substream);
|
|
|
|
+ spin_lock(&aaci->lock);
|
|
|
|
+ }
|
|
|
|
+ if (!(aacirun->cr & CR_EN))
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ val = readl(aacirun->base + AACI_SR);
|
|
|
|
+ if (!(val & SR_RXHF))
|
|
|
|
+ break;
|
|
|
|
+ if (!(val & SR_RXFF))
|
|
|
|
+ len >>= 1;
|
|
|
|
+
|
|
|
|
+ aacirun->bytes -= len;
|
|
|
|
+
|
|
|
|
+ /* reading 16 bytes at a time */
|
|
|
|
+ for( ; len > 0; len -= 16) {
|
|
|
|
+ asm(
|
|
|
|
+ "ldmia %1, {r0, r1, r2, r3}\n\t"
|
|
|
|
+ "stmia %0!, {r0, r1, r2, r3}"
|
|
|
|
+ : "+r" (ptr)
|
|
|
|
+ : "r" (aacirun->fifo)
|
|
|
|
+ : "r0", "r1", "r2", "r3", "cc");
|
|
|
|
+
|
|
|
|
+ if (ptr >= aacirun->end)
|
|
|
|
+ ptr = aacirun->start;
|
|
|
|
+ }
|
|
|
|
+ } while(1);
|
|
|
|
+ aacirun->ptr = ptr;
|
|
|
|
+ }
|
|
|
|
+
|
|
if (mask & ISR_URINTR) {
|
|
if (mask & ISR_URINTR) {
|
|
dev_dbg(&aaci->dev->dev, "TX underrun on chan %d\n", channel);
|
|
dev_dbg(&aaci->dev->dev, "TX underrun on chan %d\n", channel);
|
|
writel(ICLR_TXUEC1 << channel, aaci->base + AACI_INTCLR);
|
|
writel(ICLR_TXUEC1 << channel, aaci->base + AACI_INTCLR);
|
|
@@ -193,7 +252,7 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask)
|
|
snd_pcm_period_elapsed(aacirun->substream);
|
|
snd_pcm_period_elapsed(aacirun->substream);
|
|
spin_lock(&aaci->lock);
|
|
spin_lock(&aaci->lock);
|
|
}
|
|
}
|
|
- if (!(aacirun->cr & TXCR_TXEN))
|
|
|
|
|
|
+ if (!(aacirun->cr & CR_EN))
|
|
break;
|
|
break;
|
|
|
|
|
|
val = readl(aacirun->base + AACI_SR);
|
|
val = readl(aacirun->base + AACI_SR);
|
|
@@ -331,8 +390,9 @@ static struct snd_pcm_hardware aaci_hw_info = {
|
|
.periods_max = PAGE_SIZE / 16,
|
|
.periods_max = PAGE_SIZE / 16,
|
|
};
|
|
};
|
|
|
|
|
|
-static int aaci_pcm_open(struct aaci *aaci, struct snd_pcm_substream *substream,
|
|
|
|
- struct aaci_runtime *aacirun)
|
|
|
|
|
|
+static int __aaci_pcm_open(struct aaci *aaci,
|
|
|
|
+ struct snd_pcm_substream *substream,
|
|
|
|
+ struct aaci_runtime *aacirun)
|
|
{
|
|
{
|
|
struct snd_pcm_runtime *runtime = substream->runtime;
|
|
struct snd_pcm_runtime *runtime = substream->runtime;
|
|
int ret;
|
|
int ret;
|
|
@@ -381,7 +441,7 @@ static int aaci_pcm_close(struct snd_pcm_substream *substream)
|
|
struct aaci *aaci = substream->private_data;
|
|
struct aaci *aaci = substream->private_data;
|
|
struct aaci_runtime *aacirun = substream->runtime->private_data;
|
|
struct aaci_runtime *aacirun = substream->runtime->private_data;
|
|
|
|
|
|
- WARN_ON(aacirun->cr & TXCR_TXEN);
|
|
|
|
|
|
+ WARN_ON(aacirun->cr & CR_EN);
|
|
|
|
|
|
aacirun->substream = NULL;
|
|
aacirun->substream = NULL;
|
|
free_irq(aaci->dev->irq[0], aaci);
|
|
free_irq(aaci->dev->irq[0], aaci);
|
|
@@ -396,7 +456,7 @@ static int aaci_pcm_hw_free(struct snd_pcm_substream *substream)
|
|
/*
|
|
/*
|
|
* This must not be called with the device enabled.
|
|
* This must not be called with the device enabled.
|
|
*/
|
|
*/
|
|
- WARN_ON(aacirun->cr & TXCR_TXEN);
|
|
|
|
|
|
+ WARN_ON(aacirun->cr & CR_EN);
|
|
|
|
|
|
if (aacirun->pcm_open)
|
|
if (aacirun->pcm_open)
|
|
snd_ac97_pcm_close(aacirun->pcm);
|
|
snd_ac97_pcm_close(aacirun->pcm);
|
|
@@ -423,9 +483,15 @@ static int aaci_pcm_hw_params(struct snd_pcm_substream *substream,
|
|
if (err < 0)
|
|
if (err < 0)
|
|
goto out;
|
|
goto out;
|
|
|
|
|
|
- err = snd_ac97_pcm_open(aacirun->pcm, params_rate(params),
|
|
|
|
- params_channels(params),
|
|
|
|
- aacirun->pcm->r[0].slots);
|
|
|
|
|
|
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
|
|
|
+ err = snd_ac97_pcm_open(aacirun->pcm, params_rate(params),
|
|
|
|
+ params_channels(params),
|
|
|
|
+ aacirun->pcm->r[0].slots);
|
|
|
|
+ else
|
|
|
|
+ err = snd_ac97_pcm_open(aacirun->pcm, params_rate(params),
|
|
|
|
+ params_channels(params),
|
|
|
|
+ aacirun->pcm->r[1].slots);
|
|
|
|
+
|
|
if (err)
|
|
if (err)
|
|
goto out;
|
|
goto out;
|
|
|
|
|
|
@@ -468,9 +534,9 @@ static int aaci_pcm_mmap(struct snd_pcm_substream *substream, struct vm_area_str
|
|
* Playback specific ALSA stuff
|
|
* Playback specific ALSA stuff
|
|
*/
|
|
*/
|
|
static const u32 channels_to_txmask[] = {
|
|
static const u32 channels_to_txmask[] = {
|
|
- [2] = TXCR_TX3 | TXCR_TX4,
|
|
|
|
- [4] = TXCR_TX3 | TXCR_TX4 | TXCR_TX7 | TXCR_TX8,
|
|
|
|
- [6] = TXCR_TX3 | TXCR_TX4 | TXCR_TX7 | TXCR_TX8 | TXCR_TX6 | TXCR_TX9,
|
|
|
|
|
|
+ [2] = CR_SL3 | CR_SL4,
|
|
|
|
+ [4] = CR_SL3 | CR_SL4 | CR_SL7 | CR_SL8,
|
|
|
|
+ [6] = CR_SL3 | CR_SL4 | CR_SL7 | CR_SL8 | CR_SL6 | CR_SL9,
|
|
};
|
|
};
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -505,7 +571,7 @@ aaci_rule_channels(struct snd_pcm_hw_params *p, struct snd_pcm_hw_rule *rule)
|
|
chan_mask);
|
|
chan_mask);
|
|
}
|
|
}
|
|
|
|
|
|
-static int aaci_pcm_playback_open(struct snd_pcm_substream *substream)
|
|
|
|
|
|
+static int aaci_pcm_open(struct snd_pcm_substream *substream)
|
|
{
|
|
{
|
|
struct aaci *aaci = substream->private_data;
|
|
struct aaci *aaci = substream->private_data;
|
|
int ret;
|
|
int ret;
|
|
@@ -520,7 +586,12 @@ static int aaci_pcm_playback_open(struct snd_pcm_substream *substream)
|
|
if (ret)
|
|
if (ret)
|
|
return ret;
|
|
return ret;
|
|
|
|
|
|
- return aaci_pcm_open(aaci, substream, &aaci->playback);
|
|
|
|
|
|
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
|
|
|
+ ret = __aaci_pcm_open(aaci, substream, &aaci->playback);
|
|
|
|
+ } else {
|
|
|
|
+ ret = __aaci_pcm_open(aaci, substream, &aaci->capture);
|
|
|
|
+ }
|
|
|
|
+ return ret;
|
|
}
|
|
}
|
|
|
|
|
|
static int aaci_pcm_playback_hw_params(struct snd_pcm_substream *substream,
|
|
static int aaci_pcm_playback_hw_params(struct snd_pcm_substream *substream,
|
|
@@ -541,11 +612,11 @@ static int aaci_pcm_playback_hw_params(struct snd_pcm_substream *substream,
|
|
* FIXME: double rate slots?
|
|
* FIXME: double rate slots?
|
|
*/
|
|
*/
|
|
if (ret >= 0) {
|
|
if (ret >= 0) {
|
|
- aacirun->cr = TXCR_FEN | TXCR_COMPACT | TXCR_TSZ16;
|
|
|
|
|
|
+ aacirun->cr = CR_FEN | CR_COMPACT | CR_SZ16;
|
|
aacirun->cr |= channels_to_txmask[channels];
|
|
aacirun->cr |= channels_to_txmask[channels];
|
|
|
|
|
|
aacirun->fifosz = aaci->fifosize * 4;
|
|
aacirun->fifosz = aaci->fifosize * 4;
|
|
- if (aacirun->cr & TXCR_COMPACT)
|
|
|
|
|
|
+ if (aacirun->cr & CR_COMPACT)
|
|
aacirun->fifosz >>= 1;
|
|
aacirun->fifosz >>= 1;
|
|
}
|
|
}
|
|
return ret;
|
|
return ret;
|
|
@@ -558,7 +629,7 @@ static void aaci_pcm_playback_stop(struct aaci_runtime *aacirun)
|
|
ie = readl(aacirun->base + AACI_IE);
|
|
ie = readl(aacirun->base + AACI_IE);
|
|
ie &= ~(IE_URIE|IE_TXIE);
|
|
ie &= ~(IE_URIE|IE_TXIE);
|
|
writel(ie, aacirun->base + AACI_IE);
|
|
writel(ie, aacirun->base + AACI_IE);
|
|
- aacirun->cr &= ~TXCR_TXEN;
|
|
|
|
|
|
+ aacirun->cr &= ~CR_EN;
|
|
aaci_chan_wait_ready(aacirun);
|
|
aaci_chan_wait_ready(aacirun);
|
|
writel(aacirun->cr, aacirun->base + AACI_TXCR);
|
|
writel(aacirun->cr, aacirun->base + AACI_TXCR);
|
|
}
|
|
}
|
|
@@ -568,7 +639,7 @@ static void aaci_pcm_playback_start(struct aaci_runtime *aacirun)
|
|
u32 ie;
|
|
u32 ie;
|
|
|
|
|
|
aaci_chan_wait_ready(aacirun);
|
|
aaci_chan_wait_ready(aacirun);
|
|
- aacirun->cr |= TXCR_TXEN;
|
|
|
|
|
|
+ aacirun->cr |= CR_EN;
|
|
|
|
|
|
ie = readl(aacirun->base + AACI_IE);
|
|
ie = readl(aacirun->base + AACI_IE);
|
|
ie |= IE_URIE | IE_TXIE;
|
|
ie |= IE_URIE | IE_TXIE;
|
|
@@ -616,7 +687,7 @@ static int aaci_pcm_playback_trigger(struct snd_pcm_substream *substream, int cm
|
|
}
|
|
}
|
|
|
|
|
|
static struct snd_pcm_ops aaci_playback_ops = {
|
|
static struct snd_pcm_ops aaci_playback_ops = {
|
|
- .open = aaci_pcm_playback_open,
|
|
|
|
|
|
+ .open = aaci_pcm_open,
|
|
.close = aaci_pcm_close,
|
|
.close = aaci_pcm_close,
|
|
.ioctl = snd_pcm_lib_ioctl,
|
|
.ioctl = snd_pcm_lib_ioctl,
|
|
.hw_params = aaci_pcm_playback_hw_params,
|
|
.hw_params = aaci_pcm_playback_hw_params,
|
|
@@ -627,7 +698,133 @@ static struct snd_pcm_ops aaci_playback_ops = {
|
|
.mmap = aaci_pcm_mmap,
|
|
.mmap = aaci_pcm_mmap,
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+static int aaci_pcm_capture_hw_params(snd_pcm_substream_t *substream,
|
|
|
|
+ snd_pcm_hw_params_t *params)
|
|
|
|
+{
|
|
|
|
+ struct aaci *aaci = substream->private_data;
|
|
|
|
+ struct aaci_runtime *aacirun = substream->runtime->private_data;
|
|
|
|
+ int ret;
|
|
|
|
+
|
|
|
|
+ ret = aaci_pcm_hw_params(substream, aacirun, params);
|
|
|
|
+
|
|
|
|
+ if (ret >= 0) {
|
|
|
|
+ aacirun->cr = CR_FEN | CR_COMPACT | CR_SZ16;
|
|
|
|
+
|
|
|
|
+ /* Line in record: slot 3 and 4 */
|
|
|
|
+ aacirun->cr |= CR_SL3 | CR_SL4;
|
|
|
|
+
|
|
|
|
+ aacirun->fifosz = aaci->fifosize * 4;
|
|
|
|
+
|
|
|
|
+ if (aacirun->cr & CR_COMPACT)
|
|
|
|
+ aacirun->fifosz >>= 1;
|
|
|
|
+ }
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void aaci_pcm_capture_stop(struct aaci_runtime *aacirun)
|
|
|
|
+{
|
|
|
|
+ u32 ie;
|
|
|
|
+
|
|
|
|
+ aaci_chan_wait_ready(aacirun);
|
|
|
|
+
|
|
|
|
+ ie = readl(aacirun->base + AACI_IE);
|
|
|
|
+ ie &= ~(IE_ORIE | IE_RXIE);
|
|
|
|
+ writel(ie, aacirun->base+AACI_IE);
|
|
|
|
+
|
|
|
|
+ aacirun->cr &= ~CR_EN;
|
|
|
|
|
|
|
|
+ writel(aacirun->cr, aacirun->base + AACI_RXCR);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void aaci_pcm_capture_start(struct aaci_runtime *aacirun)
|
|
|
|
+{
|
|
|
|
+ u32 ie;
|
|
|
|
+
|
|
|
|
+ aaci_chan_wait_ready(aacirun);
|
|
|
|
+
|
|
|
|
+#ifdef DEBUG
|
|
|
|
+ /* RX Timeout value: bits 28:17 in RXCR */
|
|
|
|
+ aacirun->cr |= 0xf << 17;
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+ aacirun->cr |= CR_EN;
|
|
|
|
+ writel(aacirun->cr, aacirun->base + AACI_RXCR);
|
|
|
|
+
|
|
|
|
+ ie = readl(aacirun->base + AACI_IE);
|
|
|
|
+ ie |= IE_ORIE |IE_RXIE; // overrun and rx interrupt -- half full
|
|
|
|
+ writel(ie, aacirun->base + AACI_IE);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int aaci_pcm_capture_trigger(snd_pcm_substream_t *substream, int cmd){
|
|
|
|
+
|
|
|
|
+ struct aaci *aaci = substream->private_data;
|
|
|
|
+ struct aaci_runtime *aacirun = substream->runtime->private_data;
|
|
|
|
+ unsigned long flags;
|
|
|
|
+ int ret = 0;
|
|
|
|
+
|
|
|
|
+ spin_lock_irqsave(&aaci->lock, flags);
|
|
|
|
+
|
|
|
|
+ switch (cmd) {
|
|
|
|
+ case SNDRV_PCM_TRIGGER_START:
|
|
|
|
+ aaci_pcm_capture_start(aacirun);
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SNDRV_PCM_TRIGGER_RESUME:
|
|
|
|
+ aaci_pcm_capture_start(aacirun);
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SNDRV_PCM_TRIGGER_STOP:
|
|
|
|
+ aaci_pcm_capture_stop(aacirun);
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SNDRV_PCM_TRIGGER_SUSPEND:
|
|
|
|
+ aaci_pcm_capture_stop(aacirun);
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ default:
|
|
|
|
+ ret = -EINVAL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ spin_unlock_irqrestore(&aaci->lock, flags);
|
|
|
|
+
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int aaci_pcm_capture_prepare(snd_pcm_substream_t *substream)
|
|
|
|
+{
|
|
|
|
+ struct snd_pcm_runtime *runtime = substream->runtime;
|
|
|
|
+ struct aaci *aaci = substream->private_data;
|
|
|
|
+
|
|
|
|
+ aaci_pcm_prepare(substream);
|
|
|
|
+
|
|
|
|
+ /* allow changing of sample rate */
|
|
|
|
+ aaci_ac97_write(aaci->ac97, AC97_EXTENDED_STATUS, 0x0001); /* VRA */
|
|
|
|
+ aaci_ac97_write(aaci->ac97, AC97_PCM_LR_ADC_RATE, runtime->rate);
|
|
|
|
+ aaci_ac97_write(aaci->ac97, AC97_PCM_MIC_ADC_RATE, runtime->rate);
|
|
|
|
+
|
|
|
|
+ /* Record select: Mic: 0, Aux: 3, Line: 4 */
|
|
|
|
+ aaci_ac97_write(aaci->ac97, AC97_REC_SEL, 0x0404);
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static snd_pcm_ops_t aaci_capture_ops = {
|
|
|
|
+ .open = aaci_pcm_open,
|
|
|
|
+ .close = aaci_pcm_close,
|
|
|
|
+ .ioctl = snd_pcm_lib_ioctl,
|
|
|
|
+ .hw_params = aaci_pcm_capture_hw_params,
|
|
|
|
+ .hw_free = aaci_pcm_hw_free,
|
|
|
|
+ .prepare = aaci_pcm_capture_prepare,
|
|
|
|
+ .trigger = aaci_pcm_capture_trigger,
|
|
|
|
+ .pointer = aaci_pcm_pointer,
|
|
|
|
+ .mmap = aaci_pcm_mmap,
|
|
|
|
+};
|
|
|
|
|
|
/*
|
|
/*
|
|
* Power Management.
|
|
* Power Management.
|
|
@@ -667,7 +864,7 @@ static int aaci_resume(struct amba_device *dev)
|
|
|
|
|
|
|
|
|
|
static struct ac97_pcm ac97_defs[] __devinitdata = {
|
|
static struct ac97_pcm ac97_defs[] __devinitdata = {
|
|
- [0] = { /* Front PCM */
|
|
|
|
|
|
+ [0] = { /* Front PCM */
|
|
.exclusive = 1,
|
|
.exclusive = 1,
|
|
.r = {
|
|
.r = {
|
|
[0] = {
|
|
[0] = {
|
|
@@ -741,6 +938,7 @@ static int __devinit aaci_probe_ac97(struct aaci *aaci)
|
|
ret = snd_ac97_mixer(ac97_bus, &ac97_template, &ac97);
|
|
ret = snd_ac97_mixer(ac97_bus, &ac97_template, &ac97);
|
|
if (ret)
|
|
if (ret)
|
|
goto out;
|
|
goto out;
|
|
|
|
+ aaci->ac97 = ac97;
|
|
|
|
|
|
/*
|
|
/*
|
|
* Disable AC97 PC Beep input on audio codecs.
|
|
* Disable AC97 PC Beep input on audio codecs.
|
|
@@ -753,6 +951,7 @@ static int __devinit aaci_probe_ac97(struct aaci *aaci)
|
|
goto out;
|
|
goto out;
|
|
|
|
|
|
aaci->playback.pcm = &ac97_bus->pcms[0];
|
|
aaci->playback.pcm = &ac97_bus->pcms[0];
|
|
|
|
+ aaci->capture.pcm = &ac97_bus->pcms[1];
|
|
|
|
|
|
out:
|
|
out:
|
|
return ret;
|
|
return ret;
|
|
@@ -802,7 +1001,7 @@ static int __devinit aaci_init_pcm(struct aaci *aaci)
|
|
struct snd_pcm *pcm;
|
|
struct snd_pcm *pcm;
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
- ret = snd_pcm_new(aaci->card, "AACI AC'97", 0, 1, 0, &pcm);
|
|
|
|
|
|
+ ret = snd_pcm_new(aaci->card, "AACI AC'97", 0, 1, 1, &pcm);
|
|
if (ret == 0) {
|
|
if (ret == 0) {
|
|
aaci->pcm = pcm;
|
|
aaci->pcm = pcm;
|
|
pcm->private_data = aaci;
|
|
pcm->private_data = aaci;
|
|
@@ -811,6 +1010,7 @@ static int __devinit aaci_init_pcm(struct aaci *aaci)
|
|
strlcpy(pcm->name, DRIVER_NAME, sizeof(pcm->name));
|
|
strlcpy(pcm->name, DRIVER_NAME, sizeof(pcm->name));
|
|
|
|
|
|
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &aaci_playback_ops);
|
|
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &aaci_playback_ops);
|
|
|
|
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &aaci_capture_ops);
|
|
}
|
|
}
|
|
|
|
|
|
return ret;
|
|
return ret;
|
|
@@ -818,15 +1018,15 @@ static int __devinit aaci_init_pcm(struct aaci *aaci)
|
|
|
|
|
|
static unsigned int __devinit aaci_size_fifo(struct aaci *aaci)
|
|
static unsigned int __devinit aaci_size_fifo(struct aaci *aaci)
|
|
{
|
|
{
|
|
- void __iomem *base = aaci->base + AACI_CSCH1;
|
|
|
|
|
|
+ struct aaci_runtime *aacirun = &aaci->playback;
|
|
int i;
|
|
int i;
|
|
|
|
|
|
- writel(TXCR_FEN | TXCR_TSZ16 | TXCR_TXEN, base + AACI_TXCR);
|
|
|
|
|
|
+ writel(CR_FEN | CR_SZ16 | CR_EN, aacirun->base + AACI_TXCR);
|
|
|
|
|
|
- for (i = 0; !(readl(base + AACI_SR) & SR_TXFF) && i < 4096; i++)
|
|
|
|
- writel(0, aaci->base + AACI_DR1);
|
|
|
|
|
|
+ for (i = 0; !(readl(aacirun->base + AACI_SR) & SR_TXFF) && i < 4096; i++)
|
|
|
|
+ writel(0, aacirun->fifo);
|
|
|
|
|
|
- writel(0, base + AACI_TXCR);
|
|
|
|
|
|
+ writel(0, aacirun->base + AACI_TXCR);
|
|
|
|
|
|
/*
|
|
/*
|
|
* Re-initialise the AACI after the FIFO depth test, to
|
|
* Re-initialise the AACI after the FIFO depth test, to
|
|
@@ -873,6 +1073,12 @@ static int __devinit aaci_probe(struct amba_device *dev, void *id)
|
|
aaci->playback.base = aaci->base + AACI_CSCH1;
|
|
aaci->playback.base = aaci->base + AACI_CSCH1;
|
|
aaci->playback.fifo = aaci->base + AACI_DR1;
|
|
aaci->playback.fifo = aaci->base + AACI_DR1;
|
|
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Capture uses AACI channel 0
|
|
|
|
+ */
|
|
|
|
+ aaci->capture.base = aaci->base + AACI_CSCH1;
|
|
|
|
+ aaci->capture.fifo = aaci->base + AACI_DR1;
|
|
|
|
+
|
|
for (i = 0; i < 4; i++) {
|
|
for (i = 0; i < 4; i++) {
|
|
void __iomem *base = aaci->base + i * 0x14;
|
|
void __iomem *base = aaci->base + i * 0x14;
|
|
|
|
|
|
@@ -908,7 +1114,7 @@ static int __devinit aaci_probe(struct amba_device *dev, void *id)
|
|
ret = snd_card_register(aaci->card);
|
|
ret = snd_card_register(aaci->card);
|
|
if (ret == 0) {
|
|
if (ret == 0) {
|
|
dev_info(&dev->dev, "%s, fifo %d\n", aaci->card->longname,
|
|
dev_info(&dev->dev, "%s, fifo %d\n", aaci->card->longname,
|
|
- aaci->fifosize);
|
|
|
|
|
|
+ aaci->fifosize);
|
|
amba_set_drvdata(dev, aaci->card);
|
|
amba_set_drvdata(dev, aaci->card);
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|