summaryrefslogtreecommitdiff
path: root/recipes/linux/linux-2.6.30/at91sam9263ek/hrw-linux-2.6.30-exp.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes/linux/linux-2.6.30/at91sam9263ek/hrw-linux-2.6.30-exp.patch')
-rw-r--r--recipes/linux/linux-2.6.30/at91sam9263ek/hrw-linux-2.6.30-exp.patch1816
1 files changed, 1816 insertions, 0 deletions
diff --git a/recipes/linux/linux-2.6.30/at91sam9263ek/hrw-linux-2.6.30-exp.patch b/recipes/linux/linux-2.6.30/at91sam9263ek/hrw-linux-2.6.30-exp.patch
new file mode 100644
index 0000000000..0e377b0512
--- /dev/null
+++ b/recipes/linux/linux-2.6.30/at91sam9263ek/hrw-linux-2.6.30-exp.patch
@@ -0,0 +1,1816 @@
+This is hacked version of linux-2.6.28-exp.patch from Atmel. I removed most of
+things not related to at91sam9263ek so it is not safe to use it on other
+boards (probably not so save also on this one).
+
+This adds sound support, touchscreen pressure and ability to use SRAM for
+Ethernet buffers.
+
+OE-Signed-off-by: Marcin Juszkiewicz <marcin@juszkiewicz.com.pl>
+
+---
+ arch/arm/mach-at91/include/mach/at91_pmc.h | 27
+ drivers/input/touchscreen/atmel_tsadcc.c | 16
+ drivers/mmc/host/at91_mci.c | 39 -
+ drivers/net/Kconfig | 6
+ drivers/net/macb.c | 72 ++
+ drivers/net/macb.h | 9
+ sound/arm/Kconfig | 9
+ sound/arm/Makefile | 4
+ sound/arm/at91-ac97.c | 911 +++++++++++++++++++++++++++++
+ sound/arm/at91-ac97.h | 295 +++++++++
+ 11 files changed, 1485 insertions(+), 62 deletions(-)
+
+--- linux-2.6.30.orig/arch/arm/mach-at91/include/mach/at91_pmc.h
++++ linux-2.6.30/arch/arm/mach-at91/include/mach/at91_pmc.h
+@@ -21,11 +21,11 @@
+
+ #define AT91_PMC_SCSR (AT91_PMC + 0x08) /* System Clock Status Register */
+ #define AT91_PMC_PCK (1 << 0) /* Processor Clock */
+ #define AT91RM9200_PMC_UDP (1 << 1) /* USB Devcice Port Clock [AT91RM9200 only] */
+ #define AT91RM9200_PMC_MCKUDP (1 << 2) /* USB Device Port Master Clock Automatic Disable on Suspend [AT91RM9200 only] */
+-#define AT91CAP9_PMC_DDR (1 << 2) /* DDR Clock [AT91CAP9 revC only] */
++#define AT91CAP9_PMC_DDR (1 << 2) /* DDR Clock Enable [some SAM9 only] */
+ #define AT91RM9200_PMC_UHP (1 << 4) /* USB Host Port Clock [AT91RM9200 only] */
+ #define AT91SAM926x_PMC_UHP (1 << 6) /* USB Host Port Clock [AT91SAM926x only] */
+ #define AT91CAP9_PMC_UHP (1 << 6) /* USB Host Port Clock [AT91CAP9 only] */
+ #define AT91SAM926x_PMC_UDP (1 << 7) /* USB Devcice Port Clock [AT91SAM926x only] */
+ #define AT91_PMC_PCK0 (1 << 8) /* Programmable Clock 0 */
+@@ -38,15 +38,15 @@
+
+ #define AT91_PMC_PCER (AT91_PMC + 0x10) /* Peripheral Clock Enable Register */
+ #define AT91_PMC_PCDR (AT91_PMC + 0x14) /* Peripheral Clock Disable Register */
+ #define AT91_PMC_PCSR (AT91_PMC + 0x18) /* Peripheral Clock Status Register */
+
+-#define AT91_CKGR_UCKR (AT91_PMC + 0x1C) /* UTMI Clock Register [SAM9RL, CAP9] */
++#define AT91_CKGR_UCKR (AT91_PMC + 0x1C) /* UTMI Clock Register [some SAM9, CAP9] */
+ #define AT91_PMC_UPLLEN (1 << 16) /* UTMI PLL Enable */
+ #define AT91_PMC_UPLLCOUNT (0xf << 20) /* UTMI PLL Start-up Time */
+ #define AT91_PMC_BIASEN (1 << 24) /* UTMI BIAS Enable */
+-#define AT91_PMC_BIASCOUNT (0xf << 28) /* UTMI PLL Start-up Time */
++#define AT91_PMC_BIASCOUNT (0xf << 28) /* UTMI BIAS Start-up Time */
+
+ #define AT91_CKGR_MOR (AT91_PMC + 0x20) /* Main Oscillator Register [not on SAM9RL] */
+ #define AT91_PMC_MOSCEN (1 << 0) /* Main Oscillator Enable */
+ #define AT91_PMC_OSCBYPASS (1 << 1) /* Oscillator Bypass [SAM9x, CAP9] */
+ #define AT91_PMC_OSCOUNT (0xff << 8) /* Main Oscillator Start-up Time */
+@@ -71,10 +71,11 @@
+ #define AT91_PMC_CSS (3 << 0) /* Master Clock Selection */
+ #define AT91_PMC_CSS_SLOW (0 << 0)
+ #define AT91_PMC_CSS_MAIN (1 << 0)
+ #define AT91_PMC_CSS_PLLA (2 << 0)
+ #define AT91_PMC_CSS_PLLB (3 << 0)
++#define AT91_PMC_CSS_UPLL (3 << 0) /* [some SAM9 only] */
+ #define AT91_PMC_PRES (7 << 2) /* Master Clock Prescaler */
+ #define AT91_PMC_PRES_1 (0 << 2)
+ #define AT91_PMC_PRES_2 (1 << 2)
+ #define AT91_PMC_PRES_4 (2 << 2)
+ #define AT91_PMC_PRES_8 (3 << 2)
+@@ -87,25 +88,39 @@
+ #define AT91RM9200_PMC_MDIV_3 (2 << 8)
+ #define AT91RM9200_PMC_MDIV_4 (3 << 8)
+ #define AT91SAM9_PMC_MDIV_1 (0 << 8) /* [SAM9,CAP9 only] */
+ #define AT91SAM9_PMC_MDIV_2 (1 << 8)
+ #define AT91SAM9_PMC_MDIV_4 (2 << 8)
+-#define AT91SAM9_PMC_MDIV_6 (3 << 8)
++#define AT91SAM9_PMC_MDIV_6 (3 << 8) /* [some SAM9 only] */
++#define AT91SAM9_PMC_MDIV_3 (3 << 8) /* [some SAM9 only] */
+ #define AT91_PMC_PDIV (1 << 12) /* Processor Clock Division [some SAM9 only] */
+ #define AT91_PMC_PDIV_1 (0 << 12)
+ #define AT91_PMC_PDIV_2 (1 << 12)
+
+-#define AT91_PMC_PCKR(n) (AT91_PMC + 0x40 + ((n) * 4)) /* Programmable Clock 0-4 Registers */
++#define AT91_PMC_PLLADIV2 (1 << 12) /* PLLA divisor by 2 [some SAM9 only] */
++#define AT91_PMC_PLLADIV2_OFF (0 << 12)
++#define AT91_PMC_PLLADIV2_ON (1 << 12)
++
++#define AT91_PMC_USB (AT91_PMC + 0x38) /* USB Clock Register [some SAM9 only] */
++#define AT91_PMC_USBS (0x1 << 0) /* USB OHCI Input clock selection */
++#define AT91_PMC_USBS_PLLA (0 << 0)
++#define AT91_PMC_USBS_UPLL (1 << 0)
++#define AT91_PMC_OHCIUSBDIV (0xF << 8) /* Divider for USB OHCI Clock */
++
++#define AT91_PMC_PCKR(n) (AT91_PMC + 0x40 + ((n) * 4)) /* Programmable Clock 0-N Registers */
++#define AT91_PMC_CSSMCK (0x1 << 8) /* CSS or Master Clock Selection */
++#define AT91_PMC_CSSMCK_CSS (0 << 8)
++#define AT91_PMC_CSSMCK_MCK (1 << 8)
+
+ #define AT91_PMC_IER (AT91_PMC + 0x60) /* Interrupt Enable Register */
+ #define AT91_PMC_IDR (AT91_PMC + 0x64) /* Interrupt Disable Register */
+ #define AT91_PMC_SR (AT91_PMC + 0x68) /* Status Register */
+ #define AT91_PMC_MOSCS (1 << 0) /* MOSCS Flag */
+ #define AT91_PMC_LOCKA (1 << 1) /* PLLA Lock */
+ #define AT91_PMC_LOCKB (1 << 2) /* PLLB Lock */
+ #define AT91_PMC_MCKRDY (1 << 3) /* Master Clock */
+-#define AT91_PMC_LOCKU (1 << 6) /* UPLL Lock [AT91CAP9 only] */
++#define AT91_PMC_LOCKU (1 << 6) /* UPLL Lock [some SAM9, AT91CAP9 only] */
+ #define AT91_PMC_OSCSEL (1 << 7) /* Slow Clock Oscillator [AT91CAP9 revC only] */
+ #define AT91_PMC_PCK0RDY (1 << 8) /* Programmable Clock 0 */
+ #define AT91_PMC_PCK1RDY (1 << 9) /* Programmable Clock 1 */
+ #define AT91_PMC_PCK2RDY (1 << 10) /* Programmable Clock 2 */
+ #define AT91_PMC_PCK3RDY (1 << 11) /* Programmable Clock 3 */
+--- linux-2.6.30.orig/drivers/input/touchscreen/atmel_tsadcc.c
++++ linux-2.6.30/drivers/input/touchscreen/atmel_tsadcc.c
+@@ -34,10 +34,11 @@
+ #define ATMEL_TSADCC_TSAMOD_ADC_ONLY_MODE (0x0) /* ADC Mode */
+ #define ATMEL_TSADCC_TSAMOD_TS_ONLY_MODE (0x1) /* Touch Screen Only Mode */
+ #define ATMEL_TSADCC_LOWRES (1 << 4) /* Resolution selection */
+ #define ATMEL_TSADCC_SLEEP (1 << 5) /* Sleep mode */
+ #define ATMEL_TSADCC_PENDET (1 << 6) /* Pen Detect selection */
++#define ATMEL_TSADCC_PRES (1 << 7) /* Pressure Measurement Selection */
+ #define ATMEL_TSADCC_PRESCAL (0x3f << 8) /* Prescalar Rate Selection */
+ #define ATMEL_TSADCC_STARTUP (0x7f << 16) /* Start Up time */
+ #define ATMEL_TSADCC_SHTIM (0xf << 24) /* Sample & Hold time */
+ #define ATMEL_TSADCC_PENDBC (0xf << 28) /* Pen Detect debouncing time */
+
+@@ -82,20 +83,25 @@
+ #define ATMEL_TSADCC_CDR2 0x38 /* Channel Data 2 */
+ #define ATMEL_TSADCC_CDR3 0x3C /* Channel Data 3 */
+ #define ATMEL_TSADCC_CDR4 0x40 /* Channel Data 4 */
+ #define ATMEL_TSADCC_CDR5 0x44 /* Channel Data 5 */
+
++#define ATMEL_TSADCC_XPOS 0x50
++#define ATMEL_TSADCC_Z1DAT 0x54
++#define ATMEL_TSADCC_Z2DAT 0x58
++
++
+ #define ADC_CLOCK 1000000
+
+ struct atmel_tsadcc {
+ struct input_dev *input;
+ char phys[32];
+ struct clk *clk;
+ int irq;
+ unsigned int prev_absx;
+ unsigned int prev_absy;
+- unsigned char bufferedmeasure;
++ unsigned char bufferedmeasure;
+ };
+
+ static void __iomem *tsc_base;
+
+ #define atmel_tsadcc_read(reg) __raw_readl(tsc_base + (reg))
+@@ -122,10 +128,13 @@ static irqreturn_t atmel_tsadcc_interrup
+ ATMEL_TSADCC_EOC(3) | ATMEL_TSADCC_NOCNT);
+ atmel_tsadcc_write(ATMEL_TSADCC_IER, ATMEL_TSADCC_PENCNT);
+
+ input_report_key(input_dev, BTN_TOUCH, 0);
+ ts_dev->bufferedmeasure = 0;
++#ifdef CONFIG_TS_ABS_PRESSURE
++ input_report_abs(input_dev, ABS_PRESSURE, 0);
++#endif
+ input_sync(input_dev);
+
+ } else if (status & ATMEL_TSADCC_PENCNT) {
+ /* Pen detected */
+ reg = atmel_tsadcc_read(ATMEL_TSADCC_MR);
+@@ -146,10 +155,13 @@ static irqreturn_t atmel_tsadcc_interrup
+ * be erroneous.
+ * Always report previous measurement */
+ input_report_abs(input_dev, ABS_X, ts_dev->prev_absx);
+ input_report_abs(input_dev, ABS_Y, ts_dev->prev_absy);
+ input_report_key(input_dev, BTN_TOUCH, 1);
++#ifdef CONFIG_TS_ABS_PRESSURE
++ input_report_abs(input_dev, ABS_PRESSURE, 7500);
++#endif
+ input_sync(input_dev);
+ } else
+ ts_dev->bufferedmeasure = 1;
+
+ /* Now make new measurement */
+@@ -245,10 +257,11 @@ static int __devinit atmel_tsadcc_probe(
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+
+ input_set_abs_params(input_dev, ABS_X, 0, 0x3FF, 0, 0);
+ input_set_abs_params(input_dev, ABS_Y, 0, 0x3FF, 0, 0);
++ input_set_abs_params(input_dev, ABS_PRESSURE, 0, 15000, 0, 0);
+
+ /* clk_enable() always returns 0, no need to check it */
+ clk_enable(ts_dev->clk);
+
+ prsc = clk_get_rate(ts_dev->clk);
+@@ -297,10 +310,11 @@ err_free_mem:
+ static int __devexit atmel_tsadcc_remove(struct platform_device *pdev)
+ {
+ struct atmel_tsadcc *ts_dev = dev_get_drvdata(&pdev->dev);
+ struct resource *res;
+
++ disable_irq(ts_dev->irq);
+ free_irq(ts_dev->irq, ts_dev);
+
+ input_unregister_device(ts_dev->input);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+--- linux-2.6.30.orig/drivers/mmc/host/at91_mci.c
++++ linux-2.6.30/drivers/mmc/host/at91_mci.c
+@@ -77,10 +77,20 @@
+ #include <mach/cpu.h>
+ #include <mach/at91_mci.h>
+
+ #define DRIVER_NAME "at91_mci"
+
++static inline int at91mci_is_rev2(void)
++{
++ return ( cpu_is_at91sam9260()
++ || cpu_is_at91sam9263()
++ || cpu_is_at91cap9()
++ || cpu_is_at91sam9rl()
++ || cpu_is_at91sam9g20()
++ );
++}
++
+ #define FL_SENT_COMMAND (1 << 0)
+ #define FL_SENT_STOP (1 << 1)
+
+ #define AT91_MCI_ERRORS (AT91_MCI_RINDE | AT91_MCI_RDIRE | AT91_MCI_RCRCE \
+ | AT91_MCI_RENDE | AT91_MCI_RTOE | AT91_MCI_DCRCE \
+@@ -199,12 +209,12 @@ static inline void at91_mci_sg_to_dma(st
+ unsigned *dmabuf = host->buffer;
+
+ size = data->blksz * data->blocks;
+ len = data->sg_len;
+
+- /* AT91SAM926[0/3] Data Write Operation and number of bytes erratum */
+- if (cpu_is_at91sam9260() || cpu_is_at91sam9263() || cpu_is_at91sam9g20())
++ /* at91mci rev2 Data Write Operation and number of bytes erratum */
++ if (at91mci_is_rev2())
+ if (host->total_length == 12)
+ memset(dmabuf, 0, 12);
+
+ /*
+ * Just loop through all entries. Size might not
+@@ -460,11 +470,11 @@ static void at91_mci_enable(struct at91m
+ at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
+ at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
+ at91_mci_write(host, AT91_MCI_DTOR, AT91_MCI_DTOMUL_1M | AT91_MCI_DTOCYC);
+ mr = AT91_MCI_PDCMODE | 0x34a;
+
+- if (cpu_is_at91sam9260() || cpu_is_at91sam9263() || cpu_is_at91sam9g20())
++ if (at91mci_is_rev2())
+ mr |= AT91_MCI_RDPROOF | AT91_MCI_WRPROOF;
+
+ at91_mci_write(host, AT91_MCI_MR, mr);
+
+ /* use Slot A or B (only one at same time) */
+@@ -613,14 +623,14 @@ static void at91_mci_send_command(struct
+ /*
+ * Handle a write
+ */
+ host->total_length = block_length * blocks;
+ /*
+- * AT91SAM926[0/3] Data Write Operation and
++ * at91mci rev2 Data Write Operation and
+ * number of bytes erratum
+ */
+- if (cpu_is_at91sam9260 () || cpu_is_at91sam9263() || cpu_is_at91sam9g20())
++ if (at91mci_is_rev2())
+ if (host->total_length < 12)
+ host->total_length = 12;
+
+ host->buffer = kmalloc(host->total_length, GFP_KERNEL);
+ if (!host->buffer) {
+@@ -676,15 +686,14 @@ static void at91_mci_process_next(struct
+ else if ((!(host->flags & FL_SENT_STOP)) && host->request->stop) {
+ host->flags |= FL_SENT_STOP;
+ at91_mci_send_command(host, host->request->stop);
+ } else {
+ del_timer(&host->timer);
+- /* the at91rm9200 mci controller hangs after some transfers,
++ /* the mci controller hangs after some transfers,
+ * and the workaround is to reset it after each transfer.
+ */
+- if (cpu_is_at91rm9200())
+- at91_reset_host(host);
++ at91_reset_host(host);
+ mmc_request_done(host->mmc, host->request);
+ }
+ }
+
+ /*
+@@ -1005,28 +1014,35 @@ static int __init at91_mci_probe(struct
+
+ mmc->ops = &at91_mci_ops;
+ mmc->f_min = 375000;
+ mmc->f_max = 25000000;
+ mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
+- mmc->caps = MMC_CAP_SDIO_IRQ;
++ mmc->caps = 0;
+
+ mmc->max_blk_size = 4095;
+ mmc->max_blk_count = mmc->max_req_size;
+
+ host = mmc_priv(mmc);
+ host->mmc = mmc;
+ host->buffer = NULL;
+ host->bus_mode = 0;
+ host->board = pdev->dev.platform_data;
+ if (host->board->wire4) {
+- if (cpu_is_at91sam9260() || cpu_is_at91sam9263() || cpu_is_at91sam9g20())
++ if (at91mci_is_rev2())
+ mmc->caps |= MMC_CAP_4_BIT_DATA;
+ else
+ dev_warn(&pdev->dev, "4 wire bus mode not supported"
+ " - using 1 wire\n");
+ }
+
++ /* Add SDIO capability when available */
++ if (at91mci_is_rev2()) {
++ /* at91mci rev2 sdio interrupt erratum */
++ if (host->board->wire4 || !host->board->slot_b)
++ mmc->caps |= MMC_CAP_SDIO_IRQ;
++ }
++
+ /*
+ * Reserve GPIOs ... board init code makes sure these pins are set
+ * up as GPIOs with the right direction (input, except for vcc)
+ */
+ if (host->board->det_pin) {
+@@ -1079,12 +1095,11 @@ static int __init at91_mci_probe(struct
+
+ /*
+ * Allocate the MCI interrupt
+ */
+ host->irq = platform_get_irq(pdev, 0);
+- ret = request_irq(host->irq, at91_mci_irq, IRQF_SHARED,
+- mmc_hostname(mmc), host);
++ ret = request_irq(host->irq, at91_mci_irq, 0, mmc_hostname(mmc), host);
+ if (ret) {
+ dev_dbg(&pdev->dev, "request MCI interrupt failed\n");
+ goto fail0;
+ }
+
+--- linux-2.6.30.orig/drivers/net/Kconfig
++++ linux-2.6.30/drivers/net/Kconfig
+@@ -226,10 +226,16 @@ config MACB
+ parts. Say Y to include support for the MACB chip.
+
+ To compile this driver as a module, choose M here: the module
+ will be called macb.
+
++config MACB_TX_SRAM
++ bool "Atmel MACB TX buffers in internal SRAM"
++ depends on NET_ETHERNET && MACB && (ARCH_AT91SAM9260 || ARCH_AT91SAM9263)
++ help
++ Use internal SRAM for TX buffers.
++
+ source "drivers/net/arm/Kconfig"
+
+ config AX88796
+ tristate "ASIX AX88796 NE2000 clone support"
+ depends on ARM || MIPS || SUPERH
+--- linux-2.6.30.orig/drivers/net/macb.c
++++ linux-2.6.30/drivers/net/macb.c
+@@ -31,13 +31,25 @@
+ #define RX_RING_BYTES (sizeof(struct dma_desc) * RX_RING_SIZE)
+
+ /* Make the IP header word-aligned (the ethernet header is 14 bytes) */
+ #define RX_OFFSET 2
+
+-#define TX_RING_SIZE 128
++#if defined(CONFIG_ARCH_AT91) && defined(CONFIG_MACB_TX_SRAM)
++ #if defined(CONFIG_ARCH_AT91SAM9260)
++ #define TX_RING_SIZE 2
++ #elif defined(CONFIG_ARCH_AT91SAM9263)
++ #define TX_RING_SIZE 32
++ #endif
++ #define TX_BUFFER_SIZE 1536
++ #define TX_RING_BYTES (sizeof(struct dma_desc) * TX_RING_SIZE)
++ #define TX_DMA_SIZE ((TX_RING_BYTES) + (TX_RING_SIZE) * (TX_BUFFER_SIZE))
++#else
++ #define TX_RING_SIZE 128
++ #define TX_RING_BYTES (sizeof(struct dma_desc) * TX_RING_SIZE)
++#endif
++
+ #define DEF_TX_RING_PENDING (TX_RING_SIZE - 1)
+-#define TX_RING_BYTES (sizeof(struct dma_desc) * TX_RING_SIZE)
+
+ #define TX_RING_GAP(bp) \
+ (TX_RING_SIZE - (bp)->tx_pending)
+ #define TX_BUFFS_AVAIL(bp) \
+ (((bp)->tx_tail <= (bp)->tx_head) ? \
+@@ -376,12 +388,14 @@ static void macb_tx(struct macb *bp)
+ if (!(bufstat & MACB_BIT(TX_USED)))
+ break;
+
+ dev_dbg(&bp->pdev->dev, "skb %u (data %p) TX complete\n",
+ tail, skb->data);
++#if !defined(CONFIG_MACB_TX_SRAM)
+ dma_unmap_single(&bp->pdev->dev, rp->mapping, skb->len,
+ DMA_TO_DEVICE);
++#endif
+ bp->stats.tx_packets++;
+ bp->stats.tx_bytes += skb->len;
+ rp->skb = NULL;
+ dev_kfree_skb_irq(skb);
+ }
+@@ -633,23 +647,30 @@ static int macb_start_xmit(struct sk_buf
+ return 1;
+ }
+
+ entry = bp->tx_head;
+ dev_dbg(&bp->pdev->dev, "Allocated ring entry %u\n", entry);
++#if defined(CONFIG_ARCH_AT91) && defined(CONFIG_MACB_TX_SRAM)
++ mapping = bp->tx_ring[entry].addr;
++ memcpy(bp->tx_buffers + entry * TX_BUFFER_SIZE, skb->data, len);
++#else
+ mapping = dma_map_single(&bp->pdev->dev, skb->data,
+ len, DMA_TO_DEVICE);
++#endif
+ bp->tx_skb[entry].skb = skb;
+ bp->tx_skb[entry].mapping = mapping;
+ dev_dbg(&bp->pdev->dev, "Mapped skb data %p to DMA addr %08lx\n",
+ skb->data, (unsigned long)mapping);
+
+ ctrl = MACB_BF(TX_FRMLEN, len);
+ ctrl |= MACB_BIT(TX_LAST);
+ if (entry == (TX_RING_SIZE - 1))
+ ctrl |= MACB_BIT(TX_WRAP);
+
++#if !defined(CONFIG_MACB_TX_SRAM)
+ bp->tx_ring[entry].addr = mapping;
++#endif
+ bp->tx_ring[entry].ctrl = ctrl;
+ wmb();
+
+ entry = NEXT_TX(entry);
+ bp->tx_head = entry;
+@@ -676,20 +697,29 @@ static void macb_free_consistent(struct
+ dma_free_coherent(&bp->pdev->dev, RX_RING_BYTES,
+ bp->rx_ring, bp->rx_ring_dma);
+ bp->rx_ring = NULL;
+ }
+ if (bp->tx_ring) {
++#if defined(CONFIG_ARCH_AT91) && defined(CONFIG_MACB_TX_SRAM)
++ iounmap((void *)bp->tx_ring);
++#else
+ dma_free_coherent(&bp->pdev->dev, TX_RING_BYTES,
+ bp->tx_ring, bp->tx_ring_dma);
++#endif
+ bp->tx_ring = NULL;
+ }
+ if (bp->rx_buffers) {
+ dma_free_coherent(&bp->pdev->dev,
+ RX_RING_SIZE * RX_BUFFER_SIZE,
+ bp->rx_buffers, bp->rx_buffers_dma);
+ bp->rx_buffers = NULL;
+ }
++
++#if defined(CONFIG_ARCH_AT91) && defined(CONFIG_MACB_TX_SRAM)
++ if (bp->tx_ring_dma)
++ release_mem_region(bp->tx_ring_dma, TX_DMA_SIZE);
++#endif
+ }
+
+ static int macb_alloc_consistent(struct macb *bp)
+ {
+ int size;
+@@ -706,18 +736,48 @@ static int macb_alloc_consistent(struct
+ goto out_err;
+ dev_dbg(&bp->pdev->dev,
+ "Allocated RX ring of %d bytes at %08lx (mapped %p)\n",
+ size, (unsigned long)bp->rx_ring_dma, bp->rx_ring);
+
++#if defined(CONFIG_ARCH_AT91) && defined(CONFIG_MACB_TX_SRAM)
++#if defined(CONFIG_ARCH_AT91SAM9260)
++ if (request_mem_region(AT91SAM9260_SRAM0_BASE, TX_DMA_SIZE, "macb")) {
++ bp->tx_ring_dma = AT91SAM9260_SRAM0_BASE;
++ } else {
++ if (request_mem_region(AT91SAM9260_SRAM1_BASE, TX_DMA_SIZE, "macb")) {
++ bp->tx_ring_dma = AT91SAM9260_SRAM1_BASE;
++ } else {
++ printk(KERN_WARNING "Cannot request SRAM memory for TX ring, already used\n");
++ return -EBUSY;
++ }
++ }
++#elif defined(CONFIG_ARCH_AT91SAM9263)
++ if (request_mem_region(AT91SAM9263_SRAM0_BASE, TX_DMA_SIZE, "macb")) {
++ bp->tx_ring_dma = AT91SAM9263_SRAM0_BASE;
++ } else {
++ printk(KERN_WARNING "Cannot request SRAM memory for TX ring, already used\n");
++ return -EBUSY;
++ }
++#endif
++
++ bp->tx_ring = ioremap(bp->tx_ring_dma, TX_DMA_SIZE);
++ if (!bp->tx_ring)
++ return -ENOMEM;
++
++ bp->tx_buffers_dma = bp->tx_ring_dma + TX_RING_BYTES;
++ bp->tx_buffers = (char *) bp->tx_ring + TX_RING_BYTES;
++#else
+ size = TX_RING_BYTES;
+ bp->tx_ring = dma_alloc_coherent(&bp->pdev->dev, size,
+ &bp->tx_ring_dma, GFP_KERNEL);
+ if (!bp->tx_ring)
+ goto out_err;
++
+ dev_dbg(&bp->pdev->dev,
+ "Allocated TX ring of %d bytes at %08lx (mapped %p)\n",
+ size, (unsigned long)bp->tx_ring_dma, bp->tx_ring);
++#endif
+
+ size = RX_RING_SIZE * RX_BUFFER_SIZE;
+ bp->rx_buffers = dma_alloc_coherent(&bp->pdev->dev, size,
+ &bp->rx_buffers_dma, GFP_KERNEL);
+ if (!bp->rx_buffers)
+@@ -744,14 +804,22 @@ static void macb_init_rings(struct macb
+ bp->rx_ring[i].ctrl = 0;
+ addr += RX_BUFFER_SIZE;
+ }
+ bp->rx_ring[RX_RING_SIZE - 1].addr |= MACB_BIT(RX_WRAP);
+
++#if defined(CONFIG_ARCH_AT91) && defined(CONFIG_MACB_TX_SRAM)
++ for (i = 0; i < TX_RING_SIZE; i++) {
++ bp->tx_ring[i].addr = bp->tx_buffers_dma + i * TX_BUFFER_SIZE;
++ bp->tx_ring[i].ctrl = MACB_BIT(TX_USED);
++ }
++#else
+ for (i = 0; i < TX_RING_SIZE; i++) {
+ bp->tx_ring[i].addr = 0;
+ bp->tx_ring[i].ctrl = MACB_BIT(TX_USED);
+ }
++#endif
++
+ bp->tx_ring[TX_RING_SIZE - 1].ctrl |= MACB_BIT(TX_WRAP);
+
+ bp->rx_tail = bp->tx_head = bp->tx_tail = 0;
+ }
+
+--- linux-2.6.30.orig/drivers/net/macb.h
++++ linux-2.6.30/drivers/net/macb.h
+@@ -367,12 +367,17 @@ struct macb {
+
+ unsigned int tx_head, tx_tail;
+ struct dma_desc *tx_ring;
+ struct ring_info *tx_skb;
+
++#if defined(CONFIG_ARCH_AT91)
++ void *tx_buffers;
++#endif
++
+ spinlock_t lock;
+ struct platform_device *pdev;
++ struct clk *macb_clk;
+ struct clk *pclk;
+ struct clk *hclk;
+ struct net_device *dev;
+ struct napi_struct napi;
+ struct net_device_stats stats;
+@@ -380,10 +385,14 @@ struct macb {
+
+ dma_addr_t rx_ring_dma;
+ dma_addr_t tx_ring_dma;
+ dma_addr_t rx_buffers_dma;
+
++#if defined(CONFIG_ARCH_AT91)
++ dma_addr_t tx_buffers_dma;
++#endif
++
+ unsigned int rx_pending, tx_pending;
+
+ struct mii_bus *mii_bus;
+ struct phy_device *phy_dev;
+ unsigned int link;
+--- linux-2.6.30.orig/sound/arm/Kconfig
++++ linux-2.6.30/sound/arm/Kconfig
+@@ -37,7 +37,16 @@ config SND_PXA2XX_AC97
+ select SND_PXA2XX_LIB_AC97
+ help
+ Say Y or M if you want to support any AC97 codec attached to
+ the PXA2xx AC97 interface.
+
++config SND_AT91_AC97
++ tristate "AC97 Controller driver for SAM926X familly from ATMEL"
++ depends on SND && ARCH_AT91
++ select SND_PCM
++ select SND_AC97_CODEC
++ help
++ Say Y or M if you want to support any AC97 codec attached to
++ the SAM926X AC97 Controller.
++
+ endif # SND_ARM
+
+--- linux-2.6.30.orig/sound/arm/Makefile
++++ linux-2.6.30/sound/arm/Makefile
+@@ -12,5 +12,9 @@ obj-$(CONFIG_SND_PXA2XX_LIB) += snd-pxa2
+ snd-pxa2xx-lib-y := pxa2xx-pcm-lib.o
+ snd-pxa2xx-lib-$(CONFIG_SND_PXA2XX_LIB_AC97) += pxa2xx-ac97-lib.o
+
+ obj-$(CONFIG_SND_PXA2XX_AC97) += snd-pxa2xx-ac97.o
+ snd-pxa2xx-ac97-objs := pxa2xx-ac97.o
++
++obj-$(CONFIG_SND_AT91_AC97) += snd-at91-ac97.o
++snd-at91-ac97-objs := at91-ac97.o
++
+--- /dev/null
++++ linux-2.6.30/sound/arm/at91-ac97.c
+@@ -0,0 +1,911 @@
++/*
++ * at91-ac97.c -- AC'97 driver for atmel boards.
++ *
++ * Copyright (C) 2005 SAN People
++ * Copyright (C) 2006 Atmel
++ *
++ * Author: Patrice Vilchez <patrice.vilchez@atmel.com>
++ * Sedji Gaouaou <sedji.gaouaou@atmel.com>
++ * ATMEL CORP.
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#include <linux/platform_device.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/delay.h>
++#include <linux/clk.h>
++#include <linux/atmel_pdc.h>
++#include <linux/io.h>
++
++#include <sound/core.h>
++#include <sound/initval.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++#include <sound/ac97_codec.h>
++#include <sound/soc.h>
++
++#include <asm/cacheflush.h>
++
++#include <mach/hardware.h>
++#include <mach/gpio.h>
++#include <mach/board.h>
++
++#include "at91-ac97.h"
++
++
++/*
++ * module parameters
++ */
++static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
++static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
++static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
++
++module_param_array(index, int, NULL, 0444);
++MODULE_PARM_DESC(index, "Index value for AC97 controller");
++module_param_array(id, charp, NULL, 0444);
++MODULE_PARM_DESC(id, "ID string for AC97 controller");
++module_param_array(enable, bool, NULL, 0444);
++MODULE_PARM_DESC(enable, "Enable AC97 controller");
++
++typedef struct at91_ac97 {
++ spinlock_t lock;
++ void *regs;
++ int period;
++ struct clk *ac97_clk;
++ struct snd_pcm_substream *playback_substream;
++ struct snd_pcm_substream *capture_substream;
++ struct snd_card *card;
++ struct snd_pcm *pcm;
++ struct snd_ac97 *ac97;
++ struct snd_ac97_bus *ac97_bus;
++ int irq;
++ struct platform_device *pdev;
++ u8 reset_pin;
++} at91_ac97_t;
++
++
++/*
++ * PIO management functions
++ */
++void at91_ac97c_drive_reset(at91_ac97_t *chip, unsigned int value)
++{
++ at91_set_gpio_value(chip->reset_pin, value);
++}
++
++static const char driver_name[] = "at91-ac97";
++
++
++/*
++ * PCM part
++ */
++static struct snd_pcm_hardware snd_at91_ac97_playback_hw = {
++ .info = (SNDRV_PCM_INFO_INTERLEAVED
++ | SNDRV_PCM_INFO_MMAP
++ | SNDRV_PCM_INFO_MMAP_VALID
++ | SNDRV_PCM_INFO_BLOCK_TRANSFER),
++ .formats = (SNDRV_PCM_FMTBIT_S16_LE
++ | SNDRV_PCM_FMTBIT_S16_BE),
++ .rates = SNDRV_PCM_RATE_CONTINUOUS,
++ .rate_min = 8000,
++ .rate_max = 48000,
++ .channels_min = 2,
++ .channels_max = 2,
++ .buffer_bytes_max = 256*1024,
++ .period_bytes_min = 1024,
++ .period_bytes_max = 4*1024,
++ .periods_min = 1,
++ .periods_max = 64,
++};
++
++static struct snd_pcm_hardware snd_at91_ac97_capture_hw = {
++ .info = (SNDRV_PCM_INFO_INTERLEAVED
++ | SNDRV_PCM_INFO_MMAP
++ | SNDRV_PCM_INFO_MMAP_VALID
++ | SNDRV_PCM_INFO_BLOCK_TRANSFER),
++ .formats = (SNDRV_PCM_FMTBIT_S16_LE
++ | SNDRV_PCM_FMTBIT_S16_BE),
++ .rates = SNDRV_PCM_RATE_CONTINUOUS,
++ .rate_min = 8000,
++ .rate_max = 48000,
++ .channels_min = 1,
++ .channels_max = 2,
++ .buffer_bytes_max = 256*1024,
++ .period_bytes_min = 1024,
++ .period_bytes_max = 4*1024,
++ .periods_min = 1,
++ .periods_max = 64,
++};
++
++static int snd_at91_ac97_playback_open(struct snd_pcm_substream *substream)
++{
++ at91_ac97_t *chip = snd_pcm_substream_chip(substream);
++ struct snd_pcm_runtime *runtime = substream->runtime;
++
++ runtime->hw = snd_at91_ac97_playback_hw;
++ chip->playback_substream = substream;
++ chip->period = 0;
++
++ pr_debug("%s : snd_at91_ac97_playback_open\n\r", driver_name);
++
++ return 0;
++}
++
++static int snd_at91_ac97_capture_open(struct snd_pcm_substream *substream)
++{
++ at91_ac97_t *chip = snd_pcm_substream_chip(substream);
++ struct snd_pcm_runtime *runtime = substream->runtime;
++
++ runtime->hw = snd_at91_ac97_capture_hw;
++ chip->capture_substream = substream;
++ chip->period = 0;
++
++ pr_debug("%s : snd_at91_ac97_capture_open\n\r", driver_name);
++
++ return 0;
++}
++
++static int snd_at91_ac97_playback_close(struct snd_pcm_substream *substream)
++{
++ at91_ac97_t *chip = snd_pcm_substream_chip(substream);
++
++ chip->playback_substream = NULL;
++
++ return 0;
++}
++
++static int snd_at91_ac97_capture_close(struct snd_pcm_substream *substream)
++{
++ at91_ac97_t *chip = snd_pcm_substream_chip(substream);
++
++ chip->capture_substream = NULL;
++
++ return 0;
++}
++
++static int snd_at91_ac97_playback_hw_params(struct snd_pcm_substream *substream,
++ struct snd_pcm_hw_params *hw_params)
++{
++ int err;
++
++ err = snd_pcm_lib_malloc_pages(substream,
++ params_buffer_bytes(hw_params));
++
++ return err;
++}
++
++static int snd_at91_ac97_capture_hw_params(struct snd_pcm_substream *substream,
++ struct snd_pcm_hw_params *hw_params)
++{
++ int err;
++
++ err = snd_pcm_lib_malloc_pages(substream,
++ params_buffer_bytes(hw_params));
++
++ return err;
++}
++
++static int snd_at91_ac97_playback_hw_free(struct snd_pcm_substream *substream)
++{
++
++ snd_pcm_lib_free_pages(substream);
++
++ return 0;
++}
++
++static int snd_at91_ac97_capture_hw_free(struct snd_pcm_substream *substream)
++{
++
++ snd_pcm_lib_free_pages(substream);
++
++ return 0;
++}
++
++static int snd_at91_ac97_playback_prepare(struct snd_pcm_substream *substream)
++{
++ at91_ac97_t *chip = snd_pcm_substream_chip(substream);
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ int block_size = frames_to_bytes(runtime, runtime->period_size);
++ unsigned long word = 0;
++
++ pr_debug("%s : block_size = %d\n\r", driver_name, block_size);
++
++ /* Assign slots to channels */
++ switch (substream->runtime->channels) {
++ /* TODO: Support more than two channels */
++ case 1:
++ word |= AT91C_AC97C_CHID3_CA;
++ break;
++ case 2:
++ default:
++ /* Assign Left and Right slots (3,4) to Channel A */
++ word |= AT91C_AC97C_CHID3_CA | AT91C_AC97C_CHID4_CA;
++ break;
++ }
++
++ ac97c_writel(chip, OCA, word);
++
++ /*
++ * Configure sample format and size..
++ */
++ word = AT91C_AC97C_PDCEN | AT91C_AC97C_SIZE_16_BITS;
++
++ switch (runtime->format) {
++ case SNDRV_PCM_FORMAT_S16_BE:
++ word |= AT91C_AC97C_CEM;
++ break;
++ case SNDRV_PCM_FORMAT_S16_LE:
++ default:
++ break;
++ }
++
++ ac97c_writel(chip, CAMR, word);
++
++ /* Set variable rate if needed */
++ if (runtime->rate != 48000) {
++ word = ac97c_readl(chip, MR);
++ word |= AT91C_AC97C_VRA;
++ ac97c_writel(chip, MR, word);
++ } else {
++ /* Clear Variable Rate Bit */
++ word = ac97c_readl(chip, MR);
++ word &= ~AT91C_AC97C_VRA;
++ ac97c_writel(chip, MR, word);
++ }
++
++ /* Set rate */
++ snd_ac97_set_rate(chip->ac97, AC97_PCM_FRONT_DAC_RATE, runtime->rate);
++
++ pr_debug("%s : dma_addr = %x\n\r : dma_area = %x\n\r"
++ " : dma_bytes = %d\n\r",
++ driver_name, runtime->dma_addr,
++ runtime->dma_area, runtime->dma_bytes);
++
++ /* Initialize and start the PDC */
++ writel(runtime->dma_addr, chip->regs + ATMEL_PDC_TPR);
++ writel(block_size / 2, chip->regs + ATMEL_PDC_TCR);
++ writel(runtime->dma_addr + block_size, chip->regs + ATMEL_PDC_TNPR);
++ writel(block_size / 2, chip->regs + ATMEL_PDC_TNCR);
++
++ /* Enable Channel A interrupts */
++ ac97c_writel(chip, IER, AT91C_AC97C_CAEVT);
++
++ pr_debug("%s : snd_at91_ac97_playback_prepare\n\r", driver_name);
++
++ return 0;
++}
++
++static int snd_at91_ac97_capture_prepare(struct snd_pcm_substream *substream)
++{
++ at91_ac97_t *chip = snd_pcm_substream_chip(substream);
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ int block_size = frames_to_bytes(runtime, runtime->period_size);
++ unsigned long word = 0;
++
++ pr_debug("%s : block_size = %d\n\r", driver_name, block_size);
++
++
++ /* Assign slots to channels */
++ switch (substream->runtime->channels) {
++ /* TODO: Support more than two channels */
++ case 1:
++ word |= AT91C_AC97C_CHID3_CA;
++ break;
++ case 2:
++ default:
++ /* Assign Left and Right slots (3,4) to Channel A */
++ word |= AT91C_AC97C_CHID3_CA | AT91C_AC97C_CHID4_CA;
++ break;
++ }
++
++ ac97c_writel(chip, ICA, word);
++
++ /*
++ * Configure sample format and size.
++ */
++ word = AT91C_AC97C_PDCEN | AT91C_AC97C_SIZE_16_BITS;
++
++ switch (runtime->format) {
++ case SNDRV_PCM_FORMAT_S16_BE:
++ word |= AT91C_AC97C_CEM;
++ break;
++ case SNDRV_PCM_FORMAT_S16_LE:
++ break;
++ }
++
++ ac97c_writel(chip, CAMR, word);
++
++ /* Set variable rate if needed */
++ if (runtime->rate != 48000) {
++ word = ac97c_readl(chip, MR);
++ word |= AT91C_AC97C_VRA;
++ ac97c_writel(chip, MR, word);
++ } else {
++ /* Clear Variable Rate Bit */
++ word = ac97c_readl(chip, MR);
++ word &= ~AT91C_AC97C_VRA;
++ ac97c_writel(chip, MR, word);
++ }
++
++ /* Set rate */
++ snd_ac97_set_rate(chip->ac97, AC97_PCM_LR_ADC_RATE, runtime->rate);
++
++ pr_debug("%s : dma_addr = %x\n\r : dma_area = %x\n\r"
++ " : dma_bytes = %d\n\r",
++ driver_name, runtime->dma_addr,
++ runtime->dma_area, runtime->dma_bytes);
++
++ /* Initialize and start the PDC */
++ writel(runtime->dma_addr, chip->regs + ATMEL_PDC_RPR);
++ writel(block_size / 2, chip->regs + ATMEL_PDC_RCR);
++ writel(runtime->dma_addr + block_size, chip->regs + ATMEL_PDC_RNPR);
++ writel(block_size / 2, chip->regs + ATMEL_PDC_RNCR);
++
++ /* Enable Channel A interrupts */
++ ac97c_writel(chip, IER, AT91C_AC97C_CAEVT);
++
++ pr_debug("%s : snd_at91_ac97_capture_prepare\n\r", driver_name);
++
++ return 0;
++}
++
++static int snd_at91_ac97_playback_trigger(struct snd_pcm_substream *substream,
++ int cmd)
++{
++ at91_ac97_t *chip = snd_pcm_substream_chip(substream);
++ unsigned long camr, ptcr = 0, flags;
++ int err = 0;
++
++ spin_lock_irqsave(&chip->lock, flags);
++ camr = ac97c_readl(chip, CAMR);
++
++ switch (cmd) {
++ case SNDRV_PCM_TRIGGER_START:
++ camr |= (AT91C_AC97C_CEN | AT91C_AC97C_ENDTX);
++ ptcr = ATMEL_PDC_TXTEN;
++ break;
++ case SNDRV_PCM_TRIGGER_STOP:
++ camr &= ~(AT91C_AC97C_CEN | AT91C_AC97C_ENDTX);
++ ptcr = ATMEL_PDC_TXTDIS;
++ break;
++ default:
++ err = -EINVAL;
++ break;
++ }
++
++ ac97c_writel(chip, CAMR, camr);
++
++ writel(ptcr, chip->regs + ATMEL_PDC_PTCR);
++
++ spin_unlock_irqrestore(&chip->lock, flags);
++
++ pr_debug("%s : snd_at91_ac97_playback_trigger\n\r", driver_name);
++
++ return err;
++}
++
++static int snd_at91_ac97_capture_trigger(struct snd_pcm_substream *substream,
++ int cmd)
++{
++ at91_ac97_t *chip = snd_pcm_substream_chip(substream);
++ unsigned long camr, ptcr = 0, flags;
++ int err = 0;
++
++ spin_lock_irqsave(&chip->lock, flags);
++ camr = ac97c_readl(chip, CAMR);
++
++ switch (cmd) {
++ case SNDRV_PCM_TRIGGER_START:
++ camr |= (AT91C_AC97C_CEN |
++ AT91C_AC97C_ENDRX |
++ AT91C_AC97C_OVRUN);
++ ptcr = ATMEL_PDC_RXTEN;
++ break;
++ case SNDRV_PCM_TRIGGER_STOP:
++ camr &= ~(AT91C_AC97C_CEN |
++ AT91C_AC97C_ENDRX |
++ AT91C_AC97C_OVRUN);
++ ptcr = ATMEL_PDC_RXTDIS;
++ break;
++ default:
++ err = -EINVAL;
++ break;
++ }
++
++ ac97c_writel(chip, CAMR, camr);
++
++ writel(ptcr, chip->regs + ATMEL_PDC_PTCR);
++
++ spin_unlock_irqrestore(&chip->lock, flags);
++
++ pr_debug("%s : snd_at91_ac97_capture_trigger\n\r", driver_name);
++
++ return err;
++}
++
++static snd_pcm_uframes_t
++snd_at91_ac97_playback_pointer(struct snd_pcm_substream *substream)
++{
++ at91_ac97_t *chip = snd_pcm_substream_chip(substream);
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ snd_pcm_uframes_t pos;
++ unsigned long bytes;
++
++ bytes = readl(chip->regs + ATMEL_PDC_TPR) - runtime->dma_addr;
++
++ pos = bytes_to_frames(runtime, bytes);
++
++ if (pos >= runtime->buffer_size)
++ pos -= runtime->buffer_size;
++
++ pr_debug("%s : snd_at91_ac97_playback_pointer\n\r", driver_name);
++
++ return pos;
++}
++
++static snd_pcm_uframes_t
++snd_at91_ac97_capture_pointer(struct snd_pcm_substream *substream)
++{
++ at91_ac97_t *chip = snd_pcm_substream_chip(substream);
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ snd_pcm_uframes_t pos;
++ unsigned long bytes;
++
++ bytes = readl(chip->regs + ATMEL_PDC_RPR) - runtime->dma_addr;
++ pos = bytes_to_frames(runtime, bytes);
++ if (pos >= runtime->buffer_size)
++ pos -= runtime->buffer_size;
++
++ pr_debug("%s : snd_at91_ac97_capture_pointer\n\r", driver_name);
++
++ return pos;
++}
++
++static struct snd_pcm_ops at91_ac97_playback_ops = {
++ .open = snd_at91_ac97_playback_open,
++ .close = snd_at91_ac97_playback_close,
++ .ioctl = snd_pcm_lib_ioctl,
++ .hw_params = snd_at91_ac97_playback_hw_params,
++ .hw_free = snd_at91_ac97_playback_hw_free,
++ .prepare = snd_at91_ac97_playback_prepare,
++ .trigger = snd_at91_ac97_playback_trigger,
++ .pointer = snd_at91_ac97_playback_pointer,
++};
++
++static struct snd_pcm_ops at91_ac97_capture_ops = {
++ .open = snd_at91_ac97_capture_open,
++ .close = snd_at91_ac97_capture_close,
++ .ioctl = snd_pcm_lib_ioctl,
++ .hw_params = snd_at91_ac97_capture_hw_params,
++ .hw_free = snd_at91_ac97_capture_hw_free,
++ .prepare = snd_at91_ac97_capture_prepare,
++ .trigger = snd_at91_ac97_capture_trigger,
++ .pointer = snd_at91_ac97_capture_pointer,
++};
++
++static struct ac97_pcm at91_ac97_pcm_defs[] __devinitdata = {
++ /* Playback */
++ {
++ .exclusive = 1,
++ .r = { {
++ .slots = ((1 << AC97_SLOT_PCM_LEFT)
++ | (1 << AC97_SLOT_PCM_RIGHT)),
++ } },
++ },
++ /* PCM in */
++ {
++ .stream = 1,
++ .exclusive = 1,
++ .r = { {
++ .slots = ((1 << AC97_SLOT_PCM_LEFT)
++ | (1 << AC97_SLOT_PCM_RIGHT)),
++ } }
++ },
++ /* Mic in */
++ {
++ .stream = 1,
++ .exclusive = 1,
++ .r = { {
++ .slots = (1<<AC97_SLOT_MIC),
++ } }
++ },
++};
++
++static int __devinit snd_at91_ac97_pcm_new(at91_ac97_t *chip)
++{
++ struct snd_pcm *pcm;
++ int err;
++
++ err = snd_ac97_pcm_assign(chip->ac97_bus,
++ ARRAY_SIZE(at91_ac97_pcm_defs),
++ at91_ac97_pcm_defs);
++ if (err)
++ return err;
++
++ err = snd_pcm_new(chip->card, "Atmel AC97", 0, 1, 1, &pcm);
++ if (err)
++ return err;
++
++ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
++ &chip->pdev->dev,
++ 128 * 1024, 256 * 1024);
++
++ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
++ &at91_ac97_playback_ops);
++ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &at91_ac97_capture_ops);
++
++ pcm->private_data = chip;
++ pcm->info_flags = 0;
++ strcpy(pcm->name, "Atmel AC97");
++ chip->pcm = pcm;
++
++ return 0;
++}
++
++
++/*
++ * Mixer part
++ */
++static int snd_at91_ac97_mixer_new(at91_ac97_t *chip)
++{
++ int err;
++ struct snd_ac97_template template;
++
++ memset(&template, 0, sizeof(template));
++ template.private_data = chip;
++ template.num = 0;
++ template.addr = 0;
++ err = snd_ac97_mixer(chip->ac97_bus, &template, &chip->ac97);
++
++ return err;
++}
++
++static irqreturn_t snd_at91_ac97_interrupt(int irq, void *dev_id)
++{
++ at91_ac97_t *chip = dev_id;
++ unsigned long status;
++ unsigned long dummy;
++
++ status = ac97c_readl(chip, SR);
++
++ if (status & AT91C_AC97C_CAEVT) {
++ struct snd_pcm_runtime *runtime;
++ int offset, next_period, block_size;
++ unsigned long casr, camr, test;
++
++ casr = ac97c_readl(chip, CASR);
++ camr = ac97c_readl(chip, CAMR);
++ test = casr & camr;
++
++ if ((casr & camr) & AT91C_AC97C_ENDTX) {
++ runtime = chip->playback_substream->runtime;
++ block_size = frames_to_bytes(runtime,
++ runtime->period_size);
++ chip->period++;
++
++ if (chip->period == runtime->periods)
++ chip->period = 0;
++ next_period = chip->period + 1;
++ if (next_period == runtime->periods)
++ next_period = 0;
++
++ offset = block_size * next_period;
++
++ writel(runtime->dma_addr + offset,
++ chip->regs + ATMEL_PDC_TNPR);
++ writel(block_size / 2, chip->regs + ATMEL_PDC_TNCR);
++
++ snd_pcm_period_elapsed(chip->playback_substream);
++ }
++ if ((casr & camr) & AT91C_AC97C_ENDRX) {
++ runtime = chip->capture_substream->runtime;
++ block_size = frames_to_bytes(runtime,
++ runtime->period_size);
++ chip->period++;
++
++ if (chip->period == runtime->periods)
++ chip->period = 0;
++ next_period = chip->period + 1;
++ if (next_period == runtime->periods)
++ next_period = 0;
++
++ offset = block_size * next_period;
++
++ writel(runtime->dma_addr + offset,
++ chip->regs + ATMEL_PDC_RNPR);
++ writel(block_size / 2, chip->regs + ATMEL_PDC_RNCR);
++ snd_pcm_period_elapsed(chip->capture_substream);
++ }
++ if ((casr & camr) & AT91C_AC97C_OVRUN)
++ printk(KERN_INFO " AC97_irq - overrun!\n");
++ } else {
++ printk(KERN_WARNING
++ "Spurious AC97 interrupt, status = 0x%08lx\n",
++ status);
++ }
++
++ dummy = ac97c_readl(chip, SR);
++
++ return IRQ_HANDLED;
++}
++
++
++/*
++ * CODEC part
++ */
++static void snd_at91_ac97_hard_reset(at91_ac97_t *chip)
++{
++ /* Enable AC97 Controller.*/
++ /* Perform a cold (hard) reset of the AC97 codec.*/
++ ac97c_writel(chip, MR, 0);
++ ac97c_writel(chip, MR, AT91C_AC97C_ENA);
++
++ at91_ac97c_drive_reset(chip, 0);
++ udelay(1);
++ at91_ac97c_drive_reset(chip, 1);
++ udelay(1);
++}
++
++static void snd_at91_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
++ unsigned short val)
++{
++ at91_ac97_t *chip = ac97->private_data;
++ unsigned long word;
++ int timeout = 0x100;
++
++ pr_debug("%s : Writing codec register 0x%x = 0x%x\n\r",
++ driver_name, reg, val);
++
++ word = (reg & 0x7f) << 16 | val;
++
++ do {
++ if (ac97c_readl(chip, COSR) & AT91C_AC97C_TXRDY) {
++ ac97c_writel(chip, COTHR, word);
++ return;
++ }
++ udelay(1);
++ } while (--timeout);
++
++ snd_printk(KERN_WARNING "at91-ac97: codec write timeout\n\r");
++}
++
++static unsigned short snd_at91_ac97_read(struct snd_ac97 *ac97,
++ unsigned short reg)
++{
++ at91_ac97_t *chip = ac97->private_data;
++ unsigned long word;
++ int timeout = 40;
++
++ word = (0x80 | (reg & 0x7f)) << 16;
++
++ do {
++ if (ac97c_readl(chip, COSR) & AT91C_AC97C_TXRDY) {
++ ac97c_writel(chip, COTHR, word);
++ break;
++ }
++ udelay(1);
++ } while (--timeout);
++
++ if (!timeout)
++ goto timed_out;
++
++ timeout = 0x100;
++
++ do {
++ if (ac97c_readl(chip, COSR) & AT91C_AC97C_RXRDY) {
++ unsigned short val =
++ (unsigned short) ac97c_readl(chip, CORHR);
++ return val;
++ }
++ udelay(1);
++ } while (--timeout);
++
++ if (!timeout)
++ goto timed_out;
++
++timed_out:
++ snd_printk(KERN_WARNING "at91-ac97: codec write timeout\n\r");
++ return 0xffff;
++}
++
++static void snd_at91_ac97_warm_reset(struct snd_ac97 *ac97)
++{
++ at91_ac97_t *chip = ac97->private_data;
++ unsigned int mr = ac97c_readl(chip, MR);
++
++ mr |= AT91C_AC97C_WRST;
++
++ ac97c_writel(chip, MR, mr);
++ udelay(1);
++
++ mr &= ~AT91C_AC97C_WRST;
++ ac97c_writel(chip, MR, mr);
++}
++
++static void snd_at91_ac97_destroy(struct snd_card *card)
++{
++ at91_ac97_t *chip = get_chip(card);
++
++ if (chip->irq != -1)
++ free_irq(chip->irq, chip);
++
++ if (chip->regs)
++ iounmap(chip->regs);
++}
++
++static int __devinit snd_at91_ac97_create(struct snd_card *card,
++ struct platform_device *pdev)
++{
++ static struct snd_ac97_bus_ops ops = {
++ .write = snd_at91_ac97_write,
++ .read = snd_at91_ac97_read,
++ .reset = snd_at91_ac97_warm_reset,
++ };
++
++ at91_ac97_t *chip = get_chip(card);
++ int irq, err = 0;
++
++
++
++ card->private_free = snd_at91_ac97_destroy;
++
++ spin_lock_init(&chip->lock);
++ chip->card = card;
++ chip->pdev = pdev;
++ chip->irq = -1;
++
++ if (!(platform_resource_flags(pdev, 0) & IORESOURCE_MEM)
++ || !(platform_resource_flags(pdev, 1) & IORESOURCE_IRQ))
++ return -ENODEV;
++
++ irq = platform_resource_start(pdev, 1);
++
++ err = request_irq(irq, snd_at91_ac97_interrupt, 0, "ac97", chip);
++ if (err) {
++ snd_printk(KERN_WARNING "unable to request IRQ%d\n", irq);
++ return err;
++ }
++
++ chip->irq = irq;
++ snd_printk(KERN_INFO "AC97C regs = %08X \n",
++ platform_resource_start(pdev, 0));
++ snd_printk(KERN_INFO "AC97C irq = %d \n", irq);
++
++ chip->regs = ioremap(platform_resource_start(pdev, 0),
++ platform_resource_len(pdev, 0));
++ if (!chip->regs) {
++ snd_printk(KERN_WARNING "unable to remap AC97C io memory\n");
++ return -ENOMEM;
++ }
++
++ snd_card_set_dev(card, &pdev->dev);
++
++ err = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus);
++
++ return err;
++}
++
++static int __devinit snd_at91_ac97_probe(struct platform_device *pdev)
++{
++ static int dev;
++ struct atmel_ac97_data *pdata = pdev->dev.platform_data;
++ struct snd_card *card;
++ at91_ac97_t *chip;
++ int err;
++
++ if (dev >= SNDRV_CARDS)
++ return -ENODEV;
++ if (!enable[dev]) {
++ dev++;
++ return -ENOENT;
++ }
++
++ card = snd_card_new(index[dev], id[dev], THIS_MODULE,
++ sizeof(at91_ac97_t));
++ if (!card)
++ return -ENOMEM;
++ chip = get_chip(card);
++
++ err = snd_at91_ac97_create(card, pdev);
++ if (err)
++ goto out_free_card;
++
++ /* Enable AC97 Controller clock*/
++ chip->reset_pin = pdata->reset_pin;
++ chip->ac97_clk = clk_get(NULL, "ac97_clk");
++ if (!chip->ac97_clk)
++ goto out_free_card;
++
++ clk_enable(chip->ac97_clk);
++
++ /* Perform a codec hard reset.*/
++ /* This also enables the AC97 Controller.*/
++ snd_at91_ac97_hard_reset(chip);
++
++ err = snd_at91_ac97_mixer_new(chip);
++ if (err)
++ goto out_free_card;
++
++ err = snd_at91_ac97_pcm_new(chip);
++ if (err)
++ goto out_free_card;
++
++ strcpy(card->driver, "ac97c");
++ strcpy(card->shortname, "Atmel AC97");
++ sprintf(card->longname, "Atmel AC97 Controller at %#lx, irq %i",
++ (unsigned long) platform_resource_start(pdev, 0),
++ (int) chip->irq);
++
++ err = snd_card_register(card);
++ if (err)
++ goto out_free_card;
++
++ dev_set_drvdata(&pdev->dev, card);
++ dev++;
++ return 0;
++
++out_free_card:
++ snd_card_free(card);
++ return err;
++}
++
++static int __devexit snd_at91_ac97_remove(struct platform_device *pdev)
++{
++ struct snd_card *card = dev_get_drvdata(&pdev->dev);
++ at91_ac97_t *chip = get_chip(card);
++
++
++ snd_card_free(card);
++
++ /* Disable AC97 Controller*/
++ ac97c_writel(chip, MR, 0);
++
++ /* Disable AC97 Controller clock*/
++ clk_disable(chip->ac97_clk);
++
++ dev_set_drvdata(&pdev->dev, NULL);
++
++ return 0;
++}
++
++static struct platform_driver at91_ac97_driver = {
++ .probe = snd_at91_ac97_probe,
++ .remove = __devexit_p(snd_at91_ac97_remove),
++ .driver =
++ {
++ .name = "ac97c",
++ }
++ ,
++};
++
++static int __init at91_ac97_init(void)
++{
++ return platform_driver_register(&at91_ac97_driver);
++}
++
++static void __exit at91_ac97_exit(void)
++{
++ platform_driver_unregister(&at91_ac97_driver);
++}
++
++module_init(at91_ac97_init);
++module_exit(at91_ac97_exit);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("Driver for Atmel AC97 Controller");
++MODULE_AUTHOR("Atmel");
+--- /dev/null
++++ linux-2.6.30/sound/arm/at91-ac97.h
+@@ -0,0 +1,295 @@
++/*
++ * at91-ac97.h -- Hardware definition for the ac97c peripheral
++ * in the ATMEL at91sam926x processor
++ *
++ * Copyright (C) 2005 SAN People
++ * Copyright (C) 2006 Atmel
++ *
++ * Author: Patrice Vilchez <patrice.vilchez@atmel.com>
++ * ATMEL CORP.
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#ifndef __AC97C_H
++#define __AC97C_H
++
++/* -------------------------------------------------------- */
++/* AC97C ID definitions for AT91SAM926x */
++/* -------------------------------------------------------- */
++#ifndef AT91C_ID_AC97C
++#define AT91C_ID_AC97C 18 /**< AC97 Controller id */
++#endif /* AT91C_ID_AC97C */
++
++/* -------------------------------------------------------- */
++/* AC97C Base Address definitions for AT91SAM926x */
++/* -------------------------------------------------------- */
++#define AT91C_BASE_AC97C 0xFFFA0000 /**< AC97C base address */
++
++/* -------------------------------------------------------- */
++/* PIO definition for AC97C hardware peripheral */
++/* -------------------------------------------------------- */
++#define AT91C_PB1_AC97CK (1 << 1) /**< */
++#define AT91C_PB0_AC97FS (1 << 0) /**< */
++#define AT91C_PB3_AC97RX (1 << 3) /**< */
++#define AT91C_PB2_AC97TX (1 << 2) /**< */
++
++/* -------------------------------------------------------- */
++/* Register offset definition for AC97C hardware peripheral */
++/* -------------------------------------------------------- */
++#define AC97C_MR (0x0008) /**< Mode Register */
++#define AC97C_ICA (0x0010) /**< Input Channel AssignementRegister */
++#define AC97C_OCA (0x0014) /**< Output Channel Assignement Register */
++#define AC97C_CARHR (0x0020) /**< Channel A Receive Holding Register */
++#define AC97C_CATHR (0x0024) /**< Channel A Transmit Holding Register */
++#define AC97C_CASR (0x0028) /**< Channel A Status Register */
++#define AC97C_CAMR (0x002C) /**< Channel A Mode Register */
++#define AC97C_CBRHR (0x0030) /**< Channel B Receive Holding Register (optional) */
++#define AC97C_CBTHR (0x0034) /**< Channel B Transmit Holding Register (optional) */
++#define AC97C_CBSR (0x0038) /**< Channel B Status Register */
++#define AC97C_CBMR (0x003C) /**< Channel B Mode Register */
++#define AC97C_CORHR (0x0040) /**< COdec Transmit Holding Register */
++#define AC97C_COTHR (0x0044) /**< COdec Transmit Holding Register */
++#define AC97C_COSR (0x0048) /**< CODEC Status Register */
++#define AC97C_COMR (0x004C) /**< CODEC Mask Status Register */
++#define AC97C_SR (0x0050) /**< Status Register */
++#define AC97C_IER (0x0054) /**< Interrupt Enable Register */
++#define AC97C_IDR (0x0058) /**< Interrupt Disable Register */
++#define AC97C_IMR (0x005C) /**< Interrupt Mask Register */
++#define AC97C_VERSION (0x00FC) /**< Version Register */
++
++/* -------------------------------------------------------- */
++/* Bitfields definition for AC97C hardware peripheral */
++/* -------------------------------------------------------- */
++/* --- Register AC97C_MR */
++#define AT91C_AC97C_ENA (0x1 << 0) /**< (AC97C) AC97 Controller Global Enable */
++#define AT91C_AC97C_WRST (0x1 << 1) /**< (AC97C) Warm Reset */
++#define AT91C_AC97C_VRA (0x1 << 2) /**< (AC97C) Variable RAte (for Data Slots) */
++/* --- Register AC97C_ICA */
++#define AT91C_AC97C_CHID3 (0x7 << 0) /**< (AC97C) Channel Id for the input slot 3 */
++#define AT91C_AC97C_CHID3_NONE 0x0 /**< (AC97C) No data will be transmitted during this slot */
++#define AT91C_AC97C_CHID3_CA 0x1 /**< (AC97C) Channel A data will be transmitted during this slot */
++#define AT91C_AC97C_CHID3_CB 0x2 /**< (AC97C) Channel B data will be transmitted during this slot */
++#define AT91C_AC97C_CHID3_CC 0x3 /**< (AC97C) Channel C data will be transmitted during this slot */
++#define AT91C_AC97C_CHID4 (0x7 << 3) /**< (AC97C) Channel Id for the input slot 4 */
++#define AT91C_AC97C_CHID4_NONE (0x0 << 3) /**< (AC97C) No data will be transmitted during this slot */
++#define AT91C_AC97C_CHID4_CA (0x1 << 3) /**< (AC97C) Channel A data will be transmitted during this slot */
++#define AT91C_AC97C_CHID4_CB (0x2 << 3) /**< (AC97C) Channel B data will be transmitted during this slot */
++#define AT91C_AC97C_CHID4_CC (0x3 << 3) /**< (AC97C) Channel C data will be transmitted during this slot */
++#define AT91C_AC97C_CHID5 (0x7 << 6) /**< (AC97C) Channel Id for the input slot 5 */
++#define AT91C_AC97C_CHID5_NONE (0x0 << 6) /**< (AC97C) No data will be transmitted during this slot */
++#define AT91C_AC97C_CHID5_CA (0x1 << 6) /**< (AC97C) Channel A data will be transmitted during this slot */
++#define AT91C_AC97C_CHID5_CB (0x2 << 6) /**< (AC97C) Channel B data will be transmitted during this slot */
++#define AT91C_AC97C_CHID5_CC (0x3 << 6) /**< (AC97C) Channel C data will be transmitted during this slot */
++#define AT91C_AC97C_CHID6 (0x7 << 9) /**< (AC97C) Channel Id for the input slot 6 */
++#define AT91C_AC97C_CHID6_NONE (0x0 << 9) /**< (AC97C) No data will be transmitted during this slot */
++#define AT91C_AC97C_CHID6_CA (0x1 << 9) /**< (AC97C) Channel A data will be transmitted during this slot */
++#define AT91C_AC97C_CHID6_CB (0x2 << 9) /**< (AC97C) Channel B data will be transmitted during this slot */
++#define AT91C_AC97C_CHID6_CC (0x3 << 9) /**< (AC97C) Channel C data will be transmitted during this slot */
++#define AT91C_AC97C_CHID7 (0x7 << 12) /**< (AC97C) Channel Id for the input slot 7 */
++#define AT91C_AC97C_CHID7_NONE (0x0 << 12) /**< (AC97C) No data will be transmitted during this slot */
++#define AT91C_AC97C_CHID7_CA (0x1 << 12) /**< (AC97C) Channel A data will be transmitted during this slot */
++#define AT91C_AC97C_CHID7_CB (0x2 << 12) /**< (AC97C) Channel B data will be transmitted during this slot */
++#define AT91C_AC97C_CHID7_CC (0x3 << 12) /**< (AC97C) Channel C data will be transmitted during this slot */
++#define AT91C_AC97C_CHID8 (0x7 << 15) /**< (AC97C) Channel Id for the input slot 8 */
++#define AT91C_AC97C_CHID8_NONE (0x0 << 15) /**< (AC97C) No data will be transmitted during this slot */
++#define AT91C_AC97C_CHID8_CA (0x1 << 15) /**< (AC97C) Channel A data will be transmitted during this slot */
++#define AT91C_AC97C_CHID8_CB (0x2 << 15) /**< (AC97C) Channel B data will be transmitted during this slot */
++#define AT91C_AC97C_CHID8_CC (0x3 << 15) /**< (AC97C) Channel C data will be transmitted during this slot */
++#define AT91C_AC97C_CHID9 (0x7 << 18) /**< (AC97C) Channel Id for the input slot 9 */
++#define AT91C_AC97C_CHID9_NONE (0x0 << 18) /**< (AC97C) No data will be transmitted during this slot */
++#define AT91C_AC97C_CHID9_CA (0x1 << 18) /**< (AC97C) Channel A data will be transmitted during this slot */
++#define AT91C_AC97C_CHID9_CB (0x2 << 18) /**< (AC97C) Channel B data will be transmitted during this slot */
++#define AT91C_AC97C_CHID9_CC (0x3 << 18) /**< (AC97C) Channel C data will be transmitted during this slot */
++#define AT91C_AC97C_CHID10 (0x7 << 21) /**< (AC97C) Channel Id for the input slot 10 */
++#define AT91C_AC97C_CHID10_NONE (0x0 << 21) /**< (AC97C) No data will be transmitted during this slot */
++#define AT91C_AC97C_CHID10_CA (0x1 << 21) /**< (AC97C) Channel A data will be transmitted during this slot */
++#define AT91C_AC97C_CHID10_CB (0x2 << 21) /**< (AC97C) Channel B data will be transmitted during this slot */
++#define AT91C_AC97C_CHID10_CC (0x3 << 21) /**< (AC97C) Channel C data will be transmitted during this slot */
++#define AT91C_AC97C_CHID11 (0x7 << 24) /**< (AC97C) Channel Id for the input slot 11 */
++#define AT91C_AC97C_CHID11_NONE (0x0 << 24) /**< (AC97C) No data will be transmitted during this slot */
++#define AT91C_AC97C_CHID11_CA (0x1 << 24) /**< (AC97C) Channel A data will be transmitted during this slot */
++#define AT91C_AC97C_CHID11_CB (0x2 << 24) /**< (AC97C) Channel B data will be transmitted during this slot */
++#define AT91C_AC97C_CHID11_CC (0x3 << 24) /**< (AC97C) Channel C data will be transmitted during this slot */
++#define AT91C_AC97C_CHID12 (0x7 << 27) /**< (AC97C) Channel Id for the input slot 12 */
++#define AT91C_AC97C_CHID12_NONE (0x0 << 27) /**< (AC97C) No data will be transmitted during this slot */
++#define AT91C_AC97C_CHID12_CA (0x1 << 27) /**< (AC97C) Channel A data will be transmitted during this slot */
++#define AT91C_AC97C_CHID12_CB (0x2 << 27) /**< (AC97C) Channel B data will be transmitted during this slot */
++#define AT91C_AC97C_CHID12_CC (0x3 << 27) /**< (AC97C) Channel C data will be transmitted during this slot */
++/* --- Register AC97C_OCA */
++#define AT91C_AC97C_CHID3 (0x7 << 0) /**< (AC97C) Channel Id for the input slot 3 */
++#define AT91C_AC97C_CHID3_NONE 0x0 /**< (AC97C) No data will be transmitted during this slot */
++#define AT91C_AC97C_CHID3_CA 0x1 /**< (AC97C) Channel A data will be transmitted during this slot */
++#define AT91C_AC97C_CHID3_CB 0x2 /**< (AC97C) Channel B data will be transmitted during this slot */
++#define AT91C_AC97C_CHID3_CC 0x3 /**< (AC97C) Channel C data will be transmitted during this slot */
++#define AT91C_AC97C_CHID4 (0x7 << 3) /**< (AC97C) Channel Id for the input slot 4 */
++#define AT91C_AC97C_CHID4_NONE (0x0 << 3) /**< (AC97C) No data will be transmitted during this slot */
++#define AT91C_AC97C_CHID4_CA (0x1 << 3) /**< (AC97C) Channel A data will be transmitted during this slot */
++#define AT91C_AC97C_CHID4_CB (0x2 << 3) /**< (AC97C) Channel B data will be transmitted during this slot */
++#define AT91C_AC97C_CHID4_CC (0x3 << 3) /**< (AC97C) Channel C data will be transmitted during this slot */
++#define AT91C_AC97C_CHID5 (0x7 << 6) /**< (AC97C) Channel Id for the input slot 5 */
++#define AT91C_AC97C_CHID5_NONE (0x0 << 6) /**< (AC97C) No data will be transmitted during this slot */
++#define AT91C_AC97C_CHID5_CA (0x1 << 6) /**< (AC97C) Channel A data will be transmitted during this slot */
++#define AT91C_AC97C_CHID5_CB (0x2 << 6) /**< (AC97C) Channel B data will be transmitted during this slot */
++#define AT91C_AC97C_CHID5_CC (0x3 << 6) /**< (AC97C) Channel C data will be transmitted during this slot */
++#define AT91C_AC97C_CHID6 (0x7 << 9) /**< (AC97C) Channel Id for the input slot 6 */
++#define AT91C_AC97C_CHID6_NONE (0x0 << 9) /**< (AC97C) No data will be transmitted during this slot */
++#define AT91C_AC97C_CHID6_CA (0x1 << 9) /**< (AC97C) Channel A data will be transmitted during this slot */
++#define AT91C_AC97C_CHID6_CB (0x2 << 9) /**< (AC97C) Channel B data will be transmitted during this slot */
++#define AT91C_AC97C_CHID6_CC (0x3 << 9) /**< (AC97C) Channel C data will be transmitted during this slot */
++#define AT91C_AC97C_CHID7 (0x7 << 12) /**< (AC97C) Channel Id for the input slot 7 */
++#define AT91C_AC97C_CHID7_NONE (0x0 << 12) /**< (AC97C) No data will be transmitted during this slot */
++#define AT91C_AC97C_CHID7_CA (0x1 << 12) /**< (AC97C) Channel A data will be transmitted during this slot */
++#define AT91C_AC97C_CHID7_CB (0x2 << 12) /**< (AC97C) Channel B data will be transmitted during this slot */
++#define AT91C_AC97C_CHID7_CC (0x3 << 12) /**< (AC97C) Channel C data will be transmitted during this slot */
++#define AT91C_AC97C_CHID8 (0x7 << 15) /**< (AC97C) Channel Id for the input slot 8 */
++#define AT91C_AC97C_CHID8_NONE (0x0 << 15) /**< (AC97C) No data will be transmitted during this slot */
++#define AT91C_AC97C_CHID8_CA (0x1 << 15) /**< (AC97C) Channel A data will be transmitted during this slot */
++#define AT91C_AC97C_CHID8_CB (0x2 << 15) /**< (AC97C) Channel B data will be transmitted during this slot */
++#define AT91C_AC97C_CHID8_CC (0x3 << 15) /**< (AC97C) Channel C data will be transmitted during this slot */
++#define AT91C_AC97C_CHID9 (0x7 << 18) /**< (AC97C) Channel Id for the input slot 9 */
++#define AT91C_AC97C_CHID9_NONE (0x0 << 18) /**< (AC97C) No data will be transmitted during this slot */
++#define AT91C_AC97C_CHID9_CA (0x1 << 18) /**< (AC97C) Channel A data will be transmitted during this slot */
++#define AT91C_AC97C_CHID9_CB (0x2 << 18) /**< (AC97C) Channel B data will be transmitted during this slot */
++#define AT91C_AC97C_CHID9_CC (0x3 << 18) /**< (AC97C) Channel C data will be transmitted during this slot */
++#define AT91C_AC97C_CHID10 (0x7 << 21) /**< (AC97C) Channel Id for the input slot 10 */
++#define AT91C_AC97C_CHID10_NONE (0x0 << 21) /**< (AC97C) No data will be transmitted during this slot */
++#define AT91C_AC97C_CHID10_CA (0x1 << 21) /**< (AC97C) Channel A data will be transmitted during this slot */
++#define AT91C_AC97C_CHID10_CB (0x2 << 21) /**< (AC97C) Channel B data will be transmitted during this slot */
++#define AT91C_AC97C_CHID10_CC (0x3 << 21) /**< (AC97C) Channel C data will be transmitted during this slot */
++#define AT91C_AC97C_CHID11 (0x7 << 24) /**< (AC97C) Channel Id for the input slot 11 */
++#define AT91C_AC97C_CHID11_NONE (0x0 << 24) /**< (AC97C) No data will be transmitted during this slot */
++#define AT91C_AC97C_CHID11_CA (0x1 << 24) /**< (AC97C) Channel A data will be transmitted during this slot */
++#define AT91C_AC97C_CHID11_CB (0x2 << 24) /**< (AC97C) Channel B data will be transmitted during this slot */
++#define AT91C_AC97C_CHID11_CC (0x3 << 24) /**< (AC97C) Channel C data will be transmitted during this slot */
++#define AT91C_AC97C_CHID12 (0x7 << 27) /**< (AC97C) Channel Id for the input slot 12 */
++#define AT91C_AC97C_CHID12_NONE (0x0 << 27) /**< (AC97C) No data will be transmitted during this slot */
++#define AT91C_AC97C_CHID12_CA (0x1 << 27) /**< (AC97C) Channel A data will be transmitted during this slot */
++#define AT91C_AC97C_CHID12_CB (0x2 << 27) /**< (AC97C) Channel B data will be transmitted during this slot */
++#define AT91C_AC97C_CHID12_CC (0x3 << 27) /**< (AC97C) Channel C data will be transmitted during this slot */
++/* --- Register AC97C_CARHR */
++#define AT91C_AC97C_RDATA (0xFFFFF << 0) /**< (AC97C) Receive data */
++/* --- Register AC97C_CATHR */
++#define AT91C_AC97C_TDATA (0xFFFFF << 0) /**< (AC97C) Transmit data */
++/* --- Register AC97C_CASR */
++#define AT91C_AC97C_TXRDY (0x1 << 0) /**< (AC97C) */
++#define AT91C_AC97C_TXEMPTY (0x1 << 1) /**< (AC97C) */
++#define AT91C_AC97C_UNRUN (0x1 << 2) /**< (AC97C) */
++#define AT91C_AC97C_RXRDY (0x1 << 4) /**< (AC97C) */
++#define AT91C_AC97C_OVRUN (0x1 << 5) /**< (AC97C) */
++#define AT91C_AC97C_ENDTX (0x1 << 10) /**< (AC97C) */
++#define AT91C_AC97C_TXBUFE (0x1 << 11) /**< (AC97C) */
++#define AT91C_AC97C_ENDRX (0x1 << 14) /**< (AC97C) */
++#define AT91C_AC97C_RXBUFF (0x1 << 15) /**< (AC97C) */
++/* --- Register AC97C_CAMR */
++#define AT91C_AC97C_TXRDY (0x1 << 0) /**< (AC97C) */
++#define AT91C_AC97C_TXEMPTY (0x1 << 1) /**< (AC97C) */
++#define AT91C_AC97C_UNRUN (0x1 << 2) /**< (AC97C) */
++#define AT91C_AC97C_RXRDY (0x1 << 4) /**< (AC97C) */
++#define AT91C_AC97C_OVRUN (0x1 << 5) /**< (AC97C) */
++#define AT91C_AC97C_ENDTX (0x1 << 10) /**< (AC97C) */
++#define AT91C_AC97C_TXBUFE (0x1 << 11) /**< (AC97C) */
++#define AT91C_AC97C_ENDRX (0x1 << 14) /**< (AC97C) */
++#define AT91C_AC97C_RXBUFF (0x1 << 15) /**< (AC97C) */
++#define AT91C_AC97C_SIZE (0x3 << 16) /**< (AC97C) */
++#define AT91C_AC97C_SIZE_20_BITS (0x0 << 16) /**< (AC97C) Data size is 20 bits */
++#define AT91C_AC97C_SIZE_18_BITS (0x1 << 16) /**< (AC97C) Data size is 18 bits */
++#define AT91C_AC97C_SIZE_16_BITS (0x2 << 16) /**< (AC97C) Data size is 16 bits */
++#define AT91C_AC97C_SIZE_10_BITS (0x3 << 16) /**< (AC97C) Data size is 10 bits */
++#define AT91C_AC97C_CEM (0x1 << 18) /**< (AC97C) */
++#define AT91C_AC97C_CEN (0x1 << 21) /**< (AC97C) */
++#define AT91C_AC97C_PDCEN (0x1 << 22) /**< (AC97C) */
++/* --- Register AC97C_CBRHR */
++#define AT91C_AC97C_RDATA (0xFFFFF << 0) /**< (AC97C) Receive data */
++/* --- Register AC97C_CBTHR */
++#define AT91C_AC97C_TDATA (0xFFFFF << 0) /**< (AC97C) Transmit data */
++/* --- Register AC97C_CBSR */
++#define AT91C_AC97C_TXRDY (0x1 << 0) /**< (AC97C) */
++#define AT91C_AC97C_TXEMPTY (0x1 << 1) /**< (AC97C) */
++#define AT91C_AC97C_UNRUN (0x1 << 2) /**< (AC97C) */
++#define AT91C_AC97C_RXRDY (0x1 << 4) /**< (AC97C) */
++#define AT91C_AC97C_OVRUN (0x1 << 5) /**< (AC97C) */
++/* --- Register AC97C_CBMR */
++#define AT91C_AC97C_TXRDY (0x1 << 0) /**< (AC97C) */
++#define AT91C_AC97C_TXEMPTY (0x1 << 1) /**< (AC97C) */
++#define AT91C_AC97C_UNRUN (0x1 << 2) /**< (AC97C) */
++#define AT91C_AC97C_RXRDY (0x1 << 4) /**< (AC97C) */
++#define AT91C_AC97C_OVRUN (0x1 << 5) /**< (AC97C) */
++#define AT91C_AC97C_SIZE (0x3 << 16) /**< (AC97C) */
++#define AT91C_AC97C_SIZE_20_BITS (0x0 << 16) /**< (AC97C) Data size is 20 bits */
++#define AT91C_AC97C_SIZE_18_BITS (0x1 << 16) /**< (AC97C) Data size is 18 bits */
++#define AT91C_AC97C_SIZE_16_BITS (0x2 << 16) /**< (AC97C) Data size is 16 bits */
++#define AT91C_AC97C_SIZE_10_BITS (0x3 << 16) /**< (AC97C) Data size is 10 bits */
++#define AT91C_AC97C_CEM (0x1 << 18) /**< (AC97C) */
++#define AT91C_AC97C_CEN (0x1 << 21) /**< (AC97C) */
++/* --- Register AC97C_CORHR */
++#define AT91C_AC97C_SDATA (0xFFFF << 0) /**< (AC97C) Status Data */
++/* --- Register AC97C_COTHR */
++#define AT91C_AC97C_CDATA (0xFFFF << 0) /**< (AC97C) Command Data */
++#define AT91C_AC97C_CADDR (0x7F << 16) /**< (AC97C) COdec control register index */
++#define AT91C_AC97C_READ (0x1 << 23) /**< (AC97C) Read/Write command */
++/* --- Register AC97C_COSR */
++#define AT91C_AC97C_TXRDY (0x1 << 0) /**< (AC97C) */
++#define AT91C_AC97C_TXEMPTY (0x1 << 1) /**< (AC97C) */
++#define AT91C_AC97C_UNRUN (0x1 << 2) /**< (AC97C) */
++#define AT91C_AC97C_RXRDY (0x1 << 4) /**< (AC97C) */
++/* --- Register AC97C_COMR */
++#define AT91C_AC97C_TXRDY (0x1 << 0) /**< (AC97C) */
++#define AT91C_AC97C_TXEMPTY (0x1 << 1) /**< (AC97C) */
++#define AT91C_AC97C_UNRUN (0x1 << 2) /**< (AC97C) */
++#define AT91C_AC97C_RXRDY (0x1 << 4) /**< (AC97C) */
++/* --- Register AC97C_SR */
++#define AT91C_AC97C_SOF (0x1 << 0) /**< (AC97C) */
++#define AT91C_AC97C_WKUP (0x1 << 1) /**< (AC97C) */
++#define AT91C_AC97C_COEVT (0x1 << 2) /**< (AC97C) */
++#define AT91C_AC97C_CAEVT (0x1 << 3) /**< (AC97C) */
++#define AT91C_AC97C_CBEVT (0x1 << 4) /**< (AC97C) */
++/* --- Register AC97C_IER */
++#define AT91C_AC97C_SOF (0x1 << 0) /**< (AC97C) */
++#define AT91C_AC97C_WKUP (0x1 << 1) /**< (AC97C) */
++#define AT91C_AC97C_COEVT (0x1 << 2) /**< (AC97C) */
++#define AT91C_AC97C_CAEVT (0x1 << 3) /**< (AC97C) */
++#define AT91C_AC97C_CBEVT (0x1 << 4) /**< (AC97C) */
++/* --- Register AC97C_IDR */
++#define AT91C_AC97C_SOF (0x1 << 0) /**< (AC97C) */
++#define AT91C_AC97C_WKUP (0x1 << 1) /**< (AC97C) */
++#define AT91C_AC97C_COEVT (0x1 << 2) /**< (AC97C) */
++#define AT91C_AC97C_CAEVT (0x1 << 3) /**< (AC97C) */
++#define AT91C_AC97C_CBEVT (0x1 << 4) /**< (AC97C) */
++/* --- Register AC97C_IMR */
++#define AT91C_AC97C_SOF (0x1 << 0) /**< (AC97C) */
++#define AT91C_AC97C_WKUP (0x1 << 1) /**< (AC97C) */
++#define AT91C_AC97C_COEVT (0x1 << 2) /**< (AC97C) */
++#define AT91C_AC97C_CAEVT (0x1 << 3) /**< (AC97C) */
++#define AT91C_AC97C_CBEVT (0x1 << 4) /**< (AC97C) */
++
++#define platform_num_resources(dev) ((dev)->num_resources)
++#define platform_resource_start(dev, i) ((dev)->resource[(i)].start)
++#define platform_resource_end(dev, i) ((dev)->resource[(i)].end)
++#define platform_resource_flags(dev, i) ((dev)->resource[(i)].flags)
++#define platform_resource_len(dev, i) \
++ (platform_resource_end((dev), (i)) - \
++ platform_resource_start((dev), (i)) + 1)
++
++#define get_chip(card) ((at91_ac97_t *)(card)->private_data)
++
++#define ac97c_writel(chip, reg, val) \
++ writel((val), (chip)->regs + AC97C_##reg)
++
++#define ac97c_readl(chip, reg) \
++ readl((chip)->regs + AC97C_##reg)
++
++#endif /* __AC97C_H */