switch to 2.6.38
[openwrt/openwrt.git] / target / linux / coldfire / patches / 009-Add-ALSA-driver-for-MCF5445x.patch
1 From d37d2d880efdc0ce515df4155ddafef3835d1b7f Mon Sep 17 00:00:00 2001
2 From: Alison Wang <b18965@freescale.com>
3 Date: Thu, 4 Aug 2011 09:59:41 +0800
4 Subject: [PATCH 09/52] Add ALSA driver for MCF5445x
5
6 Add ALSA driver for MCF54451 and MCF54455.
7
8 Signed-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 +