1cb5a6ffcSRussell King /* 2cb5a6ffcSRussell King * linux/sound/arm/aaci.c - ARM PrimeCell AACI PL041 driver 3cb5a6ffcSRussell King * 4cb5a6ffcSRussell King * Copyright (C) 2003 Deep Blue Solutions Ltd, All Rights Reserved. 5cb5a6ffcSRussell King * 6cb5a6ffcSRussell King * This program is free software; you can redistribute it and/or modify 7cb5a6ffcSRussell King * it under the terms of the GNU General Public License version 2 as 8cb5a6ffcSRussell King * published by the Free Software Foundation. 9cb5a6ffcSRussell King * 10cb5a6ffcSRussell King * Documentation: ARM DDI 0173B 11cb5a6ffcSRussell King */ 12cb5a6ffcSRussell King #include <linux/module.h> 13cb5a6ffcSRussell King #include <linux/delay.h> 14cb5a6ffcSRussell King #include <linux/init.h> 15cb5a6ffcSRussell King #include <linux/ioport.h> 16cb5a6ffcSRussell King #include <linux/device.h> 17cb5a6ffcSRussell King #include <linux/spinlock.h> 18cb5a6ffcSRussell King #include <linux/interrupt.h> 19cb5a6ffcSRussell King #include <linux/err.h> 20a62c80e5SRussell King #include <linux/amba/bus.h> 2188cdca9cSRussell King #include <linux/io.h> 22cb5a6ffcSRussell King 23cb5a6ffcSRussell King #include <sound/core.h> 24cb5a6ffcSRussell King #include <sound/initval.h> 25cb5a6ffcSRussell King #include <sound/ac97_codec.h> 26cb5a6ffcSRussell King #include <sound/pcm.h> 27cb5a6ffcSRussell King #include <sound/pcm_params.h> 28cb5a6ffcSRussell King 29cb5a6ffcSRussell King #include "aaci.h" 30cb5a6ffcSRussell King 31cb5a6ffcSRussell King #define DRIVER_NAME "aaci-pl041" 32cb5a6ffcSRussell King 33250c7a61SRussell King #define FRAME_PERIOD_US 21 34250c7a61SRussell King 35cb5a6ffcSRussell King /* 36cb5a6ffcSRussell King * PM support is not complete. Turn it off. 37cb5a6ffcSRussell King */ 38cb5a6ffcSRussell King #undef CONFIG_PM 39cb5a6ffcSRussell King 40ceb9e476STakashi Iwai static void aaci_ac97_select_codec(struct aaci *aaci, struct snd_ac97 *ac97) 41cb5a6ffcSRussell King { 42cb5a6ffcSRussell King u32 v, maincr = aaci->maincr | MAINCR_SCRA(ac97->num); 43cb5a6ffcSRussell King 44cb5a6ffcSRussell King /* 45cb5a6ffcSRussell King * Ensure that the slot 1/2 RX registers are empty. 46cb5a6ffcSRussell King */ 47cb5a6ffcSRussell King v = readl(aaci->base + AACI_SLFR); 48cb5a6ffcSRussell King if (v & SLFR_2RXV) 49cb5a6ffcSRussell King readl(aaci->base + AACI_SL2RX); 50cb5a6ffcSRussell King if (v & SLFR_1RXV) 51cb5a6ffcSRussell King readl(aaci->base + AACI_SL1RX); 52cb5a6ffcSRussell King 53cb5a6ffcSRussell King writel(maincr, aaci->base + AACI_MAINCR); 54cb5a6ffcSRussell King } 55cb5a6ffcSRussell King 56cb5a6ffcSRussell King /* 57cb5a6ffcSRussell King * P29: 58cb5a6ffcSRussell King * The recommended use of programming the external codec through slot 1 59cb5a6ffcSRussell King * and slot 2 data is to use the channels during setup routines and the 60cb5a6ffcSRussell King * slot register at any other time. The data written into slot 1, slot 2 61cb5a6ffcSRussell King * and slot 12 registers is transmitted only when their corresponding 62cb5a6ffcSRussell King * SI1TxEn, SI2TxEn and SI12TxEn bits are set in the AACI_MAINCR 63cb5a6ffcSRussell King * register. 64cb5a6ffcSRussell King */ 6514d178a1SKevin Hilman static void aaci_ac97_write(struct snd_ac97 *ac97, unsigned short reg, 6614d178a1SKevin Hilman unsigned short val) 67cb5a6ffcSRussell King { 68cb5a6ffcSRussell King struct aaci *aaci = ac97->private_data; 69250c7a61SRussell King int timeout; 70cb5a6ffcSRussell King u32 v; 71cb5a6ffcSRussell King 72cb5a6ffcSRussell King if (ac97->num >= 4) 73cb5a6ffcSRussell King return; 74cb5a6ffcSRussell King 7512aa7579SIngo Molnar mutex_lock(&aaci->ac97_sem); 76cb5a6ffcSRussell King 77cb5a6ffcSRussell King aaci_ac97_select_codec(aaci, ac97); 78cb5a6ffcSRussell King 79cb5a6ffcSRussell King /* 80cb5a6ffcSRussell King * P54: You must ensure that AACI_SL2TX is always written 81cb5a6ffcSRussell King * to, if required, before data is written to AACI_SL1TX. 82cb5a6ffcSRussell King */ 83cb5a6ffcSRussell King writel(val << 4, aaci->base + AACI_SL2TX); 84cb5a6ffcSRussell King writel(reg << 12, aaci->base + AACI_SL1TX); 85cb5a6ffcSRussell King 86250c7a61SRussell King /* Initially, wait one frame period */ 87250c7a61SRussell King udelay(FRAME_PERIOD_US); 88250c7a61SRussell King 89250c7a61SRussell King /* And then wait an additional eight frame periods for it to be sent */ 90250c7a61SRussell King timeout = FRAME_PERIOD_US * 8; 91cb5a6ffcSRussell King do { 92250c7a61SRussell King udelay(1); 93cb5a6ffcSRussell King v = readl(aaci->base + AACI_SLFR); 94f6f35bbeSRoel Kluin } while ((v & (SLFR_1TXB|SLFR_2TXB)) && --timeout); 9514d178a1SKevin Hilman 9669058cd6SRussell King if (v & (SLFR_1TXB|SLFR_2TXB)) 9714d178a1SKevin Hilman dev_err(&aaci->dev->dev, 9814d178a1SKevin Hilman "timeout waiting for write to complete\n"); 99cb5a6ffcSRussell King 10012aa7579SIngo Molnar mutex_unlock(&aaci->ac97_sem); 101cb5a6ffcSRussell King } 102cb5a6ffcSRussell King 103cb5a6ffcSRussell King /* 104cb5a6ffcSRussell King * Read an AC'97 register. 105cb5a6ffcSRussell King */ 106ceb9e476STakashi Iwai static unsigned short aaci_ac97_read(struct snd_ac97 *ac97, unsigned short reg) 107cb5a6ffcSRussell King { 108cb5a6ffcSRussell King struct aaci *aaci = ac97->private_data; 109250c7a61SRussell King int timeout, retries = 10; 110cb5a6ffcSRussell King u32 v; 111cb5a6ffcSRussell King 112cb5a6ffcSRussell King if (ac97->num >= 4) 113cb5a6ffcSRussell King return ~0; 114cb5a6ffcSRussell King 11512aa7579SIngo Molnar mutex_lock(&aaci->ac97_sem); 116cb5a6ffcSRussell King 117cb5a6ffcSRussell King aaci_ac97_select_codec(aaci, ac97); 118cb5a6ffcSRussell King 119cb5a6ffcSRussell King /* 120cb5a6ffcSRussell King * Write the register address to slot 1. 121cb5a6ffcSRussell King */ 122cb5a6ffcSRussell King writel((reg << 12) | (1 << 19), aaci->base + AACI_SL1TX); 123cb5a6ffcSRussell King 124250c7a61SRussell King /* Initially, wait one frame period */ 125250c7a61SRussell King udelay(FRAME_PERIOD_US); 126250c7a61SRussell King 127250c7a61SRussell King /* And then wait an additional eight frame periods for it to be sent */ 128250c7a61SRussell King timeout = FRAME_PERIOD_US * 8; 129cb5a6ffcSRussell King do { 130250c7a61SRussell King udelay(1); 131cb5a6ffcSRussell King v = readl(aaci->base + AACI_SLFR); 132f6f35bbeSRoel Kluin } while ((v & SLFR_1TXB) && --timeout); 13314d178a1SKevin Hilman 13469058cd6SRussell King if (v & SLFR_1TXB) { 13514d178a1SKevin Hilman dev_err(&aaci->dev->dev, "timeout on slot 1 TX busy\n"); 13614d178a1SKevin Hilman v = ~0; 13714d178a1SKevin Hilman goto out; 13814d178a1SKevin Hilman } 139cb5a6ffcSRussell King 140250c7a61SRussell King /* Now wait for the response frame */ 141250c7a61SRussell King udelay(FRAME_PERIOD_US); 142cb5a6ffcSRussell King 143250c7a61SRussell King /* And then wait an additional eight frame periods for data */ 144250c7a61SRussell King timeout = FRAME_PERIOD_US * 8; 145cb5a6ffcSRussell King do { 146250c7a61SRussell King udelay(1); 147cb5a6ffcSRussell King cond_resched(); 148cb5a6ffcSRussell King v = readl(aaci->base + AACI_SLFR) & (SLFR_1RXV|SLFR_2RXV); 149f6f35bbeSRoel Kluin } while ((v != (SLFR_1RXV|SLFR_2RXV)) && --timeout); 150cb5a6ffcSRussell King 15169058cd6SRussell King if (v != (SLFR_1RXV|SLFR_2RXV)) { 15214d178a1SKevin Hilman dev_err(&aaci->dev->dev, "timeout on RX valid\n"); 15314d178a1SKevin Hilman v = ~0; 15414d178a1SKevin Hilman goto out; 15514d178a1SKevin Hilman } 15614d178a1SKevin Hilman 15714d178a1SKevin Hilman do { 158cb5a6ffcSRussell King v = readl(aaci->base + AACI_SL1RX) >> 12; 159cb5a6ffcSRussell King if (v == reg) { 160cb5a6ffcSRussell King v = readl(aaci->base + AACI_SL2RX) >> 4; 16114d178a1SKevin Hilman break; 16214d178a1SKevin Hilman } else if (--retries) { 16314d178a1SKevin Hilman dev_warn(&aaci->dev->dev, 16414d178a1SKevin Hilman "ac97 read back fail. retry\n"); 16514d178a1SKevin Hilman continue; 166cb5a6ffcSRussell King } else { 16714d178a1SKevin Hilman dev_warn(&aaci->dev->dev, 168cb5a6ffcSRussell King "wrong ac97 register read back (%x != %x)\n", 169cb5a6ffcSRussell King v, reg); 170cb5a6ffcSRussell King v = ~0; 171cb5a6ffcSRussell King } 17214d178a1SKevin Hilman } while (retries); 17314d178a1SKevin Hilman out: 17412aa7579SIngo Molnar mutex_unlock(&aaci->ac97_sem); 175cb5a6ffcSRussell King return v; 176cb5a6ffcSRussell King } 177cb5a6ffcSRussell King 178d6a89fefSRussell King static inline void 179d6a89fefSRussell King aaci_chan_wait_ready(struct aaci_runtime *aacirun, unsigned long mask) 180cb5a6ffcSRussell King { 181cb5a6ffcSRussell King u32 val; 182cb5a6ffcSRussell King int timeout = 5000; 183cb5a6ffcSRussell King 184cb5a6ffcSRussell King do { 185250c7a61SRussell King udelay(1); 186cb5a6ffcSRussell King val = readl(aacirun->base + AACI_SR); 187d6a89fefSRussell King } while (val & mask && timeout--); 188cb5a6ffcSRussell King } 189cb5a6ffcSRussell King 190cb5a6ffcSRussell King 191cb5a6ffcSRussell King 192cb5a6ffcSRussell King /* 193cb5a6ffcSRussell King * Interrupt support. 194cb5a6ffcSRussell King */ 19562578cbfSKevin Hilman static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask) 196cb5a6ffcSRussell King { 19741762b8cSKevin Hilman if (mask & ISR_ORINTR) { 19841762b8cSKevin Hilman dev_warn(&aaci->dev->dev, "RX overrun on chan %d\n", channel); 19941762b8cSKevin Hilman writel(ICLR_RXOEC1 << channel, aaci->base + AACI_INTCLR); 20041762b8cSKevin Hilman } 20141762b8cSKevin Hilman 20241762b8cSKevin Hilman if (mask & ISR_RXTOINTR) { 20341762b8cSKevin Hilman dev_warn(&aaci->dev->dev, "RX timeout on chan %d\n", channel); 20441762b8cSKevin Hilman writel(ICLR_RXTOFEC1 << channel, aaci->base + AACI_INTCLR); 20541762b8cSKevin Hilman } 20641762b8cSKevin Hilman 20741762b8cSKevin Hilman if (mask & ISR_RXINTR) { 20841762b8cSKevin Hilman struct aaci_runtime *aacirun = &aaci->capture; 209ea51d0b1SRussell King bool period_elapsed = false; 21041762b8cSKevin Hilman void *ptr; 21141762b8cSKevin Hilman 21241762b8cSKevin Hilman if (!aacirun->substream || !aacirun->start) { 213898eb71cSJoe Perches dev_warn(&aaci->dev->dev, "RX interrupt???\n"); 21441762b8cSKevin Hilman writel(0, aacirun->base + AACI_IE); 21541762b8cSKevin Hilman return; 21641762b8cSKevin Hilman } 21741762b8cSKevin Hilman 218d6a89fefSRussell King spin_lock(&aacirun->lock); 219d6a89fefSRussell King 220d6a89fefSRussell King ptr = aacirun->ptr; 22141762b8cSKevin Hilman do { 2225d350cbaSRussell King unsigned int len = aacirun->fifo_bytes; 22341762b8cSKevin Hilman u32 val; 22441762b8cSKevin Hilman 22541762b8cSKevin Hilman if (aacirun->bytes <= 0) { 22641762b8cSKevin Hilman aacirun->bytes += aacirun->period; 227ea51d0b1SRussell King period_elapsed = true; 22841762b8cSKevin Hilman } 22941762b8cSKevin Hilman if (!(aacirun->cr & CR_EN)) 23041762b8cSKevin Hilman break; 23141762b8cSKevin Hilman 23241762b8cSKevin Hilman val = readl(aacirun->base + AACI_SR); 23341762b8cSKevin Hilman if (!(val & SR_RXHF)) 23441762b8cSKevin Hilman break; 23541762b8cSKevin Hilman if (!(val & SR_RXFF)) 23641762b8cSKevin Hilman len >>= 1; 23741762b8cSKevin Hilman 23841762b8cSKevin Hilman aacirun->bytes -= len; 23941762b8cSKevin Hilman 24041762b8cSKevin Hilman /* reading 16 bytes at a time */ 24141762b8cSKevin Hilman for( ; len > 0; len -= 16) { 24241762b8cSKevin Hilman asm( 24341762b8cSKevin Hilman "ldmia %1, {r0, r1, r2, r3}\n\t" 24441762b8cSKevin Hilman "stmia %0!, {r0, r1, r2, r3}" 24541762b8cSKevin Hilman : "+r" (ptr) 24641762b8cSKevin Hilman : "r" (aacirun->fifo) 24741762b8cSKevin Hilman : "r0", "r1", "r2", "r3", "cc"); 24841762b8cSKevin Hilman 24941762b8cSKevin Hilman if (ptr >= aacirun->end) 25041762b8cSKevin Hilman ptr = aacirun->start; 25141762b8cSKevin Hilman } 25241762b8cSKevin Hilman } while(1); 253d6a89fefSRussell King 25441762b8cSKevin Hilman aacirun->ptr = ptr; 255d6a89fefSRussell King 256d6a89fefSRussell King spin_unlock(&aacirun->lock); 257ea51d0b1SRussell King 258ea51d0b1SRussell King if (period_elapsed) 259ea51d0b1SRussell King snd_pcm_period_elapsed(aacirun->substream); 26041762b8cSKevin Hilman } 26141762b8cSKevin Hilman 262cb5a6ffcSRussell King if (mask & ISR_URINTR) { 26362578cbfSKevin Hilman dev_dbg(&aaci->dev->dev, "TX underrun on chan %d\n", channel); 26462578cbfSKevin Hilman writel(ICLR_TXUEC1 << channel, aaci->base + AACI_INTCLR); 265cb5a6ffcSRussell King } 266cb5a6ffcSRussell King 267cb5a6ffcSRussell King if (mask & ISR_TXINTR) { 268cb5a6ffcSRussell King struct aaci_runtime *aacirun = &aaci->playback; 269ea51d0b1SRussell King bool period_elapsed = false; 270cb5a6ffcSRussell King void *ptr; 271cb5a6ffcSRussell King 272cb5a6ffcSRussell King if (!aacirun->substream || !aacirun->start) { 273898eb71cSJoe Perches dev_warn(&aaci->dev->dev, "TX interrupt???\n"); 274cb5a6ffcSRussell King writel(0, aacirun->base + AACI_IE); 275cb5a6ffcSRussell King return; 276cb5a6ffcSRussell King } 277cb5a6ffcSRussell King 278d6a89fefSRussell King spin_lock(&aacirun->lock); 279d6a89fefSRussell King 280cb5a6ffcSRussell King ptr = aacirun->ptr; 281cb5a6ffcSRussell King do { 2825d350cbaSRussell King unsigned int len = aacirun->fifo_bytes; 283cb5a6ffcSRussell King u32 val; 284cb5a6ffcSRussell King 285cb5a6ffcSRussell King if (aacirun->bytes <= 0) { 286cb5a6ffcSRussell King aacirun->bytes += aacirun->period; 287ea51d0b1SRussell King period_elapsed = true; 288cb5a6ffcSRussell King } 28941762b8cSKevin Hilman if (!(aacirun->cr & CR_EN)) 290cb5a6ffcSRussell King break; 291cb5a6ffcSRussell King 292cb5a6ffcSRussell King val = readl(aacirun->base + AACI_SR); 293cb5a6ffcSRussell King if (!(val & SR_TXHE)) 294cb5a6ffcSRussell King break; 295cb5a6ffcSRussell King if (!(val & SR_TXFE)) 296cb5a6ffcSRussell King len >>= 1; 297cb5a6ffcSRussell King 298cb5a6ffcSRussell King aacirun->bytes -= len; 299cb5a6ffcSRussell King 300cb5a6ffcSRussell King /* writing 16 bytes at a time */ 301cb5a6ffcSRussell King for ( ; len > 0; len -= 16) { 302cb5a6ffcSRussell King asm( 303cb5a6ffcSRussell King "ldmia %0!, {r0, r1, r2, r3}\n\t" 304cb5a6ffcSRussell King "stmia %1, {r0, r1, r2, r3}" 305cb5a6ffcSRussell King : "+r" (ptr) 306cb5a6ffcSRussell King : "r" (aacirun->fifo) 307cb5a6ffcSRussell King : "r0", "r1", "r2", "r3", "cc"); 308cb5a6ffcSRussell King 309cb5a6ffcSRussell King if (ptr >= aacirun->end) 310cb5a6ffcSRussell King ptr = aacirun->start; 311cb5a6ffcSRussell King } 312cb5a6ffcSRussell King } while (1); 313cb5a6ffcSRussell King 314cb5a6ffcSRussell King aacirun->ptr = ptr; 315d6a89fefSRussell King 316d6a89fefSRussell King spin_unlock(&aacirun->lock); 317ea51d0b1SRussell King 318ea51d0b1SRussell King if (period_elapsed) 319ea51d0b1SRussell King snd_pcm_period_elapsed(aacirun->substream); 320cb5a6ffcSRussell King } 321cb5a6ffcSRussell King } 322cb5a6ffcSRussell King 3237d12e780SDavid Howells static irqreturn_t aaci_irq(int irq, void *devid) 324cb5a6ffcSRussell King { 325cb5a6ffcSRussell King struct aaci *aaci = devid; 326cb5a6ffcSRussell King u32 mask; 327cb5a6ffcSRussell King int i; 328cb5a6ffcSRussell King 329cb5a6ffcSRussell King mask = readl(aaci->base + AACI_ALLINTS); 330cb5a6ffcSRussell King if (mask) { 331cb5a6ffcSRussell King u32 m = mask; 332cb5a6ffcSRussell King for (i = 0; i < 4; i++, m >>= 7) { 333cb5a6ffcSRussell King if (m & 0x7f) { 33462578cbfSKevin Hilman aaci_fifo_irq(aaci, i, m); 335cb5a6ffcSRussell King } 336cb5a6ffcSRussell King } 337cb5a6ffcSRussell King } 338cb5a6ffcSRussell King 339cb5a6ffcSRussell King return mask ? IRQ_HANDLED : IRQ_NONE; 340cb5a6ffcSRussell King } 341cb5a6ffcSRussell King 342cb5a6ffcSRussell King 343cb5a6ffcSRussell King 344cb5a6ffcSRussell King /* 345cb5a6ffcSRussell King * ALSA support. 346cb5a6ffcSRussell King */ 347ceb9e476STakashi Iwai static struct snd_pcm_hardware aaci_hw_info = { 348cb5a6ffcSRussell King .info = SNDRV_PCM_INFO_MMAP | 349cb5a6ffcSRussell King SNDRV_PCM_INFO_MMAP_VALID | 350cb5a6ffcSRussell King SNDRV_PCM_INFO_INTERLEAVED | 351cb5a6ffcSRussell King SNDRV_PCM_INFO_BLOCK_TRANSFER | 352cb5a6ffcSRussell King SNDRV_PCM_INFO_RESUME, 353cb5a6ffcSRussell King 354cb5a6ffcSRussell King /* 355cb5a6ffcSRussell King * ALSA doesn't support 18-bit or 20-bit packed into 32-bit 356cb5a6ffcSRussell King * words. It also doesn't support 12-bit at all. 357cb5a6ffcSRussell King */ 358cb5a6ffcSRussell King .formats = SNDRV_PCM_FMTBIT_S16_LE, 359cb5a6ffcSRussell King 3606ca867c8SRussell King /* rates are setup from the AC'97 codec */ 361cb5a6ffcSRussell King .channels_min = 2, 362e831d80bSRussell King .channels_max = 2, 363cb5a6ffcSRussell King .buffer_bytes_max = 64 * 1024, 364cb5a6ffcSRussell King .period_bytes_min = 256, 365cb5a6ffcSRussell King .period_bytes_max = PAGE_SIZE, 366cb5a6ffcSRussell King .periods_min = 4, 367cb5a6ffcSRussell King .periods_max = PAGE_SIZE / 16, 368cb5a6ffcSRussell King }; 369cb5a6ffcSRussell King 370e831d80bSRussell King /* 371e831d80bSRussell King * We can support two and four channel audio. Unfortunately 372e831d80bSRussell King * six channel audio requires a non-standard channel ordering: 373e831d80bSRussell King * 2 -> FL(3), FR(4) 374e831d80bSRussell King * 4 -> FL(3), FR(4), SL(7), SR(8) 375e831d80bSRussell King * 6 -> FL(3), FR(4), SL(7), SR(8), C(6), LFE(9) (required) 376e831d80bSRussell King * FL(3), FR(4), C(6), SL(7), SR(8), LFE(9) (actual) 377e831d80bSRussell King * This requires an ALSA configuration file to correct. 378e831d80bSRussell King */ 379e831d80bSRussell King static int aaci_rule_channels(struct snd_pcm_hw_params *p, 380e831d80bSRussell King struct snd_pcm_hw_rule *rule) 381e831d80bSRussell King { 382e831d80bSRussell King static unsigned int channel_list[] = { 2, 4, 6 }; 383e831d80bSRussell King struct aaci *aaci = rule->private; 384e831d80bSRussell King unsigned int mask = 1 << 0, slots; 385e831d80bSRussell King 386e831d80bSRussell King /* pcms[0] is the our 5.1 PCM instance. */ 387e831d80bSRussell King slots = aaci->ac97_bus->pcms[0].r[0].slots; 388e831d80bSRussell King if (slots & (1 << AC97_SLOT_PCM_SLEFT)) { 389e831d80bSRussell King mask |= 1 << 1; 390e831d80bSRussell King if (slots & (1 << AC97_SLOT_LFE)) 391e831d80bSRussell King mask |= 1 << 2; 392e831d80bSRussell King } 393e831d80bSRussell King 394e831d80bSRussell King return snd_interval_list(hw_param_interval(p, rule->var), 395e831d80bSRussell King ARRAY_SIZE(channel_list), channel_list, mask); 396e831d80bSRussell King } 397e831d80bSRussell King 398e831d80bSRussell King static int aaci_pcm_open(struct snd_pcm_substream *substream) 399cb5a6ffcSRussell King { 400ceb9e476STakashi Iwai struct snd_pcm_runtime *runtime = substream->runtime; 401e831d80bSRussell King struct aaci *aaci = substream->private_data; 402e831d80bSRussell King struct aaci_runtime *aacirun; 403b60fb519SRussell King int ret = 0; 404cb5a6ffcSRussell King 405e831d80bSRussell King if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 406e831d80bSRussell King aacirun = &aaci->playback; 407e831d80bSRussell King } else { 408e831d80bSRussell King aacirun = &aaci->capture; 409e831d80bSRussell King } 410e831d80bSRussell King 411cb5a6ffcSRussell King aacirun->substream = substream; 412cb5a6ffcSRussell King runtime->private_data = aacirun; 413cb5a6ffcSRussell King runtime->hw = aaci_hw_info; 4146ca867c8SRussell King runtime->hw.rates = aacirun->pcm->rates; 4156ca867c8SRussell King snd_pcm_limit_hw_rates(runtime); 416cb5a6ffcSRussell King 417e831d80bSRussell King if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 418e831d80bSRussell King runtime->hw.channels_max = 6; 419e831d80bSRussell King 420e831d80bSRussell King /* Add rule describing channel dependency. */ 421e831d80bSRussell King ret = snd_pcm_hw_rule_add(substream->runtime, 0, 422e831d80bSRussell King SNDRV_PCM_HW_PARAM_CHANNELS, 423e831d80bSRussell King aaci_rule_channels, aaci, 424e831d80bSRussell King SNDRV_PCM_HW_PARAM_CHANNELS, -1); 425e831d80bSRussell King if (ret) 426e831d80bSRussell King return ret; 427e831d80bSRussell King 428e831d80bSRussell King if (aacirun->pcm->r[1].slots) 429a08d5658SRussell King snd_ac97_pcm_double_rate_rules(runtime); 430e831d80bSRussell King } 431a08d5658SRussell King 432cb5a6ffcSRussell King /* 4335d350cbaSRussell King * ALSA wants the byte-size of the FIFOs. As we only support 4345d350cbaSRussell King * 16-bit samples, this is twice the FIFO depth irrespective 4355d350cbaSRussell King * of whether it's in compact mode or not. 436cb5a6ffcSRussell King */ 4375d350cbaSRussell King runtime->hw.fifo_size = aaci->fifo_depth * 2; 438cb5a6ffcSRussell King 439b60fb519SRussell King mutex_lock(&aaci->irq_lock); 440b60fb519SRussell King if (!aaci->users++) { 441b60fb519SRussell King ret = request_irq(aaci->dev->irq[0], aaci_irq, 442b60fb519SRussell King IRQF_SHARED | IRQF_DISABLED, DRIVER_NAME, aaci); 443b60fb519SRussell King if (ret != 0) 444b60fb519SRussell King aaci->users--; 445b60fb519SRussell King } 446b60fb519SRussell King mutex_unlock(&aaci->irq_lock); 447cb5a6ffcSRussell King 448cb5a6ffcSRussell King return ret; 449cb5a6ffcSRussell King } 450cb5a6ffcSRussell King 451cb5a6ffcSRussell King 452cb5a6ffcSRussell King /* 453cb5a6ffcSRussell King * Common ALSA stuff 454cb5a6ffcSRussell King */ 455ceb9e476STakashi Iwai static int aaci_pcm_close(struct snd_pcm_substream *substream) 456cb5a6ffcSRussell King { 457cb5a6ffcSRussell King struct aaci *aaci = substream->private_data; 458cb5a6ffcSRussell King struct aaci_runtime *aacirun = substream->runtime->private_data; 459cb5a6ffcSRussell King 46041762b8cSKevin Hilman WARN_ON(aacirun->cr & CR_EN); 461cb5a6ffcSRussell King 462cb5a6ffcSRussell King aacirun->substream = NULL; 463b60fb519SRussell King 464b60fb519SRussell King mutex_lock(&aaci->irq_lock); 465b60fb519SRussell King if (!--aaci->users) 466cb5a6ffcSRussell King free_irq(aaci->dev->irq[0], aaci); 467b60fb519SRussell King mutex_unlock(&aaci->irq_lock); 468cb5a6ffcSRussell King 469cb5a6ffcSRussell King return 0; 470cb5a6ffcSRussell King } 471cb5a6ffcSRussell King 472ceb9e476STakashi Iwai static int aaci_pcm_hw_free(struct snd_pcm_substream *substream) 473cb5a6ffcSRussell King { 474cb5a6ffcSRussell King struct aaci_runtime *aacirun = substream->runtime->private_data; 475cb5a6ffcSRussell King 476cb5a6ffcSRussell King /* 477cb5a6ffcSRussell King * This must not be called with the device enabled. 478cb5a6ffcSRussell King */ 47941762b8cSKevin Hilman WARN_ON(aacirun->cr & CR_EN); 480cb5a6ffcSRussell King 481cb5a6ffcSRussell King if (aacirun->pcm_open) 482cb5a6ffcSRussell King snd_ac97_pcm_close(aacirun->pcm); 483cb5a6ffcSRussell King aacirun->pcm_open = 0; 484cb5a6ffcSRussell King 485cb5a6ffcSRussell King /* 486cb5a6ffcSRussell King * Clear out the DMA and any allocated buffers. 487cb5a6ffcSRussell King */ 488d6797322STakashi Iwai snd_pcm_lib_free_pages(substream); 489cb5a6ffcSRussell King 490cb5a6ffcSRussell King return 0; 491cb5a6ffcSRussell King } 492cb5a6ffcSRussell King 49358e8a474SRussell King /* Channel to slot mask */ 49458e8a474SRussell King static const u32 channels_to_slotmask[] = { 49558e8a474SRussell King [2] = CR_SL3 | CR_SL4, 49658e8a474SRussell King [4] = CR_SL3 | CR_SL4 | CR_SL7 | CR_SL8, 49758e8a474SRussell King [6] = CR_SL3 | CR_SL4 | CR_SL7 | CR_SL8 | CR_SL6 | CR_SL9, 49858e8a474SRussell King }; 49958e8a474SRussell King 500ceb9e476STakashi Iwai static int aaci_pcm_hw_params(struct snd_pcm_substream *substream, 501ceb9e476STakashi Iwai struct snd_pcm_hw_params *params) 502cb5a6ffcSRussell King { 50358e8a474SRussell King struct aaci_runtime *aacirun = substream->runtime->private_data; 50458e8a474SRussell King unsigned int channels = params_channels(params); 50558e8a474SRussell King unsigned int rate = params_rate(params); 50658e8a474SRussell King int dbl = rate > 48000; 507cb5a6ffcSRussell King int err; 508cb5a6ffcSRussell King 509cb5a6ffcSRussell King aaci_pcm_hw_free(substream); 5104acd57c3SRussell King if (aacirun->pcm_open) { 5114acd57c3SRussell King snd_ac97_pcm_close(aacirun->pcm); 5124acd57c3SRussell King aacirun->pcm_open = 0; 5134acd57c3SRussell King } 514cb5a6ffcSRussell King 51558e8a474SRussell King /* channels is already limited to 2, 4, or 6 by aaci_rule_channels */ 51658e8a474SRussell King if (dbl && channels != 2) 51758e8a474SRussell King return -EINVAL; 51858e8a474SRussell King 519d6797322STakashi Iwai err = snd_pcm_lib_malloc_pages(substream, 520cb5a6ffcSRussell King params_buffer_bytes(params)); 5214e30b691SRussell King if (err >= 0) { 52258e8a474SRussell King struct aaci *aaci = substream->private_data; 523a08d5658SRussell King 52458e8a474SRussell King err = snd_ac97_pcm_open(aacirun->pcm, rate, channels, 525a08d5658SRussell King aacirun->pcm->r[dbl].slots); 526cb5a6ffcSRussell King 5274e30b691SRussell King aacirun->pcm_open = err == 0; 528d3aee799SRussell King aacirun->cr = CR_FEN | CR_COMPACT | CR_SZ16; 52958e8a474SRussell King aacirun->cr |= channels_to_slotmask[channels + dbl * 2]; 530d3aee799SRussell King 5315d350cbaSRussell King /* 5325d350cbaSRussell King * fifo_bytes is the number of bytes we transfer to/from 5335d350cbaSRussell King * the FIFO, including padding. So that's x4. As we're 5345d350cbaSRussell King * in compact mode, the FIFO is half the size. 5355d350cbaSRussell King */ 5365d350cbaSRussell King aacirun->fifo_bytes = aaci->fifo_depth * 4 / 2; 5374e30b691SRussell King } 538cb5a6ffcSRussell King 539cb5a6ffcSRussell King return err; 540cb5a6ffcSRussell King } 541cb5a6ffcSRussell King 542ceb9e476STakashi Iwai static int aaci_pcm_prepare(struct snd_pcm_substream *substream) 543cb5a6ffcSRussell King { 544ceb9e476STakashi Iwai struct snd_pcm_runtime *runtime = substream->runtime; 545cb5a6ffcSRussell King struct aaci_runtime *aacirun = runtime->private_data; 546cb5a6ffcSRussell King 547c0dea82cSRussell King aacirun->period = snd_pcm_lib_period_bytes(substream); 5484e30b691SRussell King aacirun->start = runtime->dma_area; 54988cdca9cSRussell King aacirun->end = aacirun->start + snd_pcm_lib_buffer_bytes(substream); 550cb5a6ffcSRussell King aacirun->ptr = aacirun->start; 551c0dea82cSRussell King aacirun->bytes = aacirun->period; 552cb5a6ffcSRussell King 553cb5a6ffcSRussell King return 0; 554cb5a6ffcSRussell King } 555cb5a6ffcSRussell King 556ceb9e476STakashi Iwai static snd_pcm_uframes_t aaci_pcm_pointer(struct snd_pcm_substream *substream) 557cb5a6ffcSRussell King { 558ceb9e476STakashi Iwai struct snd_pcm_runtime *runtime = substream->runtime; 559cb5a6ffcSRussell King struct aaci_runtime *aacirun = runtime->private_data; 560cb5a6ffcSRussell King ssize_t bytes = aacirun->ptr - aacirun->start; 561cb5a6ffcSRussell King 562cb5a6ffcSRussell King return bytes_to_frames(runtime, bytes); 563cb5a6ffcSRussell King } 564cb5a6ffcSRussell King 565cb5a6ffcSRussell King 566cb5a6ffcSRussell King /* 567cb5a6ffcSRussell King * Playback specific ALSA stuff 568cb5a6ffcSRussell King */ 569cb5a6ffcSRussell King static void aaci_pcm_playback_stop(struct aaci_runtime *aacirun) 570cb5a6ffcSRussell King { 571cb5a6ffcSRussell King u32 ie; 572cb5a6ffcSRussell King 573cb5a6ffcSRussell King ie = readl(aacirun->base + AACI_IE); 574cb5a6ffcSRussell King ie &= ~(IE_URIE|IE_TXIE); 575cb5a6ffcSRussell King writel(ie, aacirun->base + AACI_IE); 57641762b8cSKevin Hilman aacirun->cr &= ~CR_EN; 577d6a89fefSRussell King aaci_chan_wait_ready(aacirun, SR_TXB); 578cb5a6ffcSRussell King writel(aacirun->cr, aacirun->base + AACI_TXCR); 579cb5a6ffcSRussell King } 580cb5a6ffcSRussell King 581cb5a6ffcSRussell King static void aaci_pcm_playback_start(struct aaci_runtime *aacirun) 582cb5a6ffcSRussell King { 583cb5a6ffcSRussell King u32 ie; 584cb5a6ffcSRussell King 585d6a89fefSRussell King aaci_chan_wait_ready(aacirun, SR_TXB); 58641762b8cSKevin Hilman aacirun->cr |= CR_EN; 587cb5a6ffcSRussell King 588cb5a6ffcSRussell King ie = readl(aacirun->base + AACI_IE); 589cb5a6ffcSRussell King ie |= IE_URIE | IE_TXIE; 590cb5a6ffcSRussell King writel(ie, aacirun->base + AACI_IE); 591cb5a6ffcSRussell King writel(aacirun->cr, aacirun->base + AACI_TXCR); 592cb5a6ffcSRussell King } 593cb5a6ffcSRussell King 594ceb9e476STakashi Iwai static int aaci_pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd) 595cb5a6ffcSRussell King { 596cb5a6ffcSRussell King struct aaci_runtime *aacirun = substream->runtime->private_data; 597cb5a6ffcSRussell King unsigned long flags; 598cb5a6ffcSRussell King int ret = 0; 599cb5a6ffcSRussell King 600d6a89fefSRussell King spin_lock_irqsave(&aacirun->lock, flags); 601d6a89fefSRussell King 602cb5a6ffcSRussell King switch (cmd) { 603cb5a6ffcSRussell King case SNDRV_PCM_TRIGGER_START: 604cb5a6ffcSRussell King aaci_pcm_playback_start(aacirun); 605cb5a6ffcSRussell King break; 606cb5a6ffcSRussell King 607cb5a6ffcSRussell King case SNDRV_PCM_TRIGGER_RESUME: 608cb5a6ffcSRussell King aaci_pcm_playback_start(aacirun); 609cb5a6ffcSRussell King break; 610cb5a6ffcSRussell King 611cb5a6ffcSRussell King case SNDRV_PCM_TRIGGER_STOP: 612cb5a6ffcSRussell King aaci_pcm_playback_stop(aacirun); 613cb5a6ffcSRussell King break; 614cb5a6ffcSRussell King 615cb5a6ffcSRussell King case SNDRV_PCM_TRIGGER_SUSPEND: 616cb5a6ffcSRussell King aaci_pcm_playback_stop(aacirun); 617cb5a6ffcSRussell King break; 618cb5a6ffcSRussell King 619cb5a6ffcSRussell King case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 620cb5a6ffcSRussell King break; 621cb5a6ffcSRussell King 622cb5a6ffcSRussell King case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 623cb5a6ffcSRussell King break; 624cb5a6ffcSRussell King 625cb5a6ffcSRussell King default: 626cb5a6ffcSRussell King ret = -EINVAL; 627cb5a6ffcSRussell King } 628d6a89fefSRussell King 629d6a89fefSRussell King spin_unlock_irqrestore(&aacirun->lock, flags); 630cb5a6ffcSRussell King 631cb5a6ffcSRussell King return ret; 632cb5a6ffcSRussell King } 633cb5a6ffcSRussell King 634ceb9e476STakashi Iwai static struct snd_pcm_ops aaci_playback_ops = { 63541762b8cSKevin Hilman .open = aaci_pcm_open, 636cb5a6ffcSRussell King .close = aaci_pcm_close, 637cb5a6ffcSRussell King .ioctl = snd_pcm_lib_ioctl, 63858e8a474SRussell King .hw_params = aaci_pcm_hw_params, 639cb5a6ffcSRussell King .hw_free = aaci_pcm_hw_free, 640cb5a6ffcSRussell King .prepare = aaci_pcm_prepare, 641cb5a6ffcSRussell King .trigger = aaci_pcm_playback_trigger, 642cb5a6ffcSRussell King .pointer = aaci_pcm_pointer, 643cb5a6ffcSRussell King }; 644cb5a6ffcSRussell King 64541762b8cSKevin Hilman static void aaci_pcm_capture_stop(struct aaci_runtime *aacirun) 64641762b8cSKevin Hilman { 64741762b8cSKevin Hilman u32 ie; 64841762b8cSKevin Hilman 649d6a89fefSRussell King aaci_chan_wait_ready(aacirun, SR_RXB); 65041762b8cSKevin Hilman 65141762b8cSKevin Hilman ie = readl(aacirun->base + AACI_IE); 65241762b8cSKevin Hilman ie &= ~(IE_ORIE | IE_RXIE); 65341762b8cSKevin Hilman writel(ie, aacirun->base+AACI_IE); 65441762b8cSKevin Hilman 65541762b8cSKevin Hilman aacirun->cr &= ~CR_EN; 65641762b8cSKevin Hilman 65741762b8cSKevin Hilman writel(aacirun->cr, aacirun->base + AACI_RXCR); 65841762b8cSKevin Hilman } 65941762b8cSKevin Hilman 66041762b8cSKevin Hilman static void aaci_pcm_capture_start(struct aaci_runtime *aacirun) 66141762b8cSKevin Hilman { 66241762b8cSKevin Hilman u32 ie; 66341762b8cSKevin Hilman 664d6a89fefSRussell King aaci_chan_wait_ready(aacirun, SR_RXB); 66541762b8cSKevin Hilman 66641762b8cSKevin Hilman #ifdef DEBUG 66741762b8cSKevin Hilman /* RX Timeout value: bits 28:17 in RXCR */ 66841762b8cSKevin Hilman aacirun->cr |= 0xf << 17; 66941762b8cSKevin Hilman #endif 67041762b8cSKevin Hilman 67141762b8cSKevin Hilman aacirun->cr |= CR_EN; 67241762b8cSKevin Hilman writel(aacirun->cr, aacirun->base + AACI_RXCR); 67341762b8cSKevin Hilman 67441762b8cSKevin Hilman ie = readl(aacirun->base + AACI_IE); 67541762b8cSKevin Hilman ie |= IE_ORIE |IE_RXIE; // overrun and rx interrupt -- half full 67641762b8cSKevin Hilman writel(ie, aacirun->base + AACI_IE); 67741762b8cSKevin Hilman } 67841762b8cSKevin Hilman 6798a371840SRussell King static int aaci_pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd) 6808a371840SRussell King { 68141762b8cSKevin Hilman struct aaci_runtime *aacirun = substream->runtime->private_data; 68241762b8cSKevin Hilman unsigned long flags; 68341762b8cSKevin Hilman int ret = 0; 68441762b8cSKevin Hilman 685d6a89fefSRussell King spin_lock_irqsave(&aacirun->lock, flags); 68641762b8cSKevin Hilman 68741762b8cSKevin Hilman switch (cmd) { 68841762b8cSKevin Hilman case SNDRV_PCM_TRIGGER_START: 68941762b8cSKevin Hilman aaci_pcm_capture_start(aacirun); 69041762b8cSKevin Hilman break; 69141762b8cSKevin Hilman 69241762b8cSKevin Hilman case SNDRV_PCM_TRIGGER_RESUME: 69341762b8cSKevin Hilman aaci_pcm_capture_start(aacirun); 69441762b8cSKevin Hilman break; 69541762b8cSKevin Hilman 69641762b8cSKevin Hilman case SNDRV_PCM_TRIGGER_STOP: 69741762b8cSKevin Hilman aaci_pcm_capture_stop(aacirun); 69841762b8cSKevin Hilman break; 69941762b8cSKevin Hilman 70041762b8cSKevin Hilman case SNDRV_PCM_TRIGGER_SUSPEND: 70141762b8cSKevin Hilman aaci_pcm_capture_stop(aacirun); 70241762b8cSKevin Hilman break; 70341762b8cSKevin Hilman 70441762b8cSKevin Hilman case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 70541762b8cSKevin Hilman break; 70641762b8cSKevin Hilman 70741762b8cSKevin Hilman case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 70841762b8cSKevin Hilman break; 70941762b8cSKevin Hilman 71041762b8cSKevin Hilman default: 71141762b8cSKevin Hilman ret = -EINVAL; 71241762b8cSKevin Hilman } 71341762b8cSKevin Hilman 714d6a89fefSRussell King spin_unlock_irqrestore(&aacirun->lock, flags); 71541762b8cSKevin Hilman 71641762b8cSKevin Hilman return ret; 71741762b8cSKevin Hilman } 71841762b8cSKevin Hilman 7198a371840SRussell King static int aaci_pcm_capture_prepare(struct snd_pcm_substream *substream) 72041762b8cSKevin Hilman { 72141762b8cSKevin Hilman struct snd_pcm_runtime *runtime = substream->runtime; 72241762b8cSKevin Hilman struct aaci *aaci = substream->private_data; 72341762b8cSKevin Hilman 72441762b8cSKevin Hilman aaci_pcm_prepare(substream); 72541762b8cSKevin Hilman 72641762b8cSKevin Hilman /* allow changing of sample rate */ 72741762b8cSKevin Hilman aaci_ac97_write(aaci->ac97, AC97_EXTENDED_STATUS, 0x0001); /* VRA */ 72841762b8cSKevin Hilman aaci_ac97_write(aaci->ac97, AC97_PCM_LR_ADC_RATE, runtime->rate); 72941762b8cSKevin Hilman aaci_ac97_write(aaci->ac97, AC97_PCM_MIC_ADC_RATE, runtime->rate); 73041762b8cSKevin Hilman 73141762b8cSKevin Hilman /* Record select: Mic: 0, Aux: 3, Line: 4 */ 73241762b8cSKevin Hilman aaci_ac97_write(aaci->ac97, AC97_REC_SEL, 0x0404); 73341762b8cSKevin Hilman 73441762b8cSKevin Hilman return 0; 73541762b8cSKevin Hilman } 73641762b8cSKevin Hilman 7378a371840SRussell King static struct snd_pcm_ops aaci_capture_ops = { 73841762b8cSKevin Hilman .open = aaci_pcm_open, 73941762b8cSKevin Hilman .close = aaci_pcm_close, 74041762b8cSKevin Hilman .ioctl = snd_pcm_lib_ioctl, 74158e8a474SRussell King .hw_params = aaci_pcm_hw_params, 74241762b8cSKevin Hilman .hw_free = aaci_pcm_hw_free, 74341762b8cSKevin Hilman .prepare = aaci_pcm_capture_prepare, 74441762b8cSKevin Hilman .trigger = aaci_pcm_capture_trigger, 74541762b8cSKevin Hilman .pointer = aaci_pcm_pointer, 74641762b8cSKevin Hilman }; 747cb5a6ffcSRussell King 748cb5a6ffcSRussell King /* 749cb5a6ffcSRussell King * Power Management. 750cb5a6ffcSRussell King */ 751cb5a6ffcSRussell King #ifdef CONFIG_PM 752ceb9e476STakashi Iwai static int aaci_do_suspend(struct snd_card *card, unsigned int state) 753cb5a6ffcSRussell King { 754cb5a6ffcSRussell King struct aaci *aaci = card->private_data; 755792a6c51STakashi Iwai snd_power_change_state(card, SNDRV_CTL_POWER_D3cold); 756cb5a6ffcSRussell King snd_pcm_suspend_all(aaci->pcm); 757cb5a6ffcSRussell King return 0; 758cb5a6ffcSRussell King } 759cb5a6ffcSRussell King 760ceb9e476STakashi Iwai static int aaci_do_resume(struct snd_card *card, unsigned int state) 761cb5a6ffcSRussell King { 762792a6c51STakashi Iwai snd_power_change_state(card, SNDRV_CTL_POWER_D0); 763cb5a6ffcSRussell King return 0; 764cb5a6ffcSRussell King } 765cb5a6ffcSRussell King 766e36d394dSRichard Purdie static int aaci_suspend(struct amba_device *dev, pm_message_t state) 767cb5a6ffcSRussell King { 768ceb9e476STakashi Iwai struct snd_card *card = amba_get_drvdata(dev); 769cb5a6ffcSRussell King return card ? aaci_do_suspend(card) : 0; 770cb5a6ffcSRussell King } 771cb5a6ffcSRussell King 772cb5a6ffcSRussell King static int aaci_resume(struct amba_device *dev) 773cb5a6ffcSRussell King { 774ceb9e476STakashi Iwai struct snd_card *card = amba_get_drvdata(dev); 775cb5a6ffcSRussell King return card ? aaci_do_resume(card) : 0; 776cb5a6ffcSRussell King } 777cb5a6ffcSRussell King #else 778cb5a6ffcSRussell King #define aaci_do_suspend NULL 779cb5a6ffcSRussell King #define aaci_do_resume NULL 780cb5a6ffcSRussell King #define aaci_suspend NULL 781cb5a6ffcSRussell King #define aaci_resume NULL 782cb5a6ffcSRussell King #endif 783cb5a6ffcSRussell King 784cb5a6ffcSRussell King 785cb5a6ffcSRussell King static struct ac97_pcm ac97_defs[] __devinitdata = { 786cb5a6ffcSRussell King [0] = { /* Front PCM */ 787cb5a6ffcSRussell King .exclusive = 1, 788cb5a6ffcSRussell King .r = { 789cb5a6ffcSRussell King [0] = { 790cb5a6ffcSRussell King .slots = (1 << AC97_SLOT_PCM_LEFT) | 791cb5a6ffcSRussell King (1 << AC97_SLOT_PCM_RIGHT) | 792cb5a6ffcSRussell King (1 << AC97_SLOT_PCM_CENTER) | 793cb5a6ffcSRussell King (1 << AC97_SLOT_PCM_SLEFT) | 794cb5a6ffcSRussell King (1 << AC97_SLOT_PCM_SRIGHT) | 795cb5a6ffcSRussell King (1 << AC97_SLOT_LFE), 796cb5a6ffcSRussell King }, 797a08d5658SRussell King [1] = { 798a08d5658SRussell King .slots = (1 << AC97_SLOT_PCM_LEFT) | 799a08d5658SRussell King (1 << AC97_SLOT_PCM_RIGHT) | 800a08d5658SRussell King (1 << AC97_SLOT_PCM_LEFT_0) | 801a08d5658SRussell King (1 << AC97_SLOT_PCM_RIGHT_0), 802a08d5658SRussell King }, 803cb5a6ffcSRussell King }, 804cb5a6ffcSRussell King }, 805cb5a6ffcSRussell King [1] = { /* PCM in */ 806cb5a6ffcSRussell King .stream = 1, 807cb5a6ffcSRussell King .exclusive = 1, 808cb5a6ffcSRussell King .r = { 809cb5a6ffcSRussell King [0] = { 810cb5a6ffcSRussell King .slots = (1 << AC97_SLOT_PCM_LEFT) | 811cb5a6ffcSRussell King (1 << AC97_SLOT_PCM_RIGHT), 812cb5a6ffcSRussell King }, 813cb5a6ffcSRussell King }, 814cb5a6ffcSRussell King }, 815cb5a6ffcSRussell King [2] = { /* Mic in */ 816cb5a6ffcSRussell King .stream = 1, 817cb5a6ffcSRussell King .exclusive = 1, 818cb5a6ffcSRussell King .r = { 819cb5a6ffcSRussell King [0] = { 820cb5a6ffcSRussell King .slots = (1 << AC97_SLOT_MIC), 821cb5a6ffcSRussell King }, 822cb5a6ffcSRussell King }, 823cb5a6ffcSRussell King } 824cb5a6ffcSRussell King }; 825cb5a6ffcSRussell King 826ceb9e476STakashi Iwai static struct snd_ac97_bus_ops aaci_bus_ops = { 827cb5a6ffcSRussell King .write = aaci_ac97_write, 828cb5a6ffcSRussell King .read = aaci_ac97_read, 829cb5a6ffcSRussell King }; 830cb5a6ffcSRussell King 831cb5a6ffcSRussell King static int __devinit aaci_probe_ac97(struct aaci *aaci) 832cb5a6ffcSRussell King { 833ceb9e476STakashi Iwai struct snd_ac97_template ac97_template; 834ceb9e476STakashi Iwai struct snd_ac97_bus *ac97_bus; 835ceb9e476STakashi Iwai struct snd_ac97 *ac97; 836cb5a6ffcSRussell King int ret; 837cb5a6ffcSRussell King 838cb5a6ffcSRussell King /* 839cb5a6ffcSRussell King * Assert AACIRESET for 2us 840cb5a6ffcSRussell King */ 841cb5a6ffcSRussell King writel(0, aaci->base + AACI_RESET); 842cb5a6ffcSRussell King udelay(2); 843cb5a6ffcSRussell King writel(RESET_NRST, aaci->base + AACI_RESET); 844cb5a6ffcSRussell King 845cb5a6ffcSRussell King /* 846cb5a6ffcSRussell King * Give the AC'97 codec more than enough time 847cb5a6ffcSRussell King * to wake up. (42us = ~2 frames at 48kHz.) 848cb5a6ffcSRussell King */ 849250c7a61SRussell King udelay(FRAME_PERIOD_US * 2); 850cb5a6ffcSRussell King 851cb5a6ffcSRussell King ret = snd_ac97_bus(aaci->card, 0, &aaci_bus_ops, aaci, &ac97_bus); 852cb5a6ffcSRussell King if (ret) 853cb5a6ffcSRussell King goto out; 854cb5a6ffcSRussell King 855cb5a6ffcSRussell King ac97_bus->clock = 48000; 856cb5a6ffcSRussell King aaci->ac97_bus = ac97_bus; 857cb5a6ffcSRussell King 858ceb9e476STakashi Iwai memset(&ac97_template, 0, sizeof(struct snd_ac97_template)); 859cb5a6ffcSRussell King ac97_template.private_data = aaci; 860cb5a6ffcSRussell King ac97_template.num = 0; 861cb5a6ffcSRussell King ac97_template.scaps = AC97_SCAP_SKIP_MODEM; 862cb5a6ffcSRussell King 863cb5a6ffcSRussell King ret = snd_ac97_mixer(ac97_bus, &ac97_template, &ac97); 864cb5a6ffcSRussell King if (ret) 865cb5a6ffcSRussell King goto out; 86641762b8cSKevin Hilman aaci->ac97 = ac97; 867cb5a6ffcSRussell King 868cb5a6ffcSRussell King /* 869cb5a6ffcSRussell King * Disable AC97 PC Beep input on audio codecs. 870cb5a6ffcSRussell King */ 871cb5a6ffcSRussell King if (ac97_is_audio(ac97)) 872cb5a6ffcSRussell King snd_ac97_write_cache(ac97, AC97_PC_BEEP, 0x801e); 873cb5a6ffcSRussell King 874cb5a6ffcSRussell King ret = snd_ac97_pcm_assign(ac97_bus, ARRAY_SIZE(ac97_defs), ac97_defs); 875cb5a6ffcSRussell King if (ret) 876cb5a6ffcSRussell King goto out; 877cb5a6ffcSRussell King 878cb5a6ffcSRussell King aaci->playback.pcm = &ac97_bus->pcms[0]; 87941762b8cSKevin Hilman aaci->capture.pcm = &ac97_bus->pcms[1]; 880cb5a6ffcSRussell King 881cb5a6ffcSRussell King out: 882cb5a6ffcSRussell King return ret; 883cb5a6ffcSRussell King } 884cb5a6ffcSRussell King 885ceb9e476STakashi Iwai static void aaci_free_card(struct snd_card *card) 886cb5a6ffcSRussell King { 887cb5a6ffcSRussell King struct aaci *aaci = card->private_data; 888cb5a6ffcSRussell King if (aaci->base) 889cb5a6ffcSRussell King iounmap(aaci->base); 890cb5a6ffcSRussell King } 891cb5a6ffcSRussell King 892cb5a6ffcSRussell King static struct aaci * __devinit aaci_init_card(struct amba_device *dev) 893cb5a6ffcSRussell King { 894cb5a6ffcSRussell King struct aaci *aaci; 895ceb9e476STakashi Iwai struct snd_card *card; 896bd7dd77cSTakashi Iwai int err; 897cb5a6ffcSRussell King 898bd7dd77cSTakashi Iwai err = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, 899bd7dd77cSTakashi Iwai THIS_MODULE, sizeof(struct aaci), &card); 900bd7dd77cSTakashi Iwai if (err < 0) 901631e8ad4STakashi Iwai return NULL; 902cb5a6ffcSRussell King 903cb5a6ffcSRussell King card->private_free = aaci_free_card; 904cb5a6ffcSRussell King 905cb5a6ffcSRussell King strlcpy(card->driver, DRIVER_NAME, sizeof(card->driver)); 906cb5a6ffcSRussell King strlcpy(card->shortname, "ARM AC'97 Interface", sizeof(card->shortname)); 907cb5a6ffcSRussell King snprintf(card->longname, sizeof(card->longname), 908f006d8fcSRussell King "%s PL%03x rev%u at 0x%08llx, irq %d", 909f006d8fcSRussell King card->shortname, amba_part(dev), amba_rev(dev), 910f006d8fcSRussell King (unsigned long long)dev->res.start, dev->irq[0]); 911cb5a6ffcSRussell King 912cb5a6ffcSRussell King aaci = card->private_data; 91312aa7579SIngo Molnar mutex_init(&aaci->ac97_sem); 914b60fb519SRussell King mutex_init(&aaci->irq_lock); 915cb5a6ffcSRussell King aaci->card = card; 916cb5a6ffcSRussell King aaci->dev = dev; 917cb5a6ffcSRussell King 918cb5a6ffcSRussell King /* Set MAINCR to allow slot 1 and 2 data IO */ 919cb5a6ffcSRussell King aaci->maincr = MAINCR_IE | MAINCR_SL1RXEN | MAINCR_SL1TXEN | 920cb5a6ffcSRussell King MAINCR_SL2RXEN | MAINCR_SL2TXEN; 921cb5a6ffcSRussell King 922cb5a6ffcSRussell King return aaci; 923cb5a6ffcSRussell King } 924cb5a6ffcSRussell King 925cb5a6ffcSRussell King static int __devinit aaci_init_pcm(struct aaci *aaci) 926cb5a6ffcSRussell King { 927ceb9e476STakashi Iwai struct snd_pcm *pcm; 928cb5a6ffcSRussell King int ret; 929cb5a6ffcSRussell King 93041762b8cSKevin Hilman ret = snd_pcm_new(aaci->card, "AACI AC'97", 0, 1, 1, &pcm); 931cb5a6ffcSRussell King if (ret == 0) { 932cb5a6ffcSRussell King aaci->pcm = pcm; 933cb5a6ffcSRussell King pcm->private_data = aaci; 934cb5a6ffcSRussell King pcm->info_flags = 0; 935cb5a6ffcSRussell King 936cb5a6ffcSRussell King strlcpy(pcm->name, DRIVER_NAME, sizeof(pcm->name)); 937cb5a6ffcSRussell King 938cb5a6ffcSRussell King snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &aaci_playback_ops); 93941762b8cSKevin Hilman snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &aaci_capture_ops); 940d6797322STakashi Iwai snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, 941d4946431STakashi Iwai NULL, 0, 64 * 1024); 942cb5a6ffcSRussell King } 943cb5a6ffcSRussell King 944cb5a6ffcSRussell King return ret; 945cb5a6ffcSRussell King } 946cb5a6ffcSRussell King 947cb5a6ffcSRussell King static unsigned int __devinit aaci_size_fifo(struct aaci *aaci) 948cb5a6ffcSRussell King { 94941762b8cSKevin Hilman struct aaci_runtime *aacirun = &aaci->playback; 950cb5a6ffcSRussell King int i; 951cb5a6ffcSRussell King 9525d350cbaSRussell King /* 9535d350cbaSRussell King * Enable the channel, but don't assign it to any slots, so 9545d350cbaSRussell King * it won't empty onto the AC'97 link. 9555d350cbaSRussell King */ 95641762b8cSKevin Hilman writel(CR_FEN | CR_SZ16 | CR_EN, aacirun->base + AACI_TXCR); 957cb5a6ffcSRussell King 95841762b8cSKevin Hilman for (i = 0; !(readl(aacirun->base + AACI_SR) & SR_TXFF) && i < 4096; i++) 95941762b8cSKevin Hilman writel(0, aacirun->fifo); 960cb5a6ffcSRussell King 96141762b8cSKevin Hilman writel(0, aacirun->base + AACI_TXCR); 962cb5a6ffcSRussell King 963cb5a6ffcSRussell King /* 964cb5a6ffcSRussell King * Re-initialise the AACI after the FIFO depth test, to 965cb5a6ffcSRussell King * ensure that the FIFOs are empty. Unfortunately, merely 966cb5a6ffcSRussell King * disabling the channel doesn't clear the FIFO. 967cb5a6ffcSRussell King */ 968cb5a6ffcSRussell King writel(aaci->maincr & ~MAINCR_IE, aaci->base + AACI_MAINCR); 969cb5a6ffcSRussell King writel(aaci->maincr, aaci->base + AACI_MAINCR); 970cb5a6ffcSRussell King 971cb5a6ffcSRussell King /* 9725d350cbaSRussell King * If we hit 4096 entries, we failed. Go back to the specified 973cb5a6ffcSRussell King * fifo depth. 974cb5a6ffcSRussell King */ 975cb5a6ffcSRussell King if (i == 4096) 976cb5a6ffcSRussell King i = 8; 977cb5a6ffcSRussell King 978cb5a6ffcSRussell King return i; 979cb5a6ffcSRussell King } 980cb5a6ffcSRussell King 98103fbdb15SAlessandro Rubini static int __devinit aaci_probe(struct amba_device *dev, struct amba_id *id) 982cb5a6ffcSRussell King { 983cb5a6ffcSRussell King struct aaci *aaci; 984cb5a6ffcSRussell King int ret, i; 985cb5a6ffcSRussell King 986cb5a6ffcSRussell King ret = amba_request_regions(dev, NULL); 987cb5a6ffcSRussell King if (ret) 988cb5a6ffcSRussell King return ret; 989cb5a6ffcSRussell King 990cb5a6ffcSRussell King aaci = aaci_init_card(dev); 991631e8ad4STakashi Iwai if (!aaci) { 992631e8ad4STakashi Iwai ret = -ENOMEM; 993cb5a6ffcSRussell King goto out; 994cb5a6ffcSRussell King } 995cb5a6ffcSRussell King 996dc890c2dSLinus Walleij aaci->base = ioremap(dev->res.start, resource_size(&dev->res)); 997cb5a6ffcSRussell King if (!aaci->base) { 998cb5a6ffcSRussell King ret = -ENOMEM; 999cb5a6ffcSRussell King goto out; 1000cb5a6ffcSRussell King } 1001cb5a6ffcSRussell King 1002cb5a6ffcSRussell King /* 1003cb5a6ffcSRussell King * Playback uses AACI channel 0 1004cb5a6ffcSRussell King */ 1005d6a89fefSRussell King spin_lock_init(&aaci->playback.lock); 1006cb5a6ffcSRussell King aaci->playback.base = aaci->base + AACI_CSCH1; 1007cb5a6ffcSRussell King aaci->playback.fifo = aaci->base + AACI_DR1; 1008cb5a6ffcSRussell King 100941762b8cSKevin Hilman /* 101041762b8cSKevin Hilman * Capture uses AACI channel 0 101141762b8cSKevin Hilman */ 1012d6a89fefSRussell King spin_lock_init(&aaci->capture.lock); 101341762b8cSKevin Hilman aaci->capture.base = aaci->base + AACI_CSCH1; 101441762b8cSKevin Hilman aaci->capture.fifo = aaci->base + AACI_DR1; 101541762b8cSKevin Hilman 1016cb5a6ffcSRussell King for (i = 0; i < 4; i++) { 1017e12ba644Sviro@ZenIV.linux.org.uk void __iomem *base = aaci->base + i * 0x14; 1018cb5a6ffcSRussell King 1019cb5a6ffcSRussell King writel(0, base + AACI_IE); 1020cb5a6ffcSRussell King writel(0, base + AACI_TXCR); 1021cb5a6ffcSRussell King writel(0, base + AACI_RXCR); 1022cb5a6ffcSRussell King } 1023cb5a6ffcSRussell King 1024cb5a6ffcSRussell King writel(0x1fff, aaci->base + AACI_INTCLR); 1025cb5a6ffcSRussell King writel(aaci->maincr, aaci->base + AACI_MAINCR); 1026b68b58fdSPhilby John /* 1027b68b58fdSPhilby John * Fix: ac97 read back fail errors by reading 1028b68b58fdSPhilby John * from any arbitrary aaci register. 1029b68b58fdSPhilby John */ 1030b68b58fdSPhilby John readl(aaci->base + AACI_CSCH1); 1031cb5a6ffcSRussell King ret = aaci_probe_ac97(aaci); 1032cb5a6ffcSRussell King if (ret) 1033cb5a6ffcSRussell King goto out; 1034cb5a6ffcSRussell King 1035f27f218cSCatalin Marinas /* 1036f27f218cSCatalin Marinas * Size the FIFOs (must be multiple of 16). 10375d350cbaSRussell King * This is the number of entries in the FIFO. 1038f27f218cSCatalin Marinas */ 10395d350cbaSRussell King aaci->fifo_depth = aaci_size_fifo(aaci); 10405d350cbaSRussell King if (aaci->fifo_depth & 15) { 10415d350cbaSRussell King printk(KERN_WARNING "AACI: FIFO depth %d not supported\n", 10425d350cbaSRussell King aaci->fifo_depth); 1043f27f218cSCatalin Marinas ret = -ENODEV; 1044f27f218cSCatalin Marinas goto out; 1045f27f218cSCatalin Marinas } 1046f27f218cSCatalin Marinas 1047cb5a6ffcSRussell King ret = aaci_init_pcm(aaci); 1048cb5a6ffcSRussell King if (ret) 1049cb5a6ffcSRussell King goto out; 1050cb5a6ffcSRussell King 1051a76af199STakashi Iwai snd_card_set_dev(aaci->card, &dev->dev); 1052a76af199STakashi Iwai 1053cb5a6ffcSRussell King ret = snd_card_register(aaci->card); 1054cb5a6ffcSRussell King if (ret == 0) { 10555d350cbaSRussell King dev_info(&dev->dev, "%s\n", aaci->card->longname); 10565d350cbaSRussell King dev_info(&dev->dev, "FIFO %u entries\n", aaci->fifo_depth); 1057cb5a6ffcSRussell King amba_set_drvdata(dev, aaci->card); 1058cb5a6ffcSRussell King return ret; 1059cb5a6ffcSRussell King } 1060cb5a6ffcSRussell King 1061cb5a6ffcSRussell King out: 1062cb5a6ffcSRussell King if (aaci) 1063cb5a6ffcSRussell King snd_card_free(aaci->card); 1064cb5a6ffcSRussell King amba_release_regions(dev); 1065cb5a6ffcSRussell King return ret; 1066cb5a6ffcSRussell King } 1067cb5a6ffcSRussell King 1068cb5a6ffcSRussell King static int __devexit aaci_remove(struct amba_device *dev) 1069cb5a6ffcSRussell King { 1070ceb9e476STakashi Iwai struct snd_card *card = amba_get_drvdata(dev); 1071cb5a6ffcSRussell King 1072cb5a6ffcSRussell King amba_set_drvdata(dev, NULL); 1073cb5a6ffcSRussell King 1074cb5a6ffcSRussell King if (card) { 1075cb5a6ffcSRussell King struct aaci *aaci = card->private_data; 1076cb5a6ffcSRussell King writel(0, aaci->base + AACI_MAINCR); 1077cb5a6ffcSRussell King 1078cb5a6ffcSRussell King snd_card_free(card); 1079cb5a6ffcSRussell King amba_release_regions(dev); 1080cb5a6ffcSRussell King } 1081cb5a6ffcSRussell King 1082cb5a6ffcSRussell King return 0; 1083cb5a6ffcSRussell King } 1084cb5a6ffcSRussell King 1085cb5a6ffcSRussell King static struct amba_id aaci_ids[] = { 1086cb5a6ffcSRussell King { 1087cb5a6ffcSRussell King .id = 0x00041041, 1088cb5a6ffcSRussell King .mask = 0x000fffff, 1089cb5a6ffcSRussell King }, 1090cb5a6ffcSRussell King { 0, 0 }, 1091cb5a6ffcSRussell King }; 1092cb5a6ffcSRussell King 1093cb5a6ffcSRussell King static struct amba_driver aaci_driver = { 1094cb5a6ffcSRussell King .drv = { 1095cb5a6ffcSRussell King .name = DRIVER_NAME, 1096cb5a6ffcSRussell King }, 1097cb5a6ffcSRussell King .probe = aaci_probe, 1098cb5a6ffcSRussell King .remove = __devexit_p(aaci_remove), 1099cb5a6ffcSRussell King .suspend = aaci_suspend, 1100cb5a6ffcSRussell King .resume = aaci_resume, 1101cb5a6ffcSRussell King .id_table = aaci_ids, 1102cb5a6ffcSRussell King }; 1103cb5a6ffcSRussell King 1104cb5a6ffcSRussell King static int __init aaci_init(void) 1105cb5a6ffcSRussell King { 1106cb5a6ffcSRussell King return amba_driver_register(&aaci_driver); 1107cb5a6ffcSRussell King } 1108cb5a6ffcSRussell King 1109cb5a6ffcSRussell King static void __exit aaci_exit(void) 1110cb5a6ffcSRussell King { 1111cb5a6ffcSRussell King amba_driver_unregister(&aaci_driver); 1112cb5a6ffcSRussell King } 1113cb5a6ffcSRussell King 1114cb5a6ffcSRussell King module_init(aaci_init); 1115cb5a6ffcSRussell King module_exit(aaci_exit); 1116cb5a6ffcSRussell King 1117cb5a6ffcSRussell King MODULE_LICENSE("GPL"); 1118cb5a6ffcSRussell King MODULE_DESCRIPTION("ARM PrimeCell PL041 Advanced Audio CODEC Interface driver"); 1119