summaryrefslogtreecommitdiff
path: root/packages/linux/linux-2.6.18/atmel-ac97c-alsa-driver.patch
diff options
context:
space:
mode:
Diffstat (limited to 'packages/linux/linux-2.6.18/atmel-ac97c-alsa-driver.patch')
-rw-r--r--packages/linux/linux-2.6.18/atmel-ac97c-alsa-driver.patch1383
1 files changed, 0 insertions, 1383 deletions
diff --git a/packages/linux/linux-2.6.18/atmel-ac97c-alsa-driver.patch b/packages/linux/linux-2.6.18/atmel-ac97c-alsa-driver.patch
deleted file mode 100644
index fe3d2ee209..0000000000
--- a/packages/linux/linux-2.6.18/atmel-ac97c-alsa-driver.patch
+++ /dev/null
@@ -1,1383 +0,0 @@
----
- sound/avr32/Kconfig | 25 +
- sound/avr32/Makefile | 3
- sound/avr32/ac97c.c | 1250 +++++++++++++++++++++++++++++++++++++++++++++++++++
- sound/avr32/ac97c.h | 71 ++
- 4 files changed, 1349 insertions(+)
-
-Index: linux-2.6.18-avr32/sound/avr32/Kconfig
-===================================================================
---- linux-2.6.18-avr32.orig/sound/avr32/Kconfig 2006-11-02 15:56:20.000000000 +0100
-+++ linux-2.6.18-avr32/sound/avr32/Kconfig 2006-11-02 16:02:29.000000000 +0100
-@@ -3,4 +3,29 @@
- menu "ALSA AVR32 devices"
- depends on SND != n && AVR32
-
-+config SND_ATMEL_AC97
-+ tristate "Atmel AC97 Controller Driver"
-+ depends on SND
-+ select SND_PCM
-+ select SND_AC97_CODEC
-+ help
-+ ALSA sound driver for the Atmel AC97 controller.
-+
-+config SND_ATMEL_AC97_USE_ALSA_MALLOC_CALLS
-+ bool "Use the built-in malloc calls in the alsa driver"
-+ default n
-+ depends on SND_ATMEL_AC97
-+ help
-+ Say Y if the built-in malloc calls in the alsa driver should be
-+ used instead of the native dma_alloc_coherent and dma_free_coherent
-+ function calls. Enabling this feature may break the rmmod feature.
-+
-+config SND_ATMEL_AC97C_USE_PDC
-+ bool "Use PDC for DMA transfers to/from the Atmel AC97 Controller"
-+ default n
-+ depends on SND_ATMEL_AC97
-+ help
-+ Say Y if PDC (Peripheral DMA Controller) is used for DMA transfers
-+ to/from the Atmel AC97C instead of using the generic DMA framework.
-+
- endmenu
-Index: linux-2.6.18-avr32/sound/avr32/Makefile
-===================================================================
---- linux-2.6.18-avr32.orig/sound/avr32/Makefile 2006-11-02 15:56:20.000000000 +0100
-+++ linux-2.6.18-avr32/sound/avr32/Makefile 2006-11-02 16:02:29.000000000 +0100
-@@ -1,3 +1,6 @@
- #
- # Makefile for ALSA
- #
-+
-+snd-atmel-ac97-objs := ac97c.o
-+obj-$(CONFIG_SND_ATMEL_AC97) += snd-atmel-ac97.o
-Index: linux-2.6.18-avr32/sound/avr32/ac97c.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.18-avr32/sound/avr32/ac97c.c 2006-11-02 16:02:56.000000000 +0100
-@@ -0,0 +1,1250 @@
-+/*
-+ * Driver for the Atmel AC97 Controller
-+ *
-+ * Copyright (C) 2005-2006 Atmel Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#include <linux/clk.h>
-+#include <linux/delay.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/init.h>
-+#include <linux/interrupt.h>
-+#include <linux/module.h>
-+#include <linux/platform_device.h>
-+#include <linux/mutex.h>
-+
-+#include <sound/driver.h>
-+#include <sound/core.h>
-+#include <sound/initval.h>
-+#include <sound/pcm.h>
-+#include <sound/pcm_params.h>
-+#include <sound/ac97_codec.h>
-+#ifndef SND_ATMEL_AC97_USE_ALSA_MALLOC_CALLS
-+#include <sound/memalloc.h>
-+#endif
-+
-+#include <asm/io.h>
-+
-+#include "ac97c.h"
-+
-+static DEFINE_MUTEX(opened_mutex);
-+
-+/* 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");
-+
-+#ifndef CONFIG_SND_ATMEL_AC97C_USE_PDC
-+#include <asm/dma-controller.h>
-+
-+struct atmel_ac97_dma_info {
-+ struct dma_request_cyclic req_tx;
-+ struct dma_request_cyclic req_rx;
-+ unsigned short rx_periph_id;
-+ unsigned short tx_periph_id;
-+};
-+#endif
-+
-+
-+typedef struct atmel_ac97 {
-+ spinlock_t lock;
-+ void __iomem *regs;
-+ int period;
-+
-+ snd_pcm_substream_t *playback_substream;
-+ snd_pcm_substream_t *capture_substream;
-+ snd_card_t *card;
-+ snd_pcm_t *pcm;
-+ ac97_t *ac97;
-+ ac97_bus_t *ac97_bus;
-+ int irq;
-+ int opened;
-+ u64 cur_format;
-+ unsigned int cur_rate;
-+ struct clk *mck;
-+ struct platform_device *pdev;
-+ struct atmel_ac97_dma_info dma;
-+} atmel_ac97_t;
-+#define get_chip(card) ((atmel_ac97_t *)(card)->private_data)
-+
-+#define ac97c_writel(chip, reg, val) \
-+ __raw_writel((val), (chip)->regs + AC97C_##reg)
-+#define ac97c_readl(chip, reg) \
-+ __raw_readl((chip)->regs + AC97C_##reg)
-+
-+/* PCM part */
-+
-+static snd_pcm_hardware_t snd_atmel_ac97_playback_hw = {
-+ .info = (SNDRV_PCM_INFO_INTERLEAVED
-+ |SNDRV_PCM_INFO_MMAP
-+ |SNDRV_PCM_INFO_MMAP_VALID
-+ |SNDRV_PCM_INFO_BLOCK_TRANSFER
-+ |SNDRV_PCM_INFO_JOINT_DUPLEX),
-+ .formats = (SNDRV_PCM_FMTBIT_S16_BE|SNDRV_PCM_FMTBIT_S16_LE),
-+ .rates = (SNDRV_PCM_RATE_CONTINUOUS),
-+ .rate_min = 4000,
-+ .rate_max = 48000,
-+ .channels_min = 1,
-+ .channels_max = 6,
-+ .buffer_bytes_max = 64*1024,
-+ .period_bytes_min = 512,
-+#ifdef CONFIG_SND_ATMEL_AC97C_USE_PDC
-+ .period_bytes_max = 64*1024,
-+#else
-+ .period_bytes_max = 4095,
-+#endif
-+ .periods_min = 8,
-+ .periods_max = 1024,
-+};
-+
-+static snd_pcm_hardware_t snd_atmel_ac97_capture_hw = {
-+ .info = (SNDRV_PCM_INFO_INTERLEAVED
-+ |SNDRV_PCM_INFO_MMAP
-+ |SNDRV_PCM_INFO_MMAP_VALID
-+ |SNDRV_PCM_INFO_BLOCK_TRANSFER
-+ |SNDRV_PCM_INFO_JOINT_DUPLEX),
-+ .formats = (SNDRV_PCM_FMTBIT_S16_BE|SNDRV_PCM_FMTBIT_S16_LE),
-+ .rates = (SNDRV_PCM_RATE_CONTINUOUS),
-+ .rate_min = 4000,
-+ .rate_max = 48000,
-+ .channels_min = 1,
-+ .channels_max = 2,
-+ .buffer_bytes_max = 64*1024,
-+ .period_bytes_min = 512,
-+#ifdef CONFIG_SND_ATMEL_AC97C_USE_PDC
-+ .period_bytes_max = 64*1024,
-+#else
-+ .period_bytes_max = 4095,
-+#endif
-+ .periods_min = 8,
-+ .periods_max = 1024,
-+};
-+
-+/* Joint full duplex variables */
-+unsigned int hw_rates[1];
-+unsigned int hw_formats[1];
-+struct snd_pcm_hw_constraint_list hw_constraint_rates;
-+struct snd_pcm_hw_constraint_list hw_constraint_formats;
-+
-+/*
-+ * PCM functions
-+ */
-+static int
-+snd_atmel_ac97_playback_open(snd_pcm_substream_t *substream)
-+{
-+ atmel_ac97_t *chip = snd_pcm_substream_chip(substream);
-+ snd_pcm_runtime_t *runtime = substream->runtime;
-+
-+ mutex_lock(&opened_mutex);
-+ chip->opened++;
-+ runtime->hw = snd_atmel_ac97_playback_hw;
-+ if (chip->cur_rate) {
-+ runtime->hw.rate_min = chip->cur_rate;
-+ runtime->hw.rate_max = chip->cur_rate;
-+ }
-+ if (chip->cur_format)
-+ runtime->hw.formats = (1ULL<<chip->cur_format);
-+ mutex_unlock(&opened_mutex);
-+ chip->playback_substream = substream;
-+ chip->period = 0;
-+ return 0;
-+}
-+
-+static int
-+snd_atmel_ac97_capture_open(snd_pcm_substream_t *substream)
-+{
-+ atmel_ac97_t *chip = snd_pcm_substream_chip(substream);
-+ snd_pcm_runtime_t *runtime = substream->runtime;
-+
-+ mutex_lock(&opened_mutex);
-+ chip->opened++;
-+ runtime->hw = snd_atmel_ac97_capture_hw;
-+ if (chip->cur_rate) {
-+ runtime->hw.rate_min = chip->cur_rate;
-+ runtime->hw.rate_max = chip->cur_rate;
-+ }
-+ if (chip->cur_format)
-+ runtime->hw.formats = (1ULL<<chip->cur_format);
-+ mutex_unlock(&opened_mutex);
-+ chip->capture_substream = substream;
-+ chip->period = 0;
-+ return 0;
-+}
-+
-+static int snd_atmel_ac97_playback_close(snd_pcm_substream_t *substream)
-+{
-+ atmel_ac97_t *chip = snd_pcm_substream_chip(substream);
-+ mutex_lock(&opened_mutex);
-+ chip->opened--;
-+ if (!chip->opened) {
-+ chip->cur_rate = 0;
-+ chip->cur_format = 0;
-+ }
-+ mutex_unlock(&opened_mutex);
-+ return 0;
-+}
-+
-+static int snd_atmel_ac97_capture_close(snd_pcm_substream_t *substream)
-+{
-+ atmel_ac97_t *chip = snd_pcm_substream_chip(substream);
-+ mutex_lock(&opened_mutex);
-+ chip->opened--;
-+ if (!chip->opened) {
-+ chip->cur_rate = 0;
-+ chip->cur_format = 0;
-+ }
-+ mutex_unlock(&opened_mutex);
-+ return 0;
-+}
-+
-+static int snd_atmel_ac97_playback_hw_params(snd_pcm_substream_t *substream,
-+ snd_pcm_hw_params_t *hw_params)
-+{
-+ atmel_ac97_t *chip = snd_pcm_substream_chip(substream);
-+#ifdef SND_ATMEL_AC97_USE_ALSA_MALLOC_CALLS
-+ int err;
-+ err = snd_pcm_lib_malloc_pages(substream,
-+ params_buffer_bytes(hw_params));
-+
-+ if (err < 0)
-+ return err;
-+
-+ /* Set restrictions to params */
-+ mutex_lock(&opened_mutex);
-+ chip->cur_rate = params_rate(hw_params);
-+ chip->cur_format = params_format(hw_params);
-+ mutex_unlock(&opened_mutex);
-+
-+ return err;
-+#else
-+ int pg;
-+ size_t size = params_buffer_bytes(hw_params);
-+ struct snd_pcm_runtime *runtime;
-+ struct snd_dma_buffer *dmab = NULL;
-+
-+ substream->dma_buffer.dev.type = SNDRV_DMA_TYPE_DEV;
-+ snd_assert(substream != NULL, return -EINVAL);
-+ runtime = substream->runtime;
-+ snd_assert(runtime != NULL, return -EINVAL);
-+
-+ /* Set restrictions to params */
-+ mutex_lock(&opened_mutex);
-+ chip->cur_rate = params_rate(hw_params);
-+ chip->cur_format = params_format(hw_params);
-+ mutex_unlock(&opened_mutex);
-+
-+ /* check if buffer is already allocated */
-+ if (runtime->dma_buffer_p) {
-+ size_t size_previouse;
-+ int pg_previouse;
-+
-+ /* new buffer is smaler than previouse allocated buffer */
-+ if (runtime->dma_buffer_p->bytes >= size) {
-+ runtime->dma_bytes = size;
-+ return 0; /* don't change buffer size */
-+ }
-+
-+ size_previouse = runtime->dma_buffer_p->bytes;
-+ pg_previouse = get_order(size_previouse);
-+
-+ dma_free_coherent(runtime->dma_buffer_p->dev.dev,
-+ PAGE_SIZE << pg_previouse,
-+ runtime->dma_buffer_p->area,
-+ runtime->dma_buffer_p->addr);
-+
-+ kfree(runtime->dma_buffer_p);
-+ }
-+
-+ dmab = kzalloc(sizeof(*dmab), GFP_KERNEL);
-+ if (!dmab)
-+ return -ENOMEM;
-+
-+ dmab->dev = substream->dma_buffer.dev;
-+ dmab->bytes = 0;
-+
-+ pg = get_order(size);
-+
-+ dmab->area = dma_alloc_coherent(
-+ substream->dma_buffer.dev.dev,
-+ PAGE_SIZE << pg,
-+ (dma_addr_t *)&dmab->addr,
-+ GFP_KERNEL);
-+
-+ if (!dmab->area) {
-+ kfree(dmab);
-+ return -ENOMEM;
-+ }
-+
-+ dmab->bytes = size;
-+
-+ snd_pcm_set_runtime_buffer(substream, dmab);
-+ runtime->dma_bytes = size;
-+ return 1;
-+#endif
-+}
-+
-+static int snd_atmel_ac97_capture_hw_params(snd_pcm_substream_t *substream,
-+ snd_pcm_hw_params_t *hw_params)
-+{
-+ atmel_ac97_t *chip = snd_pcm_substream_chip(substream);
-+#ifdef SND_ATMEL_AC97_USE_ALSA_MALLOC_CALLS
-+ int err;
-+ err = snd_pcm_lib_malloc_pages(substream,
-+ params_buffer_bytes(hw_params));
-+
-+ if (err < 0)
-+ return err;
-+
-+ /* Set restrictions to params */
-+ mutex_lock(&opened_mutex);
-+ chip->cur_rate = params_rate(hw_params);
-+ chip->cur_format = params_format(hw_params);
-+ mutex_unlock(&opened_mutex);
-+
-+ return err;
-+#else
-+ int pg;
-+ size_t size = params_buffer_bytes(hw_params);
-+ struct snd_pcm_runtime *runtime;
-+ struct snd_dma_buffer *dmab = NULL;
-+
-+ substream->dma_buffer.dev.type = SNDRV_DMA_TYPE_DEV;
-+ snd_assert(substream != NULL, return -EINVAL);
-+ runtime = substream->runtime;
-+ snd_assert(runtime != NULL, return -EINVAL);
-+
-+ /* Set restrictions to params */
-+ mutex_lock(&opened_mutex);
-+ chip->cur_rate = params_rate(hw_params);
-+ chip->cur_format = params_format(hw_params);
-+ mutex_unlock(&opened_mutex);
-+
-+ /* check if buffer is already allocated */
-+ if (runtime->dma_buffer_p) {
-+ size_t size_previouse;
-+ int pg_previouse;
-+
-+ /* new buffer is smaler than previouse allocated buffer */
-+ if (runtime->dma_buffer_p->bytes >= size) {
-+ runtime->dma_bytes = size;
-+ return 0; /* don't change buffer size */
-+ }
-+
-+ size_previouse = runtime->dma_buffer_p->bytes;
-+ pg_previouse = get_order(size_previouse);
-+
-+ dma_free_coherent(runtime->dma_buffer_p->dev.dev,
-+ PAGE_SIZE << pg_previouse,
-+ runtime->dma_buffer_p->area,
-+ runtime->dma_buffer_p->addr);
-+
-+ kfree(runtime->dma_buffer_p);
-+ }
-+
-+ dmab = kzalloc(sizeof(*dmab), GFP_KERNEL);
-+ if (!dmab)
-+ return -ENOMEM;
-+
-+ dmab->dev = substream->dma_buffer.dev;
-+ dmab->bytes = 0;
-+
-+ pg = get_order(size);
-+
-+ dmab->area = dma_alloc_coherent(
-+ substream->dma_buffer.dev.dev,
-+ PAGE_SIZE << pg,
-+ (dma_addr_t *)&dmab->addr,
-+ GFP_KERNEL);
-+
-+ if (!dmab->area) {
-+ kfree(dmab);
-+ return -ENOMEM;
-+ }
-+
-+ dmab->bytes = size;
-+
-+ snd_pcm_set_runtime_buffer(substream, dmab);
-+ runtime->dma_bytes = size;
-+ return 1;
-+#endif
-+}
-+
-+static int snd_atmel_ac97_playback_hw_free(snd_pcm_substream_t *substream)
-+{
-+#ifdef SND_ATMEL_AC97_USE_ALSA_MALLOC_CALLS
-+ return snd_pcm_lib_free_pages(substream);
-+#else
-+ int pg;
-+ struct snd_pcm_runtime *runtime;
-+ struct snd_dma_buffer *dmab = NULL;
-+
-+ snd_assert(substream != NULL, return -EINVAL);
-+ runtime = substream->runtime;
-+ snd_assert(runtime != NULL, return -EINVAL);
-+ dmab = runtime->dma_buffer_p;
-+
-+ if (!dmab)
-+ return 0;
-+
-+ if (!dmab->area)
-+ return 0;
-+
-+ pg = get_order(dmab->bytes);
-+ dma_free_coherent(dmab->dev.dev, PAGE_SIZE << pg, dmab->area, dmab->addr);
-+ kfree(runtime->dma_buffer_p);
-+ snd_pcm_set_runtime_buffer(substream, NULL);
-+ return 0;
-+#endif
-+}
-+
-+static int snd_atmel_ac97_capture_hw_free(snd_pcm_substream_t *substream)
-+{
-+
-+#ifdef SND_ATMEL_AC97_USE_ALSA_MALLOC_CALLS
-+ return snd_pcm_lib_free_pages(substream);
-+#else
-+ int pg;
-+ struct snd_pcm_runtime *runtime;
-+ struct snd_dma_buffer *dmab = NULL;
-+
-+ snd_assert(substream != NULL, return -EINVAL);
-+ runtime = substream->runtime;
-+ snd_assert(runtime != NULL, return -EINVAL);
-+ dmab = runtime->dma_buffer_p;
-+
-+ if (!dmab)
-+ return 0;
-+
-+ if (!dmab->area)
-+ return 0;
-+
-+ pg = get_order(dmab->bytes);
-+ dma_free_coherent(dmab->dev.dev, PAGE_SIZE << pg, dmab->area, dmab->addr);
-+ kfree(runtime->dma_buffer_p);
-+ snd_pcm_set_runtime_buffer(substream, NULL);
-+ return 0;
-+#endif
-+}
-+
-+static int snd_atmel_ac97_playback_prepare(snd_pcm_substream_t *substream)
-+{
-+ atmel_ac97_t *chip = snd_pcm_substream_chip(substream);
-+ struct platform_device *pdev = chip->pdev;
-+ snd_pcm_runtime_t *runtime = substream->runtime;
-+ int block_size = frames_to_bytes(runtime, runtime->period_size);
-+ unsigned long word = 0;
-+ unsigned long buffer_size = 0;
-+
-+ dma_sync_single_for_device(&pdev->dev, runtime->dma_addr,
-+ block_size * 2, DMA_TO_DEVICE);
-+
-+ /* Assign slots to channels */
-+ switch (substream->runtime->channels) {
-+ case 1:
-+ word |= AC97C_CH_ASSIGN(PCM_LEFT, A);
-+ break;
-+ case 2:
-+ /* Assign Left and Right slot to Channel A */
-+ word |= AC97C_CH_ASSIGN(PCM_LEFT, A)
-+ | AC97C_CH_ASSIGN(PCM_RIGHT, A);
-+ break;
-+ default:
-+ /* TODO: support more than two channels */
-+ return -EINVAL;
-+ break;
-+ }
-+ ac97c_writel(chip, OCA, word);
-+
-+ /* Configure sample format and size */
-+ word = AC97C_CMR_PDCEN | AC97C_CMR_SIZE_16;
-+
-+ switch (runtime->format){
-+ case SNDRV_PCM_FORMAT_S16_LE:
-+ word |= AC97C_CMR_CEM_LITTLE;
-+ break;
-+ case SNDRV_PCM_FORMAT_S16_BE:
-+ default:
-+ word &= ~AC97C_CMR_CEM_LITTLE;
-+ break;
-+ }
-+
-+ ac97c_writel(chip, CAMR, word);
-+
-+ /* Set variable rate if needed */
-+ if (runtime->rate != 48000) {
-+ word = ac97c_readl(chip, MR);
-+ word |= AC97C_MR_VRA;
-+ ac97c_writel(chip, MR, word);
-+ } else {
-+ /* Clear Variable Rate Bit */
-+ word = ac97c_readl(chip, MR);
-+ word &= ~AC97C_MR_VRA;
-+ ac97c_writel(chip, MR, word);
-+ }
-+
-+ /* Set rate */
-+ snd_ac97_set_rate(chip->ac97, AC97_PCM_FRONT_DAC_RATE, runtime->rate);
-+
-+#ifdef CONFIG_SND_ATMEL_AC97C_USE_PDC
-+ /* Initialize and start the PDC */
-+ ac97c_writel(chip, CATPR, runtime->dma_addr);
-+ ac97c_writel(chip, CATCR, block_size / 4);
-+ ac97c_writel(chip, CATNPR, runtime->dma_addr + block_size);
-+ ac97c_writel(chip, CATNCR, block_size / 4);
-+ ac97c_writel(chip, PTCR, PDC_PTCR_TXTEN);
-+ /* Enable Channel A interrupts */
-+ ac97c_writel(chip, IER, AC97C_SR_CAEVT);
-+#else
-+ buffer_size = frames_to_bytes(runtime, runtime->period_size) *
-+ runtime->periods;
-+
-+ chip->dma.req_tx.buffer_size = buffer_size;
-+ chip->dma.req_tx.periods = runtime->periods;
-+
-+ BUG_ON(chip->dma.req_tx.buffer_size !=
-+ (chip->dma.req_tx.periods *
-+ frames_to_bytes(runtime, runtime->period_size)));
-+
-+ chip->dma.req_tx.buffer_start = runtime->dma_addr;
-+ chip->dma.req_tx.data_reg = (dma_addr_t)(chip->regs + AC97C_CATHR + 2);
-+ chip->dma.req_tx.periph_id = chip->dma.tx_periph_id;
-+ chip->dma.req_tx.direction = DMA_DIR_MEM_TO_PERIPH;
-+ chip->dma.req_tx.width = DMA_WIDTH_16BIT;
-+ chip->dma.req_tx.dev_id = chip;
-+#endif
-+
-+ return 0;
-+}
-+
-+static int snd_atmel_ac97_capture_prepare(snd_pcm_substream_t *substream)
-+{
-+ atmel_ac97_t *chip = snd_pcm_substream_chip(substream);
-+ struct platform_device *pdev = chip->pdev;
-+ snd_pcm_runtime_t *runtime = substream->runtime;
-+ int block_size = frames_to_bytes(runtime, runtime->period_size);
-+ unsigned long word = 0;
-+ unsigned long buffer_size = 0;
-+
-+ dma_sync_single_for_device(&pdev->dev, runtime->dma_addr,
-+ block_size * 2, DMA_FROM_DEVICE);
-+
-+ /* Assign slots to channels */
-+ switch (substream->runtime->channels) {
-+ case 1:
-+ word |= AC97C_CH_ASSIGN(PCM_LEFT, A);
-+ break;
-+ case 2:
-+ /* Assign Left and Right slot to Channel A */
-+ word |= AC97C_CH_ASSIGN(PCM_LEFT, A)
-+ | AC97C_CH_ASSIGN(PCM_RIGHT, A);
-+ break;
-+ default:
-+ /* TODO: support more than two channels */
-+ return -EINVAL;
-+ break;
-+ }
-+ ac97c_writel(chip, ICA, word);
-+
-+ /* Configure sample format and size */
-+ word = AC97C_CMR_PDCEN | AC97C_CMR_SIZE_16;
-+
-+ switch (runtime->format) {
-+ case SNDRV_PCM_FORMAT_S16_LE:
-+ word |= AC97C_CMR_CEM_LITTLE;
-+ break;
-+ case SNDRV_PCM_FORMAT_S16_BE:
-+ default:
-+ word &= ~(AC97C_CMR_CEM_LITTLE);
-+ break;
-+ }
-+
-+ ac97c_writel(chip, CAMR, word);
-+
-+ /* Set variable rate if needed */
-+ if (runtime->rate != 48000) {
-+ word = ac97c_readl(chip, MR);
-+ word |= AC97C_MR_VRA;
-+ ac97c_writel(chip, MR, word);
-+ } else {
-+ /* Clear Variable Rate Bit */
-+ word = ac97c_readl(chip, MR);
-+ word &= ~(AC97C_MR_VRA);
-+ ac97c_writel(chip, MR, word);
-+ }
-+
-+ /* Set rate */
-+ snd_ac97_set_rate(chip->ac97, AC97_PCM_LR_ADC_RATE, runtime->rate);
-+
-+#ifdef CONFIG_SND_ATMEL_AC97C_USE_PDC
-+ /* Initialize and start the PDC */
-+ ac97c_writel(chip, CARPR, runtime->dma_addr);
-+ ac97c_writel(chip, CARCR, block_size / 4);
-+ ac97c_writel(chip, CARNPR, runtime->dma_addr + block_size);
-+ ac97c_writel(chip, CARNCR, block_size / 4);
-+ ac97c_writel(chip, PTCR, PDC_PTCR_RXEN);
-+ /* Enable Channel A interrupts */
-+ ac97c_writel(chip, IER, AC97C_SR_CAEVT);
-+#else
-+ buffer_size = frames_to_bytes(runtime, runtime->period_size) *
-+ runtime->periods;
-+
-+ chip->dma.req_rx.buffer_size = buffer_size;
-+ chip->dma.req_rx.periods = runtime->periods;
-+
-+ BUG_ON(chip->dma.req_rx.buffer_size !=
-+ (chip->dma.req_rx.periods *
-+ frames_to_bytes(runtime, runtime->period_size)));
-+
-+ chip->dma.req_rx.buffer_start = runtime->dma_addr;
-+ chip->dma.req_rx.data_reg = (dma_addr_t)(chip->regs + AC97C_CARHR + 2);
-+ chip->dma.req_rx.periph_id = chip->dma.rx_periph_id;
-+ chip->dma.req_rx.direction = DMA_DIR_PERIPH_TO_MEM;
-+ chip->dma.req_rx.width = DMA_WIDTH_16BIT;
-+ chip->dma.req_rx.dev_id = chip;
-+#endif
-+
-+ return 0;
-+}
-+
-+static int snd_atmel_ac97_playback_trigger(snd_pcm_substream_t *substream, int cmd)
-+{
-+ atmel_ac97_t *chip = snd_pcm_substream_chip(substream);
-+ unsigned long camr;
-+ int flags, err = 0;
-+
-+ spin_lock_irqsave(&chip->lock, flags);
-+ camr = ac97c_readl(chip, CAMR);
-+
-+ switch (cmd) {
-+ case SNDRV_PCM_TRIGGER_START:
-+ err = dma_prepare_request_cyclic(chip->dma.req_tx.req.dmac,
-+ &chip->dma.req_tx);
-+ dma_start_request(chip->dma.req_tx.req.dmac,
-+ chip->dma.req_tx.req.channel);
-+ camr |= (AC97C_CMR_CENA
-+#ifdef CONFIG_SND_ATMEL_AC97C_USE_PDC
-+ |AC97C_CMR_TXRDY
-+#endif
-+ );
-+ break;
-+ case SNDRV_PCM_TRIGGER_STOP:
-+ err = dma_stop_request(chip->dma.req_tx.req.dmac,
-+ chip->dma.req_tx.req.channel);
-+ if (chip->opened <= 1) {
-+ camr &= ~(AC97C_CMR_CENA
-+#ifdef CONFIG_SND_ATMEL_AC97C_USE_PDC
-+ |AC97C_CMR_TXRDY
-+#endif
-+ );
-+ }
-+#ifdef CONFIG_SND_ATMEL_AC97C_USE_PDC
-+ else {
-+ camr &= ~(AC97C_CMR_TXRDY);
-+ }
-+#endif
-+ break;
-+ default:
-+ err = -EINVAL;
-+ break;
-+ }
-+
-+ ac97c_writel(chip, CAMR, camr);
-+
-+ spin_unlock_irqrestore(&chip->lock, flags);
-+ return err;
-+}
-+
-+static int snd_atmel_ac97_capture_trigger(snd_pcm_substream_t *substream, int cmd)
-+{
-+ atmel_ac97_t *chip = snd_pcm_substream_chip(substream);
-+ unsigned long camr;
-+ int flags, err = 0;
-+
-+ spin_lock_irqsave(&chip->lock, flags);
-+ camr = ac97c_readl(chip, CAMR);
-+
-+ switch (cmd) {
-+ case SNDRV_PCM_TRIGGER_START:
-+ err = dma_prepare_request_cyclic(chip->dma.req_rx.req.dmac,
-+ &chip->dma.req_rx);
-+ dma_start_request(chip->dma.req_rx.req.dmac,
-+ chip->dma.req_rx.req.channel);
-+ camr |= (AC97C_CMR_CENA
-+#ifdef CONFIG_SND_ATMEL_AC97C_USE_PDC
-+ | AC97C_CMR_RXRDY
-+#endif
-+ );
-+ break;
-+ case SNDRV_PCM_TRIGGER_STOP:
-+ err = dma_stop_request(chip->dma.req_rx.req.dmac,
-+ chip->dma.req_rx.req.channel);
-+ mutex_lock(&opened_mutex);
-+ if (chip->opened <= 1) {
-+ camr &= ~(AC97C_CMR_CENA
-+#ifdef CONFIG_SND_ATMEL_AC97C_USE_PDC
-+ | AC97C_CMR_RXRDY
-+#endif
-+ );
-+ }
-+#ifdef CONFIG_SND_ATMEL_AC97C_USE_PDC
-+ else {
-+ camr &= ~(AC97C_CSR_RXRDY);
-+ }
-+#endif
-+ mutex_unlock(&opened_mutex);
-+ break;
-+ default:
-+ err = -EINVAL;
-+ break;
-+ }
-+
-+ ac97c_writel(chip, CAMR, camr);
-+
-+ spin_unlock_irqrestore(&chip->lock, flags);
-+ return err;
-+}
-+
-+static snd_pcm_uframes_t snd_atmel_ac97_playback_pointer(snd_pcm_substream_t *substream)
-+{
-+ atmel_ac97_t *chip = snd_pcm_substream_chip(substream);
-+ snd_pcm_runtime_t *runtime = substream->runtime;
-+ snd_pcm_uframes_t pos;
-+ unsigned long bytes;
-+
-+#ifdef CONFIG_SND_ATMEL_AC97C_USE_PDC
-+ bytes = ac97c_readl(chip, CATPR) - runtime->dma_addr;
-+#else
-+ bytes = (dma_get_current_pos
-+ (chip->dma.req_tx.req.dmac,
-+ chip->dma.req_tx.req.channel) - runtime->dma_addr);
-+#endif
-+ pos = bytes_to_frames(runtime, bytes);
-+ if (pos >= runtime->buffer_size)
-+ pos -= runtime->buffer_size;
-+
-+ return pos;
-+}
-+
-+static snd_pcm_uframes_t snd_atmel_ac97_capture_pointer(snd_pcm_substream_t *substream)
-+{
-+ atmel_ac97_t *chip = snd_pcm_substream_chip(substream);
-+ snd_pcm_runtime_t *runtime = substream->runtime;
-+ snd_pcm_uframes_t pos;
-+ unsigned long bytes;
-+
-+#ifdef CONFIG_SND_ATMEL_AC97C_USE_PDC
-+ bytes = ac97c_readl(chip, CARPR) - runtime->dma_addr;
-+#else
-+ bytes = (dma_get_current_pos
-+ (chip->dma.req_rx.req.dmac,chip->dma.req_rx.req.channel) -
-+ runtime->dma_addr);
-+#endif
-+ pos = bytes_to_frames(runtime, bytes);
-+ if (pos >= runtime->buffer_size)
-+ pos -= runtime->buffer_size;
-+
-+
-+ return pos;
-+}
-+
-+static snd_pcm_ops_t atmel_ac97_playback_ops = {
-+ .open = snd_atmel_ac97_playback_open,
-+ .close = snd_atmel_ac97_playback_close,
-+ .ioctl = snd_pcm_lib_ioctl,
-+ .hw_params = snd_atmel_ac97_playback_hw_params,
-+ .hw_free = snd_atmel_ac97_playback_hw_free,
-+ .prepare = snd_atmel_ac97_playback_prepare,
-+ .trigger = snd_atmel_ac97_playback_trigger,
-+ .pointer = snd_atmel_ac97_playback_pointer,
-+};
-+
-+static snd_pcm_ops_t atmel_ac97_capture_ops = {
-+ .open = snd_atmel_ac97_capture_open,
-+ .close = snd_atmel_ac97_capture_close,
-+ .ioctl = snd_pcm_lib_ioctl,
-+ .hw_params = snd_atmel_ac97_capture_hw_params,
-+ .hw_free = snd_atmel_ac97_capture_hw_free,
-+ .prepare = snd_atmel_ac97_capture_prepare,
-+ .trigger = snd_atmel_ac97_capture_trigger,
-+ .pointer = snd_atmel_ac97_capture_pointer,
-+};
-+
-+static struct ac97_pcm atmel_ac97_pcm_defs[] __devinitdata = {
-+ /* Playback */
-+ {
-+ .exclusive = 1,
-+ .r = { {
-+ .slots = ((1 << AC97_SLOT_PCM_LEFT)
-+ | (1 << AC97_SLOT_PCM_RIGHT)
-+ | (1 << AC97_SLOT_PCM_CENTER)
-+ | (1 << AC97_SLOT_PCM_SLEFT)
-+ | (1 << AC97_SLOT_PCM_SRIGHT)
-+ | (1 << AC97_SLOT_LFE)),
-+ } }
-+ },
-+ /* 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_atmel_ac97_pcm_new(atmel_ac97_t *chip)
-+{
-+ snd_pcm_t *pcm;
-+ int err;
-+
-+ err = snd_ac97_pcm_assign(chip->ac97_bus,
-+ ARRAY_SIZE(atmel_ac97_pcm_defs),
-+ atmel_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_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
-+ &atmel_ac97_playback_ops);
-+
-+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
-+ &atmel_ac97_capture_ops);
-+
-+#ifdef SND_ATMEL_AC97_USE_ALSA_MALLOC_CALLS
-+ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-+ &chip->pdev->dev,
-+ 128 * 1024, 128 * 1024);
-+#endif
-+
-+ pcm->private_data = chip;
-+ pcm->info_flags = 0;
-+ strcpy(pcm->name, "Atmel-AC97");
-+ chip->pcm = pcm;
-+
-+ return 0;
-+}
-+
-+/* Mixer part */
-+static int snd_atmel_ac97_mixer_new(atmel_ac97_t *chip)
-+{
-+ int err;
-+ ac97_template_t template;
-+
-+ memset(&template, 0, sizeof(template));
-+ template.private_data = chip;
-+ err = snd_ac97_mixer(chip->ac97_bus, &template, &chip->ac97);
-+
-+ return err;
-+}
-+
-+#ifdef CONFIG_SND_ATMEL_AC97C_USE_PDC
-+static irqreturn_t snd_atmel_ac97_interrupt(int irq, void *dev_id,
-+ struct pt_regs *regs)
-+{
-+ atmel_ac97_t *chip = dev_id;
-+ unsigned long status;
-+
-+ status = ac97c_readl(chip, SR);
-+
-+ if (status & AC97C_SR_CAEVT) {
-+ snd_pcm_runtime_t *runtime;
-+ int offset, next_period, block_size;
-+ unsigned long casr;
-+
-+ /* FIXME: separate playback from capture */
-+ runtime = chip->playback_substream->runtime;
-+ block_size = frames_to_bytes(runtime, runtime->period_size);
-+
-+ casr = ac97c_readl(chip, CASR);
-+
-+ if (casr & AC97C_CSR_ENDTX) {
-+ 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;
-+
-+ ac97c_writel(chip, CATNPR,
-+ runtime->dma_addr + offset);
-+ ac97c_writel(chip, CATNCR, block_size / 4);
-+
-+ snd_pcm_period_elapsed(chip->playback_substream);
-+ }
-+ else if (casr & AC97C_CSR_ENDRX) {
-+ 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;
-+
-+ ac97c_writel(chip, CARNPR,
-+ runtime->dma_addr + offset);
-+ ac97c_writel(chip, CARNCR, block_size / 4);
-+
-+ snd_pcm_period_elapsed(chip->capture_substream);
-+ } else {
-+ snd_printk(KERN_INFO
-+ "atmel-ac97: spurious interrupt, status = 0x%08lx\n",
-+ (unsigned long)casr);
-+ }
-+ } else {
-+ snd_printk(KERN_INFO
-+ "atmel-ac97: spurious interrupt, status = 0x%08lx\n",
-+ status);
-+ }
-+
-+ (volatile int)ac97c_readl(chip, SR);
-+
-+ return IRQ_HANDLED;
-+}
-+
-+#else
-+
-+static void atmel_ac97_error(struct dma_request *_req)
-+{
-+ struct dma_request_cyclic *req = to_dma_request_cyclic(_req);
-+
-+ printk(KERN_WARNING
-+ "DMA Controller error, channel %d (AC97C)\n",
-+ req->req.channel);
-+}
-+
-+static void atmel_ac97_block_complete(struct dma_request *_req)
-+{
-+ struct dma_request_cyclic *req = to_dma_request_cyclic(_req);
-+ atmel_ac97_t *chip = req->dev_id;
-+ if (req->periph_id == chip->dma.tx_periph_id)
-+ snd_pcm_period_elapsed(chip->playback_substream);
-+ else
-+ snd_pcm_period_elapsed(chip->capture_substream);
-+}
-+
-+#endif
-+
-+/* CODEC part */
-+
-+static void snd_atmel_ac97_write(ac97_t *ac97, unsigned short reg,
-+ unsigned short val)
-+{
-+ atmel_ac97_t *chip = ac97->private_data;
-+ unsigned long word;
-+ int timeout = 40;
-+
-+ word = (reg & 0x7f) << 16 | val;
-+
-+ do {
-+ if (ac97c_readl(chip, COSR) & AC97C_CSR_TXRDY) {
-+ ac97c_writel(chip, COTHR, word);
-+ return;
-+ }
-+ udelay(1);
-+ } while (--timeout);
-+
-+ snd_printk(KERN_WARNING "atmel-ac97: codec write timeout\n");
-+}
-+
-+static unsigned short snd_atmel_ac97_read(ac97_t *ac97,
-+ unsigned short reg)
-+{
-+ atmel_ac97_t *chip = ac97->private_data;
-+ unsigned long word;
-+ int timeout = 40;
-+ int write = 10;
-+
-+ word = (0x80 | (reg & 0x7f)) << 16;
-+
-+ if ((ac97c_readl(chip, COSR) & AC97C_CSR_RXRDY) != 0)
-+ ac97c_readl(chip, CORHR);
-+
-+retry_write:
-+ timeout = 40;
-+
-+ do {
-+ if ((ac97c_readl(chip, COSR) & AC97C_CSR_TXRDY) != 0) {
-+ ac97c_writel(chip, COTHR, word);
-+ goto read_reg;
-+ }
-+ mdelay(10);
-+ } while (--timeout);
-+
-+ if (!--write)
-+ goto timed_out;
-+ goto retry_write;
-+
-+read_reg:
-+ do {
-+ if ((ac97c_readl(chip, COSR) & AC97C_CSR_RXRDY) != 0){
-+ unsigned short val = ac97c_readl(chip, CORHR);
-+ return val;
-+ }
-+ mdelay(10);
-+ } while (--timeout);
-+
-+ if (!--write)
-+ goto timed_out;
-+ goto retry_write;
-+
-+timed_out:
-+ snd_printk(KERN_INFO "atmel-ac97: codec read timeout\n");
-+ return 0xffff;
-+}
-+
-+static void snd_atmel_ac97_reset(atmel_ac97_t *chip)
-+{
-+ /* TODO: Perform hard reset of codec as well */
-+ ac97c_writel(chip, MR, AC97C_MR_WRST);
-+ mdelay(1);
-+ ac97c_writel(chip, MR, AC97C_MR_ENA);
-+}
-+
-+static void snd_atmel_ac97_destroy(snd_card_t *card)
-+{
-+ atmel_ac97_t *chip = get_chip(card);
-+
-+#ifdef CONFIG_SND_ATMEL_AC97C_USE_PDC
-+ if (chip->irq != -1)
-+ free_irq(chip->irq, chip);
-+#endif
-+ if (chip->regs)
-+ iounmap(chip->regs);
-+
-+ if (chip->mck) {
-+ clk_disable(chip->mck);
-+ clk_put(chip->mck);
-+ }
-+
-+#ifndef CONFIG_SND_ATMEL_AC97C_USE_PDC
-+ if (chip->dma.req_tx.req.dmac){
-+ dma_release_channel(chip->dma.req_tx.req.dmac,
-+ chip->dma.req_tx.req.channel);
-+ }
-+ if (chip->dma.req_rx.req.dmac) {
-+ dma_release_channel(chip->dma.req_rx.req.dmac,
-+ chip->dma.req_rx.req.channel);
-+ }
-+#endif
-+}
-+
-+static int __devinit snd_atmel_ac97_create(snd_card_t *card,
-+ struct platform_device *pdev)
-+{
-+ static ac97_bus_ops_t ops = {
-+ .write = snd_atmel_ac97_write,
-+ .read = snd_atmel_ac97_read,
-+ };
-+ atmel_ac97_t *chip = get_chip(card);
-+ struct resource *regs;
-+ struct clk *mck;
-+#ifdef CONFIG_SND_ATMEL_AC97C_USE_PDC
-+ int irq;
-+#endif
-+ int err;
-+
-+ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ if (!regs)
-+ return -ENXIO;
-+#ifdef CONFIG_SND_ATMEL_AC97C_USE_PDC
-+ irq = platform_get_irq(pdev, 0);
-+ if (irq < 0)
-+ return irq;
-+#endif
-+
-+ mck = clk_get(&pdev->dev, "mck");
-+ if (IS_ERR(mck))
-+ return PTR_ERR(mck);
-+ clk_enable(mck);
-+ chip->mck = mck;
-+
-+ card->private_free = snd_atmel_ac97_destroy;
-+
-+ spin_lock_init(&chip->lock);
-+ chip->card = card;
-+ chip->pdev = pdev;
-+ chip->irq = -1;
-+
-+#ifdef CONFIG_SND_ATMEL_AC97C_USE_PDC
-+ err = request_irq(irq, snd_atmel_ac97_interrupt, 0,
-+ "ac97", chip);
-+ if (err) {
-+ snd_printk("unable to request IRQ%d\n", irq);
-+ return err;
-+ }
-+ chip->irq = irq;
-+#endif
-+
-+ chip->regs = ioremap(regs->start, regs->end - regs->start + 1);
-+ if (!chip->regs)
-+ 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_atmel_ac97_probe(struct platform_device *pdev)
-+{
-+ static int dev;
-+ snd_card_t *card;
-+ atmel_ac97_t *chip;
-+ int err;
-+ int ch;
-+
-+ if (dev >= SNDRV_CARDS)
-+ return -ENODEV;
-+ if (!enable[dev]) {
-+ dev++;
-+ return -ENOENT;
-+ }
-+
-+ err = -ENOMEM;
-+
-+ mutex_init(&opened_mutex);
-+
-+ card = snd_card_new(index[dev], id[dev], THIS_MODULE,
-+ sizeof(atmel_ac97_t));
-+ if (!card)
-+ goto out;
-+ chip = get_chip(card);
-+
-+ err = snd_atmel_ac97_create(card, pdev);
-+ if (err)
-+ goto out_free_card;
-+
-+ snd_atmel_ac97_reset(chip);
-+
-+ err = snd_atmel_ac97_mixer_new(chip);
-+ if (err)
-+ goto out_free_card;
-+
-+ err = snd_atmel_ac97_pcm_new(chip);
-+ if (err)
-+ goto out_free_card;
-+
-+#ifndef CONFIG_SND_ATMEL_AC97C_USE_PDC
-+ /* TODO: Get this information from the platform device */
-+ chip->dma.req_tx.req.dmac = find_dma_controller(0);
-+ if (!chip->dma.req_tx.req.dmac) {
-+ printk(KERN_ERR
-+ "atmel-ac97c: No DMA controller for TX, aborting\n");
-+ goto out_free_card;
-+ }
-+ chip->dma.req_rx.req.dmac = find_dma_controller(0);
-+ if (!chip->dma.req_rx.req.dmac) {
-+ snd_printk(KERN_ERR
-+ "atmel-ac97c: No DMA controller available for RX, aborting\n");
-+ goto out_free_card;
-+ }
-+
-+ chip->dma.rx_periph_id = 3;
-+ chip->dma.tx_periph_id = 4;
-+
-+ ch = dma_alloc_channel(chip->dma.req_tx.req.dmac);
-+ if (ch < 0) {
-+ printk(KERN_ERR
-+ "atmel-ac97c: Unable to allocate TX DMA channel, aborting\n");
-+ goto out_free_card;
-+ }
-+ chip->dma.req_tx.req.channel = ch;
-+ chip->dma.req_tx.width = DMA_WIDTH_16BIT;
-+ chip->dma.req_tx.req.block_complete = atmel_ac97_block_complete;
-+ chip->dma.req_tx.req.error = atmel_ac97_error;
-+
-+ ch = dma_alloc_channel(chip->dma.req_rx.req.dmac);
-+ if (ch < 0) {
-+ snd_printk(KERN_ERR
-+ "atmel-ac97c: Unable to allocate RX DMA channel, aborting\n");
-+ goto out_free_card;
-+ }
-+ chip->dma.req_rx.req.channel = ch;
-+ chip->dma.req_rx.width = DMA_WIDTH_16BIT;
-+ chip->dma.req_rx.req.block_complete = atmel_ac97_block_complete;
-+ chip->dma.req_rx.req.error = atmel_ac97_error;
-+#endif
-+
-+ strcpy(card->driver, "ac97c");
-+ strcpy(card->shortname, "Atmel-AC97");
-+#ifdef CONFIG_SND_ATMEL_AC97C_USE_PDC
-+ sprintf(card->longname, "Atmel AVR32 AC97 Controller at 0x%p, irq %i",
-+ chip->regs, chip->irq);
-+#else
-+ sprintf(card->longname, "Atmel AVR32 AC97 Controller at 0x%p, dma rx %i and tx %i",
-+ chip->regs, chip->dma.rx_periph_id, chip->dma.tx_periph_id);
-+#endif
-+
-+ err = snd_card_register(card);
-+ if (err)
-+ goto out_free_card;
-+
-+ platform_set_drvdata(pdev, card);
-+ dev++;
-+ return 0;
-+
-+out_free_card:
-+ snd_card_free(card);
-+out:
-+ return err;
-+}
-+
-+static int __devexit snd_atmel_ac97_remove(struct platform_device *pdev)
-+{
-+ snd_card_t *card = platform_get_drvdata(pdev);
-+
-+ snd_card_free(card);
-+ platform_set_drvdata(pdev, NULL);
-+ return 0;
-+}
-+
-+static struct platform_driver atmel_ac97_driver = {
-+ .probe = snd_atmel_ac97_probe,
-+ .remove = __devexit_p(snd_atmel_ac97_remove),
-+ .driver = {
-+ .name = "ac97c",
-+ },
-+};
-+
-+static int __init atmel_ac97_init(void)
-+{
-+ return platform_driver_register(&atmel_ac97_driver);
-+}
-+
-+static void __exit atmel_ac97_exit(void)
-+{
-+ platform_driver_unregister(&atmel_ac97_driver);
-+}
-+
-+module_init(atmel_ac97_init);
-+module_exit(atmel_ac97_exit);
-+
-+MODULE_LICENSE("GPL");
-+MODULE_DESCRIPTION("Driver for Atmel AC97 Controller");
-+MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen@atmel.com>");
-Index: linux-2.6.18-avr32/sound/avr32/ac97c.h
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.18-avr32/sound/avr32/ac97c.h 2006-11-02 15:56:20.000000000 +0100
-@@ -0,0 +1,71 @@
-+/*
-+ * Register definitions for the Atmel AC97 Controller.
-+ *
-+ * Copyright (C) 2005-2006 Atmel Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#ifndef __SOUND_AVR32_AC97C_H
-+#define __SOUND_AVR32_AC97C_H
-+
-+#define AC97C_MR 0x08
-+#define AC97C_ICA 0x10
-+#define AC97C_OCA 0x14
-+#define AC97C_CARHR 0x20
-+#define AC97C_CATHR 0x24
-+#define AC97C_CASR 0x28
-+#define AC97C_CAMR 0x2c
-+#define AC97C_CBRHR 0x30
-+#define AC97C_CBTHR 0x34
-+#define AC97C_CBSR 0x38
-+#define AC97C_CBMR 0x3c
-+#define AC97C_CORHR 0x40
-+#define AC97C_COTHR 0x44
-+#define AC97C_COSR 0x48
-+#define AC97C_COMR 0x4c
-+#define AC97C_SR 0x50
-+#define AC97C_IER 0x54
-+#define AC97C_IDR 0x58
-+#define AC97C_IMR 0x5c
-+#define AC97C_VERSION 0xfc
-+
-+#define AC97C_CATPR PDC_TPR
-+#define AC97C_CATCR PDC_TCR
-+#define AC97C_CATNPR PDC_TNPR
-+#define AC97C_CATNCR PDC_TNCR
-+#define AC97C_CARPR PDC_RPR
-+#define AC97C_CARCR PDC_RCR
-+#define AC97C_CARNPR PDC_RNPR
-+#define AC97C_CARNCR PDC_RNCR
-+#define AC97C_PTCR PDC_PTCR
-+
-+#define AC97C_MR_ENA (1 << 0)
-+#define AC97C_MR_WRST (1 << 1)
-+#define AC97C_MR_VRA (1 << 2)
-+
-+#define AC97C_CSR_TXRDY (1 << 0)
-+#define AC97C_CSR_UNRUN (1 << 2)
-+#define AC97C_CSR_RXRDY (1 << 4)
-+#define AC97C_CSR_ENDTX (1 << 10)
-+#define AC97C_CSR_ENDRX (1 << 14)
-+
-+#define AC97C_CMR_SIZE_20 (0 << 16)
-+#define AC97C_CMR_SIZE_18 (1 << 16)
-+#define AC97C_CMR_SIZE_16 (2 << 16)
-+#define AC97C_CMR_SIZE_10 (3 << 16)
-+#define AC97C_CMR_CEM_LITTLE (1 << 18)
-+#define AC97C_CMR_CEM_BIG (0 << 18)
-+#define AC97C_CMR_CENA (1 << 21)
-+#define AC97C_CMR_PDCEN (1 << 22)
-+
-+#define AC97C_SR_CAEVT (1 << 3)
-+
-+#define AC97C_CH_ASSIGN(slot, channel) \
-+ (AC97C_CHANNEL_##channel << (3 * (AC97_SLOT_##slot - 3)))
-+#define AC97C_CHANNEL_NONE 0x0
-+#define AC97C_CHANNEL_A 0x1
-+#define AC97C_CHANNEL_B 0x2
-+
-+#endif /* __SOUND_AVR32_AC97C_H */