Root/target/linux/coldfire/patches/009-Add-ALSA-driver-for-MCF5445x.patch

1From d37d2d880efdc0ce515df4155ddafef3835d1b7f Mon Sep 17 00:00:00 2001
2From: Alison Wang <b18965@freescale.com>
3Date: Thu, 4 Aug 2011 09:59:41 +0800
4Subject: [PATCH 09/52] Add ALSA driver for MCF5445x
5
6Add ALSA driver for MCF54451 and MCF54455.
7
8Signed-off-by: Alison Wang <b18965@freescale.com>
9---
10 sound/Kconfig | 6 +-
11 sound/Makefile | 1 +
12 sound/coldfire/Kconfig | 14 +
13 sound/coldfire/Makefile | 6 +
14 sound/coldfire/coldfire-codec-spi.c | 93 ++
15 sound/coldfire/snd-coldfire.c | 1664 +++++++++++++++++++++++++++++++++++
16 sound/coldfire/snd-coldfire.h | 15 +
17 7 files changed, 1795 insertions(+), 4 deletions(-)
18 create mode 100644 sound/coldfire/Kconfig
19 create mode 100644 sound/coldfire/Makefile
20 create mode 100644 sound/coldfire/coldfire-codec-spi.c
21 create mode 100644 sound/coldfire/snd-coldfire.c
22 create mode 100644 sound/coldfire/snd-coldfire.h
23
24--- a/sound/Kconfig
25+++ b/sound/Kconfig
26@@ -59,8 +59,6 @@ config SOUND_OSS_CORE_PRECLAIM
27 
28 source "sound/oss/dmasound/Kconfig"
29 
30-if !M68K
31-
32 menuconfig SND
33     tristate "Advanced Linux Sound Architecture"
34     help
35@@ -85,6 +83,8 @@ source "sound/aoa/Kconfig"
36 
37 source "sound/arm/Kconfig"
38 
39+source "sound/coldfire/Kconfig"
40+
41 source "sound/atmel/Kconfig"
42 
43 source "sound/spi/Kconfig"
44@@ -121,8 +121,6 @@ source "sound/oss/Kconfig"
45 
46 endif # SOUND_PRIME
47 
48-endif # !M68K
49-
50 endif # SOUND
51 
52 # AC97_BUS is used from both sound and ucb1400
53--- a/sound/Makefile
54+++ b/sound/Makefile
55@@ -8,6 +8,7 @@ obj-$(CONFIG_DMASOUND) += oss/
56 obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ sh/ synth/ usb/ \
57     sparc/ spi/ parisc/ pcmcia/ mips/ soc/ atmel/
58 obj-$(CONFIG_SND_AOA) += aoa/
59+obj-$(CONFIG_SND_COLDFIRE) += coldfire/
60 
61 # This one must be compilable even if sound is configured out
62 obj-$(CONFIG_AC97_BUS) += ac97_bus.o
63--- /dev/null
64+++ b/sound/coldfire/Kconfig
65@@ -0,0 +1,14 @@
66+
67+menu "ALSA for Coldfire"
68+
69+config SND_COLDFIRE
70+ bool "Coldfire sound devices"
71+ depends on SND
72+ select SND_PCM
73+ select SSIAUDIO_USE_EDMA
74+ default y
75+ help
76+ Support for sound devices specific to Coldfire architectures.
77+
78+endmenu
79+
80--- /dev/null
81+++ b/sound/coldfire/Makefile
82@@ -0,0 +1,6 @@
83+#
84+# Makefile for Coldfire ALSA
85+#
86+
87+obj-y += snd-coldfire.o coldfire-codec-spi.o
88+
89--- /dev/null
90+++ b/sound/coldfire/coldfire-codec-spi.c
91@@ -0,0 +1,93 @@
92+/*
93+ * linux/sound/coldfire/coldfire-codec-spi.c
94+ *
95+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved.
96+ * Author: Kurt Mahan <kmahan@freescale.com>
97+ *
98+ * Simple SPI interface for the CODEC.
99+ *
100+ * This is free software; you can redistribute it and/or modify
101+ * it under the terms of the GNU General Public License as published by
102+ * the Free Software Foundation; either version 2 of the License, or
103+ * (at your option) any later version.
104+ */
105+
106+#include <linux/device.h>
107+#include <linux/init.h>
108+#include <linux/spi/spi.h>
109+#include <linux/kernel.h>
110+#include <asm/mcfsim.h>
111+#include <asm/coldfire.h>
112+#include <linux/delay.h>
113+
114+#define MCF_CODEC_SPI_DRIVER_NAME "mcf_codec_spi"
115+
116+static struct spi_device *mcf_codec_spi;
117+
118+/*
119+ * Write CODEC register via SPI
120+ */
121+int mcf_codec_spi_write(u8 addr, u16 data)
122+{
123+ u16 spi_word;
124+
125+ if (mcf_codec_spi == NULL)
126+ return -ENODEV;
127+
128+ spi_word = ((addr & 0x7F)<<9)|(data & 0x1FF);
129+ return spi_write(mcf_codec_spi, (const u8 *)&spi_word,
130+ sizeof(spi_word));
131+}
132+EXPORT_SYMBOL(mcf_codec_spi_write);
133+
134+static int __devinit mcf_codec_spi_probe(struct spi_device *spi)
135+{
136+ spi->dev.power.power_state = PMSG_ON;
137+ mcf_codec_spi = spi;
138+
139+ return 0;
140+}
141+
142+static int __devexit mcf_codec_spi_remove(struct spi_device *spi)
143+{
144+ return 0;
145+}
146+
147+static int mcf_codec_spi_suspend(struct spi_device *spi, pm_message_t message)
148+{
149+ return 0;
150+}
151+
152+static int mcf_codec_spi_resume(struct spi_device *spi)
153+{
154+ return 0;
155+}
156+
157+static struct spi_driver mcf_codec_spi_driver = {
158+ .driver = {
159+ .name = MCF_CODEC_SPI_DRIVER_NAME,
160+ .bus = &spi_bus_type,
161+ .owner = THIS_MODULE,
162+ },
163+ .probe = mcf_codec_spi_probe,
164+ .remove = __devexit_p(mcf_codec_spi_remove),
165+ .suspend = mcf_codec_spi_suspend,
166+ .resume = mcf_codec_spi_resume,
167+};
168+
169+static int __init mcf_codec_spi_init(void)
170+{
171+ return spi_register_driver(&mcf_codec_spi_driver);
172+}
173+module_init(mcf_codec_spi_init);
174+
175+static void __exit mcf_codec_spi_exit(void)
176+{
177+ spi_unregister_driver(&mcf_codec_spi_driver);
178+}
179+module_exit(mcf_codec_spi_exit);
180+
181+
182+MODULE_DESCRIPTION("Coldfire Codec SPI driver");
183+MODULE_AUTHOR("Kurt Mahan, Freescale Semiconductor, Inc.");
184+MODULE_LICENSE("GPL");
185--- /dev/null
186+++ b/sound/coldfire/snd-coldfire.c
187@@ -0,0 +1,1664 @@
188+/*
189+ * linux/sound/coldfire/snd-coldfire.c
190+ *
191+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved.
192+ * Author: York Sun <r58495@freescale.com>
193+ * Alison Wang <b18965@freescale.com>
194+ *
195+ * Coldfire ALSA driver based on SSI and TLV320A
196+ *
197+ * This is free software; you can redistribute it and/or modify
198+ * it under the terms of the GNU General Public License as published by
199+ * the Free Software Foundation; either version 2 of the License, or
200+ * (at your option) any later version.
201+ *
202+ ***************************************************************************
203+ *
204+ * NOTE: This driver was tested on MCF5445x, MCF5301x, MCF5227x, MCF532x and
205+ * MCF537x platforms.
206+ * */
207+
208+#include <linux/module.h>
209+#include <linux/moduleparam.h>
210+#include <linux/platform_device.h>
211+#include <linux/init.h>
212+#include <linux/device.h>
213+#include <linux/slab.h>
214+#include <linux/dma-mapping.h>
215+#include <linux/ioctl.h>
216+#include <linux/soundcard.h>
217+#include <linux/spi/spi.h>
218+
219+#include <sound/core.h>
220+#include <sound/pcm.h>
221+#include <sound/pcm_params.h>
222+#include <sound/control.h>
223+#include <linux/fs.h>
224+#include <linux/delay.h>
225+
226+#include <asm/mcfsim.h>
227+#include <asm/coldfire.h>
228+#include <asm/mcf_edma.h>
229+#include "snd-coldfire.h"
230+
231+#if defined(CONFIG_M5445X)
232+#include <asm/mcf5445x_ssi.h>
233+#endif
234+
235+#define CF_ALSA_DEBUG 0
236+#if CF_ALSA_DEBUG
237+#define DBG(fmt, args...) printk(KERN_INFO "[%s] " fmt , \
238+ __func__, ## args)
239+#else
240+#define DBG(fmt, args...) do {} while (0)
241+#endif
242+
243+#define SOUND_CARD_NAME "Coldfire ALSA"
244+#define MAX_BUFFER_SIZE (32*1024)
245+
246+/* eDMA channel for SSI channel 0,1 TX,RX */
247+#define DMA_TX_TCD0 MCF_EDMA_CHAN_TIMER2
248+#define DMA_TX_TCD1 MCF_EDMA_CHAN_TIMER3
249+#define DMA_RX_TCD0 MCF_EDMA_CHAN_TIMER0
250+#define DMA_RX_TCD1 MCF_EDMA_CHAN_TIMER1
251+
252+#define CODEC_LEFT_IN_REG (0x00)
253+#define CODEC_RIGHT_IN_REG (0x01)
254+#define CODEC_LEFT_HP_VOL_REG (0x02)
255+#define CODEC_RIGHT_HP_VOL_REG (0x03)
256+#define CODEC_ANALOG_APATH_REG (0x04)
257+#define CODEC_DIGITAL_APATH_REG (0x05)
258+#define CODEC_POWER_DOWN_REG (0x06)
259+#define CODEC_DIGITAL_IF_FMT_REG (0x07)
260+#define CODEC_SAMPLE_RATE_REG (0x08)
261+#define CODEC_DIGITAL_IF_ACT_REG (0x09)
262+#define CODEC_RESET_REG (0x0f)
263+
264+#define TLV320AIC23_CODEC_SAMPLE_RATE_REG (0x08)
265+#define TLV320AIC23_CODEC_SAMPLERATE_REG_8KHZ (0x0C)
266+#define TLV320AIC23_CODEC_SAMPLERATE_REG_11KHZ (0x0C)
267+#define TLV320AIC23_CODEC_SAMPLERATE_REG_16KHZ (0x58)
268+#define TLV320AIC23_CODEC_SAMPLERATE_REG_22KHZ (0x62)
269+#define TLV320AIC23_CODEC_SAMPLERATE_REG_44KHZ (0x22)
270+#define TLV320AIC23_CODEC_SAMPLERATE_REG_48KHZ (0x00)
271+
272+#define MCF_SSI_AUDIO_IRQ_LEVEL (5)
273+#define TLV320A_VOL_MAX 0x07F
274+#define TLV320A_VOL_MIN 0x030
275+#define TLV320A_VOL_INIT 0x065
276+#define TLV320A_LINEIN_MAX 0x1F
277+#define TLV320A_LINEIN_INIT 0x17
278+#define TLV320A_ANALOGPATH_INIT 0x11
279+
280+/* Codec settings */
281+#define MCF_SSI_AUDIO_MCLK_1 (12288000U) /*Hz*/
282+#define MCF_SSI_AUDIO_MCLK_2 (16934400U) /*Hz*/
283+#define MCF_SSI_AUDIO_MCLK_3 (14112000U) /*Hz*/
284+#define MCF_SSI_AUDIO_MCLK_4 (18432000U) /*Hz*/
285+
286+#define MCF_SSI_AUDIO_SSDIV_VALUE_1 \
287+ ((((u32)MCF_CLK*2)/MCF_SSI_AUDIO_MCLK_1)+ \
288+ (((((u32)MCF_CLK*2*10)/MCF_SSI_AUDIO_MCLK_1)%10) > 5))
289+
290+#define MCF_SSI_AUDIO_SSDIV_VALUE_2 \
291+ ((((u32)MCF_CLK*2)/MCF_SSI_AUDIO_MCLK_2)+ \
292+ (((((u32)MCF_CLK*2*10)/MCF_SSI_AUDIO_MCLK_2)%10) > 5))
293+
294+#define MCF_SSI_AUDIO_SSDIV_VALUE_3 \
295+ ((((u32)MCF_CLK*2)/MCF_SSI_AUDIO_MCLK_3)+ \
296+ (((((u32)MCF_CLK*2*10)/MCF_SSI_AUDIO_MCLK_3)%10) > 5))
297+
298+#define MCF_SSI_AUDIO_SSDIV_VALUE_4 \
299+ ((((u32)MCF_CLK*2)/MCF_SSI_AUDIO_MCLK_4)+ \
300+ (((((u32)MCF_CLK*2*10)/MCF_SSI_AUDIO_MCLK_4)%10) > 5))
301+
302+#define SNDRV_COLDFIRE_PCM_PLAYBACK_FORMATS SNDRV_PCM_FMTBIT_S16_BE
303+#define SNDRV_COLDFIRE_PCM_CAPTURE_FORMATS SNDRV_PCM_FMTBIT_S16_BE
304+
305+#define RXFWM 2
306+#define TXFWM 2
307+#define HW_PERIODS_BYTES_MIN 4096
308+#define HW_PERIODS_BYTES_STEP 4096
309+
310+#define INPUT_MICROPHONE 0
311+#define INPUT_LINEIN 1
312+#define NUM_TCDS 4
313+
314+static char *id;
315+static struct platform_device *device;
316+static int g_tx_dmaing;
317+static int g_rx_dmaing;
318+static unsigned char g_mastervol, g_lineinvol, g_analogpath;
319+
320+/** Use 4 TCDs for scatter/gather address
321+ * to setup dma chain, one TCD per period
322+ * so that we don't need change them on the fly
323+ */
324+
325+/**
326+ * Link Descriptor
327+ *
328+ * must be aligned on a 32-byte boundary.
329+ */
330+struct dma_tcd {
331+ __be32 saddr; /* source address */
332+ __be16 attr; /* transfer attribute */
333+ __be16 soffset; /* source offset */
334+ __be32 nbytes; /* minor byte count */
335+ __be32 slast; /* last source address adjust */
336+ __be32 daddr; /* dest address */
337+ __be16 citer; /* current minor looplink, major count */
338+ __be16 doffset; /* dest offset */
339+ __be32 dlast_sga; /* last dest addr adjust, scatter/gather addr*/
340+ __be16 biter; /* begging minor looklink, major count */
341+ __be16 csr; /* control and status */
342+} __packed;
343+
344+/** dma_private: p-substream DMA data
345+ *
346+ * The tcd[] array is first because it needs to be aligned on a 32-byte
347+ * boundary, so putting it first will ensure alignment without padding the
348+ * structure.
349+ *
350+ * @tcd[]: array of TCDs
351+ */
352+struct dma_private {
353+ struct dma_tcd tcd0[NUM_TCDS];
354+ struct dma_tcd tcd1[NUM_TCDS];
355+ dma_addr_t tcd_buf_phys; /* physical address of dma_private */
356+ dma_addr_t dma_buf_phys;
357+ dma_addr_t dma_buf_next;
358+ dma_addr_t dma_buf_end;
359+ size_t period_size;
360+ unsigned int num_periods;
361+};
362+
363+struct tlv320a_audio_device {
364+ struct spi_device *spi;
365+ u32 speed;
366+ u32 stereo;
367+ u32 bits;
368+ u32 format;
369+ u8 isopen;
370+ u8 dmaing;
371+ u8 ssi_enabled;
372+ u8 channel;
373+ spinlock_t lock;
374+ u8 *audio_buf;
375+};
376+
377+/* chip specific define */
378+struct chip_spec {
379+ struct snd_card *card;
380+ struct snd_pcm *pcm;
381+ struct tlv320a_audio_device *audio_device;
382+ u32 offset;
383+ void *mixer_data;
384+};
385+
386+/* hardware definition */
387+static struct snd_pcm_hardware snd_coldfire_playback_hw = {
388+ .info = (SNDRV_PCM_INFO_INTERLEAVED |
389+#if defined(CONFIG_MMU)
390+ SNDRV_PCM_INFO_MMAP |
391+ SNDRV_PCM_INFO_MMAP_VALID|
392+#endif
393+ SNDRV_PCM_INFO_BLOCK_TRANSFER),
394+ .formats = SNDRV_COLDFIRE_PCM_PLAYBACK_FORMATS,
395+ .rates = SNDRV_PCM_RATE_8000_48000,
396+ .rate_min = 8000,
397+ .rate_max = 48000,
398+ .channels_min = 1,
399+ .channels_max = 2,
400+ .buffer_bytes_max = MAX_BUFFER_SIZE,
401+ .period_bytes_min = HW_PERIODS_BYTES_MIN,
402+ .period_bytes_max = MAX_BUFFER_SIZE/NUM_TCDS,
403+ .periods_min = NUM_TCDS,
404+ .periods_max = NUM_TCDS,
405+ .fifo_size = 0,
406+};
407+
408+/* hardware definition */
409+static struct snd_pcm_hardware snd_coldfire_capture_hw = {
410+ .info = (SNDRV_PCM_INFO_INTERLEAVED |
411+#if defined(CONFIG_MMU)
412+ SNDRV_PCM_INFO_MMAP |
413+ SNDRV_PCM_INFO_MMAP_VALID|
414+#endif
415+ SNDRV_PCM_INFO_BLOCK_TRANSFER),
416+ .formats = SNDRV_COLDFIRE_PCM_CAPTURE_FORMATS,
417+ .rates = SNDRV_PCM_RATE_8000_48000,
418+ .rate_min = 8000,
419+ .rate_max = 48000,
420+ .channels_min = 1,
421+ .channels_max = 2,
422+ .buffer_bytes_max = MAX_BUFFER_SIZE,
423+ .period_bytes_min = HW_PERIODS_BYTES_MIN,
424+ .period_bytes_max = MAX_BUFFER_SIZE/NUM_TCDS,
425+ .periods_min = NUM_TCDS,
426+ .periods_max = NUM_TCDS,
427+ .fifo_size = 0,
428+};
429+
430+static unsigned int rates[] = {8000, 11025, 16000, 22000,
431+ 22050, 44000, 44100, 48000};
432+
433+/* hw constraints */
434+static struct snd_pcm_hw_constraint_list constraints_rates = {
435+ .count = ARRAY_SIZE(rates),
436+ .list = rates,
437+ .mask = 0,
438+};
439+
440+static inline void ssi_audio_dma_playback_start(void)
441+{
442+ g_tx_dmaing = 1;
443+ mcf_edma_start_transfer(DMA_TX_TCD0);
444+ mcf_edma_start_transfer(DMA_TX_TCD1);
445+}
446+
447+static inline void ssi_audio_dma_capture_start(void)
448+{
449+ g_rx_dmaing = 1;
450+ mcf_edma_start_transfer(DMA_RX_TCD0);
451+ mcf_edma_start_transfer(DMA_RX_TCD1);
452+}
453+
454+static inline void ssi_audio_dma_playback_stop(void)
455+{
456+ g_tx_dmaing = 0;
457+ mcf_edma_stop_transfer(DMA_TX_TCD0);
458+ mcf_edma_stop_transfer(DMA_TX_TCD1);
459+}
460+
461+inline void ssi_audio_dma_capture_stop(void)
462+{
463+ g_rx_dmaing = 0;
464+ mcf_edma_stop_transfer(DMA_RX_TCD0);
465+ mcf_edma_stop_transfer(DMA_RX_TCD1);
466+}
467+
468+/**
469+ * fill_tcd_params - Fill transfer control descriptor (TCD)
470+ * @base: base address of TCD
471+ * @source: source address
472+ * @dest: destination address
473+ * @attr: attributes
474+ * @soff: source offset
475+ * @nbytes: number of bytes to be transfered in minor loop
476+ * @slast: last source address adjustment
477+ * @citer: major loop count
478+ * @biter: beginning minor loop count
479+ * @doff: destination offset
480+ * @dlast_sga: last destination address adjustment
481+ * @major_int: generate interrupt after each major loop
482+ * @disable_req: disable DMA request after major loop
483+ * @enable_sg: enable scatter/gather address
484+ */
485+void fill_tcd_params(u32 base, u32 source, u32 dest,
486+ u32 attr, u32 soff, u32 nbytes, u32 slast,
487+ u32 citer, u32 biter, u32 doff, u32 dlast_sga,
488+ int major_int, int disable_req, int enable_sg)
489+{
490+ struct dma_tcd *tcd = (struct dma_tcd *) base;
491+
492+ tcd->saddr = source;
493+ tcd->attr = attr;
494+ tcd->soffset = soff;
495+ tcd->nbytes = nbytes;
496+ tcd->slast = slast;
497+ tcd->daddr = dest;
498+ tcd->citer = citer & 0x7fff;
499+ tcd->doffset = doff;
500+ tcd->dlast_sga = dlast_sga;
501+ tcd->biter = biter & 0x7fff;
502+ tcd->csr = ((major_int) ? 0x2 : 0) |
503+ ((disable_req) ? 0x8 : 0) |
504+ ((enable_sg) ? 0x10 : 0);
505+}
506+
507+static int
508+ssi_audio_dma_playback_config(struct snd_pcm_substream *substream)
509+{
510+ struct snd_pcm_runtime *runtime = substream->runtime;
511+ struct dma_private *dma_private = runtime->private_data;
512+ u32 size = frames_to_bytes(runtime, runtime->period_size);
513+ u32 offset, soffset, daddr0, daddr1, attr, sga0, sga1;
514+ u32 i, nbyte, major_loops;
515+
516+ if ((runtime->channels < 1) || (runtime->channels > 2)) {
517+ printk(KERN_ERR "Error on channels = %d\n", runtime->channels);
518+ return -EINVAL;
519+ }
520+
521+ dma_private->dma_buf_phys = runtime->dma_addr;
522+ dma_private->dma_buf_next = dma_private->dma_buf_phys;
523+ dma_private->dma_buf_end = dma_private->dma_buf_phys +
524+ runtime->periods * size;
525+
526+ if (runtime->format == SNDRV_PCM_FORMAT_S16_BE) {
527+ nbyte = 2 * TXFWM;
528+ soffset = 2 * runtime->channels;
529+ daddr0 = (u32)&MCF_SSI_TX0 + 2;
530+ daddr1 = (u32)&MCF_SSI_TX1 + 2;
531+ attr = MCF_EDMA_TCD_ATTR_SSIZE_16BIT |
532+ MCF_EDMA_TCD_ATTR_DSIZE_16BIT;
533+ } else {
534+ printk(KERN_ERR "Not supported PCM format %x\n",
535+ runtime->format);
536+ return -EINVAL;
537+ }
538+
539+ major_loops = size/nbyte/runtime->channels;
540+ sga0 = (u32)dma_private->tcd_buf_phys;
541+ sga1 = (u32)dma_private->tcd_buf_phys +
542+ 4 * sizeof(struct dma_tcd);
543+
544+#if defined(CONFIG_M5301x) || defined(CONFIG_M5445X)
545+ MCF_EDMA_TCD10_CSR = 0;
546+ MCF_EDMA_TCD11_CSR = 0;
547+#else
548+ MCF_EDMA_TCD11_CSR = 0;
549+ MCF_EDMA_TCD12_CSR = 0;
550+#endif
551+ offset = (runtime->channels - 1) * 2;
552+ mcf_edma_set_tcd_params(DMA_TX_TCD0,
553+ (u32)dma_private->dma_buf_next,
554+ daddr0,
555+ attr,
556+ soffset,
557+ nbyte,
558+ 0, /* slast */
559+ major_loops, /* citer */
560+ major_loops, /* biter */
561+ 0, /* dest offset */
562+ sga0,
563+ 1, /* major_int */
564+ 0); /* enable dma request after */
565+
566+ mcf_edma_set_tcd_params(DMA_TX_TCD1,
567+ (u32)dma_private->dma_buf_next + offset,
568+ daddr1,
569+ attr,
570+ soffset,
571+ nbyte,
572+ 0, /* slast */
573+ major_loops, /* citer */
574+ major_loops, /* biter */
575+ 0, /* dest offset */
576+ sga1,
577+ 0, /* major_int */
578+ 0); /* enable dma request after */
579+
580+ while (!(MCF_EDMA_TCD_CSR(DMA_TX_TCD0) & MCF_EDMA_TCD_CSR_E_SG))
581+ MCF_EDMA_TCD_CSR(DMA_TX_TCD0) |= MCF_EDMA_TCD_CSR_E_SG;
582+ while (!(MCF_EDMA_TCD_CSR(DMA_TX_TCD1) & MCF_EDMA_TCD_CSR_E_SG))
583+ MCF_EDMA_TCD_CSR(DMA_TX_TCD1) |= MCF_EDMA_TCD_CSR_E_SG;
584+
585+ for (i = 0; i < NUM_TCDS; i++) {
586+ dma_private->dma_buf_next += size;
587+ if (dma_private->dma_buf_next >= dma_private->dma_buf_end)
588+ dma_private->dma_buf_next = dma_private->dma_buf_phys;
589+ sga0 = (u32)dma_private->tcd_buf_phys +
590+ ((i+1)%NUM_TCDS) * sizeof(struct dma_tcd);
591+ sga1 = (u32)dma_private->tcd_buf_phys +
592+ ((i+1)%NUM_TCDS + 4) * sizeof(struct dma_tcd);
593+ DBG("sga0 = 0x%x, sga1 = 0x%x.\n", sga0, sga1);
594+ fill_tcd_params((u32)&dma_private->tcd0[i],
595+ (u32)dma_private->dma_buf_next,
596+ daddr0,
597+ attr,
598+ soffset,
599+ nbyte,
600+ 0, /* slast */
601+ major_loops, /* citer */
602+ major_loops, /* biter */
603+ 0, /* dest offset */
604+ sga0,
605+ 1, /* major_int */
606+ 0, /* enable dma request after */
607+ 1); /* enable scatter/gather */
608+
609+ fill_tcd_params((u32)&dma_private->tcd1[i],
610+ (u32)dma_private->dma_buf_next + offset,
611+ daddr1,
612+ attr,
613+ soffset,
614+ nbyte,
615+ 0, /* slast */
616+ major_loops, /* citer */
617+ major_loops, /* biter */
618+ 0, /* dest offset */
619+ sga1,
620+ 0, /* major_int */
621+ 0, /* enable dma request after */
622+ 1); /* enable scatter/gather */
623+ }
624+
625+ return 0;
626+}
627+
628+static int
629+ssi_audio_dma_capture_config(struct snd_pcm_substream *substream)
630+{
631+ struct snd_pcm_runtime *runtime = substream->runtime;
632+ struct dma_private *dma_private = runtime->private_data;
633+ u32 size = frames_to_bytes(runtime, runtime->period_size);
634+ u32 offset, saddr0, saddr1, doffset, attr, sga0, sga1;
635+ int i, nbyte, major_loops;
636+
637+ if ((runtime->channels < 1) || (runtime->channels > 2)) {
638+ printk(KERN_ERR "Error on channels = %d\n", runtime->channels);
639+ return -EINVAL;
640+ }
641+
642+ dma_private->dma_buf_phys = runtime->dma_addr;
643+ dma_private->dma_buf_next = dma_private->dma_buf_phys;
644+ dma_private->dma_buf_end = dma_private->dma_buf_phys +
645+ runtime->periods * size;
646+
647+ switch (runtime->format) {
648+ case SNDRV_PCM_FORMAT_S16_BE:
649+ saddr0 = (u32)&MCF_SSI_RX0 + 2;
650+ saddr1 = (u32)&MCF_SSI_RX1 + 2;
651+ nbyte = 2 * RXFWM;
652+ doffset = 2 * runtime->channels;
653+ attr = MCF_EDMA_TCD_ATTR_SSIZE_16BIT |
654+ MCF_EDMA_TCD_ATTR_DSIZE_16BIT;
655+ break;
656+ default:
657+ printk(KERN_ERR "Not supported PCM format %x\n",
658+ runtime->format);
659+ return -EINVAL;
660+ }
661+
662+ major_loops = size/nbyte/runtime->channels;
663+ sga0 = (u32)dma_private->tcd_buf_phys;
664+ sga1 = (u32)dma_private->tcd_buf_phys +
665+ 4 * sizeof(struct dma_tcd);
666+
667+#if defined(CONFIG_M5301x) || defined(CONFIG_M5445X)
668+ MCF_EDMA_TCD8_CSR = 0;
669+ MCF_EDMA_TCD9_CSR = 0;
670+#else
671+ MCF_EDMA_TCD9_CSR = 0;
672+ MCF_EDMA_TCD10_CSR = 0;
673+#endif
674+ offset = (runtime->channels - 1) * 2;
675+ mcf_edma_set_tcd_params(DMA_RX_TCD0,
676+ saddr0,
677+ (u32)dma_private->dma_buf_next,
678+ attr,
679+ 0, /* source offset */
680+ nbyte,
681+ 0, /* slast */
682+ major_loops, /* citer */
683+ major_loops, /* biter */
684+ doffset,
685+ sga0,
686+ 1, /* major_int */
687+ 0); /* enable dma request after */
688+
689+ mcf_edma_set_tcd_params(DMA_RX_TCD1,
690+ saddr1,
691+ (u32)dma_private->dma_buf_next + offset,
692+ attr,
693+ 0, /* source offset */
694+ nbyte,
695+ 0, /* slast */
696+ major_loops, /* citer */
697+ major_loops, /* biter */
698+ doffset,
699+ sga1,
700+ 0, /* major_int */
701+ 0); /* enable dma request after */
702+
703+ while (!(MCF_EDMA_TCD_CSR(DMA_RX_TCD0) & MCF_EDMA_TCD_CSR_E_SG))
704+ MCF_EDMA_TCD_CSR(DMA_RX_TCD0) |= MCF_EDMA_TCD_CSR_E_SG;
705+ while (!(MCF_EDMA_TCD_CSR(DMA_RX_TCD1) & MCF_EDMA_TCD_CSR_E_SG))
706+ MCF_EDMA_TCD_CSR(DMA_RX_TCD1) |= MCF_EDMA_TCD_CSR_E_SG;
707+
708+ for (i = 0; i < NUM_TCDS; i++) {
709+ dma_private->dma_buf_next += size;
710+ if (dma_private->dma_buf_next >= dma_private->dma_buf_end)
711+ dma_private->dma_buf_next = dma_private->dma_buf_phys;
712+ sga0 = (u32)dma_private->tcd_buf_phys +
713+ ((i+1)%NUM_TCDS) * sizeof(struct dma_tcd);
714+ sga1 = (u32)dma_private->tcd_buf_phys +
715+ ((i+1)%NUM_TCDS + 4) * sizeof(struct dma_tcd);
716+ fill_tcd_params((u32)&dma_private->tcd0[i],
717+ saddr0,
718+ (u32)dma_private->dma_buf_next,
719+ attr,
720+ 0, /* source offset */
721+ nbyte,
722+ 0, /* slast */
723+ major_loops, /* citer */
724+ major_loops, /* biter */
725+ doffset,
726+ sga0,
727+ 1, /* major_int */
728+ 0, /* enable dma request after */
729+ 1); /* enable scatter/gather */
730+ fill_tcd_params((u32)&dma_private->tcd1[i],
731+ saddr1,
732+ (u32)dma_private->dma_buf_next + offset,
733+ attr,
734+ 0, /* source offset */
735+ nbyte,
736+ 0, /* slast */
737+ major_loops, /* citer */
738+ major_loops, /* biter */
739+ doffset,
740+ sga1,
741+ 0, /* major_int */
742+ 0, /* enable dma request after */
743+ 1); /* enable scatter/gather */
744+ }
745+ return 0;
746+}
747+
748+static inline void ssi_audio_enable_ssi_playback(void)
749+{
750+ MCF_SSI_CR |= MCF_SSI_CR_SSI_EN | MCF_SSI_CR_TE;
751+}
752+
753+static inline void ssi_audio_enable_ssi_capture(void)
754+{
755+ MCF_SSI_CR |= MCF_SSI_CR_SSI_EN | MCF_SSI_CR_RE;
756+}
757+
758+static inline void ssi_audio_disable_ssi(void)
759+{
760+ MCF_SSI_CR &= ~(MCF_SSI_CR_TE | MCF_SSI_CR_RE | MCF_SSI_CR_SSI_EN);
761+}
762+
763+static inline void ssi_audio_disable_ssi_playback(void)
764+{
765+ MCF_SSI_CR &= ~MCF_SSI_CR_TE;
766+}
767+
768+static inline void ssi_audio_disable_ssi_capture(void)
769+{
770+ MCF_SSI_CR &= ~MCF_SSI_CR_RE;
771+}
772+
773+static irqreturn_t ssi_audio_dma_playback_handler(int channel, void *dev_id)
774+{
775+ struct snd_pcm_substream *substream;
776+ struct snd_pcm_runtime *runtime;
777+
778+ substream = (struct snd_pcm_substream *)dev_id;
779+ runtime = substream->runtime;
780+
781+ /* inform ALSA middle layer about transfer status */
782+ snd_pcm_period_elapsed(substream);
783+ mcf_edma_confirm_interrupt_handled(DMA_TX_TCD0);
784+ mcf_edma_confirm_interrupt_handled(DMA_TX_TCD1);
785+
786+ return IRQ_HANDLED;
787+}
788+
789+static irqreturn_t ssi_audio_dma_capture_handler(int channel, void *dev_id)
790+{
791+ struct snd_pcm_substream *substream;
792+ struct snd_pcm_runtime *runtime;
793+
794+ substream = (struct snd_pcm_substream *)dev_id;
795+ runtime = substream->runtime;
796+
797+ /* inform ALSA middle layer about transfer status */
798+ snd_pcm_period_elapsed(substream);
799+ mcf_edma_confirm_interrupt_handled(DMA_RX_TCD0);
800+ mcf_edma_confirm_interrupt_handled(DMA_RX_TCD1);
801+
802+ return IRQ_HANDLED;
803+}
804+
805+int ssi_audio_dma_request_playback_channel(struct snd_pcm_substream *substream)
806+{
807+ int err;
808+ struct chip_spec *chip = snd_pcm_substream_chip(substream);
809+
810+ /* request eDMA channel */
811+ err = mcf_edma_request_channel(DMA_TX_TCD0,
812+ ssi_audio_dma_playback_handler,
813+ NULL,
814+ MCF_SSI_AUDIO_IRQ_LEVEL,
815+ substream,
816+ &(chip->audio_device->lock),
817+ id);
818+ if (err < 0)
819+ return err;
820+ err = mcf_edma_request_channel(DMA_TX_TCD1,
821+ ssi_audio_dma_playback_handler,
822+ NULL,
823+ MCF_SSI_AUDIO_IRQ_LEVEL,
824+ substream,
825+ &(chip->audio_device->lock),
826+ id);
827+ return err;
828+}
829+
830+int ssi_audio_dma_request_capture_channel(struct snd_pcm_substream *substream)
831+{
832+ int err;
833+ struct chip_spec *chip = snd_pcm_substream_chip(substream);
834+
835+ /* request 2 eDMA channels for two fifo */
836+ err = mcf_edma_request_channel(DMA_RX_TCD0,
837+ ssi_audio_dma_capture_handler,
838+ NULL,
839+ MCF_SSI_AUDIO_IRQ_LEVEL,
840+ substream,
841+ &(chip->audio_device->lock),
842+ id);
843+ if (err < 0)
844+ return err;
845+ err = mcf_edma_request_channel(DMA_RX_TCD1,
846+ ssi_audio_dma_capture_handler,
847+ NULL,
848+ MCF_SSI_AUDIO_IRQ_LEVEL,
849+ substream,
850+ &(chip->audio_device->lock),
851+ id);
852+ return err;
853+}
854+
855+static inline void ssi_audio_init_dma(void)
856+{
857+ /* SSI DMA Signals mapped to DMA request */
858+ MCF_CCM_MISCCR &= ~MCF_CCM_MISCCR_TIM_DMA;
859+}
860+
861+static void ssi_audio_adjust_codec_speed(struct snd_pcm_substream *substream)
862+{
863+ ssi_audio_disable_ssi();
864+
865+ if (substream->runtime->format == SNDRV_PCM_FORMAT_S16_BE) {
866+ MCF_SSI_CCR = MCF_SSI_CCR_WL(7) | /* 16 bit word length */
867+ MCF_SSI_CCR_DC(1); /* Frame rate divider */
868+ }
869+
870+ switch (substream->runtime->rate) {
871+ case 8000:
872+#if defined(CONFIG_M532x) || defined(CONFIG_M537x)
873+ MCF_CCM_CDR = (MCF_CCM_CDR | MCF_CCM_CDR_SSIDIV(0x20))
874+ | MCF_CCM_CDR_SSIDIV(MCF_SSI_AUDIO_SSDIV_VALUE_1);
875+#else
876+ MCF_CCM_CDR = (MCF_CCM_CDR & ~MCF_CCM_CDR_SSIDIV(0xFF)) |
877+ MCF_CCM_CDR_SSIDIV(MCF_SSI_AUDIO_SSDIV_VALUE_1);
878+#endif
879+ MCF_SSI_CCR |= MCF_SSI_CCR_PM(11);
880+ mcf_codec_spi_write(TLV320AIC23_CODEC_SAMPLE_RATE_REG,
881+ TLV320AIC23_CODEC_SAMPLERATE_REG_8KHZ);
882+ break;
883+ case 11000:
884+ case 11025:
885+#if defined(CONFIG_M532x) || defined(CONFIG_M537x)
886+ MCF_CCM_CDR = (MCF_CCM_CDR & ~MCF_CCM_CDR_SSIDIV(0x3F)) |
887+ MCF_CCM_CDR_SSIDIV(0x2B);
888+ MCF_SSI_CCR |= MCF_SSI_CCR_PM(11);
889+#else
890+ MCF_CCM_CDR = (MCF_CCM_CDR & ~MCF_CCM_CDR_SSIDIV(0xFF)) |
891+ MCF_CCM_CDR_SSIDIV(MCF_SSI_AUDIO_SSDIV_VALUE_3);
892+ MCF_SSI_CCR |= MCF_SSI_CCR_PM(9);
893+#endif
894+ mcf_codec_spi_write(TLV320AIC23_CODEC_SAMPLE_RATE_REG,
895+ TLV320AIC23_CODEC_SAMPLERATE_REG_11KHZ);
896+ break;
897+ case 16000:
898+#if defined(CONFIG_M532x) || defined(CONFIG_M537x)
899+ MCF_CCM_CDR = (MCF_CCM_CDR | MCF_CCM_CDR_SSIDIV(0x20))
900+ | MCF_CCM_CDR_SSIDIV(MCF_SSI_AUDIO_SSDIV_VALUE_1);
901+#else
902+ MCF_CCM_CDR = (MCF_CCM_CDR & ~MCF_CCM_CDR_SSIDIV(0xFF)) |
903+ MCF_CCM_CDR_SSIDIV(MCF_SSI_AUDIO_SSDIV_VALUE_1);
904+#endif
905+ MCF_SSI_CCR |= MCF_SSI_CCR_PM(5);
906+ mcf_codec_spi_write(TLV320AIC23_CODEC_SAMPLE_RATE_REG,
907+ TLV320AIC23_CODEC_SAMPLERATE_REG_16KHZ);
908+ break;
909+ case 22000:
910+ case 22050:
911+#if defined(CONFIG_M532x) || defined(CONFIG_M537x)
912+ MCF_CCM_CDR = (MCF_CCM_CDR & ~MCF_CCM_CDR_SSIDIV(0x3F)) |
913+ MCF_CCM_CDR_SSIDIV(0x2B);
914+ MCF_SSI_CCR |= MCF_SSI_CCR_PM(5);
915+#else
916+ MCF_CCM_CDR = (MCF_CCM_CDR & ~MCF_CCM_CDR_SSIDIV(0xFF)) |
917+ MCF_CCM_CDR_SSIDIV(MCF_SSI_AUDIO_SSDIV_VALUE_3);
918+ MCF_SSI_CCR |= MCF_SSI_CCR_PM(4);
919+#endif
920+ mcf_codec_spi_write(TLV320AIC23_CODEC_SAMPLE_RATE_REG,
921+ TLV320AIC23_CODEC_SAMPLERATE_REG_22KHZ);
922+ break;
923+ case 48000:
924+#if defined(CONFIG_M532x) || defined(CONFIG_M537x)
925+ MCF_CCM_CDR = (MCF_CCM_CDR & ~MCF_CCM_CDR_SSIDIV(0x3F)) |
926+ MCF_CCM_CDR_SSIDIV(MCF_SSI_AUDIO_SSDIV_VALUE_4);
927+ MCF_SSI_CCR |= MCF_SSI_CCR_PM(3);
928+#else
929+ MCF_CCM_CDR = (MCF_CCM_CDR & ~MCF_CCM_CDR_SSIDIV(0xFF)) |
930+ MCF_CCM_CDR_SSIDIV(MCF_SSI_AUDIO_SSDIV_VALUE_1);
931+ MCF_SSI_CCR |= MCF_SSI_CCR_PM(1);
932+#endif
933+ mcf_codec_spi_write(TLV320AIC23_CODEC_SAMPLE_RATE_REG,
934+ TLV320AIC23_CODEC_SAMPLERATE_REG_48KHZ);
935+ break;
936+ case 44000:
937+ case 44100:
938+ default:
939+#if defined(CONFIG_M532x) || defined(CONFIG_M537x)
940+ MCF_CCM_CDR = (MCF_CCM_CDR & ~MCF_CCM_CDR_SSIDIV(0x3F)) |
941+ MCF_CCM_CDR_SSIDIV(0x2B);
942+#else
943+ MCF_CCM_CDR = (MCF_CCM_CDR & ~MCF_CCM_CDR_SSIDIV(0xFF)) |
944+ MCF_CCM_CDR_SSIDIV(MCF_SSI_AUDIO_SSDIV_VALUE_2);
945+#endif
946+ MCF_SSI_CCR |= MCF_SSI_CCR_PM(2);
947+ mcf_codec_spi_write(TLV320AIC23_CODEC_SAMPLE_RATE_REG,
948+ TLV320AIC23_CODEC_SAMPLERATE_REG_44KHZ);
949+ break;
950+ }
951+ DBG("MCF_CCM_CDR = 0x%x, MCF_SSI_CCR = 0x%x.\n",
952+ MCF_CCM_CDR, MCF_SSI_CCR);
953+}
954+
955+static void ssi_audio_codec_reset(void)
956+{
957+ mcf_codec_spi_write(CODEC_RESET_REG, 0); /* reset the audio chip */
958+ udelay(2500); /* wait for reset */
959+}
960+
961+static void
962+ssi_audio_init_codec_for_playback(struct snd_pcm_substream *substream)
963+{
964+ mcf_codec_spi_write(CODEC_LEFT_IN_REG, g_lineinvol);
965+ mcf_codec_spi_write(CODEC_RIGHT_IN_REG, g_lineinvol);
966+ mcf_codec_spi_write(CODEC_POWER_DOWN_REG, 0x060);
967+ mcf_codec_spi_write(CODEC_DIGITAL_IF_FMT_REG, 0x02);
968+ mcf_codec_spi_write(CODEC_DIGITAL_APATH_REG, 0x006);
969+ mcf_codec_spi_write(CODEC_DIGITAL_IF_ACT_REG, 0x001);
970+ mcf_codec_spi_write(CODEC_ANALOG_APATH_REG, g_analogpath);
971+ mcf_codec_spi_write(CODEC_LEFT_HP_VOL_REG, g_mastervol);
972+ mcf_codec_spi_write(CODEC_RIGHT_HP_VOL_REG, g_mastervol);
973+}
974+
975+static void
976+ssi_audio_init_codec_for_capture(struct snd_pcm_substream *substream)
977+{
978+ mcf_codec_spi_write(CODEC_LEFT_IN_REG, g_lineinvol);
979+ mcf_codec_spi_write(CODEC_RIGHT_IN_REG, g_lineinvol);
980+ mcf_codec_spi_write(CODEC_POWER_DOWN_REG, 0x060);
981+ mcf_codec_spi_write(CODEC_DIGITAL_IF_FMT_REG, 0x02);
982+ mcf_codec_spi_write(CODEC_DIGITAL_APATH_REG, 0x006);
983+ mcf_codec_spi_write(CODEC_DIGITAL_IF_ACT_REG, 0x001);
984+ mcf_codec_spi_write(CODEC_ANALOG_APATH_REG, g_analogpath);
985+ mcf_codec_spi_write(CODEC_LEFT_HP_VOL_REG, g_mastervol);
986+ mcf_codec_spi_write(CODEC_RIGHT_HP_VOL_REG, g_mastervol);
987+}
988+
989+static void ssi_audio_chip_init(void)
990+{
991+ int chip_initialized = 0;
992+ if (chip_initialized == 1)
993+ return;
994+
995+ ssi_audio_init_dma();
996+ /* Enable the SSI pins */
997+#if defined(CONFIG_M5227x)
998+ MCF_GPIO_PAR_UART = (MCF_GPIO_PAR_UART
999+ &~MCF_GPIO_PAR_UART_PAR_U1TXD(0xF)
1000+ &~MCF_GPIO_PAR_UART_PAR_U1RXD(0xF)
1001+ &~MCF_GPIO_PAR_UART_PAR_U1RTS(0xF)
1002+ &~MCF_GPIO_PAR_UART_PAR_U1CTS(0xF))
1003+ | MCF_GPIO_PAR_UART_PAR_U1CTS_SSI_BCLK
1004+ | MCF_GPIO_PAR_UART_PAR_U1RTS_SSI_FS
1005+ | MCF_GPIO_PAR_UART_PAR_U1RXD_SSI_RXD
1006+ | MCF_GPIO_PAR_UART_PAR_U1TXD_SSI_TXD;
1007+
1008+ MCF_GPIO_PAR_TIMER = (MCF_GPIO_PAR_TIMER
1009+ &~MCF_GPIO_PAR_TIMER_PAR_T3IN(0xF))
1010+ | MCF_GPIO_PAR_TIMER_PAR_T3IN_SSI_MCLK;
1011+#endif
1012+#if defined(CONFIG_M532x)
1013+ MCF_GPIO_PAR_SSI = (0
1014+ | MCF_GPIO_PAR_SSI_PAR_MCLK
1015+ | MCF_GPIO_PAR_SSI_PAR_TXD(3)
1016+ | MCF_GPIO_PAR_SSI_PAR_RXD(3)
1017+ | MCF_GPIO_PAR_SSI_PAR_FS(3)
1018+ | MCF_GPIO_PAR_SSI_PAR_BCLK(3));
1019+#endif
1020+#if defined(CONFIG_M537x)
1021+ MCF_GPIO_PAR_UART = (MCF_GPIO_PAR_UART
1022+ &~MCF_GPIO_PAR_UART_PAR_UTXD1(0xF)
1023+ &~MCF_GPIO_PAR_UART_PAR_URXD1(0xF)
1024+ &~MCF_GPIO_PAR_UART_PAR_URTS1(0xF)
1025+ &~MCF_GPIO_PAR_UART_PAR_UCTS1(0xF))
1026+ | MCF_GPIO_PAR_UART_PAR_UCTS1_SSI_BCLK
1027+ | MCF_GPIO_PAR_UART_PAR_URTS1_SSI_FS
1028+ | MCF_GPIO_PAR_UART_PAR_URXD1_SSI_RXD
1029+ | MCF_GPIO_PAR_UART_PAR_UTXD1_SSI_TXD;
1030+
1031+ MCF_GPIO_PAR_IRQ = MCF_GPIO_PAR_IRQ_PAR_IRQ4(1);
1032+#endif
1033+#if defined(CONFIG_M5301x)
1034+ MCF_GPIO_PAR_SSIH = (MCF_GPIO_PAR_SSIH_PAR_RXD_SSI_RXD |
1035+ MCF_GPIO_PAR_SSIH_PAR_TXD_SSI_TXD |
1036+ MCF_GPIO_PAR_SSIH_PAR_FS_SSI_FS |
1037+ MCF_GPIO_PAR_SSIH_PAR_MCLK_SSI_MCLK);
1038+ MCF_GPIO_PAR_SSIL = MCF_GPIO_PAR_SSIL_PAR_BCLK_SSI_BCLK;
1039+#endif
1040+#if defined(CONFIG_M5445X)
1041+ MCF_GPIO_PAR_SSI = (MCF_GPIO_PAR_SSI_MCLK |
1042+ MCF_GPIO_PAR_SSI_STXD_STXD |
1043+ MCF_GPIO_PAR_SSI_SRXD_SRXD |
1044+ MCF_GPIO_PAR_SSI_FS_FS |
1045+ MCF_GPIO_PAR_SSI_BCLK_BCLK);
1046+#endif
1047+ chip_initialized = 1;
1048+}
1049+
1050+static void ssi_audio_init_ssi_playback(void)
1051+{
1052+ /* Issue a SSI reset */
1053+ MCF_SSI_CR &= ~MCF_SSI_CR_SSI_EN;
1054+
1055+ /* SSI module uses internal CPU clock */
1056+ MCF_CCM_MISCCR |= MCF_CCM_MISCCR_SSI_SRC;
1057+#if defined(CONFIG_M5445X) || defined(CONFIG_M532x) || defined(CONFIG_M537x) \
1058+ || defined(CONFIG_M5227x)
1059+ MCF_CCM_MISCCR |= MCF_CCM_MISCCR_SSI_PUE | MCF_CCM_MISCCR_SSI_PUS;
1060+#endif
1061+#if defined(CONFIG_M5301x)
1062+ MCF_GPIO_PCRH |= MCF_GPIO_PCRH_SSI_PUS | MCF_GPIO_PCRH_SSI_PUE;
1063+#endif
1064+ MCF_SSI_CR = MCF_SSI_CR_CIS |
1065+ MCF_SSI_CR_TCH | /* Enable two channel mode */
1066+ MCF_SSI_CR_MCE | /* clock out on SSI_MCLK pin */
1067+ MCF_SSI_CR_I2S_MASTER | /* I2S master mode */
1068+ MCF_SSI_CR_SYN | /* Enable synchronous mode */
1069+ MCF_SSI_CR_NET; /* Auto set by I2S Master */
1070+
1071+ MCF_SSI_TCR = 0 |
1072+ /* internally generated bit clock */
1073+ MCF_SSI_TCR_TXDIR |
1074+ /* internally generated frame sync */
1075+ MCF_SSI_TCR_TFDIR |
1076+ /* Clock data on falling edge of bit clock */
1077+ MCF_SSI_TCR_TSCKP |
1078+ /* Frame sync active low */
1079+ MCF_SSI_TCR_TFSI |
1080+ /* TX frame sync 1 bit before data */
1081+ MCF_SSI_TCR_TEFS |
1082+ /* TX FIFO 0 enabled */
1083+ MCF_SSI_TCR_TFEN0 |
1084+ /* TX FIFO 1 enabled */
1085+ MCF_SSI_TCR_TFEN1 |
1086+ MCF_SSI_TCR_TXBIT0;
1087+
1088+ MCF_SSI_FCSR = MCF_SSI_FCSR_TFWM0(TXFWM) | MCF_SSI_FCSR_TFWM1(TXFWM);
1089+
1090+ MCF_SSI_IER = MCF_SSI_IER_TDMAE | /* DMA request enabled */
1091+ MCF_SSI_IER_TFE0 |
1092+ MCF_SSI_IER_TFE1; /* set by reset actually*/
1093+}
1094+
1095+static void ssi_audio_init_ssi_capture(void)
1096+{
1097+ /* Issue a SSI reset */
1098+ MCF_SSI_CR &= ~MCF_SSI_CR_SSI_EN;
1099+
1100+ /* SSI module uses internal CPU clock */
1101+ MCF_CCM_MISCCR |= MCF_CCM_MISCCR_SSI_SRC;
1102+#if defined(CONFIG_M5445X) || defined(CONFIG_M532x) || defined(CONFIG_M537x) \
1103+ || defined(CONFIG_M5227x)
1104+ MCF_CCM_MISCCR |= MCF_CCM_MISCCR_SSI_PUE | MCF_CCM_MISCCR_SSI_PUS;
1105+#endif
1106+#if defined(CONFIG_M5301x)
1107+ MCF_GPIO_PCRH |= MCF_GPIO_PCRH_SSI_PUS | MCF_GPIO_PCRH_SSI_PUE;
1108+#endif
1109+ MCF_SSI_CR = MCF_SSI_CR_CIS |
1110+ MCF_SSI_CR_TCH | /* Enable two channel mode */
1111+ MCF_SSI_CR_MCE | /* clock out on SSI_MCLK pin */
1112+ MCF_SSI_CR_I2S_MASTER | /* I2S master mode */
1113+ MCF_SSI_CR_SYN | /* Enable synchronous mode */
1114+ MCF_SSI_CR_NET; /* Auto set by I2S Master */
1115+
1116+ MCF_SSI_TCR = 0 |
1117+ /* internally generated bit clock */
1118+ MCF_SSI_TCR_TXDIR |
1119+ /* internally generated frame sync */
1120+ MCF_SSI_TCR_TFDIR |
1121+ /* Clock data on falling edge of bit clock */
1122+ MCF_SSI_TCR_TSCKP |
1123+ /* Frame sync active low */
1124+ MCF_SSI_TCR_TFSI |
1125+ /* TX frame sync 1 bit before data */
1126+ MCF_SSI_TCR_TEFS |
1127+ /* TX FIFO 0 enabled */
1128+ MCF_SSI_TCR_TFEN0 |
1129+ /* TX FIFO 1 enabled */
1130+ MCF_SSI_TCR_TFEN1 |
1131+ MCF_SSI_TCR_TXBIT0;
1132+
1133+ MCF_SSI_RCR = 0 |
1134+ /* Clock data on rising edge of bit clock */
1135+ MCF_SSI_RCR_RSCKP |
1136+ /* Frame sync active low */
1137+ MCF_SSI_RCR_RFSI |
1138+ /* RX frame sync 1 bit before data */
1139+ MCF_SSI_RCR_REFS |
1140+ /* RX FIFO 0 enabled */
1141+ MCF_SSI_RCR_RFEN0 |
1142+ /* RX FIFO 1 enabled */
1143+ MCF_SSI_RCR_RFEN1 |
1144+ MCF_SSI_RCR_RXBIT0; /* Auto set by I2S Master */
1145+
1146+ MCF_SSI_FCSR = MCF_SSI_FCSR_RFWM0(RXFWM) | MCF_SSI_FCSR_RFWM1(RXFWM);
1147+
1148+ /* interrupts */
1149+ MCF_SSI_IER = MCF_SSI_IER_RDMAE | /* DMA request enabled */
1150+ MCF_SSI_IER_RFF0 | /* rx FIFO 0 full */
1151+ MCF_SSI_IER_RFF1; /* rx FIFO 1 full */
1152+}
1153+
1154+static int snd_coldfire_playback_open(struct snd_pcm_substream *substream)
1155+{
1156+ int err;
1157+ struct chip_spec *chip = snd_pcm_substream_chip(substream);
1158+ struct snd_pcm_runtime *runtime = substream->runtime;
1159+ struct dma_private *dma_private;
1160+ dma_addr_t tcd_buf_phys;
1161+
1162+ runtime->hw = snd_coldfire_playback_hw;
1163+ err = snd_pcm_hw_constraint_integer(runtime,
1164+ SNDRV_PCM_HW_PARAM_PERIODS);
1165+ if (err < 0) {
1166+ printk(KERN_ERR "invalid buffer size\n");
1167+ return err;
1168+ }
1169+ /* to make sure period_bytes is the multiple of size of minor loops */
1170+ err = snd_pcm_hw_constraint_step(runtime, 0,
1171+ SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
1172+ HW_PERIODS_BYTES_STEP);
1173+ if (err < 0) {
1174+ printk(KERN_ERR "Error setting period_bytes step, "
1175+ "err=%d\n", err);
1176+ return err;
1177+ }
1178+ err = snd_pcm_hw_constraint_list(substream->runtime, 0,
1179+ SNDRV_PCM_HW_PARAM_RATE,
1180+ &constraints_rates);
1181+ if (err < 0) {
1182+ printk(KERN_ERR "Error setting rate constraints, "
1183+ "err=%d\n", err);
1184+ return err;
1185+ }
1186+ ssi_audio_chip_init();
1187+ ssi_audio_init_ssi_playback();
1188+ ssi_audio_init_codec_for_playback(substream);
1189+ err = ssi_audio_dma_request_playback_channel(substream);
1190+ if (err < 0) {
1191+ printk(KERN_ERR "Error requesting dma channel, err=%d\n", err);
1192+ return err;
1193+ }
1194+
1195+ dma_private = dma_alloc_coherent(substream->pcm->dev,
1196+ sizeof(struct dma_private), &tcd_buf_phys, GFP_KERNEL);
1197+
1198+ if (!dma_private) {
1199+ dev_err(substream->pcm->card->dev,
1200+ "can't allocate DMA private data\n");
1201+ return -ENOMEM;
1202+ }
1203+
1204+ dma_private->tcd_buf_phys = tcd_buf_phys;
1205+ runtime->private_data = dma_private;
1206+
1207+ chip->offset = 0;
1208+ g_tx_dmaing = 0;
1209+ return 0;
1210+}
1211+
1212+static int snd_coldfire_capture_open(struct snd_pcm_substream *substream)
1213+{
1214+ int err;
1215+ struct chip_spec *chip = snd_pcm_substream_chip(substream);
1216+ struct snd_pcm_runtime *runtime = substream->runtime;
1217+ struct dma_private *dma_private;
1218+ dma_addr_t tcd_buf_phys;
1219+
1220+ runtime->hw = snd_coldfire_capture_hw;
1221+
1222+ err = snd_pcm_hw_constraint_integer(runtime,
1223+ SNDRV_PCM_HW_PARAM_PERIODS);
1224+ if (err < 0) {
1225+ printk(KERN_ERR "invalid buffer size\n");
1226+ return err;
1227+ }
1228+ /* to make sure period_bytes is the multiple of size of minor loops */
1229+ err = snd_pcm_hw_constraint_step(runtime, 0,
1230+ SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
1231+ HW_PERIODS_BYTES_STEP);
1232+ if (err < 0) {
1233+ printk(KERN_ERR "Error setting period_bytes step, "
1234+ "err=%d\n", err);
1235+ return err;
1236+ }
1237+ err = snd_pcm_hw_constraint_list(substream->runtime, 0,
1238+ SNDRV_PCM_HW_PARAM_RATE,
1239+ &constraints_rates);
1240+ if (err < 0) {
1241+ printk(KERN_ERR "Error setting pcm_hw_constraint_list, "
1242+ "err=%d\n", err);
1243+ return err;
1244+ }
1245+
1246+ ssi_audio_chip_init();
1247+ ssi_audio_init_ssi_capture();
1248+ ssi_audio_init_codec_for_capture(substream);
1249+ err = ssi_audio_dma_request_capture_channel(substream);
1250+ if (err < 0) {
1251+ printk(KERN_ERR "Error requesting dma channel, err=%d\n", err);
1252+ return err;
1253+ }
1254+
1255+ dma_private = dma_alloc_coherent(substream->pcm->dev,
1256+ sizeof(struct dma_private), &tcd_buf_phys, GFP_KERNEL);
1257+
1258+ if (!dma_private) {
1259+ dev_err(substream->pcm->card->dev,
1260+ "can't allocate DMA private data\n");
1261+ return -ENOMEM;
1262+ }
1263+ dma_private->tcd_buf_phys = tcd_buf_phys;
1264+ dma_private->dma_buf_phys = substream->dma_buffer.addr;
1265+
1266+ runtime->private_data = dma_private;
1267+
1268+ chip->offset = 0;
1269+ g_rx_dmaing = 0;
1270+ return 0;
1271+}
1272+
1273+static int snd_coldfire_playback_close(struct snd_pcm_substream *substream)
1274+{
1275+ struct dma_private *dma_private = substream->runtime->private_data;
1276+
1277+ ssi_audio_dma_playback_stop();
1278+ mcf_edma_free_channel(DMA_TX_TCD0, substream);
1279+ mcf_edma_free_channel(DMA_TX_TCD1, substream);
1280+ if (dma_private) {
1281+ dma_free_coherent(substream->pcm->dev,
1282+ sizeof(struct dma_private),
1283+ dma_private, dma_private->tcd_buf_phys);
1284+ substream->runtime->private_data = NULL;
1285+ }
1286+ ssi_audio_disable_ssi();
1287+ return 0;
1288+}
1289+
1290+static int snd_coldfire_capture_close(struct snd_pcm_substream *substream)
1291+{
1292+ struct dma_private *dma_private = substream->runtime->private_data;
1293+
1294+ ssi_audio_dma_capture_stop();
1295+ mcf_edma_free_channel(DMA_RX_TCD0, substream);
1296+ mcf_edma_free_channel(DMA_RX_TCD1, substream);
1297+ /* Deallocate the fsl_dma_private structure */
1298+ if (dma_private) {
1299+ dma_free_coherent(substream->pcm->dev,
1300+ sizeof(struct dma_private),
1301+ dma_private, dma_private->tcd_buf_phys);
1302+ substream->runtime->private_data = NULL;
1303+ }
1304+ ssi_audio_disable_ssi();
1305+ return 0;
1306+}
1307+
1308+static int snd_coldfire_pcm_hw_params(struct snd_pcm_substream *substream,
1309+ struct snd_pcm_hw_params *hw_params)
1310+{
1311+ int err;
1312+
1313+ /* set runtime buffer */
1314+ err = snd_pcm_lib_malloc_pages(
1315+ substream, params_buffer_bytes(hw_params));
1316+ if (err < 0)
1317+ printk(KERN_ERR "Error allocating pages, err=%d\n", err);
1318+ return err;
1319+}
1320+
1321+static int snd_coldfire_pcm_hw_free(struct snd_pcm_substream *substream)
1322+{
1323+ /* free the memory if was newly allocated */
1324+ return snd_pcm_lib_free_pages(substream);
1325+}
1326+
1327+static int
1328+snd_coldfire_pcm_playback_prepare(struct snd_pcm_substream *substream)
1329+{
1330+ int err;
1331+
1332+ if (g_tx_dmaing == 1)
1333+ return 0;
1334+
1335+ ssi_audio_adjust_codec_speed(substream);
1336+ err = ssi_audio_dma_playback_config(substream);
1337+ if (err < 0) {
1338+ printk(KERN_ERR "Error configuring playback, "
1339+ "err=%d\n", err);
1340+ return err;
1341+ }
1342+
1343+ ssi_audio_dma_playback_start();
1344+ return 0;
1345+}
1346+
1347+static int snd_coldfire_pcm_capture_prepare(struct snd_pcm_substream *substream)
1348+{
1349+ int err;
1350+
1351+ if (g_rx_dmaing == 1)
1352+ return 0;
1353+
1354+ ssi_audio_adjust_codec_speed(substream);
1355+ err = ssi_audio_dma_capture_config(substream);
1356+ if (err < 0) {
1357+ printk(KERN_ERR "Error configuring capture, "
1358+ "err=%d\n", err);
1359+ return err;
1360+ }
1361+ ssi_audio_dma_capture_start();
1362+
1363+ return 0;
1364+}
1365+
1366+static int
1367+snd_coldfire_pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd)
1368+{
1369+ switch (cmd) {
1370+ case SNDRV_PCM_TRIGGER_START:
1371+ ssi_audio_enable_ssi_playback();
1372+ break;
1373+ case SNDRV_PCM_TRIGGER_STOP:
1374+ ssi_audio_disable_ssi_playback();
1375+ break;
1376+ default:
1377+ printk(KERN_ERR "Unsupported trigger command, cmd=%d\n", cmd);
1378+ return -EINVAL;
1379+ }
1380+
1381+ return 0;
1382+}
1383+
1384+static int
1385+snd_coldfire_pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd)
1386+{
1387+ switch (cmd) {
1388+ case SNDRV_PCM_TRIGGER_START:
1389+ ssi_audio_enable_ssi_capture();
1390+ break;
1391+ case SNDRV_PCM_TRIGGER_STOP:
1392+ ssi_audio_disable_ssi_capture();
1393+ break;
1394+ default:
1395+ printk(KERN_ERR "Unsupported trigger command, cmd=%d\n", cmd);
1396+ return -EINVAL;
1397+ }
1398+
1399+ return 0;
1400+}
1401+
1402+static snd_pcm_uframes_t
1403+snd_coldfire_pcm_playback_pointer(struct snd_pcm_substream *substream)
1404+{
1405+ struct snd_pcm_runtime *runtime = substream->runtime;
1406+ struct dma_private *dma_private = runtime->private_data;
1407+ snd_pcm_uframes_t pointer;
1408+ u32 offset;
1409+
1410+ offset = (u32)(MCF_EDMA_TCD_SADDR(DMA_TX_TCD0) -
1411+ dma_private->dma_buf_phys);
1412+ if (runtime->format == SNDRV_PCM_FORMAT_S16_BE)
1413+ pointer = offset / (runtime->channels == 1 ? 2 : 4);
1414+ else
1415+ pointer = 0;
1416+
1417+ return pointer;
1418+}
1419+
1420+static snd_pcm_uframes_t
1421+snd_coldfire_pcm_capture_pointer(struct snd_pcm_substream *substream)
1422+{
1423+ struct snd_pcm_runtime *runtime = substream->runtime;
1424+ struct dma_private *dma_private = runtime->private_data;
1425+ snd_pcm_uframes_t pointer;
1426+ u32 offset;
1427+
1428+ offset = (u32)(MCF_EDMA_TCD_DADDR(DMA_RX_TCD0) -
1429+ dma_private->dma_buf_phys);
1430+ if (runtime->format == SNDRV_PCM_FORMAT_S16_BE)
1431+ pointer = offset / (runtime->channels == 1 ? 2 : 4);
1432+ else
1433+ pointer = 0;
1434+
1435+ return pointer;
1436+}
1437+
1438+static struct snd_pcm_ops snd_coldfire_playback_ops = {
1439+ .open = snd_coldfire_playback_open,
1440+ .close = snd_coldfire_playback_close,
1441+ .ioctl = snd_pcm_lib_ioctl,
1442+ .hw_params = snd_coldfire_pcm_hw_params,
1443+ .hw_free = snd_coldfire_pcm_hw_free,
1444+ .prepare = snd_coldfire_pcm_playback_prepare,
1445+ .trigger = snd_coldfire_pcm_playback_trigger,
1446+ .pointer = snd_coldfire_pcm_playback_pointer,
1447+};
1448+
1449+static struct snd_pcm_ops snd_coldfire_capture_ops = {
1450+ .open = snd_coldfire_capture_open,
1451+ .close = snd_coldfire_capture_close,
1452+ .ioctl = snd_pcm_lib_ioctl,
1453+ .hw_params = snd_coldfire_pcm_hw_params,
1454+ .hw_free = snd_coldfire_pcm_hw_free,
1455+ .prepare = snd_coldfire_pcm_capture_prepare,
1456+ .trigger = snd_coldfire_pcm_capture_trigger,
1457+ .pointer = snd_coldfire_pcm_capture_pointer,
1458+};
1459+
1460+static int snd_coldfire_new_pcm(struct chip_spec *chip)
1461+{
1462+ struct snd_pcm *pcm;
1463+ int err;
1464+
1465+ err = snd_pcm_new(chip->card, "coldfire", 0, 1, 1,
1466+ &pcm);
1467+ if (err < 0) {
1468+ printk(KERN_ERR "Error creating new pcm, err=%d\n", err);
1469+ return err;
1470+ }
1471+ pcm->private_data = chip;
1472+ strncpy(pcm->name, SOUND_CARD_NAME, sizeof(pcm->name));
1473+ chip->pcm = pcm;
1474+ pcm->info_flags = 0;
1475+
1476+ /* set operators */
1477+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
1478+ &snd_coldfire_playback_ops);
1479+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
1480+ &snd_coldfire_capture_ops);
1481+ /* pre-allocation of buffers */
1482+ err = snd_pcm_lib_preallocate_pages_for_all(
1483+ pcm,
1484+ SNDRV_DMA_TYPE_CONTINUOUS,
1485+ snd_dma_continuous_data(GFP_KERNEL),
1486+ MAX_BUFFER_SIZE,
1487+ MAX_BUFFER_SIZE);
1488+
1489+ if (!pcm->streams[0].substream->dma_buffer.addr)
1490+ pcm->streams[0].substream->dma_buffer.addr =
1491+ virt_to_phys(pcm->streams[0].substream->dma_buffer.area);
1492+ if (!pcm->streams[1].substream->dma_buffer.addr)
1493+ pcm->streams[1].substream->dma_buffer.addr =
1494+ virt_to_phys(pcm->streams[1].substream->dma_buffer.area);
1495+
1496+ if (err) {
1497+ printk(KERN_ERR
1498+ "Can't pre-allocate DMA buffer (size=%u)\n",
1499+ MAX_BUFFER_SIZE);
1500+ return -ENOMEM;
1501+ }
1502+
1503+ chip->audio_device =
1504+ kmalloc(sizeof(struct tlv320a_audio_device), GFP_DMA);
1505+
1506+ if (!chip->audio_device) {
1507+ snd_pcm_lib_preallocate_free_for_all(pcm);
1508+ printk(KERN_ERR
1509+ "Can't allocate buffer for audio device\n");
1510+ return -ENOMEM;
1511+ }
1512+
1513+ return 0;
1514+}
1515+
1516+static int tlv320a_set_out_volume(unsigned char value)
1517+{
1518+ unsigned char data;
1519+
1520+ if (value > TLV320A_VOL_MAX)
1521+ data = TLV320A_VOL_MAX;
1522+ else
1523+ data = value;
1524+
1525+ if (mcf_codec_spi_write(CODEC_LEFT_HP_VOL_REG, data) < 0)
1526+ return -EINVAL;
1527+
1528+ if (mcf_codec_spi_write(CODEC_RIGHT_HP_VOL_REG, data) < 0)
1529+ return -EINVAL;
1530+
1531+ return 0;
1532+}
1533+
1534+static int tlv320a_info_out_volume(struct snd_kcontrol *kcontrol,
1535+ struct snd_ctl_elem_info *uinfo)
1536+{
1537+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1538+ uinfo->count = 1;
1539+ uinfo->value.integer.min = TLV320A_VOL_MIN;
1540+ uinfo->value.integer.max = TLV320A_VOL_MAX;
1541+ return 0;
1542+}
1543+
1544+static int tlv320a_get_out_volume(struct snd_kcontrol *kcontrol,
1545+ struct snd_ctl_elem_value *ucontrol)
1546+{
1547+ ucontrol->value.integer.value[0] = g_mastervol;
1548+ return 0;
1549+}
1550+
1551+static int tlv320a_put_out_volume(struct snd_kcontrol *kcontrol,
1552+ struct snd_ctl_elem_value *ucontrol)
1553+{
1554+ unsigned char vol;
1555+ int change;
1556+
1557+ vol = ucontrol->value.integer.value[0];
1558+
1559+ if (vol > TLV320A_VOL_MAX)
1560+ return -EINVAL;
1561+
1562+ change = (g_mastervol != vol);
1563+ if (change) {
1564+ g_mastervol = vol;
1565+ tlv320a_set_out_volume(vol);
1566+ }
1567+ return change;
1568+}
1569+
1570+static int tlv320a_set_linein_volume(unsigned char value)
1571+{
1572+ unsigned char data;
1573+
1574+ if (value > TLV320A_LINEIN_MAX)
1575+ data = TLV320A_LINEIN_MAX;
1576+ else
1577+ data = value;
1578+
1579+ if (mcf_codec_spi_write(CODEC_LEFT_IN_REG, data) < 0)
1580+ return -EINVAL;
1581+
1582+ if (mcf_codec_spi_write(CODEC_RIGHT_IN_REG, data) < 0)
1583+ return -EINVAL;
1584+
1585+ return 0;
1586+}
1587+
1588+static int tlv320a_info_linein_volume(struct snd_kcontrol *kcontrol,
1589+ struct snd_ctl_elem_info *uinfo)
1590+{
1591+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1592+ uinfo->count = 1;
1593+ uinfo->value.integer.min = 0;
1594+ uinfo->value.integer.max = TLV320A_LINEIN_MAX;
1595+ return 0;
1596+}
1597+
1598+static int tlv320a_get_linein_volume(struct snd_kcontrol *kcontrol,
1599+ struct snd_ctl_elem_value *ucontrol)
1600+{
1601+ ucontrol->value.integer.value[0] = g_lineinvol;
1602+ return 0;
1603+}
1604+
1605+static int tlv320a_put_linein_volume(struct snd_kcontrol *kcontrol,
1606+ struct snd_ctl_elem_value *ucontrol)
1607+{
1608+ unsigned char vol;
1609+ int change;
1610+
1611+ vol = ucontrol->value.integer.value[0];
1612+
1613+ if (vol > TLV320A_LINEIN_MAX)
1614+ return -EINVAL;
1615+
1616+ change = (g_lineinvol != vol);
1617+ if (change) {
1618+ g_lineinvol = vol;
1619+ tlv320a_set_linein_volume(vol);
1620+ }
1621+ return change;
1622+}
1623+
1624+#define tlv320a_info_mic_boost snd_ctl_boolean_mono_info
1625+static int tlv320a_get_mic_boost(struct snd_kcontrol *kcontrol,
1626+ struct snd_ctl_elem_value *ucontrol)
1627+{
1628+ ucontrol->value.integer.value[0] = ((g_analogpath & 0x1) == 1);
1629+ return 0;
1630+}
1631+
1632+static int tlv320a_put_mic_boost(struct snd_kcontrol *kcontrol,
1633+ struct snd_ctl_elem_value *ucontrol)
1634+{
1635+ int oldboost, newboost;
1636+ u8 data;
1637+ if (ucontrol->value.integer.value[0] == 1)
1638+ newboost = 1;
1639+ else
1640+ newboost = 0;
1641+ oldboost = g_analogpath & 0x1;
1642+
1643+ if (oldboost == newboost)
1644+ return 0;
1645+ data = (g_analogpath & 0xfe) | (newboost & 0x1);
1646+ if (mcf_codec_spi_write(CODEC_ANALOG_APATH_REG, data) < 0)
1647+ return -EINVAL;
1648+ g_analogpath = data;
1649+ return 1;
1650+}
1651+
1652+static int tlv320a_info_capture_source(struct snd_kcontrol *kcontrol,
1653+ struct snd_ctl_elem_info *uinfo)
1654+{
1655+ static char *texts[] = { "Line-In", "Microphone" };
1656+
1657+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1658+ uinfo->count = 1;
1659+ uinfo->value.enumerated.items = 2;
1660+ if (uinfo->value.enumerated.item > 1)
1661+ uinfo->value.enumerated.item = 1;
1662+ strcpy(uinfo->value.enumerated.name,
1663+ texts[uinfo->value.enumerated.item]);
1664+ return 0;
1665+}
1666+
1667+static int tlv320a_get_capture_source(struct snd_kcontrol *kcontrol,
1668+ struct snd_ctl_elem_value *ucontrol)
1669+{
1670+
1671+ ucontrol->value.enumerated.item[0] = ((g_analogpath & 0x4) == 0x4);
1672+ return 0;
1673+}
1674+
1675+static int tlv320a_put_capture_source(struct snd_kcontrol *kcontrol,
1676+ struct snd_ctl_elem_value *ucontrol)
1677+{
1678+ int oldinput, newinput;
1679+ u8 data;
1680+
1681+ if (ucontrol->value.enumerated.item[0] > 1)
1682+ return -EINVAL;
1683+
1684+ oldinput = (g_analogpath & 0x4) ? INPUT_MICROPHONE : INPUT_LINEIN;
1685+
1686+ if (ucontrol->value.enumerated.item[0])
1687+ newinput = INPUT_MICROPHONE;
1688+ else
1689+ newinput = INPUT_LINEIN;
1690+ if (oldinput == newinput)
1691+ return 0;
1692+ data = (g_analogpath & 0xfb) |
1693+ (newinput == INPUT_MICROPHONE ? 0x4 : 0);
1694+ if (mcf_codec_spi_write(CODEC_ANALOG_APATH_REG, data) < 0)
1695+ return -EINVAL;
1696+ g_analogpath = data;
1697+ return 1;
1698+}
1699+
1700+static struct snd_kcontrol_new tlv320_mixer_out __devinitdata = {
1701+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1702+ .name = "play volume",
1703+ .index = 0,
1704+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
1705+ .info = tlv320a_info_out_volume,
1706+ .get = tlv320a_get_out_volume,
1707+ .put = tlv320a_put_out_volume,
1708+};
1709+
1710+static struct snd_kcontrol_new tlv320_mixer_linein __devinitdata = {
1711+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1712+ .name = "record volume",
1713+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
1714+ .info = tlv320a_info_linein_volume,
1715+ .get = tlv320a_get_linein_volume,
1716+ .put = tlv320a_put_linein_volume,
1717+};
1718+
1719+static struct snd_kcontrol_new tlv320_mixer_capture_source __devinitdata = {
1720+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1721+ .name = "record source",
1722+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
1723+ .info = tlv320a_info_capture_source,
1724+ .get = tlv320a_get_capture_source,
1725+ .put = tlv320a_put_capture_source,
1726+};
1727+
1728+static struct snd_kcontrol_new tlv320_mixer_mic_boost __devinitdata = {
1729+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1730+ .name = "mic Boost",
1731+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
1732+ .info = tlv320a_info_mic_boost,
1733+ .get = tlv320a_get_mic_boost,
1734+ .put = tlv320a_put_mic_boost,
1735+};
1736+
1737+static int __devinit coldfire_alsa_audio_probe(struct platform_device *dev)
1738+{
1739+ struct snd_card *card;
1740+ struct chip_spec *chip;
1741+ int err;
1742+
1743+ err = snd_card_create(-1, id, THIS_MODULE,
1744+ sizeof(struct chip_spec), &card);
1745+ if (err < 0)
1746+ return -ENOMEM;
1747+
1748+ chip = card->private_data;
1749+
1750+ chip->card = card;
1751+ card->dev = &dev->dev;
1752+
1753+ err = snd_coldfire_new_pcm(chip);
1754+ if (err < 0)
1755+ return -ENOMEM;
1756+
1757+ strcpy(card->driver, "coldfire");
1758+ strcpy(card->shortname, "Coldfire-TLV320A");
1759+ sprintf(card->longname, "Freescale Coldfire with TLV320A");
1760+
1761+ err = snd_card_register(card);
1762+ if (err == 0) {
1763+ pr_debug(KERN_INFO "Coldfire audio support initialized\n");
1764+ platform_set_drvdata(dev, card);
1765+ }
1766+
1767+ strcpy(chip->card->mixername, "TLV320A Volume");
1768+ err = snd_ctl_add(chip->card, snd_ctl_new1(&tlv320_mixer_out, chip));
1769+ if (err)
1770+ goto error;
1771+ err = snd_ctl_add(chip->card, snd_ctl_new1(&tlv320_mixer_linein, chip));
1772+ if (err)
1773+ goto error;
1774+ err = snd_ctl_add(chip->card,
1775+ snd_ctl_new1(&tlv320_mixer_capture_source,
1776+ chip));
1777+ if (err)
1778+ goto error;
1779+ err = snd_ctl_add(chip->card,
1780+ snd_ctl_new1(&tlv320_mixer_mic_boost,
1781+ chip));
1782+ if (err)
1783+ goto error;
1784+ g_mastervol = TLV320A_VOL_INIT;
1785+ g_lineinvol = TLV320A_LINEIN_INIT;
1786+ g_analogpath = TLV320A_ANALOGPATH_INIT;
1787+ ssi_audio_codec_reset();
1788+ return 0;
1789+error:
1790+ kfree(card->private_data);
1791+ snd_card_free(card);
1792+ platform_set_drvdata(dev, NULL);
1793+ return err;
1794+}
1795+
1796+static int coldfire_alsa_audio_remove(struct platform_device *dev)
1797+{
1798+ struct snd_card *card;
1799+
1800+ card = platform_get_drvdata(dev);
1801+ kfree(card->private_data);
1802+ snd_card_free(card);
1803+ platform_set_drvdata(dev, NULL);
1804+
1805+ return 0;
1806+}
1807+
1808+static struct platform_driver coldfire_alsa_audio_driver = {
1809+ .probe = coldfire_alsa_audio_probe,
1810+ .remove = coldfire_alsa_audio_remove,
1811+ .driver = {
1812+ .name = SOUND_CARD_NAME,
1813+ },
1814+};
1815+
1816+static int __init coldfire_alsa_audio_init(void)
1817+{
1818+ int err;
1819+ err = platform_driver_register(&coldfire_alsa_audio_driver);
1820+ if (err < 0)
1821+ return err;
1822+
1823+ device = platform_device_register_simple(SOUND_CARD_NAME, -1, NULL, 0);
1824+ if (!IS_ERR(device)) {
1825+ if (platform_get_drvdata(device))
1826+ return 0;
1827+ platform_device_unregister(device);
1828+ platform_driver_unregister(&coldfire_alsa_audio_driver);
1829+ err = -ENODEV;
1830+ } else
1831+ err = PTR_ERR(device);
1832+
1833+ platform_driver_unregister(&coldfire_alsa_audio_driver);
1834+ return err;
1835+}
1836+
1837+static void __exit coldfire_alsa_audio_exit(void)
1838+{
1839+ platform_device_unregister(device);
1840+ platform_driver_unregister(&coldfire_alsa_audio_driver);
1841+}
1842+
1843+module_init(coldfire_alsa_audio_init);
1844+module_exit(coldfire_alsa_audio_exit);
1845+
1846+MODULE_DESCRIPTION("Coldfire driver for ALSA");
1847+MODULE_LICENSE("GPL");
1848+MODULE_SUPPORTED_DEVICE("{{TLV320A}}");
1849+
1850+module_param(id, charp, 0444);
1851+MODULE_PARM_DESC(id, "ID string for Coldfire + TLV320A soundcard.");
1852--- /dev/null
1853+++ b/sound/coldfire/snd-coldfire.h
1854@@ -0,0 +1,15 @@
1855+/*
1856+ * linux/sound/coldfire/snd-coldfire.h
1857+ *
1858+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved.
1859+ *
1860+ * ALSA driver for Coldfire SSI
1861+ *
1862+ * This is free software; you can redistribute it and/or modify
1863+ * it under the terms of the GNU General Public License as published by
1864+ * the Free Software Foundation; either version 2 of the License, or
1865+ * (at your option) any later version.
1866+ */
1867+
1868+extern int mcf_codec_spi_write(u8 addr, u16 data);
1869+
1870

Archive Download this file



interactive