1088 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * linux/sound/arm/aaci.c - ARM PrimeCell AACI PL041 driver4 *5 * Copyright (C) 2003 Deep Blue Solutions Ltd, All Rights Reserved.6 *7 * Documentation: ARM DDI 0173B8 */9#include <linux/module.h>10#include <linux/delay.h>11#include <linux/init.h>12#include <linux/ioport.h>13#include <linux/device.h>14#include <linux/spinlock.h>15#include <linux/interrupt.h>16#include <linux/err.h>17#include <linux/amba/bus.h>18#include <linux/io.h>19 20#include <sound/core.h>21#include <sound/initval.h>22#include <sound/ac97_codec.h>23#include <sound/pcm.h>24#include <sound/pcm_params.h>25 26#include "aaci.h"27 28#define DRIVER_NAME "aaci-pl041"29 30#define FRAME_PERIOD_US 2131 32/*33 * PM support is not complete. Turn it off.34 */35#undef CONFIG_PM36 37static void aaci_ac97_select_codec(struct aaci *aaci, struct snd_ac97 *ac97)38{39 u32 v, maincr = aaci->maincr | MAINCR_SCRA(ac97->num);40 41 /*42 * Ensure that the slot 1/2 RX registers are empty.43 */44 v = readl(aaci->base + AACI_SLFR);45 if (v & SLFR_2RXV)46 readl(aaci->base + AACI_SL2RX);47 if (v & SLFR_1RXV)48 readl(aaci->base + AACI_SL1RX);49 50 if (maincr != readl(aaci->base + AACI_MAINCR)) {51 writel(maincr, aaci->base + AACI_MAINCR);52 readl(aaci->base + AACI_MAINCR);53 udelay(1);54 }55}56 57/*58 * P29:59 * The recommended use of programming the external codec through slot 160 * and slot 2 data is to use the channels during setup routines and the61 * slot register at any other time. The data written into slot 1, slot 262 * and slot 12 registers is transmitted only when their corresponding63 * SI1TxEn, SI2TxEn and SI12TxEn bits are set in the AACI_MAINCR64 * register.65 */66static void aaci_ac97_write(struct snd_ac97 *ac97, unsigned short reg,67 unsigned short val)68{69 struct aaci *aaci = ac97->private_data;70 int timeout;71 u32 v;72 73 if (ac97->num >= 4)74 return;75 76 mutex_lock(&aaci->ac97_sem);77 78 aaci_ac97_select_codec(aaci, ac97);79 80 /*81 * P54: You must ensure that AACI_SL2TX is always written82 * to, if required, before data is written to AACI_SL1TX.83 */84 writel(val << 4, aaci->base + AACI_SL2TX);85 writel(reg << 12, aaci->base + AACI_SL1TX);86 87 /* Initially, wait one frame period */88 udelay(FRAME_PERIOD_US);89 90 /* And then wait an additional eight frame periods for it to be sent */91 timeout = FRAME_PERIOD_US * 8;92 do {93 udelay(1);94 v = readl(aaci->base + AACI_SLFR);95 } while ((v & (SLFR_1TXB|SLFR_2TXB)) && --timeout);96 97 if (v & (SLFR_1TXB|SLFR_2TXB))98 dev_err(&aaci->dev->dev,99 "timeout waiting for write to complete\n");100 101 mutex_unlock(&aaci->ac97_sem);102}103 104/*105 * Read an AC'97 register.106 */107static unsigned short aaci_ac97_read(struct snd_ac97 *ac97, unsigned short reg)108{109 struct aaci *aaci = ac97->private_data;110 int timeout, retries = 10;111 u32 v;112 113 if (ac97->num >= 4)114 return ~0;115 116 mutex_lock(&aaci->ac97_sem);117 118 aaci_ac97_select_codec(aaci, ac97);119 120 /*121 * Write the register address to slot 1.122 */123 writel((reg << 12) | (1 << 19), aaci->base + AACI_SL1TX);124 125 /* Initially, wait one frame period */126 udelay(FRAME_PERIOD_US);127 128 /* And then wait an additional eight frame periods for it to be sent */129 timeout = FRAME_PERIOD_US * 8;130 do {131 udelay(1);132 v = readl(aaci->base + AACI_SLFR);133 } while ((v & SLFR_1TXB) && --timeout);134 135 if (v & SLFR_1TXB) {136 dev_err(&aaci->dev->dev, "timeout on slot 1 TX busy\n");137 v = ~0;138 goto out;139 }140 141 /* Now wait for the response frame */142 udelay(FRAME_PERIOD_US);143 144 /* And then wait an additional eight frame periods for data */145 timeout = FRAME_PERIOD_US * 8;146 do {147 udelay(1);148 cond_resched();149 v = readl(aaci->base + AACI_SLFR) & (SLFR_1RXV|SLFR_2RXV);150 } while ((v != (SLFR_1RXV|SLFR_2RXV)) && --timeout);151 152 if (v != (SLFR_1RXV|SLFR_2RXV)) {153 dev_err(&aaci->dev->dev, "timeout on RX valid\n");154 v = ~0;155 goto out;156 }157 158 do {159 v = readl(aaci->base + AACI_SL1RX) >> 12;160 if (v == reg) {161 v = readl(aaci->base + AACI_SL2RX) >> 4;162 break;163 } else if (--retries) {164 dev_warn(&aaci->dev->dev,165 "ac97 read back fail. retry\n");166 continue;167 } else {168 dev_warn(&aaci->dev->dev,169 "wrong ac97 register read back (%x != %x)\n",170 v, reg);171 v = ~0;172 }173 } while (retries);174 out:175 mutex_unlock(&aaci->ac97_sem);176 return v;177}178 179static inline void180aaci_chan_wait_ready(struct aaci_runtime *aacirun, unsigned long mask)181{182 u32 val;183 int timeout = 5000;184 185 do {186 udelay(1);187 val = readl(aacirun->base + AACI_SR);188 } while (val & mask && timeout--);189}190 191 192 193/*194 * Interrupt support.195 */196static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask)197{198 if (mask & ISR_ORINTR) {199 dev_warn(&aaci->dev->dev, "RX overrun on chan %d\n", channel);200 writel(ICLR_RXOEC1 << channel, aaci->base + AACI_INTCLR);201 }202 203 if (mask & ISR_RXTOINTR) {204 dev_warn(&aaci->dev->dev, "RX timeout on chan %d\n", channel);205 writel(ICLR_RXTOFEC1 << channel, aaci->base + AACI_INTCLR);206 }207 208 if (mask & ISR_RXINTR) {209 struct aaci_runtime *aacirun = &aaci->capture;210 bool period_elapsed = false;211 void *ptr;212 213 if (!aacirun->substream || !aacirun->start) {214 dev_warn(&aaci->dev->dev, "RX interrupt???\n");215 writel(0, aacirun->base + AACI_IE);216 return;217 }218 219 spin_lock(&aacirun->lock);220 221 ptr = aacirun->ptr;222 do {223 unsigned int len = aacirun->fifo_bytes;224 u32 val;225 226 if (aacirun->bytes <= 0) {227 aacirun->bytes += aacirun->period;228 period_elapsed = true;229 }230 if (!(aacirun->cr & CR_EN))231 break;232 233 val = readl(aacirun->base + AACI_SR);234 if (!(val & SR_RXHF))235 break;236 if (!(val & SR_RXFF))237 len >>= 1;238 239 aacirun->bytes -= len;240 241 /* reading 16 bytes at a time */242 for( ; len > 0; len -= 16) {243 asm(244 "ldmia %1, {r0, r1, r2, r3}\n\t"245 "stmia %0!, {r0, r1, r2, r3}"246 : "+r" (ptr)247 : "r" (aacirun->fifo)248 : "r0", "r1", "r2", "r3", "cc");249 250 if (ptr >= aacirun->end)251 ptr = aacirun->start;252 }253 } while(1);254 255 aacirun->ptr = ptr;256 257 spin_unlock(&aacirun->lock);258 259 if (period_elapsed)260 snd_pcm_period_elapsed(aacirun->substream);261 }262 263 if (mask & ISR_URINTR) {264 dev_dbg(&aaci->dev->dev, "TX underrun on chan %d\n", channel);265 writel(ICLR_TXUEC1 << channel, aaci->base + AACI_INTCLR);266 }267 268 if (mask & ISR_TXINTR) {269 struct aaci_runtime *aacirun = &aaci->playback;270 bool period_elapsed = false;271 void *ptr;272 273 if (!aacirun->substream || !aacirun->start) {274 dev_warn(&aaci->dev->dev, "TX interrupt???\n");275 writel(0, aacirun->base + AACI_IE);276 return;277 }278 279 spin_lock(&aacirun->lock);280 281 ptr = aacirun->ptr;282 do {283 unsigned int len = aacirun->fifo_bytes;284 u32 val;285 286 if (aacirun->bytes <= 0) {287 aacirun->bytes += aacirun->period;288 period_elapsed = true;289 }290 if (!(aacirun->cr & CR_EN))291 break;292 293 val = readl(aacirun->base + AACI_SR);294 if (!(val & SR_TXHE))295 break;296 if (!(val & SR_TXFE))297 len >>= 1;298 299 aacirun->bytes -= len;300 301 /* writing 16 bytes at a time */302 for ( ; len > 0; len -= 16) {303 asm(304 "ldmia %0!, {r0, r1, r2, r3}\n\t"305 "stmia %1, {r0, r1, r2, r3}"306 : "+r" (ptr)307 : "r" (aacirun->fifo)308 : "r0", "r1", "r2", "r3", "cc");309 310 if (ptr >= aacirun->end)311 ptr = aacirun->start;312 }313 } while (1);314 315 aacirun->ptr = ptr;316 317 spin_unlock(&aacirun->lock);318 319 if (period_elapsed)320 snd_pcm_period_elapsed(aacirun->substream);321 }322}323 324static irqreturn_t aaci_irq(int irq, void *devid)325{326 struct aaci *aaci = devid;327 u32 mask;328 int i;329 330 mask = readl(aaci->base + AACI_ALLINTS);331 if (mask) {332 u32 m = mask;333 for (i = 0; i < 4; i++, m >>= 7) {334 if (m & 0x7f) {335 aaci_fifo_irq(aaci, i, m);336 }337 }338 }339 340 return mask ? IRQ_HANDLED : IRQ_NONE;341}342 343 344 345/*346 * ALSA support.347 */348static const struct snd_pcm_hardware aaci_hw_info = {349 .info = SNDRV_PCM_INFO_MMAP |350 SNDRV_PCM_INFO_MMAP_VALID |351 SNDRV_PCM_INFO_INTERLEAVED |352 SNDRV_PCM_INFO_BLOCK_TRANSFER |353 SNDRV_PCM_INFO_RESUME,354 355 /*356 * ALSA doesn't support 18-bit or 20-bit packed into 32-bit357 * words. It also doesn't support 12-bit at all.358 */359 .formats = SNDRV_PCM_FMTBIT_S16_LE,360 361 /* rates are setup from the AC'97 codec */362 .channels_min = 2,363 .channels_max = 2,364 .buffer_bytes_max = 64 * 1024,365 .period_bytes_min = 256,366 .period_bytes_max = PAGE_SIZE,367 .periods_min = 4,368 .periods_max = PAGE_SIZE / 16,369};370 371/*372 * We can support two and four channel audio. Unfortunately373 * six channel audio requires a non-standard channel ordering:374 * 2 -> FL(3), FR(4)375 * 4 -> FL(3), FR(4), SL(7), SR(8)376 * 6 -> FL(3), FR(4), SL(7), SR(8), C(6), LFE(9) (required)377 * FL(3), FR(4), C(6), SL(7), SR(8), LFE(9) (actual)378 * This requires an ALSA configuration file to correct.379 */380static int aaci_rule_channels(struct snd_pcm_hw_params *p,381 struct snd_pcm_hw_rule *rule)382{383 static const unsigned int channel_list[] = { 2, 4, 6 };384 struct aaci *aaci = rule->private;385 unsigned int mask = 1 << 0, slots;386 387 /* pcms[0] is the our 5.1 PCM instance. */388 slots = aaci->ac97_bus->pcms[0].r[0].slots;389 if (slots & (1 << AC97_SLOT_PCM_SLEFT)) {390 mask |= 1 << 1;391 if (slots & (1 << AC97_SLOT_LFE))392 mask |= 1 << 2;393 }394 395 return snd_interval_list(hw_param_interval(p, rule->var),396 ARRAY_SIZE(channel_list), channel_list, mask);397}398 399static int aaci_pcm_open(struct snd_pcm_substream *substream)400{401 struct snd_pcm_runtime *runtime = substream->runtime;402 struct aaci *aaci = substream->private_data;403 struct aaci_runtime *aacirun;404 int ret = 0;405 406 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {407 aacirun = &aaci->playback;408 } else {409 aacirun = &aaci->capture;410 }411 412 aacirun->substream = substream;413 runtime->private_data = aacirun;414 runtime->hw = aaci_hw_info;415 runtime->hw.rates = aacirun->pcm->rates;416 snd_pcm_limit_hw_rates(runtime);417 418 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {419 runtime->hw.channels_max = 6;420 421 /* Add rule describing channel dependency. */422 ret = snd_pcm_hw_rule_add(substream->runtime, 0,423 SNDRV_PCM_HW_PARAM_CHANNELS,424 aaci_rule_channels, aaci,425 SNDRV_PCM_HW_PARAM_CHANNELS, -1);426 if (ret)427 return ret;428 429 if (aacirun->pcm->r[1].slots)430 snd_ac97_pcm_double_rate_rules(runtime);431 }432 433 /*434 * ALSA wants the byte-size of the FIFOs. As we only support435 * 16-bit samples, this is twice the FIFO depth irrespective436 * of whether it's in compact mode or not.437 */438 runtime->hw.fifo_size = aaci->fifo_depth * 2;439 440 mutex_lock(&aaci->irq_lock);441 if (!aaci->users++) {442 ret = request_irq(aaci->dev->irq[0], aaci_irq,443 IRQF_SHARED, DRIVER_NAME, aaci);444 if (ret != 0)445 aaci->users--;446 }447 mutex_unlock(&aaci->irq_lock);448 449 return ret;450}451 452 453/*454 * Common ALSA stuff455 */456static int aaci_pcm_close(struct snd_pcm_substream *substream)457{458 struct aaci *aaci = substream->private_data;459 struct aaci_runtime *aacirun = substream->runtime->private_data;460 461 WARN_ON(aacirun->cr & CR_EN);462 463 aacirun->substream = NULL;464 465 mutex_lock(&aaci->irq_lock);466 if (!--aaci->users)467 free_irq(aaci->dev->irq[0], aaci);468 mutex_unlock(&aaci->irq_lock);469 470 return 0;471}472 473static int aaci_pcm_hw_free(struct snd_pcm_substream *substream)474{475 struct aaci_runtime *aacirun = substream->runtime->private_data;476 477 /*478 * This must not be called with the device enabled.479 */480 WARN_ON(aacirun->cr & CR_EN);481 482 if (aacirun->pcm_open)483 snd_ac97_pcm_close(aacirun->pcm);484 aacirun->pcm_open = 0;485 486 return 0;487}488 489/* Channel to slot mask */490static const u32 channels_to_slotmask[] = {491 [2] = CR_SL3 | CR_SL4,492 [4] = CR_SL3 | CR_SL4 | CR_SL7 | CR_SL8,493 [6] = CR_SL3 | CR_SL4 | CR_SL7 | CR_SL8 | CR_SL6 | CR_SL9,494};495 496static int aaci_pcm_hw_params(struct snd_pcm_substream *substream,497 struct snd_pcm_hw_params *params)498{499 struct aaci_runtime *aacirun = substream->runtime->private_data;500 struct aaci *aaci = substream->private_data;501 unsigned int channels = params_channels(params);502 unsigned int rate = params_rate(params);503 int dbl = rate > 48000;504 int err;505 506 aaci_pcm_hw_free(substream);507 if (aacirun->pcm_open) {508 snd_ac97_pcm_close(aacirun->pcm);509 aacirun->pcm_open = 0;510 }511 512 /* channels is already limited to 2, 4, or 6 by aaci_rule_channels */513 if (dbl && channels != 2)514 return -EINVAL;515 516 err = snd_ac97_pcm_open(aacirun->pcm, rate, channels,517 aacirun->pcm->r[dbl].slots);518 519 aacirun->pcm_open = err == 0;520 aacirun->cr = CR_FEN | CR_COMPACT | CR_SZ16;521 aacirun->cr |= channels_to_slotmask[channels + dbl * 2];522 523 /*524 * fifo_bytes is the number of bytes we transfer to/from525 * the FIFO, including padding. So that's x4. As we're526 * in compact mode, the FIFO is half the size.527 */528 aacirun->fifo_bytes = aaci->fifo_depth * 4 / 2;529 530 return err;531}532 533static int aaci_pcm_prepare(struct snd_pcm_substream *substream)534{535 struct snd_pcm_runtime *runtime = substream->runtime;536 struct aaci_runtime *aacirun = runtime->private_data;537 538 aacirun->period = snd_pcm_lib_period_bytes(substream);539 aacirun->start = runtime->dma_area;540 aacirun->end = aacirun->start + snd_pcm_lib_buffer_bytes(substream);541 aacirun->ptr = aacirun->start;542 aacirun->bytes = aacirun->period;543 544 return 0;545}546 547static snd_pcm_uframes_t aaci_pcm_pointer(struct snd_pcm_substream *substream)548{549 struct snd_pcm_runtime *runtime = substream->runtime;550 struct aaci_runtime *aacirun = runtime->private_data;551 ssize_t bytes = aacirun->ptr - aacirun->start;552 553 return bytes_to_frames(runtime, bytes);554}555 556 557/*558 * Playback specific ALSA stuff559 */560static void aaci_pcm_playback_stop(struct aaci_runtime *aacirun)561{562 u32 ie;563 564 ie = readl(aacirun->base + AACI_IE);565 ie &= ~(IE_URIE|IE_TXIE);566 writel(ie, aacirun->base + AACI_IE);567 aacirun->cr &= ~CR_EN;568 aaci_chan_wait_ready(aacirun, SR_TXB);569 writel(aacirun->cr, aacirun->base + AACI_TXCR);570}571 572static void aaci_pcm_playback_start(struct aaci_runtime *aacirun)573{574 u32 ie;575 576 aaci_chan_wait_ready(aacirun, SR_TXB);577 aacirun->cr |= CR_EN;578 579 ie = readl(aacirun->base + AACI_IE);580 ie |= IE_URIE | IE_TXIE;581 writel(ie, aacirun->base + AACI_IE);582 writel(aacirun->cr, aacirun->base + AACI_TXCR);583}584 585static int aaci_pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd)586{587 struct aaci_runtime *aacirun = substream->runtime->private_data;588 unsigned long flags;589 int ret = 0;590 591 spin_lock_irqsave(&aacirun->lock, flags);592 593 switch (cmd) {594 case SNDRV_PCM_TRIGGER_START:595 aaci_pcm_playback_start(aacirun);596 break;597 598 case SNDRV_PCM_TRIGGER_RESUME:599 aaci_pcm_playback_start(aacirun);600 break;601 602 case SNDRV_PCM_TRIGGER_STOP:603 aaci_pcm_playback_stop(aacirun);604 break;605 606 case SNDRV_PCM_TRIGGER_SUSPEND:607 aaci_pcm_playback_stop(aacirun);608 break;609 610 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:611 break;612 613 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:614 break;615 616 default:617 ret = -EINVAL;618 }619 620 spin_unlock_irqrestore(&aacirun->lock, flags);621 622 return ret;623}624 625static const struct snd_pcm_ops aaci_playback_ops = {626 .open = aaci_pcm_open,627 .close = aaci_pcm_close,628 .hw_params = aaci_pcm_hw_params,629 .hw_free = aaci_pcm_hw_free,630 .prepare = aaci_pcm_prepare,631 .trigger = aaci_pcm_playback_trigger,632 .pointer = aaci_pcm_pointer,633};634 635static void aaci_pcm_capture_stop(struct aaci_runtime *aacirun)636{637 u32 ie;638 639 aaci_chan_wait_ready(aacirun, SR_RXB);640 641 ie = readl(aacirun->base + AACI_IE);642 ie &= ~(IE_ORIE | IE_RXIE);643 writel(ie, aacirun->base+AACI_IE);644 645 aacirun->cr &= ~CR_EN;646 647 writel(aacirun->cr, aacirun->base + AACI_RXCR);648}649 650static void aaci_pcm_capture_start(struct aaci_runtime *aacirun)651{652 u32 ie;653 654 aaci_chan_wait_ready(aacirun, SR_RXB);655 656#ifdef DEBUG657 /* RX Timeout value: bits 28:17 in RXCR */658 aacirun->cr |= 0xf << 17;659#endif660 661 aacirun->cr |= CR_EN;662 writel(aacirun->cr, aacirun->base + AACI_RXCR);663 664 ie = readl(aacirun->base + AACI_IE);665 ie |= IE_ORIE |IE_RXIE; // overrun and rx interrupt -- half full666 writel(ie, aacirun->base + AACI_IE);667}668 669static int aaci_pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd)670{671 struct aaci_runtime *aacirun = substream->runtime->private_data;672 unsigned long flags;673 int ret = 0;674 675 spin_lock_irqsave(&aacirun->lock, flags);676 677 switch (cmd) {678 case SNDRV_PCM_TRIGGER_START:679 aaci_pcm_capture_start(aacirun);680 break;681 682 case SNDRV_PCM_TRIGGER_RESUME:683 aaci_pcm_capture_start(aacirun);684 break;685 686 case SNDRV_PCM_TRIGGER_STOP:687 aaci_pcm_capture_stop(aacirun);688 break;689 690 case SNDRV_PCM_TRIGGER_SUSPEND:691 aaci_pcm_capture_stop(aacirun);692 break;693 694 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:695 break;696 697 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:698 break;699 700 default:701 ret = -EINVAL;702 }703 704 spin_unlock_irqrestore(&aacirun->lock, flags);705 706 return ret;707}708 709static int aaci_pcm_capture_prepare(struct snd_pcm_substream *substream)710{711 struct snd_pcm_runtime *runtime = substream->runtime;712 struct aaci *aaci = substream->private_data;713 714 aaci_pcm_prepare(substream);715 716 /* allow changing of sample rate */717 aaci_ac97_write(aaci->ac97, AC97_EXTENDED_STATUS, 0x0001); /* VRA */718 aaci_ac97_write(aaci->ac97, AC97_PCM_LR_ADC_RATE, runtime->rate);719 aaci_ac97_write(aaci->ac97, AC97_PCM_MIC_ADC_RATE, runtime->rate);720 721 /* Record select: Mic: 0, Aux: 3, Line: 4 */722 aaci_ac97_write(aaci->ac97, AC97_REC_SEL, 0x0404);723 724 return 0;725}726 727static const struct snd_pcm_ops aaci_capture_ops = {728 .open = aaci_pcm_open,729 .close = aaci_pcm_close,730 .hw_params = aaci_pcm_hw_params,731 .hw_free = aaci_pcm_hw_free,732 .prepare = aaci_pcm_capture_prepare,733 .trigger = aaci_pcm_capture_trigger,734 .pointer = aaci_pcm_pointer,735};736 737/*738 * Power Management.739 */740static int aaci_do_suspend(struct snd_card *card)741{742 snd_power_change_state(card, SNDRV_CTL_POWER_D3cold);743 return 0;744}745 746static int aaci_do_resume(struct snd_card *card)747{748 snd_power_change_state(card, SNDRV_CTL_POWER_D0);749 return 0;750}751 752static int aaci_suspend(struct device *dev)753{754 struct snd_card *card = dev_get_drvdata(dev);755 return card ? aaci_do_suspend(card) : 0;756}757 758static int aaci_resume(struct device *dev)759{760 struct snd_card *card = dev_get_drvdata(dev);761 return card ? aaci_do_resume(card) : 0;762}763 764static DEFINE_SIMPLE_DEV_PM_OPS(aaci_dev_pm_ops, aaci_suspend, aaci_resume);765 766static const struct ac97_pcm ac97_defs[] = {767 [0] = { /* Front PCM */768 .exclusive = 1,769 .r = {770 [0] = {771 .slots = (1 << AC97_SLOT_PCM_LEFT) |772 (1 << AC97_SLOT_PCM_RIGHT) |773 (1 << AC97_SLOT_PCM_CENTER) |774 (1 << AC97_SLOT_PCM_SLEFT) |775 (1 << AC97_SLOT_PCM_SRIGHT) |776 (1 << AC97_SLOT_LFE),777 },778 [1] = {779 .slots = (1 << AC97_SLOT_PCM_LEFT) |780 (1 << AC97_SLOT_PCM_RIGHT) |781 (1 << AC97_SLOT_PCM_LEFT_0) |782 (1 << AC97_SLOT_PCM_RIGHT_0),783 },784 },785 },786 [1] = { /* PCM in */787 .stream = 1,788 .exclusive = 1,789 .r = {790 [0] = {791 .slots = (1 << AC97_SLOT_PCM_LEFT) |792 (1 << AC97_SLOT_PCM_RIGHT),793 },794 },795 },796 [2] = { /* Mic in */797 .stream = 1,798 .exclusive = 1,799 .r = {800 [0] = {801 .slots = (1 << AC97_SLOT_MIC),802 },803 },804 }805};806 807static const struct snd_ac97_bus_ops aaci_bus_ops = {808 .write = aaci_ac97_write,809 .read = aaci_ac97_read,810};811 812static int aaci_probe_ac97(struct aaci *aaci)813{814 struct snd_ac97_template ac97_template;815 struct snd_ac97_bus *ac97_bus;816 struct snd_ac97 *ac97;817 int ret;818 819 /*820 * Assert AACIRESET for 2us821 */822 writel(0, aaci->base + AACI_RESET);823 udelay(2);824 writel(RESET_NRST, aaci->base + AACI_RESET);825 826 /*827 * Give the AC'97 codec more than enough time828 * to wake up. (42us = ~2 frames at 48kHz.)829 */830 udelay(FRAME_PERIOD_US * 2);831 832 ret = snd_ac97_bus(aaci->card, 0, &aaci_bus_ops, aaci, &ac97_bus);833 if (ret)834 goto out;835 836 ac97_bus->clock = 48000;837 aaci->ac97_bus = ac97_bus;838 839 memset(&ac97_template, 0, sizeof(struct snd_ac97_template));840 ac97_template.private_data = aaci;841 ac97_template.num = 0;842 ac97_template.scaps = AC97_SCAP_SKIP_MODEM;843 844 ret = snd_ac97_mixer(ac97_bus, &ac97_template, &ac97);845 if (ret)846 goto out;847 aaci->ac97 = ac97;848 849 /*850 * Disable AC97 PC Beep input on audio codecs.851 */852 if (ac97_is_audio(ac97))853 snd_ac97_write_cache(ac97, AC97_PC_BEEP, 0x801e);854 855 ret = snd_ac97_pcm_assign(ac97_bus, ARRAY_SIZE(ac97_defs), ac97_defs);856 if (ret)857 goto out;858 859 aaci->playback.pcm = &ac97_bus->pcms[0];860 aaci->capture.pcm = &ac97_bus->pcms[1];861 862 out:863 return ret;864}865 866static void aaci_free_card(struct snd_card *card)867{868 struct aaci *aaci = card->private_data;869 870 iounmap(aaci->base);871}872 873static struct aaci *aaci_init_card(struct amba_device *dev)874{875 struct aaci *aaci;876 struct snd_card *card;877 int err;878 879 err = snd_card_new(&dev->dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,880 THIS_MODULE, sizeof(struct aaci), &card);881 if (err < 0)882 return NULL;883 884 card->private_free = aaci_free_card;885 886 strscpy(card->driver, DRIVER_NAME, sizeof(card->driver));887 strscpy(card->shortname, "ARM AC'97 Interface", sizeof(card->shortname));888 snprintf(card->longname, sizeof(card->longname),889 "%s PL%03x rev%u at 0x%08llx, irq %d",890 card->shortname, amba_part(dev), amba_rev(dev),891 (unsigned long long)dev->res.start, dev->irq[0]);892 893 aaci = card->private_data;894 mutex_init(&aaci->ac97_sem);895 mutex_init(&aaci->irq_lock);896 aaci->card = card;897 aaci->dev = dev;898 899 /* Set MAINCR to allow slot 1 and 2 data IO */900 aaci->maincr = MAINCR_IE | MAINCR_SL1RXEN | MAINCR_SL1TXEN |901 MAINCR_SL2RXEN | MAINCR_SL2TXEN;902 903 return aaci;904}905 906static int aaci_init_pcm(struct aaci *aaci)907{908 struct snd_pcm *pcm;909 int ret;910 911 ret = snd_pcm_new(aaci->card, "AACI AC'97", 0, 1, 1, &pcm);912 if (ret == 0) {913 aaci->pcm = pcm;914 pcm->private_data = aaci;915 pcm->info_flags = 0;916 917 strscpy(pcm->name, DRIVER_NAME, sizeof(pcm->name));918 919 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &aaci_playback_ops);920 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &aaci_capture_ops);921 snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,922 aaci->card->dev,923 0, 64 * 1024);924 }925 926 return ret;927}928 929static unsigned int aaci_size_fifo(struct aaci *aaci)930{931 struct aaci_runtime *aacirun = &aaci->playback;932 int i;933 934 /*935 * Enable the channel, but don't assign it to any slots, so936 * it won't empty onto the AC'97 link.937 */938 writel(CR_FEN | CR_SZ16 | CR_EN, aacirun->base + AACI_TXCR);939 940 for (i = 0; !(readl(aacirun->base + AACI_SR) & SR_TXFF) && i < 4096; i++)941 writel(0, aacirun->fifo);942 943 writel(0, aacirun->base + AACI_TXCR);944 945 /*946 * Re-initialise the AACI after the FIFO depth test, to947 * ensure that the FIFOs are empty. Unfortunately, merely948 * disabling the channel doesn't clear the FIFO.949 */950 writel(aaci->maincr & ~MAINCR_IE, aaci->base + AACI_MAINCR);951 readl(aaci->base + AACI_MAINCR);952 udelay(1);953 writel(aaci->maincr, aaci->base + AACI_MAINCR);954 955 /*956 * If we hit 4096 entries, we failed. Go back to the specified957 * fifo depth.958 */959 if (i == 4096)960 i = 8;961 962 return i;963}964 965static int aaci_probe(struct amba_device *dev,966 const struct amba_id *id)967{968 struct aaci *aaci;969 int ret, i;970 971 ret = amba_request_regions(dev, NULL);972 if (ret)973 return ret;974 975 aaci = aaci_init_card(dev);976 if (!aaci) {977 ret = -ENOMEM;978 goto out;979 }980 981 aaci->base = ioremap(dev->res.start, resource_size(&dev->res));982 if (!aaci->base) {983 ret = -ENOMEM;984 goto out;985 }986 987 /*988 * Playback uses AACI channel 0989 */990 spin_lock_init(&aaci->playback.lock);991 aaci->playback.base = aaci->base + AACI_CSCH1;992 aaci->playback.fifo = aaci->base + AACI_DR1;993 994 /*995 * Capture uses AACI channel 0996 */997 spin_lock_init(&aaci->capture.lock);998 aaci->capture.base = aaci->base + AACI_CSCH1;999 aaci->capture.fifo = aaci->base + AACI_DR1;1000 1001 for (i = 0; i < 4; i++) {1002 void __iomem *base = aaci->base + i * 0x14;1003 1004 writel(0, base + AACI_IE);1005 writel(0, base + AACI_TXCR);1006 writel(0, base + AACI_RXCR);1007 }1008 1009 writel(0x1fff, aaci->base + AACI_INTCLR);1010 writel(aaci->maincr, aaci->base + AACI_MAINCR);1011 /*1012 * Fix: ac97 read back fail errors by reading1013 * from any arbitrary aaci register.1014 */1015 readl(aaci->base + AACI_CSCH1);1016 ret = aaci_probe_ac97(aaci);1017 if (ret)1018 goto out;1019 1020 /*1021 * Size the FIFOs (must be multiple of 16).1022 * This is the number of entries in the FIFO.1023 */1024 aaci->fifo_depth = aaci_size_fifo(aaci);1025 if (aaci->fifo_depth & 15) {1026 printk(KERN_WARNING "AACI: FIFO depth %d not supported\n",1027 aaci->fifo_depth);1028 ret = -ENODEV;1029 goto out;1030 }1031 1032 ret = aaci_init_pcm(aaci);1033 if (ret)1034 goto out;1035 1036 ret = snd_card_register(aaci->card);1037 if (ret == 0) {1038 dev_info(&dev->dev, "%s\n", aaci->card->longname);1039 dev_info(&dev->dev, "FIFO %u entries\n", aaci->fifo_depth);1040 amba_set_drvdata(dev, aaci->card);1041 return ret;1042 }1043 1044 out:1045 if (aaci)1046 snd_card_free(aaci->card);1047 amba_release_regions(dev);1048 return ret;1049}1050 1051static void aaci_remove(struct amba_device *dev)1052{1053 struct snd_card *card = amba_get_drvdata(dev);1054 1055 if (card) {1056 struct aaci *aaci = card->private_data;1057 writel(0, aaci->base + AACI_MAINCR);1058 1059 snd_card_free(card);1060 amba_release_regions(dev);1061 }1062}1063 1064static struct amba_id aaci_ids[] = {1065 {1066 .id = 0x00041041,1067 .mask = 0x000fffff,1068 },1069 { 0, 0 },1070};1071 1072MODULE_DEVICE_TABLE(amba, aaci_ids);1073 1074static struct amba_driver aaci_driver = {1075 .drv = {1076 .name = DRIVER_NAME,1077 .pm = &aaci_dev_pm_ops,1078 },1079 .probe = aaci_probe,1080 .remove = aaci_remove,1081 .id_table = aaci_ids,1082};1083 1084module_amba_driver(aaci_driver);1085 1086MODULE_LICENSE("GPL");1087MODULE_DESCRIPTION("ARM PrimeCell PL041 Advanced Audio CODEC Interface driver");1088