aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/coldfire/patches/009-Add-ALSA-driver-for-MCF5445x.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/coldfire/patches/009-Add-ALSA-driver-for-MCF5445x.patch')
-rw-r--r--target/linux/coldfire/patches/009-Add-ALSA-driver-for-MCF5445x.patch1869
1 files changed, 0 insertions, 1869 deletions
diff --git a/target/linux/coldfire/patches/009-Add-ALSA-driver-for-MCF5445x.patch b/target/linux/coldfire/patches/009-Add-ALSA-driver-for-MCF5445x.patch
deleted file mode 100644
index 52c1f56a8c..0000000000
--- a/target/linux/coldfire/patches/009-Add-ALSA-driver-for-MCF5445x.patch
+++ /dev/null
@@ -1,1869 +0,0 @@
-From d37d2d880efdc0ce515df4155ddafef3835d1b7f Mon Sep 17 00:00:00 2001
-From: Alison Wang <b18965@freescale.com>
-Date: Thu, 4 Aug 2011 09:59:41 +0800
-Subject: [PATCH 09/52] Add ALSA driver for MCF5445x
-
-Add ALSA driver for MCF54451 and MCF54455.
-
-Signed-off-by: Alison Wang <b18965@freescale.com>
----
- sound/Kconfig | 6 +-
- sound/Makefile | 1 +
- sound/coldfire/Kconfig | 14 +
- sound/coldfire/Makefile | 6 +
- sound/coldfire/coldfire-codec-spi.c | 93 ++
- sound/coldfire/snd-coldfire.c | 1664 +++++++++++++++++++++++++++++++++++
- sound/coldfire/snd-coldfire.h | 15 +
- 7 files changed, 1795 insertions(+), 4 deletions(-)
- create mode 100644 sound/coldfire/Kconfig
- create mode 100644 sound/coldfire/Makefile
- create mode 100644 sound/coldfire/coldfire-codec-spi.c
- create mode 100644 sound/coldfire/snd-coldfire.c
- create mode 100644 sound/coldfire/snd-coldfire.h
-
---- a/sound/Kconfig
-+++ b/sound/Kconfig
-@@ -59,8 +59,6 @@ config SOUND_OSS_CORE_PRECLAIM
-
- source "sound/oss/dmasound/Kconfig"
-
--if !M68K
--
- menuconfig SND
- tristate "Advanced Linux Sound Architecture"
- help
-@@ -85,6 +83,8 @@ source "sound/aoa/Kconfig"
-
- source "sound/arm/Kconfig"
-
-+source "sound/coldfire/Kconfig"
-+
- source "sound/atmel/Kconfig"
-
- source "sound/spi/Kconfig"
-@@ -121,8 +121,6 @@ source "sound/oss/Kconfig"
-
- endif # SOUND_PRIME
-
--endif # !M68K
--
- endif # SOUND
-
- # AC97_BUS is used from both sound and ucb1400
---- a/sound/Makefile
-+++ b/sound/Makefile
-@@ -8,6 +8,7 @@ obj-$(CONFIG_DMASOUND) += oss/
- obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ sh/ synth/ usb/ \
- sparc/ spi/ parisc/ pcmcia/ mips/ soc/ atmel/
- obj-$(CONFIG_SND_AOA) += aoa/
-+obj-$(CONFIG_SND_COLDFIRE) += coldfire/
-
- # This one must be compilable even if sound is configured out
- obj-$(CONFIG_AC97_BUS) += ac97_bus.o
---- /dev/null
-+++ b/sound/coldfire/Kconfig
-@@ -0,0 +1,14 @@
-+
-+menu "ALSA for Coldfire"
-+
-+config SND_COLDFIRE
-+ bool "Coldfire sound devices"
-+ depends on SND
-+ select SND_PCM
-+ select SSIAUDIO_USE_EDMA
-+ default y
-+ help
-+ Support for sound devices specific to Coldfire architectures.
-+
-+endmenu
-+
---- /dev/null
-+++ b/sound/coldfire/Makefile
-@@ -0,0 +1,6 @@
-+#
-+# Makefile for Coldfire ALSA
-+#
-+
-+obj-y += snd-coldfire.o coldfire-codec-spi.o
-+
---- /dev/null
-+++ b/sound/coldfire/coldfire-codec-spi.c
-@@ -0,0 +1,93 @@
-+/*
-+ * linux/sound/coldfire/coldfire-codec-spi.c
-+ *
-+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved.
-+ * Author: Kurt Mahan <kmahan@freescale.com>
-+ *
-+ * Simple SPI interface for the CODEC.
-+ *
-+ * This 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.
-+ */
-+
-+#include <linux/device.h>
-+#include <linux/init.h>
-+#include <linux/spi/spi.h>
-+#include <linux/kernel.h>
-+#include <asm/mcfsim.h>
-+#include <asm/coldfire.h>
-+#include <linux/delay.h>
-+
-+#define MCF_CODEC_SPI_DRIVER_NAME "mcf_codec_spi"
-+
-+static struct spi_device *mcf_codec_spi;
-+
-+/*
-+ * Write CODEC register via SPI
-+ */
-+int mcf_codec_spi_write(u8 addr, u16 data)
-+{
-+ u16 spi_word;
-+
-+ if (mcf_codec_spi == NULL)
-+ return -ENODEV;
-+
-+ spi_word = ((addr & 0x7F)<<9)|(data & 0x1FF);
-+ return spi_write(mcf_codec_spi, (const u8 *)&spi_word,
-+ sizeof(spi_word));
-+}
-+EXPORT_SYMBOL(mcf_codec_spi_write);
-+
-+static int __devinit mcf_codec_spi_probe(struct spi_device *spi)
-+{
-+ spi->dev.power.power_state = PMSG_ON;
-+ mcf_codec_spi = spi;
-+
-+ return 0;
-+}
-+
-+static int __devexit mcf_codec_spi_remove(struct spi_device *spi)
-+{
-+ return 0;
-+}
-+
-+static int mcf_codec_spi_suspend(struct spi_device *spi, pm_message_t message)
-+{
-+ return 0;
-+}
-+
-+static int mcf_codec_spi_resume(struct spi_device *spi)
-+{
-+ return 0;
-+}
-+
-+static struct spi_driver mcf_codec_spi_driver = {
-+ .driver = {
-+ .name = MCF_CODEC_SPI_DRIVER_NAME,
-+ .bus = &spi_bus_type,
-+ .owner = THIS_MODULE,
-+ },
-+ .probe = mcf_codec_spi_probe,
-+ .remove = __devexit_p(mcf_codec_spi_remove),
-+ .suspend = mcf_codec_spi_suspend,
-+ .resume = mcf_codec_spi_resume,
-+};
-+
-+static int __init mcf_codec_spi_init(void)
-+{
-+ return spi_register_driver(&mcf_codec_spi_driver);
-+}
-+module_init(mcf_codec_spi_init);
-+
-+static void __exit mcf_codec_spi_exit(void)
-+{
-+ spi_unregister_driver(&mcf_codec_spi_driver);
-+}
-+module_exit(mcf_codec_spi_exit);
-+
-+
-+MODULE_DESCRIPTION("Coldfire Codec SPI driver");
-+MODULE_AUTHOR("Kurt Mahan, Freescale Semiconductor, Inc.");
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ b/sound/coldfire/snd-coldfire.c
-@@ -0,0 +1,1664 @@
-+/*
-+ * linux/sound/coldfire/snd-coldfire.c
-+ *
-+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved.
-+ * Author: York Sun <r58495@freescale.com>
-+ * Alison Wang <b18965@freescale.com>
-+ *
-+ * Coldfire ALSA driver based on SSI and TLV320A
-+ *
-+ * This 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.
-+ *
-+ ***************************************************************************
-+ *
-+ * NOTE: This driver was tested on MCF5445x, MCF5301x, MCF5227x, MCF532x and
-+ * MCF537x platforms.
-+ * */
-+
-+#include <linux/module.h>
-+#include <linux/moduleparam.h>
-+#include <linux/platform_device.h>
-+#include <linux/init.h>
-+#include <linux/device.h>
-+#include <linux/slab.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/ioctl.h>
-+#include <linux/soundcard.h>
-+#include <linux/spi/spi.h>
-+
-+#include <sound/core.h>
-+#include <sound/pcm.h>
-+#include <sound/pcm_params.h>
-+#include <sound/control.h>
-+#include <linux/fs.h>
-+#include <linux/delay.h>
-+
-+#include <asm/mcfsim.h>
-+#include <asm/coldfire.h>
-+#include <asm/mcf_edma.h>
-+#include "snd-coldfire.h"
-+
-+#if defined(CONFIG_M5445X)
-+#include <asm/mcf5445x_ssi.h>
-+#endif
-+
-+#define CF_ALSA_DEBUG 0
-+#if CF_ALSA_DEBUG
-+#define DBG(fmt, args...) printk(KERN_INFO "[%s] " fmt , \
-+ __func__, ## args)
-+#else
-+#define DBG(fmt, args...) do {} while (0)
-+#endif
-+
-+#define SOUND_CARD_NAME "Coldfire ALSA"
-+#define MAX_BUFFER_SIZE (32*1024)
-+
-+/* eDMA channel for SSI channel 0,1 TX,RX */
-+#define DMA_TX_TCD0 MCF_EDMA_CHAN_TIMER2
-+#define DMA_TX_TCD1 MCF_EDMA_CHAN_TIMER3
-+#define DMA_RX_TCD0 MCF_EDMA_CHAN_TIMER0
-+#define DMA_RX_TCD1 MCF_EDMA_CHAN_TIMER1
-+
-+#define CODEC_LEFT_IN_REG (0x00)
-+#define CODEC_RIGHT_IN_REG (0x01)
-+#define CODEC_LEFT_HP_VOL_REG (0x02)
-+#define CODEC_RIGHT_HP_VOL_REG (0x03)
-+#define CODEC_ANALOG_APATH_REG (0x04)
-+#define CODEC_DIGITAL_APATH_REG (0x05)
-+#define CODEC_POWER_DOWN_REG (0x06)
-+#define CODEC_DIGITAL_IF_FMT_REG (0x07)
-+#define CODEC_SAMPLE_RATE_REG (0x08)
-+#define CODEC_DIGITAL_IF_ACT_REG (0x09)
-+#define CODEC_RESET_REG (0x0f)
-+
-+#define TLV320AIC23_CODEC_SAMPLE_RATE_REG (0x08)
-+#define TLV320AIC23_CODEC_SAMPLERATE_REG_8KHZ (0x0C)
-+#define TLV320AIC23_CODEC_SAMPLERATE_REG_11KHZ (0x0C)
-+#define TLV320AIC23_CODEC_SAMPLERATE_REG_16KHZ (0x58)
-+#define TLV320AIC23_CODEC_SAMPLERATE_REG_22KHZ (0x62)
-+#define TLV320AIC23_CODEC_SAMPLERATE_REG_44KHZ (0x22)
-+#define TLV320AIC23_CODEC_SAMPLERATE_REG_48KHZ (0x00)
-+
-+#define MCF_SSI_AUDIO_IRQ_LEVEL (5)
-+#define TLV320A_VOL_MAX 0x07F
-+#define TLV320A_VOL_MIN 0x030
-+#define TLV320A_VOL_INIT 0x065
-+#define TLV320A_LINEIN_MAX 0x1F
-+#define TLV320A_LINEIN_INIT 0x17
-+#define TLV320A_ANALOGPATH_INIT 0x11
-+
-+/* Codec settings */
-+#define MCF_SSI_AUDIO_MCLK_1 (12288000U) /*Hz*/
-+#define MCF_SSI_AUDIO_MCLK_2 (16934400U) /*Hz*/
-+#define MCF_SSI_AUDIO_MCLK_3 (14112000U) /*Hz*/
-+#define MCF_SSI_AUDIO_MCLK_4 (18432000U) /*Hz*/
-+
-+#define MCF_SSI_AUDIO_SSDIV_VALUE_1 \
-+ ((((u32)MCF_CLK*2)/MCF_SSI_AUDIO_MCLK_1)+ \
-+ (((((u32)MCF_CLK*2*10)/MCF_SSI_AUDIO_MCLK_1)%10) > 5))
-+
-+#define MCF_SSI_AUDIO_SSDIV_VALUE_2 \
-+ ((((u32)MCF_CLK*2)/MCF_SSI_AUDIO_MCLK_2)+ \
-+ (((((u32)MCF_CLK*2*10)/MCF_SSI_AUDIO_MCLK_2)%10) > 5))
-+
-+#define MCF_SSI_AUDIO_SSDIV_VALUE_3 \
-+ ((((u32)MCF_CLK*2)/MCF_SSI_AUDIO_MCLK_3)+ \
-+ (((((u32)MCF_CLK*2*10)/MCF_SSI_AUDIO_MCLK_3)%10) > 5))
-+
-+#define MCF_SSI_AUDIO_SSDIV_VALUE_4 \
-+ ((((u32)MCF_CLK*2)/MCF_SSI_AUDIO_MCLK_4)+ \
-+ (((((u32)MCF_CLK*2*10)/MCF_SSI_AUDIO_MCLK_4)%10) > 5))
-+
-+#define SNDRV_COLDFIRE_PCM_PLAYBACK_FORMATS SNDRV_PCM_FMTBIT_S16_BE
-+#define SNDRV_COLDFIRE_PCM_CAPTURE_FORMATS SNDRV_PCM_FMTBIT_S16_BE
-+
-+#define RXFWM 2
-+#define TXFWM 2
-+#define HW_PERIODS_BYTES_MIN 4096
-+#define HW_PERIODS_BYTES_STEP 4096
-+
-+#define INPUT_MICROPHONE 0
-+#define INPUT_LINEIN 1
-+#define NUM_TCDS 4
-+
-+static char *id;
-+static struct platform_device *device;
-+static int g_tx_dmaing;
-+static int g_rx_dmaing;
-+static unsigned char g_mastervol, g_lineinvol, g_analogpath;
-+
-+/** Use 4 TCDs for scatter/gather address
-+ * to setup dma chain, one TCD per period
-+ * so that we don't need change them on the fly
-+ */
-+
-+/**
-+ * Link Descriptor
-+ *
-+ * must be aligned on a 32-byte boundary.
-+ */
-+struct dma_tcd {
-+ __be32 saddr; /* source address */
-+ __be16 attr; /* transfer attribute */
-+ __be16 soffset; /* source offset */
-+ __be32 nbytes; /* minor byte count */
-+ __be32 slast; /* last source address adjust */
-+ __be32 daddr; /* dest address */
-+ __be16 citer; /* current minor looplink, major count */
-+ __be16 doffset; /* dest offset */
-+ __be32 dlast_sga; /* last dest addr adjust, scatter/gather addr*/
-+ __be16 biter; /* begging minor looklink, major count */
-+ __be16 csr; /* control and status */
-+} __packed;
-+
-+/** dma_private: p-substream DMA data
-+ *
-+ * The tcd[] array is first because it needs to be aligned on a 32-byte
-+ * boundary, so putting it first will ensure alignment without padding the
-+ * structure.
-+ *
-+ * @tcd[]: array of TCDs
-+ */
-+struct dma_private {
-+ struct dma_tcd tcd0[NUM_TCDS];
-+ struct dma_tcd tcd1[NUM_TCDS];
-+ dma_addr_t tcd_buf_phys; /* physical address of dma_private */
-+ dma_addr_t dma_buf_phys;
-+ dma_addr_t dma_buf_next;
-+ dma_addr_t dma_buf_end;
-+ size_t period_size;
-+ unsigned int num_periods;
-+};
-+
-+struct tlv320a_audio_device {
-+ struct spi_device *spi;
-+ u32 speed;
-+ u32 stereo;
-+ u32 bits;
-+ u32 format;
-+ u8 isopen;
-+ u8 dmaing;
-+ u8 ssi_enabled;
-+ u8 channel;
-+ spinlock_t lock;
-+ u8 *audio_buf;
-+};
-+
-+/* chip specific define */
-+struct chip_spec {
-+ struct snd_card *card;
-+ struct snd_pcm *pcm;
-+ struct tlv320a_audio_device *audio_device;
-+ u32 offset;
-+ void *mixer_data;
-+};
-+
-+/* hardware definition */
-+static struct snd_pcm_hardware snd_coldfire_playback_hw = {
-+ .info = (SNDRV_PCM_INFO_INTERLEAVED |
-+#if defined(CONFIG_MMU)
-+ SNDRV_PCM_INFO_MMAP |
-+ SNDRV_PCM_INFO_MMAP_VALID|
-+#endif
-+ SNDRV_PCM_INFO_BLOCK_TRANSFER),
-+ .formats = SNDRV_COLDFIRE_PCM_PLAYBACK_FORMATS,
-+ .rates = SNDRV_PCM_RATE_8000_48000,
-+ .rate_min = 8000,
-+ .rate_max = 48000,
-+ .channels_min = 1,
-+ .channels_max = 2,
-+ .buffer_bytes_max = MAX_BUFFER_SIZE,
-+ .period_bytes_min = HW_PERIODS_BYTES_MIN,
-+ .period_bytes_max = MAX_BUFFER_SIZE/NUM_TCDS,
-+ .periods_min = NUM_TCDS,
-+ .periods_max = NUM_TCDS,
-+ .fifo_size = 0,
-+};
-+
-+/* hardware definition */
-+static struct snd_pcm_hardware snd_coldfire_capture_hw = {
-+ .info = (SNDRV_PCM_INFO_INTERLEAVED |
-+#if defined(CONFIG_MMU)
-+ SNDRV_PCM_INFO_MMAP |
-+ SNDRV_PCM_INFO_MMAP_VALID|
-+#endif
-+ SNDRV_PCM_INFO_BLOCK_TRANSFER),
-+ .formats = SNDRV_COLDFIRE_PCM_CAPTURE_FORMATS,
-+ .rates = SNDRV_PCM_RATE_8000_48000,
-+ .rate_min = 8000,
-+ .rate_max = 48000,
-+ .channels_min = 1,
-+ .channels_max = 2,
-+ .buffer_bytes_max = MAX_BUFFER_SIZE,
-+ .period_bytes_min = HW_PERIODS_BYTES_MIN,
-+ .period_bytes_max = MAX_BUFFER_SIZE/NUM_TCDS,
-+ .periods_min = NUM_TCDS,
-+ .periods_max = NUM_TCDS,
-+ .fifo_size = 0,
-+};
-+
-+static unsigned int rates[] = {8000, 11025, 16000, 22000,
-+ 22050, 44000, 44100, 48000};
-+
-+/* hw constraints */
-+static struct snd_pcm_hw_constraint_list constraints_rates = {
-+ .count = ARRAY_SIZE(rates),
-+ .list = rates,
-+ .mask = 0,
-+};
-+
-+static inline void ssi_audio_dma_playback_start(void)
-+{
-+ g_tx_dmaing = 1;
-+ mcf_edma_start_transfer(DMA_TX_TCD0);
-+ mcf_edma_start_transfer(DMA_TX_TCD1);
-+}
-+
-+static inline void ssi_audio_dma_capture_start(void)
-+{
-+ g_rx_dmaing = 1;
-+ mcf_edma_start_transfer(DMA_RX_TCD0);
-+ mcf_edma_start_transfer(DMA_RX_TCD1);
-+}
-+
-+static inline void ssi_audio_dma_playback_stop(void)
-+{
-+ g_tx_dmaing = 0;
-+ mcf_edma_stop_transfer(DMA_TX_TCD0);
-+ mcf_edma_stop_transfer(DMA_TX_TCD1);
-+}
-+
-+inline void ssi_audio_dma_capture_stop(void)
-+{
-+ g_rx_dmaing = 0;
-+ mcf_edma_stop_transfer(DMA_RX_TCD0);
-+ mcf_edma_stop_transfer(DMA_RX_TCD1);
-+}
-+
-+/**
-+ * fill_tcd_params - Fill transfer control descriptor (TCD)
-+ * @base: base address of TCD
-+ * @source: source address
-+ * @dest: destination address
-+ * @attr: attributes
-+ * @soff: source offset
-+ * @nbytes: number of bytes to be transfered in minor loop
-+ * @slast: last source address adjustment
-+ * @citer: major loop count
-+ * @biter: beginning minor loop count
-+ * @doff: destination offset
-+ * @dlast_sga: last destination address adjustment
-+ * @major_int: generate interrupt after each major loop
-+ * @disable_req: disable DMA request after major loop
-+ * @enable_sg: enable scatter/gather address
-+ */
-+void fill_tcd_params(u32 base, u32 source, u32 dest,
-+ u32 attr, u32 soff, u32 nbytes, u32 slast,
-+ u32 citer, u32 biter, u32 doff, u32 dlast_sga,
-+ int major_int, int disable_req, int enable_sg)
-+{
-+ struct dma_tcd *tcd = (struct dma_tcd *) base;
-+
-+ tcd->saddr = source;
-+ tcd->attr = attr;
-+ tcd->soffset = soff;
-+ tcd->nbytes = nbytes;
-+ tcd->slast = slast;
-+ tcd->daddr = dest;
-+ tcd->citer = citer & 0x7fff;
-+ tcd->doffset = doff;
-+ tcd->dlast_sga = dlast_sga;
-+ tcd->biter = biter & 0x7fff;
-+ tcd->csr = ((major_int) ? 0x2 : 0) |
-+ ((disable_req) ? 0x8 : 0) |
-+ ((enable_sg) ? 0x10 : 0);
-+}
-+
-+static int
-+ssi_audio_dma_playback_config(struct snd_pcm_substream *substream)
-+{
-+ struct snd_pcm_runtime *runtime = substream->runtime;
-+ struct dma_private *dma_private = runtime->private_data;
-+ u32 size = frames_to_bytes(runtime, runtime->period_size);
-+ u32 offset, soffset, daddr0, daddr1, attr, sga0, sga1;
-+ u32 i, nbyte, major_loops;
-+
-+ if ((runtime->channels < 1) || (runtime->channels > 2)) {
-+ printk(KERN_ERR "Error on channels = %d\n", runtime->channels);
-+ return -EINVAL;
-+ }
-+
-+ dma_private->dma_buf_phys = runtime->dma_addr;
-+ dma_private->dma_buf_next = dma_private->dma_buf_phys;
-+ dma_private->dma_buf_end = dma_private->dma_buf_phys +
-+ runtime->periods * size;
-+
-+ if (runtime->format == SNDRV_PCM_FORMAT_S16_BE) {
-+ nbyte = 2 * TXFWM;
-+ soffset = 2 * runtime->channels;
-+ daddr0 = (u32)&MCF_SSI_TX0 + 2;
-+ daddr1 = (u32)&MCF_SSI_TX1 + 2;
-+ attr = MCF_EDMA_TCD_ATTR_SSIZE_16BIT |
-+ MCF_EDMA_TCD_ATTR_DSIZE_16BIT;
-+ } else {
-+ printk(KERN_ERR "Not supported PCM format %x\n",
-+ runtime->format);
-+ return -EINVAL;
-+ }
-+
-+ major_loops = size/nbyte/runtime->channels;
-+ sga0 = (u32)dma_private->tcd_buf_phys;
-+ sga1 = (u32)dma_private->tcd_buf_phys +
-+ 4 * sizeof(struct dma_tcd);
-+
-+#if defined(CONFIG_M5301x) || defined(CONFIG_M5445X)
-+ MCF_EDMA_TCD10_CSR = 0;
-+ MCF_EDMA_TCD11_CSR = 0;
-+#else
-+ MCF_EDMA_TCD11_CSR = 0;
-+ MCF_EDMA_TCD12_CSR = 0;
-+#endif
-+ offset = (runtime->channels - 1) * 2;
-+ mcf_edma_set_tcd_params(DMA_TX_TCD0,
-+ (u32)dma_private->dma_buf_next,
-+ daddr0,
-+ attr,
-+ soffset,
-+ nbyte,
-+ 0, /* slast */
-+ major_loops, /* citer */
-+ major_loops, /* biter */
-+ 0, /* dest offset */
-+ sga0,
-+ 1, /* major_int */
-+ 0); /* enable dma request after */
-+
-+ mcf_edma_set_tcd_params(DMA_TX_TCD1,
-+ (u32)dma_private->dma_buf_next + offset,
-+ daddr1,
-+ attr,
-+ soffset,
-+ nbyte,
-+ 0, /* slast */
-+ major_loops, /* citer */
-+ major_loops, /* biter */
-+ 0, /* dest offset */
-+ sga1,
-+ 0, /* major_int */
-+ 0); /* enable dma request after */
-+
-+ while (!(MCF_EDMA_TCD_CSR(DMA_TX_TCD0) & MCF_EDMA_TCD_CSR_E_SG))
-+ MCF_EDMA_TCD_CSR(DMA_TX_TCD0) |= MCF_EDMA_TCD_CSR_E_SG;
-+ while (!(MCF_EDMA_TCD_CSR(DMA_TX_TCD1) & MCF_EDMA_TCD_CSR_E_SG))
-+ MCF_EDMA_TCD_CSR(DMA_TX_TCD1) |= MCF_EDMA_TCD_CSR_E_SG;
-+
-+ for (i = 0; i < NUM_TCDS; i++) {
-+ dma_private->dma_buf_next += size;
-+ if (dma_private->dma_buf_next >= dma_private->dma_buf_end)
-+ dma_private->dma_buf_next = dma_private->dma_buf_phys;
-+ sga0 = (u32)dma_private->tcd_buf_phys +
-+ ((i+1)%NUM_TCDS) * sizeof(struct dma_tcd);
-+ sga1 = (u32)dma_private->tcd_buf_phys +
-+ ((i+1)%NUM_TCDS + 4) * sizeof(struct dma_tcd);
-+ DBG("sga0 = 0x%x, sga1 = 0x%x.\n", sga0, sga1);
-+ fill_tcd_params((u32)&dma_private->tcd0[i],
-+ (u32)dma_private->dma_buf_next,
-+ daddr0,
-+ attr,
-+ soffset,
-+ nbyte,
-+ 0, /* slast */
-+ major_loops, /* citer */
-+ major_loops, /* biter */
-+ 0, /* dest offset */
-+ sga0,
-+ 1, /* major_int */
-+ 0, /* enable dma request after */
-+ 1); /* enable scatter/gather */
-+
-+ fill_tcd_params((u32)&dma_private->tcd1[i],
-+ (u32)dma_private->dma_buf_next + offset,
-+ daddr1,
-+ attr,
-+ soffset,
-+ nbyte,
-+ 0, /* slast */
-+ major_loops, /* citer */
-+ major_loops, /* biter */
-+ 0, /* dest offset */
-+ sga1,
-+ 0, /* major_int */
-+ 0, /* enable dma request after */
-+ 1); /* enable scatter/gather */
-+ }
-+
-+ return 0;
-+}
-+
-+static int
-+ssi_audio_dma_capture_config(struct snd_pcm_substream *substream)
-+{
-+ struct snd_pcm_runtime *runtime = substream->runtime;
-+ struct dma_private *dma_private = runtime->private_data;
-+ u32 size = frames_to_bytes(runtime, runtime->period_size);
-+ u32 offset, saddr0, saddr1, doffset, attr, sga0, sga1;
-+ int i, nbyte, major_loops;
-+
-+ if ((runtime->channels < 1) || (runtime->channels > 2)) {
-+ printk(KERN_ERR "Error on channels = %d\n", runtime->channels);
-+ return -EINVAL;
-+ }
-+
-+ dma_private->dma_buf_phys = runtime->dma_addr;
-+ dma_private->dma_buf_next = dma_private->dma_buf_phys;
-+ dma_private->dma_buf_end = dma_private->dma_buf_phys +
-+ runtime->periods * size;
-+
-+ switch (runtime->format) {
-+ case SNDRV_PCM_FORMAT_S16_BE:
-+ saddr0 = (u32)&MCF_SSI_RX0 + 2;
-+ saddr1 = (u32)&MCF_SSI_RX1 + 2;
-+ nbyte = 2 * RXFWM;
-+ doffset = 2 * runtime->channels;
-+ attr = MCF_EDMA_TCD_ATTR_SSIZE_16BIT |
-+ MCF_EDMA_TCD_ATTR_DSIZE_16BIT;
-+ break;
-+ default:
-+ printk(KERN_ERR "Not supported PCM format %x\n",
-+ runtime->format);
-+ return -EINVAL;
-+ }
-+
-+ major_loops = size/nbyte/runtime->channels;
-+ sga0 = (u32)dma_private->tcd_buf_phys;
-+ sga1 = (u32)dma_private->tcd_buf_phys +
-+ 4 * sizeof(struct dma_tcd);
-+
-+#if defined(CONFIG_M5301x) || defined(CONFIG_M5445X)
-+ MCF_EDMA_TCD8_CSR = 0;
-+ MCF_EDMA_TCD9_CSR = 0;
-+#else
-+ MCF_EDMA_TCD9_CSR = 0;
-+ MCF_EDMA_TCD10_CSR = 0;
-+#endif
-+ offset = (runtime->channels - 1) * 2;
-+ mcf_edma_set_tcd_params(DMA_RX_TCD0,
-+ saddr0,
-+ (u32)dma_private->dma_buf_next,
-+ attr,
-+ 0, /* source offset */
-+ nbyte,
-+ 0, /* slast */
-+ major_loops, /* citer */
-+ major_loops, /* biter */
-+ doffset,
-+ sga0,
-+ 1, /* major_int */
-+ 0); /* enable dma request after */
-+
-+ mcf_edma_set_tcd_params(DMA_RX_TCD1,
-+ saddr1,
-+ (u32)dma_private->dma_buf_next + offset,
-+ attr,
-+ 0, /* source offset */
-+ nbyte,
-+ 0, /* slast */
-+ major_loops, /* citer */
-+ major_loops, /* biter */
-+ doffset,
-+ sga1,
-+ 0, /* major_int */
-+ 0); /* enable dma request after */
-+
-+ while (!(MCF_EDMA_TCD_CSR(DMA_RX_TCD0) & MCF_EDMA_TCD_CSR_E_SG))
-+ MCF_EDMA_TCD_CSR(DMA_RX_TCD0) |= MCF_EDMA_TCD_CSR_E_SG;
-+ while (!(MCF_EDMA_TCD_CSR(DMA_RX_TCD1) & MCF_EDMA_TCD_CSR_E_SG))
-+ MCF_EDMA_TCD_CSR(DMA_RX_TCD1) |= MCF_EDMA_TCD_CSR_E_SG;
-+
-+ for (i = 0; i < NUM_TCDS; i++) {
-+ dma_private->dma_buf_next += size;
-+ if (dma_private->dma_buf_next >= dma_private->dma_buf_end)
-+ dma_private->dma_buf_next = dma_private->dma_buf_phys;
-+ sga0 = (u32)dma_private->tcd_buf_phys +
-+ ((i+1)%NUM_TCDS) * sizeof(struct dma_tcd);
-+ sga1 = (u32)dma_private->tcd_buf_phys +
-+ ((i+1)%NUM_TCDS + 4) * sizeof(struct dma_tcd);
-+ fill_tcd_params((u32)&dma_private->tcd0[i],
-+ saddr0,
-+ (u32)dma_private->dma_buf_next,
-+ attr,
-+ 0, /* source offset */
-+ nbyte,
-+ 0, /* slast */
-+ major_loops, /* citer */
-+ major_loops, /* biter */
-+ doffset,
-+ sga0,
-+ 1, /* major_int */
-+ 0, /* enable dma request after */
-+ 1); /* enable scatter/gather */
-+ fill_tcd_params((u32)&dma_private->tcd1[i],
-+ saddr1,
-+ (u32)dma_private->dma_buf_next + offset,
-+ attr,
-+ 0, /* source offset */
-+ nbyte,
-+ 0, /* slast */
-+ major_loops, /* citer */
-+ major_loops, /* biter */
-+ doffset,
-+ sga1,
-+ 0, /* major_int */
-+ 0, /* enable dma request after */
-+ 1); /* enable scatter/gather */
-+ }
-+ return 0;
-+}
-+
-+static inline void ssi_audio_enable_ssi_playback(void)
-+{
-+ MCF_SSI_CR |= MCF_SSI_CR_SSI_EN | MCF_SSI_CR_TE;
-+}
-+
-+static inline void ssi_audio_enable_ssi_capture(void)
-+{
-+ MCF_SSI_CR |= MCF_SSI_CR_SSI_EN | MCF_SSI_CR_RE;
-+}
-+
-+static inline void ssi_audio_disable_ssi(void)
-+{
-+ MCF_SSI_CR &= ~(MCF_SSI_CR_TE | MCF_SSI_CR_RE | MCF_SSI_CR_SSI_EN);
-+}
-+
-+static inline void ssi_audio_disable_ssi_playback(void)
-+{
-+ MCF_SSI_CR &= ~MCF_SSI_CR_TE;
-+}
-+
-+static inline void ssi_audio_disable_ssi_capture(void)
-+{
-+ MCF_SSI_CR &= ~MCF_SSI_CR_RE;
-+}
-+
-+static irqreturn_t ssi_audio_dma_playback_handler(int channel, void *dev_id)
-+{
-+ struct snd_pcm_substream *substream;
-+ struct snd_pcm_runtime *runtime;
-+
-+ substream = (struct snd_pcm_substream *)dev_id;
-+ runtime = substream->runtime;
-+
-+ /* inform ALSA middle layer about transfer status */
-+ snd_pcm_period_elapsed(substream);
-+ mcf_edma_confirm_interrupt_handled(DMA_TX_TCD0);
-+ mcf_edma_confirm_interrupt_handled(DMA_TX_TCD1);
-+
-+ return IRQ_HANDLED;
-+}
-+
-+static irqreturn_t ssi_audio_dma_capture_handler(int channel, void *dev_id)
-+{
-+ struct snd_pcm_substream *substream;
-+ struct snd_pcm_runtime *runtime;
-+
-+ substream = (struct snd_pcm_substream *)dev_id;
-+ runtime = substream->runtime;
-+
-+ /* inform ALSA middle layer about transfer status */
-+ snd_pcm_period_elapsed(substream);
-+ mcf_edma_confirm_interrupt_handled(DMA_RX_TCD0);
-+ mcf_edma_confirm_interrupt_handled(DMA_RX_TCD1);
-+
-+ return IRQ_HANDLED;
-+}
-+
-+int ssi_audio_dma_request_playback_channel(struct snd_pcm_substream *substream)
-+{
-+ int err;
-+ struct chip_spec *chip = snd_pcm_substream_chip(substream);
-+
-+ /* request eDMA channel */
-+ err = mcf_edma_request_channel(DMA_TX_TCD0,
-+ ssi_audio_dma_playback_handler,
-+ NULL,
-+ MCF_SSI_AUDIO_IRQ_LEVEL,
-+ substream,
-+ &(chip->audio_device->lock),
-+ id);
-+ if (err < 0)
-+ return err;
-+ err = mcf_edma_request_channel(DMA_TX_TCD1,
-+ ssi_audio_dma_playback_handler,
-+ NULL,
-+ MCF_SSI_AUDIO_IRQ_LEVEL,
-+ substream,
-+ &(chip->audio_device->lock),
-+ id);
-+ return err;
-+}
-+
-+int ssi_audio_dma_request_capture_channel(struct snd_pcm_substream *substream)
-+{
-+ int err;
-+ struct chip_spec *chip = snd_pcm_substream_chip(substream);
-+
-+ /* request 2 eDMA channels for two fifo */
-+ err = mcf_edma_request_channel(DMA_RX_TCD0,
-+ ssi_audio_dma_capture_handler,
-+ NULL,
-+ MCF_SSI_AUDIO_IRQ_LEVEL,
-+ substream,
-+ &(chip->audio_device->lock),
-+ id);
-+ if (err < 0)
-+ return err;
-+ err = mcf_edma_request_channel(DMA_RX_TCD1,
-+ ssi_audio_dma_capture_handler,
-+ NULL,
-+ MCF_SSI_AUDIO_IRQ_LEVEL,
-+ substream,
-+ &(chip->audio_device->lock),
-+ id);
-+ return err;
-+}
-+
-+static inline void ssi_audio_init_dma(void)
-+{
-+ /* SSI DMA Signals mapped to DMA request */
-+ MCF_CCM_MISCCR &= ~MCF_CCM_MISCCR_TIM_DMA;
-+}
-+
-+static void ssi_audio_adjust_codec_speed(struct snd_pcm_substream *substream)
-+{
-+ ssi_audio_disable_ssi();
-+
-+ if (substream->runtime->format == SNDRV_PCM_FORMAT_S16_BE) {
-+ MCF_SSI_CCR = MCF_SSI_CCR_WL(7) | /* 16 bit word length */
-+ MCF_SSI_CCR_DC(1); /* Frame rate divider */
-+ }
-+
-+ switch (substream->runtime->rate) {
-+ case 8000:
-+#if defined(CONFIG_M532x) || defined(CONFIG_M537x)
-+ MCF_CCM_CDR = (MCF_CCM_CDR | MCF_CCM_CDR_SSIDIV(0x20))
-+ | MCF_CCM_CDR_SSIDIV(MCF_SSI_AUDIO_SSDIV_VALUE_1);
-+#else
-+ MCF_CCM_CDR = (MCF_CCM_CDR & ~MCF_CCM_CDR_SSIDIV(0xFF)) |
-+ MCF_CCM_CDR_SSIDIV(MCF_SSI_AUDIO_SSDIV_VALUE_1);
-+#endif
-+ MCF_SSI_CCR |= MCF_SSI_CCR_PM(11);
-+ mcf_codec_spi_write(TLV320AIC23_CODEC_SAMPLE_RATE_REG,
-+ TLV320AIC23_CODEC_SAMPLERATE_REG_8KHZ);
-+ break;
-+ case 11000:
-+ case 11025:
-+#if defined(CONFIG_M532x) || defined(CONFIG_M537x)
-+ MCF_CCM_CDR = (MCF_CCM_CDR & ~MCF_CCM_CDR_SSIDIV(0x3F)) |
-+ MCF_CCM_CDR_SSIDIV(0x2B);
-+ MCF_SSI_CCR |= MCF_SSI_CCR_PM(11);
-+#else
-+ MCF_CCM_CDR = (MCF_CCM_CDR & ~MCF_CCM_CDR_SSIDIV(0xFF)) |
-+ MCF_CCM_CDR_SSIDIV(MCF_SSI_AUDIO_SSDIV_VALUE_3);
-+ MCF_SSI_CCR |= MCF_SSI_CCR_PM(9);
-+#endif
-+ mcf_codec_spi_write(TLV320AIC23_CODEC_SAMPLE_RATE_REG,
-+ TLV320AIC23_CODEC_SAMPLERATE_REG_11KHZ);
-+ break;
-+ case 16000:
-+#if defined(CONFIG_M532x) || defined(CONFIG_M537x)
-+ MCF_CCM_CDR = (MCF_CCM_CDR | MCF_CCM_CDR_SSIDIV(0x20))
-+ | MCF_CCM_CDR_SSIDIV(MCF_SSI_AUDIO_SSDIV_VALUE_1);
-+#else
-+ MCF_CCM_CDR = (MCF_CCM_CDR & ~MCF_CCM_CDR_SSIDIV(0xFF)) |
-+ MCF_CCM_CDR_SSIDIV(MCF_SSI_AUDIO_SSDIV_VALUE_1);
-+#endif
-+ MCF_SSI_CCR |= MCF_SSI_CCR_PM(5);
-+ mcf_codec_spi_write(TLV320AIC23_CODEC_SAMPLE_RATE_REG,
-+ TLV320AIC23_CODEC_SAMPLERATE_REG_16KHZ);
-+ break;
-+ case 22000:
-+ case 22050:
-+#if defined(CONFIG_M532x) || defined(CONFIG_M537x)
-+ MCF_CCM_CDR = (MCF_CCM_CDR & ~MCF_CCM_CDR_SSIDIV(0x3F)) |
-+ MCF_CCM_CDR_SSIDIV(0x2B);
-+ MCF_SSI_CCR |= MCF_SSI_CCR_PM(5);
-+#else
-+ MCF_CCM_CDR = (MCF_CCM_CDR & ~MCF_CCM_CDR_SSIDIV(0xFF)) |
-+ MCF_CCM_CDR_SSIDIV(MCF_SSI_AUDIO_SSDIV_VALUE_3);
-+ MCF_SSI_CCR |= MCF_SSI_CCR_PM(4);
-+#endif
-+ mcf_codec_spi_write(TLV320AIC23_CODEC_SAMPLE_RATE_REG,
-+ TLV320AIC23_CODEC_SAMPLERATE_REG_22KHZ);
-+ break;
-+ case 48000:
-+#if defined(CONFIG_M532x) || defined(CONFIG_M537x)
-+ MCF_CCM_CDR = (MCF_CCM_CDR & ~MCF_CCM_CDR_SSIDIV(0x3F)) |
-+ MCF_CCM_CDR_SSIDIV(MCF_SSI_AUDIO_SSDIV_VALUE_4);
-+ MCF_SSI_CCR |= MCF_SSI_CCR_PM(3);
-+#else
-+ MCF_CCM_CDR = (MCF_CCM_CDR & ~MCF_CCM_CDR_SSIDIV(0xFF)) |
-+ MCF_CCM_CDR_SSIDIV(MCF_SSI_AUDIO_SSDIV_VALUE_1);
-+ MCF_SSI_CCR |= MCF_SSI_CCR_PM(1);
-+#endif
-+ mcf_codec_spi_write(TLV320AIC23_CODEC_SAMPLE_RATE_REG,
-+ TLV320AIC23_CODEC_SAMPLERATE_REG_48KHZ);
-+ break;
-+ case 44000:
-+ case 44100:
-+ default:
-+#if defined(CONFIG_M532x) || defined(CONFIG_M537x)
-+ MCF_CCM_CDR = (MCF_CCM_CDR & ~MCF_CCM_CDR_SSIDIV(0x3F)) |
-+ MCF_CCM_CDR_SSIDIV(0x2B);
-+#else
-+ MCF_CCM_CDR = (MCF_CCM_CDR & ~MCF_CCM_CDR_SSIDIV(0xFF)) |
-+ MCF_CCM_CDR_SSIDIV(MCF_SSI_AUDIO_SSDIV_VALUE_2);
-+#endif
-+ MCF_SSI_CCR |= MCF_SSI_CCR_PM(2);
-+ mcf_codec_spi_write(TLV320AIC23_CODEC_SAMPLE_RATE_REG,
-+ TLV320AIC23_CODEC_SAMPLERATE_REG_44KHZ);
-+ break;
-+ }
-+ DBG("MCF_CCM_CDR = 0x%x, MCF_SSI_CCR = 0x%x.\n",
-+ MCF_CCM_CDR, MCF_SSI_CCR);
-+}
-+
-+static void ssi_audio_codec_reset(void)
-+{
-+ mcf_codec_spi_write(CODEC_RESET_REG, 0); /* reset the audio chip */
-+ udelay(2500); /* wait for reset */
-+}
-+
-+static void
-+ssi_audio_init_codec_for_playback(struct snd_pcm_substream *substream)
-+{
-+ mcf_codec_spi_write(CODEC_LEFT_IN_REG, g_lineinvol);
-+ mcf_codec_spi_write(CODEC_RIGHT_IN_REG, g_lineinvol);
-+ mcf_codec_spi_write(CODEC_POWER_DOWN_REG, 0x060);
-+ mcf_codec_spi_write(CODEC_DIGITAL_IF_FMT_REG, 0x02);
-+ mcf_codec_spi_write(CODEC_DIGITAL_APATH_REG, 0x006);
-+ mcf_codec_spi_write(CODEC_DIGITAL_IF_ACT_REG, 0x001);
-+ mcf_codec_spi_write(CODEC_ANALOG_APATH_REG, g_analogpath);
-+ mcf_codec_spi_write(CODEC_LEFT_HP_VOL_REG, g_mastervol);
-+ mcf_codec_spi_write(CODEC_RIGHT_HP_VOL_REG, g_mastervol);
-+}
-+
-+static void
-+ssi_audio_init_codec_for_capture(struct snd_pcm_substream *substream)
-+{
-+ mcf_codec_spi_write(CODEC_LEFT_IN_REG, g_lineinvol);
-+ mcf_codec_spi_write(CODEC_RIGHT_IN_REG, g_lineinvol);
-+ mcf_codec_spi_write(CODEC_POWER_DOWN_REG, 0x060);
-+ mcf_codec_spi_write(CODEC_DIGITAL_IF_FMT_REG, 0x02);
-+ mcf_codec_spi_write(CODEC_DIGITAL_APATH_REG, 0x006);
-+ mcf_codec_spi_write(CODEC_DIGITAL_IF_ACT_REG, 0x001);
-+ mcf_codec_spi_write(CODEC_ANALOG_APATH_REG, g_analogpath);
-+ mcf_codec_spi_write(CODEC_LEFT_HP_VOL_REG, g_mastervol);
-+ mcf_codec_spi_write(CODEC_RIGHT_HP_VOL_REG, g_mastervol);
-+}
-+
-+static void ssi_audio_chip_init(void)
-+{
-+ int chip_initialized = 0;
-+ if (chip_initialized == 1)
-+ return;
-+
-+ ssi_audio_init_dma();
-+ /* Enable the SSI pins */
-+#if defined(CONFIG_M5227x)
-+ MCF_GPIO_PAR_UART = (MCF_GPIO_PAR_UART
-+ &~MCF_GPIO_PAR_UART_PAR_U1TXD(0xF)
-+ &~MCF_GPIO_PAR_UART_PAR_U1RXD(0xF)
-+ &~MCF_GPIO_PAR_UART_PAR_U1RTS(0xF)
-+ &~MCF_GPIO_PAR_UART_PAR_U1CTS(0xF))
-+ | MCF_GPIO_PAR_UART_PAR_U1CTS_SSI_BCLK
-+ | MCF_GPIO_PAR_UART_PAR_U1RTS_SSI_FS
-+ | MCF_GPIO_PAR_UART_PAR_U1RXD_SSI_RXD
-+ | MCF_GPIO_PAR_UART_PAR_U1TXD_SSI_TXD;
-+
-+ MCF_GPIO_PAR_TIMER = (MCF_GPIO_PAR_TIMER
-+ &~MCF_GPIO_PAR_TIMER_PAR_T3IN(0xF))
-+ | MCF_GPIO_PAR_TIMER_PAR_T3IN_SSI_MCLK;
-+#endif
-+#if defined(CONFIG_M532x)
-+ MCF_GPIO_PAR_SSI = (0
-+ | MCF_GPIO_PAR_SSI_PAR_MCLK
-+ | MCF_GPIO_PAR_SSI_PAR_TXD(3)
-+ | MCF_GPIO_PAR_SSI_PAR_RXD(3)
-+ | MCF_GPIO_PAR_SSI_PAR_FS(3)
-+ | MCF_GPIO_PAR_SSI_PAR_BCLK(3));
-+#endif
-+#if defined(CONFIG_M537x)
-+ MCF_GPIO_PAR_UART = (MCF_GPIO_PAR_UART
-+ &~MCF_GPIO_PAR_UART_PAR_UTXD1(0xF)
-+ &~MCF_GPIO_PAR_UART_PAR_URXD1(0xF)
-+ &~MCF_GPIO_PAR_UART_PAR_URTS1(0xF)
-+ &~MCF_GPIO_PAR_UART_PAR_UCTS1(0xF))
-+ | MCF_GPIO_PAR_UART_PAR_UCTS1_SSI_BCLK
-+ | MCF_GPIO_PAR_UART_PAR_URTS1_SSI_FS
-+ | MCF_GPIO_PAR_UART_PAR_URXD1_SSI_RXD
-+ | MCF_GPIO_PAR_UART_PAR_UTXD1_SSI_TXD;
-+
-+ MCF_GPIO_PAR_IRQ = MCF_GPIO_PAR_IRQ_PAR_IRQ4(1);
-+#endif
-+#if defined(CONFIG_M5301x)
-+ MCF_GPIO_PAR_SSIH = (MCF_GPIO_PAR_SSIH_PAR_RXD_SSI_RXD |
-+ MCF_GPIO_PAR_SSIH_PAR_TXD_SSI_TXD |
-+ MCF_GPIO_PAR_SSIH_PAR_FS_SSI_FS |
-+ MCF_GPIO_PAR_SSIH_PAR_MCLK_SSI_MCLK);
-+ MCF_GPIO_PAR_SSIL = MCF_GPIO_PAR_SSIL_PAR_BCLK_SSI_BCLK;
-+#endif
-+#if defined(CONFIG_M5445X)
-+ MCF_GPIO_PAR_SSI = (MCF_GPIO_PAR_SSI_MCLK |
-+ MCF_GPIO_PAR_SSI_STXD_STXD |
-+ MCF_GPIO_PAR_SSI_SRXD_SRXD |
-+ MCF_GPIO_PAR_SSI_FS_FS |
-+ MCF_GPIO_PAR_SSI_BCLK_BCLK);
-+#endif
-+ chip_initialized = 1;
-+}
-+
-+static void ssi_audio_init_ssi_playback(void)
-+{
-+ /* Issue a SSI reset */
-+ MCF_SSI_CR &= ~MCF_SSI_CR_SSI_EN;
-+
-+ /* SSI module uses internal CPU clock */
-+ MCF_CCM_MISCCR |= MCF_CCM_MISCCR_SSI_SRC;
-+#if defined(CONFIG_M5445X) || defined(CONFIG_M532x) || defined(CONFIG_M537x) \
-+ || defined(CONFIG_M5227x)
-+ MCF_CCM_MISCCR |= MCF_CCM_MISCCR_SSI_PUE | MCF_CCM_MISCCR_SSI_PUS;
-+#endif
-+#if defined(CONFIG_M5301x)
-+ MCF_GPIO_PCRH |= MCF_GPIO_PCRH_SSI_PUS | MCF_GPIO_PCRH_SSI_PUE;
-+#endif
-+ MCF_SSI_CR = MCF_SSI_CR_CIS |
-+ MCF_SSI_CR_TCH | /* Enable two channel mode */
-+ MCF_SSI_CR_MCE | /* clock out on SSI_MCLK pin */
-+ MCF_SSI_CR_I2S_MASTER | /* I2S master mode */
-+ MCF_SSI_CR_SYN | /* Enable synchronous mode */
-+ MCF_SSI_CR_NET; /* Auto set by I2S Master */
-+
-+ MCF_SSI_TCR = 0 |
-+ /* internally generated bit clock */
-+ MCF_SSI_TCR_TXDIR |
-+ /* internally generated frame sync */
-+ MCF_SSI_TCR_TFDIR |
-+ /* Clock data on falling edge of bit clock */
-+ MCF_SSI_TCR_TSCKP |
-+ /* Frame sync active low */
-+ MCF_SSI_TCR_TFSI |
-+ /* TX frame sync 1 bit before data */
-+ MCF_SSI_TCR_TEFS |
-+ /* TX FIFO 0 enabled */
-+ MCF_SSI_TCR_TFEN0 |
-+ /* TX FIFO 1 enabled */
-+ MCF_SSI_TCR_TFEN1 |
-+ MCF_SSI_TCR_TXBIT0;
-+
-+ MCF_SSI_FCSR = MCF_SSI_FCSR_TFWM0(TXFWM) | MCF_SSI_FCSR_TFWM1(TXFWM);
-+
-+ MCF_SSI_IER = MCF_SSI_IER_TDMAE | /* DMA request enabled */
-+ MCF_SSI_IER_TFE0 |
-+ MCF_SSI_IER_TFE1; /* set by reset actually*/
-+}
-+
-+static void ssi_audio_init_ssi_capture(void)
-+{
-+ /* Issue a SSI reset */
-+ MCF_SSI_CR &= ~MCF_SSI_CR_SSI_EN;
-+
-+ /* SSI module uses internal CPU clock */
-+ MCF_CCM_MISCCR |= MCF_CCM_MISCCR_SSI_SRC;
-+#if defined(CONFIG_M5445X) || defined(CONFIG_M532x) || defined(CONFIG_M537x) \
-+ || defined(CONFIG_M5227x)
-+ MCF_CCM_MISCCR |= MCF_CCM_MISCCR_SSI_PUE | MCF_CCM_MISCCR_SSI_PUS;
-+#endif
-+#if defined(CONFIG_M5301x)
-+ MCF_GPIO_PCRH |= MCF_GPIO_PCRH_SSI_PUS | MCF_GPIO_PCRH_SSI_PUE;
-+#endif
-+ MCF_SSI_CR = MCF_SSI_CR_CIS |
-+ MCF_SSI_CR_TCH | /* Enable two channel mode */
-+ MCF_SSI_CR_MCE | /* clock out on SSI_MCLK pin */
-+ MCF_SSI_CR_I2S_MASTER | /* I2S master mode */
-+ MCF_SSI_CR_SYN | /* Enable synchronous mode */
-+ MCF_SSI_CR_NET; /* Auto set by I2S Master */
-+
-+ MCF_SSI_TCR = 0 |
-+ /* internally generated bit clock */
-+ MCF_SSI_TCR_TXDIR |
-+ /* internally generated frame sync */
-+ MCF_SSI_TCR_TFDIR |
-+ /* Clock data on falling edge of bit clock */
-+ MCF_SSI_TCR_TSCKP |
-+ /* Frame sync active low */
-+ MCF_SSI_TCR_TFSI |
-+ /* TX frame sync 1 bit before data */
-+ MCF_SSI_TCR_TEFS |
-+ /* TX FIFO 0 enabled */
-+ MCF_SSI_TCR_TFEN0 |
-+ /* TX FIFO 1 enabled */
-+ MCF_SSI_TCR_TFEN1 |
-+ MCF_SSI_TCR_TXBIT0;
-+
-+ MCF_SSI_RCR = 0 |
-+ /* Clock data on rising edge of bit clock */
-+ MCF_SSI_RCR_RSCKP |
-+ /* Frame sync active low */
-+ MCF_SSI_RCR_RFSI |
-+ /* RX frame sync 1 bit before data */
-+ MCF_SSI_RCR_REFS |
-+ /* RX FIFO 0 enabled */
-+ MCF_SSI_RCR_RFEN0 |
-+ /* RX FIFO 1 enabled */
-+ MCF_SSI_RCR_RFEN1 |
-+ MCF_SSI_RCR_RXBIT0; /* Auto set by I2S Master */
-+
-+ MCF_SSI_FCSR = MCF_SSI_FCSR_RFWM0(RXFWM) | MCF_SSI_FCSR_RFWM1(RXFWM);
-+
-+ /* interrupts */
-+ MCF_SSI_IER = MCF_SSI_IER_RDMAE | /* DMA request enabled */
-+ MCF_SSI_IER_RFF0 | /* rx FIFO 0 full */
-+ MCF_SSI_IER_RFF1; /* rx FIFO 1 full */
-+}
-+
-+static int snd_coldfire_playback_open(struct snd_pcm_substream *substream)
-+{
-+ int err;
-+ struct chip_spec *chip = snd_pcm_substream_chip(substream);
-+ struct snd_pcm_runtime *runtime = substream->runtime;
-+ struct dma_private *dma_private;
-+ dma_addr_t tcd_buf_phys;
-+
-+ runtime->hw = snd_coldfire_playback_hw;
-+ err = snd_pcm_hw_constraint_integer(runtime,
-+ SNDRV_PCM_HW_PARAM_PERIODS);
-+ if (err < 0) {
-+ printk(KERN_ERR "invalid buffer size\n");
-+ return err;
-+ }
-+ /* to make sure period_bytes is the multiple of size of minor loops */
-+ err = snd_pcm_hw_constraint_step(runtime, 0,
-+ SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
-+ HW_PERIODS_BYTES_STEP);
-+ if (err < 0) {
-+ printk(KERN_ERR "Error setting period_bytes step, "
-+ "err=%d\n", err);
-+ return err;
-+ }
-+ err = snd_pcm_hw_constraint_list(substream->runtime, 0,
-+ SNDRV_PCM_HW_PARAM_RATE,
-+ &constraints_rates);
-+ if (err < 0) {
-+ printk(KERN_ERR "Error setting rate constraints, "
-+ "err=%d\n", err);
-+ return err;
-+ }
-+ ssi_audio_chip_init();
-+ ssi_audio_init_ssi_playback();
-+ ssi_audio_init_codec_for_playback(substream);
-+ err = ssi_audio_dma_request_playback_channel(substream);
-+ if (err < 0) {
-+ printk(KERN_ERR "Error requesting dma channel, err=%d\n", err);
-+ return err;
-+ }
-+
-+ dma_private = dma_alloc_coherent(substream->pcm->dev,
-+ sizeof(struct dma_private), &tcd_buf_phys, GFP_KERNEL);
-+
-+ if (!dma_private) {
-+ dev_err(substream->pcm->card->dev,
-+ "can't allocate DMA private data\n");
-+ return -ENOMEM;
-+ }
-+
-+ dma_private->tcd_buf_phys = tcd_buf_phys;
-+ runtime->private_data = dma_private;
-+
-+ chip->offset = 0;
-+ g_tx_dmaing = 0;
-+ return 0;
-+}
-+
-+static int snd_coldfire_capture_open(struct snd_pcm_substream *substream)
-+{
-+ int err;
-+ struct chip_spec *chip = snd_pcm_substream_chip(substream);
-+ struct snd_pcm_runtime *runtime = substream->runtime;
-+ struct dma_private *dma_private;
-+ dma_addr_t tcd_buf_phys;
-+
-+ runtime->hw = snd_coldfire_capture_hw;
-+
-+ err = snd_pcm_hw_constraint_integer(runtime,
-+ SNDRV_PCM_HW_PARAM_PERIODS);
-+ if (err < 0) {
-+ printk(KERN_ERR "invalid buffer size\n");
-+ return err;
-+ }
-+ /* to make sure period_bytes is the multiple of size of minor loops */
-+ err = snd_pcm_hw_constraint_step(runtime, 0,
-+ SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
-+ HW_PERIODS_BYTES_STEP);
-+ if (err < 0) {
-+ printk(KERN_ERR "Error setting period_bytes step, "
-+ "err=%d\n", err);
-+ return err;
-+ }
-+ err = snd_pcm_hw_constraint_list(substream->runtime, 0,
-+ SNDRV_PCM_HW_PARAM_RATE,
-+ &constraints_rates);
-+ if (err < 0) {
-+ printk(KERN_ERR "Error setting pcm_hw_constraint_list, "
-+ "err=%d\n", err);
-+ return err;
-+ }
-+
-+ ssi_audio_chip_init();
-+ ssi_audio_init_ssi_capture();
-+ ssi_audio_init_codec_for_capture(substream);
-+ err = ssi_audio_dma_request_capture_channel(substream);
-+ if (err < 0) {
-+ printk(KERN_ERR "Error requesting dma channel, err=%d\n", err);
-+ return err;
-+ }
-+
-+ dma_private = dma_alloc_coherent(substream->pcm->dev,
-+ sizeof(struct dma_private), &tcd_buf_phys, GFP_KERNEL);
-+
-+ if (!dma_private) {
-+ dev_err(substream->pcm->card->dev,
-+ "can't allocate DMA private data\n");
-+ return -ENOMEM;
-+ }
-+ dma_private->tcd_buf_phys = tcd_buf_phys;
-+ dma_private->dma_buf_phys = substream->dma_buffer.addr;
-+
-+ runtime->private_data = dma_private;
-+
-+ chip->offset = 0;
-+ g_rx_dmaing = 0;
-+ return 0;
-+}
-+
-+static int snd_coldfire_playback_close(struct snd_pcm_substream *substream)
-+{
-+ struct dma_private *dma_private = substream->runtime->private_data;
-+
-+ ssi_audio_dma_playback_stop();
-+ mcf_edma_free_channel(DMA_TX_TCD0, substream);
-+ mcf_edma_free_channel(DMA_TX_TCD1, substream);
-+ if (dma_private) {
-+ dma_free_coherent(substream->pcm->dev,
-+ sizeof(struct dma_private),
-+ dma_private, dma_private->tcd_buf_phys);
-+ substream->runtime->private_data = NULL;
-+ }
-+ ssi_audio_disable_ssi();
-+ return 0;
-+}
-+
-+static int snd_coldfire_capture_close(struct snd_pcm_substream *substream)
-+{
-+ struct dma_private *dma_private = substream->runtime->private_data;
-+
-+ ssi_audio_dma_capture_stop();
-+ mcf_edma_free_channel(DMA_RX_TCD0, substream);
-+ mcf_edma_free_channel(DMA_RX_TCD1, substream);
-+ /* Deallocate the fsl_dma_private structure */
-+ if (dma_private) {
-+ dma_free_coherent(substream->pcm->dev,
-+ sizeof(struct dma_private),
-+ dma_private, dma_private->tcd_buf_phys);
-+ substream->runtime->private_data = NULL;
-+ }
-+ ssi_audio_disable_ssi();
-+ return 0;
-+}
-+
-+static int snd_coldfire_pcm_hw_params(struct snd_pcm_substream *substream,
-+ struct snd_pcm_hw_params *hw_params)
-+{
-+ int err;
-+
-+ /* set runtime buffer */
-+ err = snd_pcm_lib_malloc_pages(
-+ substream, params_buffer_bytes(hw_params));
-+ if (err < 0)
-+ printk(KERN_ERR "Error allocating pages, err=%d\n", err);
-+ return err;
-+}
-+
-+static int snd_coldfire_pcm_hw_free(struct snd_pcm_substream *substream)
-+{
-+ /* free the memory if was newly allocated */
-+ return snd_pcm_lib_free_pages(substream);
-+}
-+
-+static int
-+snd_coldfire_pcm_playback_prepare(struct snd_pcm_substream *substream)
-+{
-+ int err;
-+
-+ if (g_tx_dmaing == 1)
-+ return 0;
-+
-+ ssi_audio_adjust_codec_speed(substream);
-+ err = ssi_audio_dma_playback_config(substream);
-+ if (err < 0) {
-+ printk(KERN_ERR "Error configuring playback, "
-+ "err=%d\n", err);
-+ return err;
-+ }
-+
-+ ssi_audio_dma_playback_start();
-+ return 0;
-+}
-+
-+static int snd_coldfire_pcm_capture_prepare(struct snd_pcm_substream *substream)
-+{
-+ int err;
-+
-+ if (g_rx_dmaing == 1)
-+ return 0;
-+
-+ ssi_audio_adjust_codec_speed(substream);
-+ err = ssi_audio_dma_capture_config(substream);
-+ if (err < 0) {
-+ printk(KERN_ERR "Error configuring capture, "
-+ "err=%d\n", err);
-+ return err;
-+ }
-+ ssi_audio_dma_capture_start();
-+
-+ return 0;
-+}
-+
-+static int
-+snd_coldfire_pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd)
-+{
-+ switch (cmd) {
-+ case SNDRV_PCM_TRIGGER_START:
-+ ssi_audio_enable_ssi_playback();
-+ break;
-+ case SNDRV_PCM_TRIGGER_STOP:
-+ ssi_audio_disable_ssi_playback();
-+ break;
-+ default:
-+ printk(KERN_ERR "Unsupported trigger command, cmd=%d\n", cmd);
-+ return -EINVAL;
-+ }
-+
-+ return 0;
-+}
-+
-+static int
-+snd_coldfire_pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd)
-+{
-+ switch (cmd) {
-+ case SNDRV_PCM_TRIGGER_START:
-+ ssi_audio_enable_ssi_capture();
-+ break;
-+ case SNDRV_PCM_TRIGGER_STOP:
-+ ssi_audio_disable_ssi_capture();
-+ break;
-+ default:
-+ printk(KERN_ERR "Unsupported trigger command, cmd=%d\n", cmd);
-+ return -EINVAL;
-+ }
-+
-+ return 0;
-+}
-+
-+static snd_pcm_uframes_t
-+snd_coldfire_pcm_playback_pointer(struct snd_pcm_substream *substream)
-+{
-+ struct snd_pcm_runtime *runtime = substream->runtime;
-+ struct dma_private *dma_private = runtime->private_data;
-+ snd_pcm_uframes_t pointer;
-+ u32 offset;
-+
-+ offset = (u32)(MCF_EDMA_TCD_SADDR(DMA_TX_TCD0) -
-+ dma_private->dma_buf_phys);
-+ if (runtime->format == SNDRV_PCM_FORMAT_S16_BE)
-+ pointer = offset / (runtime->channels == 1 ? 2 : 4);
-+ else
-+ pointer = 0;
-+
-+ return pointer;
-+}
-+
-+static snd_pcm_uframes_t
-+snd_coldfire_pcm_capture_pointer(struct snd_pcm_substream *substream)
-+{
-+ struct snd_pcm_runtime *runtime = substream->runtime;
-+ struct dma_private *dma_private = runtime->private_data;
-+ snd_pcm_uframes_t pointer;
-+ u32 offset;
-+
-+ offset = (u32)(MCF_EDMA_TCD_DADDR(DMA_RX_TCD0) -
-+ dma_private->dma_buf_phys);
-+ if (runtime->format == SNDRV_PCM_FORMAT_S16_BE)
-+ pointer = offset / (runtime->channels == 1 ? 2 : 4);
-+ else
-+ pointer = 0;
-+
-+ return pointer;
-+}
-+
-+static struct snd_pcm_ops snd_coldfire_playback_ops = {
-+ .open = snd_coldfire_playback_open,
-+ .close = snd_coldfire_playback_close,
-+ .ioctl = snd_pcm_lib_ioctl,
-+ .hw_params = snd_coldfire_pcm_hw_params,
-+ .hw_free = snd_coldfire_pcm_hw_free,
-+ .prepare = snd_coldfire_pcm_playback_prepare,
-+ .trigger = snd_coldfire_pcm_playback_trigger,
-+ .pointer = snd_coldfire_pcm_playback_pointer,
-+};
-+
-+static struct snd_pcm_ops snd_coldfire_capture_ops = {
-+ .open = snd_coldfire_capture_open,
-+ .close = snd_coldfire_capture_close,
-+ .ioctl = snd_pcm_lib_ioctl,
-+ .hw_params = snd_coldfire_pcm_hw_params,
-+ .hw_free = snd_coldfire_pcm_hw_free,
-+ .prepare = snd_coldfire_pcm_capture_prepare,
-+ .trigger = snd_coldfire_pcm_capture_trigger,
-+ .pointer = snd_coldfire_pcm_capture_pointer,
-+};
-+
-+static int snd_coldfire_new_pcm(struct chip_spec *chip)
-+{
-+ struct snd_pcm *pcm;
-+ int err;
-+
-+ err = snd_pcm_new(chip->card, "coldfire", 0, 1, 1,
-+ &pcm);
-+ if (err < 0) {
-+ printk(KERN_ERR "Error creating new pcm, err=%d\n", err);
-+ return err;
-+ }
-+ pcm->private_data = chip;
-+ strncpy(pcm->name, SOUND_CARD_NAME, sizeof(pcm->name));
-+ chip->pcm = pcm;
-+ pcm->info_flags = 0;
-+
-+ /* set operators */
-+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
-+ &snd_coldfire_playback_ops);
-+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
-+ &snd_coldfire_capture_ops);
-+ /* pre-allocation of buffers */
-+ err = snd_pcm_lib_preallocate_pages_for_all(
-+ pcm,
-+ SNDRV_DMA_TYPE_CONTINUOUS,
-+ snd_dma_continuous_data(GFP_KERNEL),
-+ MAX_BUFFER_SIZE,
-+ MAX_BUFFER_SIZE);
-+
-+ if (!pcm->streams[0].substream->dma_buffer.addr)
-+ pcm->streams[0].substream->dma_buffer.addr =
-+ virt_to_phys(pcm->streams[0].substream->dma_buffer.area);
-+ if (!pcm->streams[1].substream->dma_buffer.addr)
-+ pcm->streams[1].substream->dma_buffer.addr =
-+ virt_to_phys(pcm->streams[1].substream->dma_buffer.area);
-+
-+ if (err) {
-+ printk(KERN_ERR
-+ "Can't pre-allocate DMA buffer (size=%u)\n",
-+ MAX_BUFFER_SIZE);
-+ return -ENOMEM;
-+ }
-+
-+ chip->audio_device =
-+ kmalloc(sizeof(struct tlv320a_audio_device), GFP_DMA);
-+
-+ if (!chip->audio_device) {
-+ snd_pcm_lib_preallocate_free_for_all(pcm);
-+ printk(KERN_ERR
-+ "Can't allocate buffer for audio device\n");
-+ return -ENOMEM;
-+ }
-+
-+ return 0;
-+}
-+
-+static int tlv320a_set_out_volume(unsigned char value)
-+{
-+ unsigned char data;
-+
-+ if (value > TLV320A_VOL_MAX)
-+ data = TLV320A_VOL_MAX;
-+ else
-+ data = value;
-+
-+ if (mcf_codec_spi_write(CODEC_LEFT_HP_VOL_REG, data) < 0)
-+ return -EINVAL;
-+
-+ if (mcf_codec_spi_write(CODEC_RIGHT_HP_VOL_REG, data) < 0)
-+ return -EINVAL;
-+
-+ return 0;
-+}
-+
-+static int tlv320a_info_out_volume(struct snd_kcontrol *kcontrol,
-+ struct snd_ctl_elem_info *uinfo)
-+{
-+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-+ uinfo->count = 1;
-+ uinfo->value.integer.min = TLV320A_VOL_MIN;
-+ uinfo->value.integer.max = TLV320A_VOL_MAX;
-+ return 0;
-+}
-+
-+static int tlv320a_get_out_volume(struct snd_kcontrol *kcontrol,
-+ struct snd_ctl_elem_value *ucontrol)
-+{
-+ ucontrol->value.integer.value[0] = g_mastervol;
-+ return 0;
-+}
-+
-+static int tlv320a_put_out_volume(struct snd_kcontrol *kcontrol,
-+ struct snd_ctl_elem_value *ucontrol)
-+{
-+ unsigned char vol;
-+ int change;
-+
-+ vol = ucontrol->value.integer.value[0];
-+
-+ if (vol > TLV320A_VOL_MAX)
-+ return -EINVAL;
-+
-+ change = (g_mastervol != vol);
-+ if (change) {
-+ g_mastervol = vol;
-+ tlv320a_set_out_volume(vol);
-+ }
-+ return change;
-+}
-+
-+static int tlv320a_set_linein_volume(unsigned char value)
-+{
-+ unsigned char data;
-+
-+ if (value > TLV320A_LINEIN_MAX)
-+ data = TLV320A_LINEIN_MAX;
-+ else
-+ data = value;
-+
-+ if (mcf_codec_spi_write(CODEC_LEFT_IN_REG, data) < 0)
-+ return -EINVAL;
-+
-+ if (mcf_codec_spi_write(CODEC_RIGHT_IN_REG, data) < 0)
-+ return -EINVAL;
-+
-+ return 0;
-+}
-+
-+static int tlv320a_info_linein_volume(struct snd_kcontrol *kcontrol,
-+ struct snd_ctl_elem_info *uinfo)
-+{
-+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-+ uinfo->count = 1;
-+ uinfo->value.integer.min = 0;
-+ uinfo->value.integer.max = TLV320A_LINEIN_MAX;
-+ return 0;
-+}
-+
-+static int tlv320a_get_linein_volume(struct snd_kcontrol *kcontrol,
-+ struct snd_ctl_elem_value *ucontrol)
-+{
-+ ucontrol->value.integer.value[0] = g_lineinvol;
-+ return 0;
-+}
-+
-+static int tlv320a_put_linein_volume(struct snd_kcontrol *kcontrol,
-+ struct snd_ctl_elem_value *ucontrol)
-+{
-+ unsigned char vol;
-+ int change;
-+
-+ vol = ucontrol->value.integer.value[0];
-+
-+ if (vol > TLV320A_LINEIN_MAX)
-+ return -EINVAL;
-+
-+ change = (g_lineinvol != vol);
-+ if (change) {
-+ g_lineinvol = vol;
-+ tlv320a_set_linein_volume(vol);
-+ }
-+ return change;
-+}
-+
-+#define tlv320a_info_mic_boost snd_ctl_boolean_mono_info
-+static int tlv320a_get_mic_boost(struct snd_kcontrol *kcontrol,
-+ struct snd_ctl_elem_value *ucontrol)
-+{
-+ ucontrol->value.integer.value[0] = ((g_analogpath & 0x1) == 1);
-+ return 0;
-+}
-+
-+static int tlv320a_put_mic_boost(struct snd_kcontrol *kcontrol,
-+ struct snd_ctl_elem_value *ucontrol)
-+{
-+ int oldboost, newboost;
-+ u8 data;
-+ if (ucontrol->value.integer.value[0] == 1)
-+ newboost = 1;
-+ else
-+ newboost = 0;
-+ oldboost = g_analogpath & 0x1;
-+
-+ if (oldboost == newboost)
-+ return 0;
-+ data = (g_analogpath & 0xfe) | (newboost & 0x1);
-+ if (mcf_codec_spi_write(CODEC_ANALOG_APATH_REG, data) < 0)
-+ return -EINVAL;
-+ g_analogpath = data;
-+ return 1;
-+}
-+
-+static int tlv320a_info_capture_source(struct snd_kcontrol *kcontrol,
-+ struct snd_ctl_elem_info *uinfo)
-+{
-+ static char *texts[] = { "Line-In", "Microphone" };
-+
-+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
-+ uinfo->count = 1;
-+ uinfo->value.enumerated.items = 2;
-+ if (uinfo->value.enumerated.item > 1)
-+ uinfo->value.enumerated.item = 1;
-+ strcpy(uinfo->value.enumerated.name,
-+ texts[uinfo->value.enumerated.item]);
-+ return 0;
-+}
-+
-+static int tlv320a_get_capture_source(struct snd_kcontrol *kcontrol,
-+ struct snd_ctl_elem_value *ucontrol)
-+{
-+
-+ ucontrol->value.enumerated.item[0] = ((g_analogpath & 0x4) == 0x4);
-+ return 0;
-+}
-+
-+static int tlv320a_put_capture_source(struct snd_kcontrol *kcontrol,
-+ struct snd_ctl_elem_value *ucontrol)
-+{
-+ int oldinput, newinput;
-+ u8 data;
-+
-+ if (ucontrol->value.enumerated.item[0] > 1)
-+ return -EINVAL;
-+
-+ oldinput = (g_analogpath & 0x4) ? INPUT_MICROPHONE : INPUT_LINEIN;
-+
-+ if (ucontrol->value.enumerated.item[0])
-+ newinput = INPUT_MICROPHONE;
-+ else
-+ newinput = INPUT_LINEIN;
-+ if (oldinput == newinput)
-+ return 0;
-+ data = (g_analogpath & 0xfb) |
-+ (newinput == INPUT_MICROPHONE ? 0x4 : 0);
-+ if (mcf_codec_spi_write(CODEC_ANALOG_APATH_REG, data) < 0)
-+ return -EINVAL;
-+ g_analogpath = data;
-+ return 1;
-+}
-+
-+static struct snd_kcontrol_new tlv320_mixer_out __devinitdata = {
-+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-+ .name = "play volume",
-+ .index = 0,
-+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
-+ .info = tlv320a_info_out_volume,
-+ .get = tlv320a_get_out_volume,
-+ .put = tlv320a_put_out_volume,
-+};
-+
-+static struct snd_kcontrol_new tlv320_mixer_linein __devinitdata = {
-+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-+ .name = "record volume",
-+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
-+ .info = tlv320a_info_linein_volume,
-+ .get = tlv320a_get_linein_volume,
-+ .put = tlv320a_put_linein_volume,
-+};
-+
-+static struct snd_kcontrol_new tlv320_mixer_capture_source __devinitdata = {
-+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-+ .name = "record source",
-+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
-+ .info = tlv320a_info_capture_source,
-+ .get = tlv320a_get_capture_source,
-+ .put = tlv320a_put_capture_source,
-+};
-+
-+static struct snd_kcontrol_new tlv320_mixer_mic_boost __devinitdata = {
-+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-+ .name = "mic Boost",
-+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
-+ .info = tlv320a_info_mic_boost,
-+ .get = tlv320a_get_mic_boost,
-+ .put = tlv320a_put_mic_boost,
-+};
-+
-+static int __devinit coldfire_alsa_audio_probe(struct platform_device *dev)
-+{
-+ struct snd_card *card;
-+ struct chip_spec *chip;
-+ int err;
-+
-+ err = snd_card_create(-1, id, THIS_MODULE,
-+ sizeof(struct chip_spec), &card);
-+ if (err < 0)
-+ return -ENOMEM;
-+
-+ chip = card->private_data;
-+
-+ chip->card = card;
-+ card->dev = &dev->dev;
-+
-+ err = snd_coldfire_new_pcm(chip);
-+ if (err < 0)
-+ return -ENOMEM;
-+
-+ strcpy(card->driver, "coldfire");
-+ strcpy(card->shortname, "Coldfire-TLV320A");
-+ sprintf(card->longname, "Freescale Coldfire with TLV320A");
-+
-+ err = snd_card_register(card);
-+ if (err == 0) {
-+ pr_debug(KERN_INFO "Coldfire audio support initialized\n");
-+ platform_set_drvdata(dev, card);
-+ }
-+
-+ strcpy(chip->card->mixername, "TLV320A Volume");
-+ err = snd_ctl_add(chip->card, snd_ctl_new1(&tlv320_mixer_out, chip));
-+ if (err)
-+ goto error;
-+ err = snd_ctl_add(chip->card, snd_ctl_new1(&tlv320_mixer_linein, chip));
-+ if (err)
-+ goto error;
-+ err = snd_ctl_add(chip->card,
-+ snd_ctl_new1(&tlv320_mixer_capture_source,
-+ chip));
-+ if (err)
-+ goto error;
-+ err = snd_ctl_add(chip->card,
-+ snd_ctl_new1(&tlv320_mixer_mic_boost,
-+ chip));
-+ if (err)
-+ goto error;
-+ g_mastervol = TLV320A_VOL_INIT;
-+ g_lineinvol = TLV320A_LINEIN_INIT;
-+ g_analogpath = TLV320A_ANALOGPATH_INIT;
-+ ssi_audio_codec_reset();
-+ return 0;
-+error:
-+ kfree(card->private_data);
-+ snd_card_free(card);
-+ platform_set_drvdata(dev, NULL);
-+ return err;
-+}
-+
-+static int coldfire_alsa_audio_remove(struct platform_device *dev)
-+{
-+ struct snd_card *card;
-+
-+ card = platform_get_drvdata(dev);
-+ kfree(card->private_data);
-+ snd_card_free(card);
-+ platform_set_drvdata(dev, NULL);
-+
-+ return 0;
-+}
-+
-+static struct platform_driver coldfire_alsa_audio_driver = {
-+ .probe = coldfire_alsa_audio_probe,
-+ .remove = coldfire_alsa_audio_remove,
-+ .driver = {
-+ .name = SOUND_CARD_NAME,
-+ },
-+};
-+
-+static int __init coldfire_alsa_audio_init(void)
-+{
-+ int err;
-+ err = platform_driver_register(&coldfire_alsa_audio_driver);
-+ if (err < 0)
-+ return err;
-+
-+ device = platform_device_register_simple(SOUND_CARD_NAME, -1, NULL, 0);
-+ if (!IS_ERR(device)) {
-+ if (platform_get_drvdata(device))
-+ return 0;
-+ platform_device_unregister(device);
-+ platform_driver_unregister(&coldfire_alsa_audio_driver);
-+ err = -ENODEV;
-+ } else
-+ err = PTR_ERR(device);
-+
-+ platform_driver_unregister(&coldfire_alsa_audio_driver);
-+ return err;
-+}
-+
-+static void __exit coldfire_alsa_audio_exit(void)
-+{
-+ platform_device_unregister(device);
-+ platform_driver_unregister(&coldfire_alsa_audio_driver);
-+}
-+
-+module_init(coldfire_alsa_audio_init);
-+module_exit(coldfire_alsa_audio_exit);
-+
-+MODULE_DESCRIPTION("Coldfire driver for ALSA");
-+MODULE_LICENSE("GPL");
-+MODULE_SUPPORTED_DEVICE("{{TLV320A}}");
-+
-+module_param(id, charp, 0444);
-+MODULE_PARM_DESC(id, "ID string for Coldfire + TLV320A soundcard.");
---- /dev/null
-+++ b/sound/coldfire/snd-coldfire.h
-@@ -0,0 +1,15 @@
-+/*
-+ * linux/sound/coldfire/snd-coldfire.h
-+ *
-+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved.
-+ *
-+ * ALSA driver for Coldfire SSI
-+ *
-+ * This 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.
-+ */
-+
-+extern int mcf_codec_spi_write(u8 addr, u16 data);
-+