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> 20cb5a6ffcSRussell King 21cb5a6ffcSRussell King #include <asm/io.h> 22cb5a6ffcSRussell King #include <asm/irq.h> 23cb5a6ffcSRussell King #include <asm/hardware/amba.h> 24cb5a6ffcSRussell King 25cb5a6ffcSRussell King #include <sound/driver.h> 26cb5a6ffcSRussell King #include <sound/core.h> 27cb5a6ffcSRussell King #include <sound/initval.h> 28cb5a6ffcSRussell King #include <sound/ac97_codec.h> 29cb5a6ffcSRussell King #include <sound/pcm.h> 30cb5a6ffcSRussell King #include <sound/pcm_params.h> 31cb5a6ffcSRussell King 32cb5a6ffcSRussell King #include "aaci.h" 33cb5a6ffcSRussell King #include "devdma.h" 34cb5a6ffcSRussell King 35cb5a6ffcSRussell King #define DRIVER_NAME "aaci-pl041" 36cb5a6ffcSRussell King 37cb5a6ffcSRussell King /* 38cb5a6ffcSRussell King * PM support is not complete. Turn it off. 39cb5a6ffcSRussell King */ 40cb5a6ffcSRussell King #undef CONFIG_PM 41cb5a6ffcSRussell King 42cb5a6ffcSRussell King static void aaci_ac97_select_codec(struct aaci *aaci, ac97_t *ac97) 43cb5a6ffcSRussell King { 44cb5a6ffcSRussell King u32 v, maincr = aaci->maincr | MAINCR_SCRA(ac97->num); 45cb5a6ffcSRussell King 46cb5a6ffcSRussell King /* 47cb5a6ffcSRussell King * Ensure that the slot 1/2 RX registers are empty. 48cb5a6ffcSRussell King */ 49cb5a6ffcSRussell King v = readl(aaci->base + AACI_SLFR); 50cb5a6ffcSRussell King if (v & SLFR_2RXV) 51cb5a6ffcSRussell King readl(aaci->base + AACI_SL2RX); 52cb5a6ffcSRussell King if (v & SLFR_1RXV) 53cb5a6ffcSRussell King readl(aaci->base + AACI_SL1RX); 54cb5a6ffcSRussell King 55cb5a6ffcSRussell King writel(maincr, aaci->base + AACI_MAINCR); 56cb5a6ffcSRussell King } 57cb5a6ffcSRussell King 58cb5a6ffcSRussell King /* 59cb5a6ffcSRussell King * P29: 60cb5a6ffcSRussell King * The recommended use of programming the external codec through slot 1 61cb5a6ffcSRussell King * and slot 2 data is to use the channels during setup routines and the 62cb5a6ffcSRussell King * slot register at any other time. The data written into slot 1, slot 2 63cb5a6ffcSRussell King * and slot 12 registers is transmitted only when their corresponding 64cb5a6ffcSRussell King * SI1TxEn, SI2TxEn and SI12TxEn bits are set in the AACI_MAINCR 65cb5a6ffcSRussell King * register. 66cb5a6ffcSRussell King */ 67cb5a6ffcSRussell King static void aaci_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val) 68cb5a6ffcSRussell King { 69cb5a6ffcSRussell King struct aaci *aaci = ac97->private_data; 70cb5a6ffcSRussell King u32 v; 71cb5a6ffcSRussell King 72cb5a6ffcSRussell King if (ac97->num >= 4) 73cb5a6ffcSRussell King return; 74cb5a6ffcSRussell King 75cb5a6ffcSRussell King down(&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 86cb5a6ffcSRussell King /* 87cb5a6ffcSRussell King * Wait for the transmission of both slots to complete. 88cb5a6ffcSRussell King */ 89cb5a6ffcSRussell King do { 90cb5a6ffcSRussell King v = readl(aaci->base + AACI_SLFR); 91cb5a6ffcSRussell King } while (v & (SLFR_1TXB|SLFR_2TXB)); 92cb5a6ffcSRussell King 93cb5a6ffcSRussell King up(&aaci->ac97_sem); 94cb5a6ffcSRussell King } 95cb5a6ffcSRussell King 96cb5a6ffcSRussell King /* 97cb5a6ffcSRussell King * Read an AC'97 register. 98cb5a6ffcSRussell King */ 99cb5a6ffcSRussell King static unsigned short aaci_ac97_read(ac97_t *ac97, unsigned short reg) 100cb5a6ffcSRussell King { 101cb5a6ffcSRussell King struct aaci *aaci = ac97->private_data; 102cb5a6ffcSRussell King u32 v; 103cb5a6ffcSRussell King 104cb5a6ffcSRussell King if (ac97->num >= 4) 105cb5a6ffcSRussell King return ~0; 106cb5a6ffcSRussell King 107cb5a6ffcSRussell King down(&aaci->ac97_sem); 108cb5a6ffcSRussell King 109cb5a6ffcSRussell King aaci_ac97_select_codec(aaci, ac97); 110cb5a6ffcSRussell King 111cb5a6ffcSRussell King /* 112cb5a6ffcSRussell King * Write the register address to slot 1. 113cb5a6ffcSRussell King */ 114cb5a6ffcSRussell King writel((reg << 12) | (1 << 19), aaci->base + AACI_SL1TX); 115cb5a6ffcSRussell King 116cb5a6ffcSRussell King /* 117cb5a6ffcSRussell King * Wait for the transmission to complete. 118cb5a6ffcSRussell King */ 119cb5a6ffcSRussell King do { 120cb5a6ffcSRussell King v = readl(aaci->base + AACI_SLFR); 121cb5a6ffcSRussell King } while (v & SLFR_1TXB); 122cb5a6ffcSRussell King 123cb5a6ffcSRussell King /* 124cb5a6ffcSRussell King * Give the AC'97 codec more than enough time 125cb5a6ffcSRussell King * to respond. (42us = ~2 frames at 48kHz.) 126cb5a6ffcSRussell King */ 127cb5a6ffcSRussell King udelay(42); 128cb5a6ffcSRussell King 129cb5a6ffcSRussell King /* 130cb5a6ffcSRussell King * Wait for slot 2 to indicate data. 131cb5a6ffcSRussell King */ 132cb5a6ffcSRussell King do { 133cb5a6ffcSRussell King cond_resched(); 134cb5a6ffcSRussell King v = readl(aaci->base + AACI_SLFR) & (SLFR_1RXV|SLFR_2RXV); 135cb5a6ffcSRussell King } while (v != (SLFR_1RXV|SLFR_2RXV)); 136cb5a6ffcSRussell King 137cb5a6ffcSRussell King v = readl(aaci->base + AACI_SL1RX) >> 12; 138cb5a6ffcSRussell King if (v == reg) { 139cb5a6ffcSRussell King v = readl(aaci->base + AACI_SL2RX) >> 4; 140cb5a6ffcSRussell King } else { 141cb5a6ffcSRussell King dev_err(&aaci->dev->dev, 142cb5a6ffcSRussell King "wrong ac97 register read back (%x != %x)\n", 143cb5a6ffcSRussell King v, reg); 144cb5a6ffcSRussell King v = ~0; 145cb5a6ffcSRussell King } 146cb5a6ffcSRussell King 147cb5a6ffcSRussell King up(&aaci->ac97_sem); 148cb5a6ffcSRussell King return v; 149cb5a6ffcSRussell King } 150cb5a6ffcSRussell King 151cb5a6ffcSRussell King static inline void aaci_chan_wait_ready(struct aaci_runtime *aacirun) 152cb5a6ffcSRussell King { 153cb5a6ffcSRussell King u32 val; 154cb5a6ffcSRussell King int timeout = 5000; 155cb5a6ffcSRussell King 156cb5a6ffcSRussell King do { 157cb5a6ffcSRussell King val = readl(aacirun->base + AACI_SR); 158cb5a6ffcSRussell King } while (val & (SR_TXB|SR_RXB) && timeout--); 159cb5a6ffcSRussell King } 160cb5a6ffcSRussell King 161cb5a6ffcSRussell King 162cb5a6ffcSRussell King 163cb5a6ffcSRussell King /* 164cb5a6ffcSRussell King * Interrupt support. 165cb5a6ffcSRussell King */ 166cb5a6ffcSRussell King static void aaci_fifo_irq(struct aaci *aaci, u32 mask) 167cb5a6ffcSRussell King { 168cb5a6ffcSRussell King if (mask & ISR_URINTR) { 169cb5a6ffcSRussell King writel(ICLR_TXUEC1, aaci->base + AACI_INTCLR); 170cb5a6ffcSRussell King } 171cb5a6ffcSRussell King 172cb5a6ffcSRussell King if (mask & ISR_TXINTR) { 173cb5a6ffcSRussell King struct aaci_runtime *aacirun = &aaci->playback; 174cb5a6ffcSRussell King void *ptr; 175cb5a6ffcSRussell King 176cb5a6ffcSRussell King if (!aacirun->substream || !aacirun->start) { 177cb5a6ffcSRussell King dev_warn(&aaci->dev->dev, "TX interrupt???"); 178cb5a6ffcSRussell King writel(0, aacirun->base + AACI_IE); 179cb5a6ffcSRussell King return; 180cb5a6ffcSRussell King } 181cb5a6ffcSRussell King 182cb5a6ffcSRussell King ptr = aacirun->ptr; 183cb5a6ffcSRussell King do { 184cb5a6ffcSRussell King unsigned int len = aacirun->fifosz; 185cb5a6ffcSRussell King u32 val; 186cb5a6ffcSRussell King 187cb5a6ffcSRussell King if (aacirun->bytes <= 0) { 188cb5a6ffcSRussell King aacirun->bytes += aacirun->period; 189cb5a6ffcSRussell King aacirun->ptr = ptr; 190cb5a6ffcSRussell King spin_unlock(&aaci->lock); 191cb5a6ffcSRussell King snd_pcm_period_elapsed(aacirun->substream); 192cb5a6ffcSRussell King spin_lock(&aaci->lock); 193cb5a6ffcSRussell King } 194cb5a6ffcSRussell King if (!(aacirun->cr & TXCR_TXEN)) 195cb5a6ffcSRussell King break; 196cb5a6ffcSRussell King 197cb5a6ffcSRussell King val = readl(aacirun->base + AACI_SR); 198cb5a6ffcSRussell King if (!(val & SR_TXHE)) 199cb5a6ffcSRussell King break; 200cb5a6ffcSRussell King if (!(val & SR_TXFE)) 201cb5a6ffcSRussell King len >>= 1; 202cb5a6ffcSRussell King 203cb5a6ffcSRussell King aacirun->bytes -= len; 204cb5a6ffcSRussell King 205cb5a6ffcSRussell King /* writing 16 bytes at a time */ 206cb5a6ffcSRussell King for ( ; len > 0; len -= 16) { 207cb5a6ffcSRussell King asm( 208cb5a6ffcSRussell King "ldmia %0!, {r0, r1, r2, r3}\n\t" 209cb5a6ffcSRussell King "stmia %1, {r0, r1, r2, r3}" 210cb5a6ffcSRussell King : "+r" (ptr) 211cb5a6ffcSRussell King : "r" (aacirun->fifo) 212cb5a6ffcSRussell King : "r0", "r1", "r2", "r3", "cc"); 213cb5a6ffcSRussell King 214cb5a6ffcSRussell King if (ptr >= aacirun->end) 215cb5a6ffcSRussell King ptr = aacirun->start; 216cb5a6ffcSRussell King } 217cb5a6ffcSRussell King } while (1); 218cb5a6ffcSRussell King 219cb5a6ffcSRussell King aacirun->ptr = ptr; 220cb5a6ffcSRussell King } 221cb5a6ffcSRussell King } 222cb5a6ffcSRussell King 223cb5a6ffcSRussell King static irqreturn_t aaci_irq(int irq, void *devid, struct pt_regs *regs) 224cb5a6ffcSRussell King { 225cb5a6ffcSRussell King struct aaci *aaci = devid; 226cb5a6ffcSRussell King u32 mask; 227cb5a6ffcSRussell King int i; 228cb5a6ffcSRussell King 229cb5a6ffcSRussell King spin_lock(&aaci->lock); 230cb5a6ffcSRussell King mask = readl(aaci->base + AACI_ALLINTS); 231cb5a6ffcSRussell King if (mask) { 232cb5a6ffcSRussell King u32 m = mask; 233cb5a6ffcSRussell King for (i = 0; i < 4; i++, m >>= 7) { 234cb5a6ffcSRussell King if (m & 0x7f) { 235cb5a6ffcSRussell King aaci_fifo_irq(aaci, m); 236cb5a6ffcSRussell King } 237cb5a6ffcSRussell King } 238cb5a6ffcSRussell King } 239cb5a6ffcSRussell King spin_unlock(&aaci->lock); 240cb5a6ffcSRussell King 241cb5a6ffcSRussell King return mask ? IRQ_HANDLED : IRQ_NONE; 242cb5a6ffcSRussell King } 243cb5a6ffcSRussell King 244cb5a6ffcSRussell King 245cb5a6ffcSRussell King 246cb5a6ffcSRussell King /* 247cb5a6ffcSRussell King * ALSA support. 248cb5a6ffcSRussell King */ 249cb5a6ffcSRussell King 250cb5a6ffcSRussell King struct aaci_stream { 251cb5a6ffcSRussell King unsigned char codec_idx; 252cb5a6ffcSRussell King unsigned char rate_idx; 253cb5a6ffcSRussell King }; 254cb5a6ffcSRussell King 255cb5a6ffcSRussell King static struct aaci_stream aaci_streams[] = { 256cb5a6ffcSRussell King [ACSTREAM_FRONT] = { 257cb5a6ffcSRussell King .codec_idx = 0, 258cb5a6ffcSRussell King .rate_idx = AC97_RATES_FRONT_DAC, 259cb5a6ffcSRussell King }, 260cb5a6ffcSRussell King [ACSTREAM_SURROUND] = { 261cb5a6ffcSRussell King .codec_idx = 0, 262cb5a6ffcSRussell King .rate_idx = AC97_RATES_SURR_DAC, 263cb5a6ffcSRussell King }, 264cb5a6ffcSRussell King [ACSTREAM_LFE] = { 265cb5a6ffcSRussell King .codec_idx = 0, 266cb5a6ffcSRussell King .rate_idx = AC97_RATES_LFE_DAC, 267cb5a6ffcSRussell King }, 268cb5a6ffcSRussell King }; 269cb5a6ffcSRussell King 270cb5a6ffcSRussell King static inline unsigned int aaci_rate_mask(struct aaci *aaci, int streamid) 271cb5a6ffcSRussell King { 272cb5a6ffcSRussell King struct aaci_stream *s = aaci_streams + streamid; 273cb5a6ffcSRussell King return aaci->ac97_bus->codec[s->codec_idx]->rates[s->rate_idx]; 274cb5a6ffcSRussell King } 275cb5a6ffcSRussell King 276cb5a6ffcSRussell King static unsigned int rate_list[] = { 277cb5a6ffcSRussell King 5512, 8000, 11025, 16000, 22050, 32000, 44100, 278cb5a6ffcSRussell King 48000, 64000, 88200, 96000, 176400, 192000 279cb5a6ffcSRussell King }; 280cb5a6ffcSRussell King 281cb5a6ffcSRussell King /* 282cb5a6ffcSRussell King * Double-rate rule: we can support double rate iff channels == 2 283cb5a6ffcSRussell King * (unimplemented) 284cb5a6ffcSRussell King */ 285cb5a6ffcSRussell King static int 286cb5a6ffcSRussell King aaci_rule_rate_by_channels(snd_pcm_hw_params_t *p, snd_pcm_hw_rule_t *rule) 287cb5a6ffcSRussell King { 288cb5a6ffcSRussell King struct aaci *aaci = rule->private; 289cb5a6ffcSRussell King unsigned int rate_mask = SNDRV_PCM_RATE_8000_48000|SNDRV_PCM_RATE_5512; 290cb5a6ffcSRussell King snd_interval_t *c = hw_param_interval(p, SNDRV_PCM_HW_PARAM_CHANNELS); 291cb5a6ffcSRussell King 292cb5a6ffcSRussell King switch (c->max) { 293cb5a6ffcSRussell King case 6: 294cb5a6ffcSRussell King rate_mask &= aaci_rate_mask(aaci, ACSTREAM_LFE); 295cb5a6ffcSRussell King case 4: 296cb5a6ffcSRussell King rate_mask &= aaci_rate_mask(aaci, ACSTREAM_SURROUND); 297cb5a6ffcSRussell King case 2: 298cb5a6ffcSRussell King rate_mask &= aaci_rate_mask(aaci, ACSTREAM_FRONT); 299cb5a6ffcSRussell King } 300cb5a6ffcSRussell King 301cb5a6ffcSRussell King return snd_interval_list(hw_param_interval(p, rule->var), 302cb5a6ffcSRussell King ARRAY_SIZE(rate_list), rate_list, 303cb5a6ffcSRussell King rate_mask); 304cb5a6ffcSRussell King } 305cb5a6ffcSRussell King 306cb5a6ffcSRussell King static snd_pcm_hardware_t aaci_hw_info = { 307cb5a6ffcSRussell King .info = SNDRV_PCM_INFO_MMAP | 308cb5a6ffcSRussell King SNDRV_PCM_INFO_MMAP_VALID | 309cb5a6ffcSRussell King SNDRV_PCM_INFO_INTERLEAVED | 310cb5a6ffcSRussell King SNDRV_PCM_INFO_BLOCK_TRANSFER | 311cb5a6ffcSRussell King SNDRV_PCM_INFO_RESUME, 312cb5a6ffcSRussell King 313cb5a6ffcSRussell King /* 314cb5a6ffcSRussell King * ALSA doesn't support 18-bit or 20-bit packed into 32-bit 315cb5a6ffcSRussell King * words. It also doesn't support 12-bit at all. 316cb5a6ffcSRussell King */ 317cb5a6ffcSRussell King .formats = SNDRV_PCM_FMTBIT_S16_LE, 318cb5a6ffcSRussell King 319cb5a6ffcSRussell King /* should this be continuous or knot? */ 320cb5a6ffcSRussell King .rates = SNDRV_PCM_RATE_CONTINUOUS, 321cb5a6ffcSRussell King .rate_max = 48000, 322cb5a6ffcSRussell King .rate_min = 4000, 323cb5a6ffcSRussell King .channels_min = 2, 324cb5a6ffcSRussell King .channels_max = 6, 325cb5a6ffcSRussell King .buffer_bytes_max = 64 * 1024, 326cb5a6ffcSRussell King .period_bytes_min = 256, 327cb5a6ffcSRussell King .period_bytes_max = PAGE_SIZE, 328cb5a6ffcSRussell King .periods_min = 4, 329cb5a6ffcSRussell King .periods_max = PAGE_SIZE / 16, 330cb5a6ffcSRussell King }; 331cb5a6ffcSRussell King 332cb5a6ffcSRussell King static int aaci_pcm_open(struct aaci *aaci, snd_pcm_substream_t *substream, 333cb5a6ffcSRussell King struct aaci_runtime *aacirun) 334cb5a6ffcSRussell King { 335cb5a6ffcSRussell King snd_pcm_runtime_t *runtime = substream->runtime; 336cb5a6ffcSRussell King int ret; 337cb5a6ffcSRussell King 338cb5a6ffcSRussell King aacirun->substream = substream; 339cb5a6ffcSRussell King runtime->private_data = aacirun; 340cb5a6ffcSRussell King runtime->hw = aaci_hw_info; 341cb5a6ffcSRussell King 342cb5a6ffcSRussell King /* 343cb5a6ffcSRussell King * FIXME: ALSA specifies fifo_size in bytes. If we're in normal 344cb5a6ffcSRussell King * mode, each 32-bit word contains one sample. If we're in 345cb5a6ffcSRussell King * compact mode, each 32-bit word contains two samples, effectively 346cb5a6ffcSRussell King * halving the FIFO size. However, we don't know for sure which 347cb5a6ffcSRussell King * we'll be using at this point. We set this to the lower limit. 348cb5a6ffcSRussell King */ 349cb5a6ffcSRussell King runtime->hw.fifo_size = aaci->fifosize * 2; 350cb5a6ffcSRussell King 351cb5a6ffcSRussell King /* 352cb5a6ffcSRussell King * Add rule describing hardware rate dependency 353cb5a6ffcSRussell King * on the number of channels. 354cb5a6ffcSRussell King */ 355cb5a6ffcSRussell King ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, 356cb5a6ffcSRussell King aaci_rule_rate_by_channels, aaci, 357cb5a6ffcSRussell King SNDRV_PCM_HW_PARAM_CHANNELS, 358cb5a6ffcSRussell King SNDRV_PCM_HW_PARAM_RATE, -1); 359cb5a6ffcSRussell King if (ret) 360cb5a6ffcSRussell King goto out; 361cb5a6ffcSRussell King 362cb5a6ffcSRussell King ret = request_irq(aaci->dev->irq[0], aaci_irq, SA_SHIRQ|SA_INTERRUPT, 363cb5a6ffcSRussell King DRIVER_NAME, aaci); 364cb5a6ffcSRussell King if (ret) 365cb5a6ffcSRussell King goto out; 366cb5a6ffcSRussell King 367cb5a6ffcSRussell King return 0; 368cb5a6ffcSRussell King 369cb5a6ffcSRussell King out: 370cb5a6ffcSRussell King return ret; 371cb5a6ffcSRussell King } 372cb5a6ffcSRussell King 373cb5a6ffcSRussell King 374cb5a6ffcSRussell King /* 375cb5a6ffcSRussell King * Common ALSA stuff 376cb5a6ffcSRussell King */ 377cb5a6ffcSRussell King static int aaci_pcm_close(snd_pcm_substream_t *substream) 378cb5a6ffcSRussell King { 379cb5a6ffcSRussell King struct aaci *aaci = substream->private_data; 380cb5a6ffcSRussell King struct aaci_runtime *aacirun = substream->runtime->private_data; 381cb5a6ffcSRussell King 382cb5a6ffcSRussell King WARN_ON(aacirun->cr & TXCR_TXEN); 383cb5a6ffcSRussell King 384cb5a6ffcSRussell King aacirun->substream = NULL; 385cb5a6ffcSRussell King free_irq(aaci->dev->irq[0], aaci); 386cb5a6ffcSRussell King 387cb5a6ffcSRussell King return 0; 388cb5a6ffcSRussell King } 389cb5a6ffcSRussell King 390cb5a6ffcSRussell King static int aaci_pcm_hw_free(snd_pcm_substream_t *substream) 391cb5a6ffcSRussell King { 392cb5a6ffcSRussell King struct aaci_runtime *aacirun = substream->runtime->private_data; 393cb5a6ffcSRussell King 394cb5a6ffcSRussell King /* 395cb5a6ffcSRussell King * This must not be called with the device enabled. 396cb5a6ffcSRussell King */ 397cb5a6ffcSRussell King WARN_ON(aacirun->cr & TXCR_TXEN); 398cb5a6ffcSRussell King 399cb5a6ffcSRussell King if (aacirun->pcm_open) 400cb5a6ffcSRussell King snd_ac97_pcm_close(aacirun->pcm); 401cb5a6ffcSRussell King aacirun->pcm_open = 0; 402cb5a6ffcSRussell King 403cb5a6ffcSRussell King /* 404cb5a6ffcSRussell King * Clear out the DMA and any allocated buffers. 405cb5a6ffcSRussell King */ 406cb5a6ffcSRussell King devdma_hw_free(NULL, substream); 407cb5a6ffcSRussell King 408cb5a6ffcSRussell King return 0; 409cb5a6ffcSRussell King } 410cb5a6ffcSRussell King 411cb5a6ffcSRussell King static int aaci_pcm_hw_params(snd_pcm_substream_t *substream, 412cb5a6ffcSRussell King struct aaci_runtime *aacirun, 413cb5a6ffcSRussell King snd_pcm_hw_params_t *params) 414cb5a6ffcSRussell King { 415cb5a6ffcSRussell King int err; 416cb5a6ffcSRussell King 417cb5a6ffcSRussell King aaci_pcm_hw_free(substream); 418cb5a6ffcSRussell King 419cb5a6ffcSRussell King err = devdma_hw_alloc(NULL, substream, 420cb5a6ffcSRussell King params_buffer_bytes(params)); 421cb5a6ffcSRussell King if (err < 0) 422cb5a6ffcSRussell King goto out; 423cb5a6ffcSRussell King 424cb5a6ffcSRussell King err = snd_ac97_pcm_open(aacirun->pcm, params_rate(params), 425cb5a6ffcSRussell King params_channels(params), 426cb5a6ffcSRussell King aacirun->pcm->r[0].slots); 427cb5a6ffcSRussell King if (err) 428cb5a6ffcSRussell King goto out; 429cb5a6ffcSRussell King 430cb5a6ffcSRussell King aacirun->pcm_open = 1; 431cb5a6ffcSRussell King 432cb5a6ffcSRussell King out: 433cb5a6ffcSRussell King return err; 434cb5a6ffcSRussell King } 435cb5a6ffcSRussell King 436cb5a6ffcSRussell King static int aaci_pcm_prepare(snd_pcm_substream_t *substream) 437cb5a6ffcSRussell King { 438cb5a6ffcSRussell King snd_pcm_runtime_t *runtime = substream->runtime; 439cb5a6ffcSRussell King struct aaci_runtime *aacirun = runtime->private_data; 440cb5a6ffcSRussell King 441cb5a6ffcSRussell King aacirun->start = (void *)runtime->dma_area; 442cb5a6ffcSRussell King aacirun->end = aacirun->start + runtime->dma_bytes; 443cb5a6ffcSRussell King aacirun->ptr = aacirun->start; 444cb5a6ffcSRussell King aacirun->period = 445cb5a6ffcSRussell King aacirun->bytes = frames_to_bytes(runtime, runtime->period_size); 446cb5a6ffcSRussell King 447cb5a6ffcSRussell King return 0; 448cb5a6ffcSRussell King } 449cb5a6ffcSRussell King 450cb5a6ffcSRussell King static snd_pcm_uframes_t aaci_pcm_pointer(snd_pcm_substream_t *substream) 451cb5a6ffcSRussell King { 452cb5a6ffcSRussell King snd_pcm_runtime_t *runtime = substream->runtime; 453cb5a6ffcSRussell King struct aaci_runtime *aacirun = runtime->private_data; 454cb5a6ffcSRussell King ssize_t bytes = aacirun->ptr - aacirun->start; 455cb5a6ffcSRussell King 456cb5a6ffcSRussell King return bytes_to_frames(runtime, bytes); 457cb5a6ffcSRussell King } 458cb5a6ffcSRussell King 459cb5a6ffcSRussell King static int aaci_pcm_mmap(snd_pcm_substream_t *substream, struct vm_area_struct *vma) 460cb5a6ffcSRussell King { 461cb5a6ffcSRussell King return devdma_mmap(NULL, substream, vma); 462cb5a6ffcSRussell King } 463cb5a6ffcSRussell King 464cb5a6ffcSRussell King 465cb5a6ffcSRussell King /* 466cb5a6ffcSRussell King * Playback specific ALSA stuff 467cb5a6ffcSRussell King */ 468cb5a6ffcSRussell King static const u32 channels_to_txmask[] = { 469cb5a6ffcSRussell King [2] = TXCR_TX3 | TXCR_TX4, 470cb5a6ffcSRussell King [4] = TXCR_TX3 | TXCR_TX4 | TXCR_TX7 | TXCR_TX8, 471cb5a6ffcSRussell King [6] = TXCR_TX3 | TXCR_TX4 | TXCR_TX7 | TXCR_TX8 | TXCR_TX6 | TXCR_TX9, 472cb5a6ffcSRussell King }; 473cb5a6ffcSRussell King 474cb5a6ffcSRussell King /* 475cb5a6ffcSRussell King * We can support two and four channel audio. Unfortunately 476cb5a6ffcSRussell King * six channel audio requires a non-standard channel ordering: 477cb5a6ffcSRussell King * 2 -> FL(3), FR(4) 478cb5a6ffcSRussell King * 4 -> FL(3), FR(4), SL(7), SR(8) 479cb5a6ffcSRussell King * 6 -> FL(3), FR(4), SL(7), SR(8), C(6), LFE(9) (required) 480cb5a6ffcSRussell King * FL(3), FR(4), C(6), SL(7), SR(8), LFE(9) (actual) 481cb5a6ffcSRussell King * This requires an ALSA configuration file to correct. 482cb5a6ffcSRussell King */ 483cb5a6ffcSRussell King static unsigned int channel_list[] = { 2, 4, 6 }; 484cb5a6ffcSRussell King 485cb5a6ffcSRussell King static int 486cb5a6ffcSRussell King aaci_rule_channels(snd_pcm_hw_params_t *p, snd_pcm_hw_rule_t *rule) 487cb5a6ffcSRussell King { 488cb5a6ffcSRussell King struct aaci *aaci = rule->private; 489cb5a6ffcSRussell King unsigned int chan_mask = 1 << 0, slots; 490cb5a6ffcSRussell King 491cb5a6ffcSRussell King /* 492cb5a6ffcSRussell King * pcms[0] is the our 5.1 PCM instance. 493cb5a6ffcSRussell King */ 494cb5a6ffcSRussell King slots = aaci->ac97_bus->pcms[0].r[0].slots; 495cb5a6ffcSRussell King if (slots & (1 << AC97_SLOT_PCM_SLEFT)) { 496cb5a6ffcSRussell King chan_mask |= 1 << 1; 497cb5a6ffcSRussell King if (slots & (1 << AC97_SLOT_LFE)) 498cb5a6ffcSRussell King chan_mask |= 1 << 2; 499cb5a6ffcSRussell King } 500cb5a6ffcSRussell King 501cb5a6ffcSRussell King return snd_interval_list(hw_param_interval(p, rule->var), 502cb5a6ffcSRussell King ARRAY_SIZE(channel_list), channel_list, 503cb5a6ffcSRussell King chan_mask); 504cb5a6ffcSRussell King } 505cb5a6ffcSRussell King 506cb5a6ffcSRussell King static int aaci_pcm_playback_open(snd_pcm_substream_t *substream) 507cb5a6ffcSRussell King { 508cb5a6ffcSRussell King struct aaci *aaci = substream->private_data; 509cb5a6ffcSRussell King int ret; 510cb5a6ffcSRussell King 511cb5a6ffcSRussell King /* 512cb5a6ffcSRussell King * Add rule describing channel dependency. 513cb5a6ffcSRussell King */ 514cb5a6ffcSRussell King ret = snd_pcm_hw_rule_add(substream->runtime, 0, 515cb5a6ffcSRussell King SNDRV_PCM_HW_PARAM_CHANNELS, 516cb5a6ffcSRussell King aaci_rule_channels, aaci, 517cb5a6ffcSRussell King SNDRV_PCM_HW_PARAM_CHANNELS, -1); 518cb5a6ffcSRussell King if (ret) 519cb5a6ffcSRussell King return ret; 520cb5a6ffcSRussell King 521cb5a6ffcSRussell King return aaci_pcm_open(aaci, substream, &aaci->playback); 522cb5a6ffcSRussell King } 523cb5a6ffcSRussell King 524cb5a6ffcSRussell King static int aaci_pcm_playback_hw_params(snd_pcm_substream_t *substream, 525cb5a6ffcSRussell King snd_pcm_hw_params_t *params) 526cb5a6ffcSRussell King { 527cb5a6ffcSRussell King struct aaci *aaci = substream->private_data; 528cb5a6ffcSRussell King struct aaci_runtime *aacirun = substream->runtime->private_data; 529cb5a6ffcSRussell King unsigned int channels = params_channels(params); 530cb5a6ffcSRussell King int ret; 531cb5a6ffcSRussell King 532cb5a6ffcSRussell King WARN_ON(channels >= ARRAY_SIZE(channels_to_txmask) || 533cb5a6ffcSRussell King !channels_to_txmask[channels]); 534cb5a6ffcSRussell King 535cb5a6ffcSRussell King ret = aaci_pcm_hw_params(substream, aacirun, params); 536cb5a6ffcSRussell King 537cb5a6ffcSRussell King /* 538cb5a6ffcSRussell King * Enable FIFO, compact mode, 16 bits per sample. 539cb5a6ffcSRussell King * FIXME: double rate slots? 540cb5a6ffcSRussell King */ 541cb5a6ffcSRussell King if (ret >= 0) { 542cb5a6ffcSRussell King aacirun->cr = TXCR_FEN | TXCR_COMPACT | TXCR_TSZ16; 543cb5a6ffcSRussell King aacirun->cr |= channels_to_txmask[channels]; 544cb5a6ffcSRussell King 545cb5a6ffcSRussell King aacirun->fifosz = aaci->fifosize * 4; 546cb5a6ffcSRussell King if (aacirun->cr & TXCR_COMPACT) 547cb5a6ffcSRussell King aacirun->fifosz >>= 1; 548cb5a6ffcSRussell King } 549cb5a6ffcSRussell King return ret; 550cb5a6ffcSRussell King } 551cb5a6ffcSRussell King 552cb5a6ffcSRussell King static void aaci_pcm_playback_stop(struct aaci_runtime *aacirun) 553cb5a6ffcSRussell King { 554cb5a6ffcSRussell King u32 ie; 555cb5a6ffcSRussell King 556cb5a6ffcSRussell King ie = readl(aacirun->base + AACI_IE); 557cb5a6ffcSRussell King ie &= ~(IE_URIE|IE_TXIE); 558cb5a6ffcSRussell King writel(ie, aacirun->base + AACI_IE); 559cb5a6ffcSRussell King aacirun->cr &= ~TXCR_TXEN; 560cb5a6ffcSRussell King aaci_chan_wait_ready(aacirun); 561cb5a6ffcSRussell King writel(aacirun->cr, aacirun->base + AACI_TXCR); 562cb5a6ffcSRussell King } 563cb5a6ffcSRussell King 564cb5a6ffcSRussell King static void aaci_pcm_playback_start(struct aaci_runtime *aacirun) 565cb5a6ffcSRussell King { 566cb5a6ffcSRussell King u32 ie; 567cb5a6ffcSRussell King 568cb5a6ffcSRussell King aaci_chan_wait_ready(aacirun); 569cb5a6ffcSRussell King aacirun->cr |= TXCR_TXEN; 570cb5a6ffcSRussell King 571cb5a6ffcSRussell King ie = readl(aacirun->base + AACI_IE); 572cb5a6ffcSRussell King ie |= IE_URIE | IE_TXIE; 573cb5a6ffcSRussell King writel(ie, aacirun->base + AACI_IE); 574cb5a6ffcSRussell King writel(aacirun->cr, aacirun->base + AACI_TXCR); 575cb5a6ffcSRussell King } 576cb5a6ffcSRussell King 577cb5a6ffcSRussell King static int aaci_pcm_playback_trigger(snd_pcm_substream_t *substream, int cmd) 578cb5a6ffcSRussell King { 579cb5a6ffcSRussell King struct aaci *aaci = substream->private_data; 580cb5a6ffcSRussell King struct aaci_runtime *aacirun = substream->runtime->private_data; 581cb5a6ffcSRussell King unsigned long flags; 582cb5a6ffcSRussell King int ret = 0; 583cb5a6ffcSRussell King 584cb5a6ffcSRussell King spin_lock_irqsave(&aaci->lock, flags); 585cb5a6ffcSRussell King switch (cmd) { 586cb5a6ffcSRussell King case SNDRV_PCM_TRIGGER_START: 587cb5a6ffcSRussell King aaci_pcm_playback_start(aacirun); 588cb5a6ffcSRussell King break; 589cb5a6ffcSRussell King 590cb5a6ffcSRussell King case SNDRV_PCM_TRIGGER_RESUME: 591cb5a6ffcSRussell King aaci_pcm_playback_start(aacirun); 592cb5a6ffcSRussell King break; 593cb5a6ffcSRussell King 594cb5a6ffcSRussell King case SNDRV_PCM_TRIGGER_STOP: 595cb5a6ffcSRussell King aaci_pcm_playback_stop(aacirun); 596cb5a6ffcSRussell King break; 597cb5a6ffcSRussell King 598cb5a6ffcSRussell King case SNDRV_PCM_TRIGGER_SUSPEND: 599cb5a6ffcSRussell King aaci_pcm_playback_stop(aacirun); 600cb5a6ffcSRussell King break; 601cb5a6ffcSRussell King 602cb5a6ffcSRussell King case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 603cb5a6ffcSRussell King break; 604cb5a6ffcSRussell King 605cb5a6ffcSRussell King case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 606cb5a6ffcSRussell King break; 607cb5a6ffcSRussell King 608cb5a6ffcSRussell King default: 609cb5a6ffcSRussell King ret = -EINVAL; 610cb5a6ffcSRussell King } 611cb5a6ffcSRussell King spin_unlock_irqrestore(&aaci->lock, flags); 612cb5a6ffcSRussell King 613cb5a6ffcSRussell King return ret; 614cb5a6ffcSRussell King } 615cb5a6ffcSRussell King 616cb5a6ffcSRussell King static snd_pcm_ops_t aaci_playback_ops = { 617cb5a6ffcSRussell King .open = aaci_pcm_playback_open, 618cb5a6ffcSRussell King .close = aaci_pcm_close, 619cb5a6ffcSRussell King .ioctl = snd_pcm_lib_ioctl, 620cb5a6ffcSRussell King .hw_params = aaci_pcm_playback_hw_params, 621cb5a6ffcSRussell King .hw_free = aaci_pcm_hw_free, 622cb5a6ffcSRussell King .prepare = aaci_pcm_prepare, 623cb5a6ffcSRussell King .trigger = aaci_pcm_playback_trigger, 624cb5a6ffcSRussell King .pointer = aaci_pcm_pointer, 625cb5a6ffcSRussell King .mmap = aaci_pcm_mmap, 626cb5a6ffcSRussell King }; 627cb5a6ffcSRussell King 628cb5a6ffcSRussell King 629cb5a6ffcSRussell King 630cb5a6ffcSRussell King /* 631cb5a6ffcSRussell King * Power Management. 632cb5a6ffcSRussell King */ 633cb5a6ffcSRussell King #ifdef CONFIG_PM 634cb5a6ffcSRussell King static int aaci_do_suspend(snd_card_t *card, unsigned int state) 635cb5a6ffcSRussell King { 636cb5a6ffcSRussell King struct aaci *aaci = card->private_data; 637cb5a6ffcSRussell King if (aaci->card->power_state != SNDRV_CTL_POWER_D3cold) { 638cb5a6ffcSRussell King snd_pcm_suspend_all(aaci->pcm); 639cb5a6ffcSRussell King snd_power_change_state(aaci->card, SNDRV_CTL_POWER_D3cold); 640cb5a6ffcSRussell King } 641cb5a6ffcSRussell King return 0; 642cb5a6ffcSRussell King } 643cb5a6ffcSRussell King 644cb5a6ffcSRussell King static int aaci_do_resume(snd_card_t *card, unsigned int state) 645cb5a6ffcSRussell King { 646cb5a6ffcSRussell King struct aaci *aaci = card->private_data; 647cb5a6ffcSRussell King if (aaci->card->power_state != SNDRV_CTL_POWER_D0) { 648cb5a6ffcSRussell King snd_power_change_state(aaci->card, SNDRV_CTL_POWER_D0); 649cb5a6ffcSRussell King } 650cb5a6ffcSRussell King return 0; 651cb5a6ffcSRussell King } 652cb5a6ffcSRussell King 653cb5a6ffcSRussell King static int aaci_suspend(struct amba_device *dev, u32 state) 654cb5a6ffcSRussell King { 655cb5a6ffcSRussell King snd_card_t *card = amba_get_drvdata(dev); 656cb5a6ffcSRussell King return card ? aaci_do_suspend(card) : 0; 657cb5a6ffcSRussell King } 658cb5a6ffcSRussell King 659cb5a6ffcSRussell King static int aaci_resume(struct amba_device *dev) 660cb5a6ffcSRussell King { 661cb5a6ffcSRussell King snd_card_t *card = amba_get_drvdata(dev); 662cb5a6ffcSRussell King return card ? aaci_do_resume(card) : 0; 663cb5a6ffcSRussell King } 664cb5a6ffcSRussell King #else 665cb5a6ffcSRussell King #define aaci_do_suspend NULL 666cb5a6ffcSRussell King #define aaci_do_resume NULL 667cb5a6ffcSRussell King #define aaci_suspend NULL 668cb5a6ffcSRussell King #define aaci_resume NULL 669cb5a6ffcSRussell King #endif 670cb5a6ffcSRussell King 671cb5a6ffcSRussell King 672cb5a6ffcSRussell King static struct ac97_pcm ac97_defs[] __devinitdata = { 673cb5a6ffcSRussell King [0] = { /* Front PCM */ 674cb5a6ffcSRussell King .exclusive = 1, 675cb5a6ffcSRussell King .r = { 676cb5a6ffcSRussell King [0] = { 677cb5a6ffcSRussell King .slots = (1 << AC97_SLOT_PCM_LEFT) | 678cb5a6ffcSRussell King (1 << AC97_SLOT_PCM_RIGHT) | 679cb5a6ffcSRussell King (1 << AC97_SLOT_PCM_CENTER) | 680cb5a6ffcSRussell King (1 << AC97_SLOT_PCM_SLEFT) | 681cb5a6ffcSRussell King (1 << AC97_SLOT_PCM_SRIGHT) | 682cb5a6ffcSRussell King (1 << AC97_SLOT_LFE), 683cb5a6ffcSRussell King }, 684cb5a6ffcSRussell King }, 685cb5a6ffcSRussell King }, 686cb5a6ffcSRussell King [1] = { /* PCM in */ 687cb5a6ffcSRussell King .stream = 1, 688cb5a6ffcSRussell King .exclusive = 1, 689cb5a6ffcSRussell King .r = { 690cb5a6ffcSRussell King [0] = { 691cb5a6ffcSRussell King .slots = (1 << AC97_SLOT_PCM_LEFT) | 692cb5a6ffcSRussell King (1 << AC97_SLOT_PCM_RIGHT), 693cb5a6ffcSRussell King }, 694cb5a6ffcSRussell King }, 695cb5a6ffcSRussell King }, 696cb5a6ffcSRussell King [2] = { /* Mic in */ 697cb5a6ffcSRussell King .stream = 1, 698cb5a6ffcSRussell King .exclusive = 1, 699cb5a6ffcSRussell King .r = { 700cb5a6ffcSRussell King [0] = { 701cb5a6ffcSRussell King .slots = (1 << AC97_SLOT_MIC), 702cb5a6ffcSRussell King }, 703cb5a6ffcSRussell King }, 704cb5a6ffcSRussell King } 705cb5a6ffcSRussell King }; 706cb5a6ffcSRussell King 707cb5a6ffcSRussell King static ac97_bus_ops_t aaci_bus_ops = { 708cb5a6ffcSRussell King .write = aaci_ac97_write, 709cb5a6ffcSRussell King .read = aaci_ac97_read, 710cb5a6ffcSRussell King }; 711cb5a6ffcSRussell King 712cb5a6ffcSRussell King static int __devinit aaci_probe_ac97(struct aaci *aaci) 713cb5a6ffcSRussell King { 714cb5a6ffcSRussell King ac97_template_t ac97_template; 715cb5a6ffcSRussell King ac97_bus_t *ac97_bus; 716cb5a6ffcSRussell King ac97_t *ac97; 717cb5a6ffcSRussell King int ret; 718cb5a6ffcSRussell King 719cb5a6ffcSRussell King /* 720cb5a6ffcSRussell King * Assert AACIRESET for 2us 721cb5a6ffcSRussell King */ 722cb5a6ffcSRussell King writel(0, aaci->base + AACI_RESET); 723cb5a6ffcSRussell King udelay(2); 724cb5a6ffcSRussell King writel(RESET_NRST, aaci->base + AACI_RESET); 725cb5a6ffcSRussell King 726cb5a6ffcSRussell King /* 727cb5a6ffcSRussell King * Give the AC'97 codec more than enough time 728cb5a6ffcSRussell King * to wake up. (42us = ~2 frames at 48kHz.) 729cb5a6ffcSRussell King */ 730cb5a6ffcSRussell King udelay(42); 731cb5a6ffcSRussell King 732cb5a6ffcSRussell King ret = snd_ac97_bus(aaci->card, 0, &aaci_bus_ops, aaci, &ac97_bus); 733cb5a6ffcSRussell King if (ret) 734cb5a6ffcSRussell King goto out; 735cb5a6ffcSRussell King 736cb5a6ffcSRussell King ac97_bus->clock = 48000; 737cb5a6ffcSRussell King aaci->ac97_bus = ac97_bus; 738cb5a6ffcSRussell King 739cb5a6ffcSRussell King memset(&ac97_template, 0, sizeof(ac97_template_t)); 740cb5a6ffcSRussell King ac97_template.private_data = aaci; 741cb5a6ffcSRussell King ac97_template.num = 0; 742cb5a6ffcSRussell King ac97_template.scaps = AC97_SCAP_SKIP_MODEM; 743cb5a6ffcSRussell King 744cb5a6ffcSRussell King ret = snd_ac97_mixer(ac97_bus, &ac97_template, &ac97); 745cb5a6ffcSRussell King if (ret) 746cb5a6ffcSRussell King goto out; 747cb5a6ffcSRussell King 748cb5a6ffcSRussell King /* 749cb5a6ffcSRussell King * Disable AC97 PC Beep input on audio codecs. 750cb5a6ffcSRussell King */ 751cb5a6ffcSRussell King if (ac97_is_audio(ac97)) 752cb5a6ffcSRussell King snd_ac97_write_cache(ac97, AC97_PC_BEEP, 0x801e); 753cb5a6ffcSRussell King 754cb5a6ffcSRussell King ret = snd_ac97_pcm_assign(ac97_bus, ARRAY_SIZE(ac97_defs), ac97_defs); 755cb5a6ffcSRussell King if (ret) 756cb5a6ffcSRussell King goto out; 757cb5a6ffcSRussell King 758cb5a6ffcSRussell King aaci->playback.pcm = &ac97_bus->pcms[0]; 759cb5a6ffcSRussell King 760cb5a6ffcSRussell King out: 761cb5a6ffcSRussell King return ret; 762cb5a6ffcSRussell King } 763cb5a6ffcSRussell King 764cb5a6ffcSRussell King static void aaci_free_card(snd_card_t *card) 765cb5a6ffcSRussell King { 766cb5a6ffcSRussell King struct aaci *aaci = card->private_data; 767cb5a6ffcSRussell King if (aaci->base) 768cb5a6ffcSRussell King iounmap(aaci->base); 769cb5a6ffcSRussell King } 770cb5a6ffcSRussell King 771cb5a6ffcSRussell King static struct aaci * __devinit aaci_init_card(struct amba_device *dev) 772cb5a6ffcSRussell King { 773cb5a6ffcSRussell King struct aaci *aaci; 774cb5a6ffcSRussell King snd_card_t *card; 775cb5a6ffcSRussell King 776cb5a6ffcSRussell King card = snd_card_new(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, 777cb5a6ffcSRussell King THIS_MODULE, sizeof(struct aaci)); 778cb5a6ffcSRussell King if (card == NULL) 779cb5a6ffcSRussell King return ERR_PTR(-ENOMEM); 780cb5a6ffcSRussell King 781cb5a6ffcSRussell King card->private_free = aaci_free_card; 782cb5a6ffcSRussell King snd_card_set_pm_callback(card, aaci_do_suspend, aaci_do_resume, NULL); 783cb5a6ffcSRussell King 784cb5a6ffcSRussell King strlcpy(card->driver, DRIVER_NAME, sizeof(card->driver)); 785cb5a6ffcSRussell King strlcpy(card->shortname, "ARM AC'97 Interface", sizeof(card->shortname)); 786cb5a6ffcSRussell King snprintf(card->longname, sizeof(card->longname), 787cb5a6ffcSRussell King "%s at 0x%08lx, irq %d", 788cb5a6ffcSRussell King card->shortname, dev->res.start, dev->irq[0]); 789cb5a6ffcSRussell King 790cb5a6ffcSRussell King aaci = card->private_data; 791cb5a6ffcSRussell King init_MUTEX(&aaci->ac97_sem); 792cb5a6ffcSRussell King spin_lock_init(&aaci->lock); 793cb5a6ffcSRussell King aaci->card = card; 794cb5a6ffcSRussell King aaci->dev = dev; 795cb5a6ffcSRussell King 796cb5a6ffcSRussell King /* Set MAINCR to allow slot 1 and 2 data IO */ 797cb5a6ffcSRussell King aaci->maincr = MAINCR_IE | MAINCR_SL1RXEN | MAINCR_SL1TXEN | 798cb5a6ffcSRussell King MAINCR_SL2RXEN | MAINCR_SL2TXEN; 799cb5a6ffcSRussell King 800cb5a6ffcSRussell King return aaci; 801cb5a6ffcSRussell King } 802cb5a6ffcSRussell King 803cb5a6ffcSRussell King static int __devinit aaci_init_pcm(struct aaci *aaci) 804cb5a6ffcSRussell King { 805cb5a6ffcSRussell King snd_pcm_t *pcm; 806cb5a6ffcSRussell King int ret; 807cb5a6ffcSRussell King 808cb5a6ffcSRussell King ret = snd_pcm_new(aaci->card, "AACI AC'97", 0, 1, 0, &pcm); 809cb5a6ffcSRussell King if (ret == 0) { 810cb5a6ffcSRussell King aaci->pcm = pcm; 811cb5a6ffcSRussell King pcm->private_data = aaci; 812cb5a6ffcSRussell King pcm->info_flags = 0; 813cb5a6ffcSRussell King 814cb5a6ffcSRussell King strlcpy(pcm->name, DRIVER_NAME, sizeof(pcm->name)); 815cb5a6ffcSRussell King 816cb5a6ffcSRussell King snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &aaci_playback_ops); 817cb5a6ffcSRussell King } 818cb5a6ffcSRussell King 819cb5a6ffcSRussell King return ret; 820cb5a6ffcSRussell King } 821cb5a6ffcSRussell King 822cb5a6ffcSRussell King static unsigned int __devinit aaci_size_fifo(struct aaci *aaci) 823cb5a6ffcSRussell King { 824e12ba644Sviro@ZenIV.linux.org.uk void __iomem *base = aaci->base + AACI_CSCH1; 825cb5a6ffcSRussell King int i; 826cb5a6ffcSRussell King 827cb5a6ffcSRussell King writel(TXCR_FEN | TXCR_TSZ16 | TXCR_TXEN, base + AACI_TXCR); 828cb5a6ffcSRussell King 829cb5a6ffcSRussell King for (i = 0; !(readl(base + AACI_SR) & SR_TXFF) && i < 4096; i++) 830cb5a6ffcSRussell King writel(0, aaci->base + AACI_DR1); 831cb5a6ffcSRussell King 832cb5a6ffcSRussell King writel(0, base + AACI_TXCR); 833cb5a6ffcSRussell King 834cb5a6ffcSRussell King /* 835cb5a6ffcSRussell King * Re-initialise the AACI after the FIFO depth test, to 836cb5a6ffcSRussell King * ensure that the FIFOs are empty. Unfortunately, merely 837cb5a6ffcSRussell King * disabling the channel doesn't clear the FIFO. 838cb5a6ffcSRussell King */ 839cb5a6ffcSRussell King writel(aaci->maincr & ~MAINCR_IE, aaci->base + AACI_MAINCR); 840cb5a6ffcSRussell King writel(aaci->maincr, aaci->base + AACI_MAINCR); 841cb5a6ffcSRussell King 842cb5a6ffcSRussell King /* 843cb5a6ffcSRussell King * If we hit 4096, we failed. Go back to the specified 844cb5a6ffcSRussell King * fifo depth. 845cb5a6ffcSRussell King */ 846cb5a6ffcSRussell King if (i == 4096) 847cb5a6ffcSRussell King i = 8; 848cb5a6ffcSRussell King 849cb5a6ffcSRussell King return i; 850cb5a6ffcSRussell King } 851cb5a6ffcSRussell King 852cb5a6ffcSRussell King static int __devinit aaci_probe(struct amba_device *dev, void *id) 853cb5a6ffcSRussell King { 854cb5a6ffcSRussell King struct aaci *aaci; 855cb5a6ffcSRussell King int ret, i; 856cb5a6ffcSRussell King 857cb5a6ffcSRussell King ret = amba_request_regions(dev, NULL); 858cb5a6ffcSRussell King if (ret) 859cb5a6ffcSRussell King return ret; 860cb5a6ffcSRussell King 861cb5a6ffcSRussell King aaci = aaci_init_card(dev); 862cb5a6ffcSRussell King if (IS_ERR(aaci)) { 863cb5a6ffcSRussell King ret = PTR_ERR(aaci); 864cb5a6ffcSRussell King goto out; 865cb5a6ffcSRussell King } 866cb5a6ffcSRussell King 867cb5a6ffcSRussell King aaci->base = ioremap(dev->res.start, SZ_4K); 868cb5a6ffcSRussell King if (!aaci->base) { 869cb5a6ffcSRussell King ret = -ENOMEM; 870cb5a6ffcSRussell King goto out; 871cb5a6ffcSRussell King } 872cb5a6ffcSRussell King 873cb5a6ffcSRussell King /* 874cb5a6ffcSRussell King * Playback uses AACI channel 0 875cb5a6ffcSRussell King */ 876cb5a6ffcSRussell King aaci->playback.base = aaci->base + AACI_CSCH1; 877cb5a6ffcSRussell King aaci->playback.fifo = aaci->base + AACI_DR1; 878cb5a6ffcSRussell King 879cb5a6ffcSRussell King for (i = 0; i < 4; i++) { 880e12ba644Sviro@ZenIV.linux.org.uk void __iomem *base = aaci->base + i * 0x14; 881cb5a6ffcSRussell King 882cb5a6ffcSRussell King writel(0, base + AACI_IE); 883cb5a6ffcSRussell King writel(0, base + AACI_TXCR); 884cb5a6ffcSRussell King writel(0, base + AACI_RXCR); 885cb5a6ffcSRussell King } 886cb5a6ffcSRussell King 887cb5a6ffcSRussell King writel(0x1fff, aaci->base + AACI_INTCLR); 888cb5a6ffcSRussell King writel(aaci->maincr, aaci->base + AACI_MAINCR); 889cb5a6ffcSRussell King 890cb5a6ffcSRussell King /* 891cb5a6ffcSRussell King * Size the FIFOs. 892cb5a6ffcSRussell King */ 893cb5a6ffcSRussell King aaci->fifosize = aaci_size_fifo(aaci); 894cb5a6ffcSRussell King 895cb5a6ffcSRussell King ret = aaci_probe_ac97(aaci); 896cb5a6ffcSRussell King if (ret) 897cb5a6ffcSRussell King goto out; 898cb5a6ffcSRussell King 899cb5a6ffcSRussell King ret = aaci_init_pcm(aaci); 900cb5a6ffcSRussell King if (ret) 901cb5a6ffcSRussell King goto out; 902cb5a6ffcSRussell King 903a76af199STakashi Iwai snd_card_set_dev(aaci->card, &dev->dev); 904a76af199STakashi Iwai 905cb5a6ffcSRussell King ret = snd_card_register(aaci->card); 906cb5a6ffcSRussell King if (ret == 0) { 907cb5a6ffcSRussell King dev_info(&dev->dev, "%s, fifo %d\n", aaci->card->longname, 908cb5a6ffcSRussell King aaci->fifosize); 909cb5a6ffcSRussell King amba_set_drvdata(dev, aaci->card); 910cb5a6ffcSRussell King return ret; 911cb5a6ffcSRussell King } 912cb5a6ffcSRussell King 913cb5a6ffcSRussell King out: 914cb5a6ffcSRussell King if (aaci) 915cb5a6ffcSRussell King snd_card_free(aaci->card); 916cb5a6ffcSRussell King amba_release_regions(dev); 917cb5a6ffcSRussell King return ret; 918cb5a6ffcSRussell King } 919cb5a6ffcSRussell King 920cb5a6ffcSRussell King static int __devexit aaci_remove(struct amba_device *dev) 921cb5a6ffcSRussell King { 922cb5a6ffcSRussell King snd_card_t *card = amba_get_drvdata(dev); 923cb5a6ffcSRussell King 924cb5a6ffcSRussell King amba_set_drvdata(dev, NULL); 925cb5a6ffcSRussell King 926cb5a6ffcSRussell King if (card) { 927cb5a6ffcSRussell King struct aaci *aaci = card->private_data; 928cb5a6ffcSRussell King writel(0, aaci->base + AACI_MAINCR); 929cb5a6ffcSRussell King 930cb5a6ffcSRussell King snd_card_free(card); 931cb5a6ffcSRussell King amba_release_regions(dev); 932cb5a6ffcSRussell King } 933cb5a6ffcSRussell King 934cb5a6ffcSRussell King return 0; 935cb5a6ffcSRussell King } 936cb5a6ffcSRussell King 937cb5a6ffcSRussell King static struct amba_id aaci_ids[] = { 938cb5a6ffcSRussell King { 939cb5a6ffcSRussell King .id = 0x00041041, 940cb5a6ffcSRussell King .mask = 0x000fffff, 941cb5a6ffcSRussell King }, 942cb5a6ffcSRussell King { 0, 0 }, 943cb5a6ffcSRussell King }; 944cb5a6ffcSRussell King 945cb5a6ffcSRussell King static struct amba_driver aaci_driver = { 946cb5a6ffcSRussell King .drv = { 947cb5a6ffcSRussell King .name = DRIVER_NAME, 948cb5a6ffcSRussell King }, 949cb5a6ffcSRussell King .probe = aaci_probe, 950cb5a6ffcSRussell King .remove = __devexit_p(aaci_remove), 951cb5a6ffcSRussell King .suspend = aaci_suspend, 952cb5a6ffcSRussell King .resume = aaci_resume, 953cb5a6ffcSRussell King .id_table = aaci_ids, 954cb5a6ffcSRussell King }; 955cb5a6ffcSRussell King 956cb5a6ffcSRussell King static int __init aaci_init(void) 957cb5a6ffcSRussell King { 958cb5a6ffcSRussell King return amba_driver_register(&aaci_driver); 959cb5a6ffcSRussell King } 960cb5a6ffcSRussell King 961cb5a6ffcSRussell King static void __exit aaci_exit(void) 962cb5a6ffcSRussell King { 963cb5a6ffcSRussell King amba_driver_unregister(&aaci_driver); 964cb5a6ffcSRussell King } 965cb5a6ffcSRussell King 966cb5a6ffcSRussell King module_init(aaci_init); 967cb5a6ffcSRussell King module_exit(aaci_exit); 968cb5a6ffcSRussell King 969cb5a6ffcSRussell King MODULE_LICENSE("GPL"); 970cb5a6ffcSRussell King MODULE_DESCRIPTION("ARM PrimeCell PL041 Advanced Audio CODEC Interface driver"); 971