sg3-utils: add newer buildable version
[openembedded.git] / recipes / linux / linux-kirkwood / 0001-ARM-Kirkwood-Sound-Sound-driver-added.patch
1 From 89aa6dd15306a1ce11da0f2cb67bda74999e178e Mon Sep 17 00:00:00 2001
2 From: Tanmay Upadhyay <tanmay.upadhyay@einfochips.com>
3 Date: Tue, 24 Nov 2009 21:49:24 +0530
4 Subject: [PATCH] ARM: Kirkwood: Sound: Sound driver added
5
6 The driver is based on the Marvell kirkwood sound driver available in
7 2.6.22.18 kernel.
8
9 Signed-off-by: Tanmay Upadhyay <tanmay.upadhyay@einfochips.com>
10 ---
11  arch/arm/mach-kirkwood/common.c                |   39 +
12  arch/arm/mach-kirkwood/common.h                |    2 +
13  arch/arm/mach-kirkwood/include/mach/kirkwood.h |    3 +
14  arch/arm/mach-kirkwood/openrd_client-setup.c   |   27 +
15  include/linux/mv88fx_audio.h                   |  111 ++
16  sound/soc/Kconfig                              |    1 +
17  sound/soc/Makefile                             |    1 +
18  sound/soc/kirkwood/Kconfig                     |   29 +
19  sound/soc/kirkwood/Makefile                    |    7 +
20  sound/soc/kirkwood/cs42l51.c                   |  304 +++++
21  sound/soc/kirkwood/cs42l51.h                   |   59 +
22  sound/soc/kirkwood/kirkwood_audio_hal.c        |  821 +++++++++++++
23  sound/soc/kirkwood/kirkwood_audio_hal.h        |  109 ++
24  sound/soc/kirkwood/kirkwood_audio_regs.h       |  310 +++++
25  sound/soc/kirkwood/kirkwood_pcm.c              | 1505 ++++++++++++++++++++++++
26  15 files changed, 3328 insertions(+), 0 deletions(-)
27  create mode 100644 include/linux/mv88fx_audio.h
28  create mode 100644 sound/soc/kirkwood/Kconfig
29  create mode 100644 sound/soc/kirkwood/Makefile
30  create mode 100644 sound/soc/kirkwood/cs42l51.c
31  create mode 100644 sound/soc/kirkwood/cs42l51.h
32  create mode 100644 sound/soc/kirkwood/kirkwood_audio_hal.c
33  create mode 100644 sound/soc/kirkwood/kirkwood_audio_hal.h
34  create mode 100644 sound/soc/kirkwood/kirkwood_audio_regs.h
35  create mode 100644 sound/soc/kirkwood/kirkwood_pcm.c
36
37 diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c
38 index 0acb61f..4d66c06 100644
39 --- a/arch/arm/mach-kirkwood/common.c
40 +++ b/arch/arm/mach-kirkwood/common.c
41 @@ -15,6 +15,7 @@
42  #include <linux/mbus.h>
43  #include <linux/mv643xx_eth.h>
44  #include <linux/mv643xx_i2c.h>
45 +#include <linux/mv88fx_audio.h>
46  #include <linux/ata_platform.h>
47  #include <linux/mtd/nand.h>
48  #include <linux/spi/orion_spi.h>
49 @@ -969,3 +970,41 @@ static int __init kirkwood_clock_gate(void)
50         return 0;
51  }
52  late_initcall(kirkwood_clock_gate);
53 +
54 +/*****************************************************************************
55 + * Audio
56 + ****************************************************************************/
57 +
58 +static struct resource kirkwood_audio_resources[] = {
59 +       [0] = {
60 +               .start  = AUDIO_PHYS_BASE,
61 +               .end    = AUDIO_PHYS_BASE + SZ_16K - 1,
62 +               .flags  = IORESOURCE_MEM,
63 +       },
64 +       [1] = {
65 +               .start  = IRQ_KIRKWOOD_I2S,
66 +               .end    = IRQ_KIRKWOOD_I2S,
67 +               .flags  = IORESOURCE_IRQ,
68 +       },
69 +};
70 +
71 +static u64 kirkwood_audio_dmamask = 0xFFFFFFFFUL;
72 +
73 +static struct platform_device kirkwood_audio = {
74 +       .name           = MV88FX_AUDIO_NAME,
75 +       .id             = -1,
76 +       .num_resources  = ARRAY_SIZE(kirkwood_audio_resources),
77 +       .resource       = kirkwood_audio_resources,
78 +       .dev            = {
79 +               .dma_mask = &kirkwood_audio_dmamask,
80 +               .coherent_dma_mask = 0xffffffff,
81 +       },
82 +};
83 +
84 +void __init kirkwood_audio_init(struct mv88fx_snd_platform_data *audio_data)
85 +{
86 +       kirkwood_clk_ctrl |= CGC_AUDIO;
87 +       kirkwood_audio.dev.platform_data = audio_data;
88 +
89 +       platform_device_register(&kirkwood_audio);
90 +}
91 diff --git a/arch/arm/mach-kirkwood/common.h b/arch/arm/mach-kirkwood/common.h
92 index d7de434..b79a25c 100644
93 --- a/arch/arm/mach-kirkwood/common.h
94 +++ b/arch/arm/mach-kirkwood/common.h
95 @@ -16,6 +16,7 @@ struct mv643xx_eth_platform_data;
96  struct mv_sata_platform_data;
97  struct mvsdio_platform_data;
98  struct mtd_partition;
99 +struct mv88fx_snd_platform_data;
100  
101  /*
102   * Basic Kirkwood init functions used early by machine-setup.
103 @@ -41,6 +42,7 @@ void kirkwood_i2c_init(void);
104  void kirkwood_uart0_init(void);
105  void kirkwood_uart1_init(void);
106  void kirkwood_nand_init(struct mtd_partition *parts, int nr_parts, int delay);
107 +void kirkwood_audio_init(struct mv88fx_snd_platform_data *audio_data);
108  
109  extern int kirkwood_tclk;
110  extern struct sys_timer kirkwood_timer;
111 diff --git a/arch/arm/mach-kirkwood/include/mach/kirkwood.h b/arch/arm/mach-kirkwood/include/mach/kirkwood.h
112 index 54c1327..90ced65 100644
113 --- a/arch/arm/mach-kirkwood/include/mach/kirkwood.h
114 +++ b/arch/arm/mach-kirkwood/include/mach/kirkwood.h
115 @@ -95,6 +95,9 @@
116  
117  #define SDIO_PHYS_BASE         (KIRKWOOD_REGS_PHYS_BASE | 0x90000)
118  
119 +#define AUDIO_PHYS_BASE                (KIRKWOOD_REGS_PHYS_BASE | 0xA0000)
120 +#define AUDIO_VIRT_BASE                (KIRKWOOD_REGS_VIRT_BASE | 0xA0000)
121 +
122  /*
123   * Supported devices and revisions.
124   */
125 diff --git a/arch/arm/mach-kirkwood/openrd_client-setup.c b/arch/arm/mach-kirkwood/openrd_client-setup.c
126 index a55a1bc..72acc22 100644
127 --- a/arch/arm/mach-kirkwood/openrd_client-setup.c
128 +++ b/arch/arm/mach-kirkwood/openrd_client-setup.c
129 @@ -14,11 +14,13 @@
130  #include <linux/mtd/partitions.h>
131  #include <linux/ata_platform.h>
132  #include <linux/mv643xx_eth.h>
133 +#include <linux/mv88fx_audio.h>
134  #include <linux/gpio.h>
135  #include <asm/mach-types.h>
136  #include <asm/mach/arch.h>
137  #include <mach/kirkwood.h>
138  #include <plat/mvsdio.h>
139 +#include <linux/autoconf.h>
140  #include "common.h"
141  #include "mpp.h"
142  
143 @@ -59,6 +61,21 @@ static unsigned int openrd_client_mpp_config[] __initdata = {
144         0
145  };
146  
147 +static struct mv88fx_snd_platform_data openrd_client_audio_data = {
148 +       .i2c_bus_no  = 0,
149 +       .i2c_address = 0x4A,
150 +/* 0 - NA, 1 - mono, 2 - stereo */
151 +#ifdef CONFIG_SND_MV88FX_SOC_I2S
152 +       .i2s_rec     = 1,
153 +       .i2s_play    = 2,
154 +#else
155 +       .spdif_rec   = 1,
156 +       .spdif_play  = 2,
157 +#endif
158 +       .dram        = &kirkwood_mbus_dram_info,
159 +       .base_offset = AUDIO_PHYS_BASE - KIRKWOOD_REGS_PHYS_BASE,
160 +};
161 +
162  static void __init openrd_client_init(void)
163  {
164         /*
165 @@ -78,6 +95,16 @@ static void __init openrd_client_init(void)
166  
167         kirkwood_sata_init(&openrd_client_sata_data);
168         kirkwood_sdio_init(&openrd_client_mvsdio_data);
169 +
170 +       /* initialize i2c */
171 +       kirkwood_i2c_init();
172 +
173 +#if defined(CONFIG_SND_MV88FX_SOC) || defined(CONFIG_SND_MV88FX_SOC_MODULE)
174 +       /* If built as a part of kernel or as a module
175 +        * initialize audio */
176 +       openrd_client_audio_data.tclk = kirkwood_tclk,
177 +       kirkwood_audio_init(&openrd_client_audio_data);
178 +#endif
179  }
180  
181  MACHINE_START(OPENRD_CLIENT, "Marvell OpenRD Client Board")
182 diff --git a/include/linux/mv88fx_audio.h b/include/linux/mv88fx_audio.h
183 new file mode 100644
184 index 0000000..6d36a3f
185 --- /dev/null
186 +++ b/include/linux/mv88fx_audio.h
187 @@ -0,0 +1,111 @@
188 +/*
189 + *
190 + *     Marvell Orion Alsa Sound driver
191 + *
192 + *     Author: Maen Suleiman
193 + *     Copyright (C) 2008 Marvell Ltd.
194 + *
195 + *
196 + * This program is free software; you can redistribute it and/or modify
197 + * it under the terms of the GNU General Public License version 2 as
198 + * published by the Free Software Foundation.
199 + *
200 + */
201 +
202 +#ifndef __LINUX_MV88FX_SND_H
203 +#define __LINUX_MV88FX_SND_H
204 +
205 +#include <linux/mbus.h>
206 +
207 +#define MV88FX_AUDIO_NAME   "mv88fx_snd"
208 +
209 +#undef MV88FX_SND_DEBUG
210 +#ifdef MV88FX_SND_DEBUG
211 +#define mv88fx_snd_debug(fmt, arg...) printk(KERN_DEBUG fmt, ##arg)
212 +#else
213 +       #define mv88fx_snd_debug(a...)
214 +#endif
215 +
216 +#define MV_AUDIO_MAX_ADDR_DECODE_WIN      2
217 +#define MV_AUDIO_RECORD_WIN_NUM           0
218 +#define MV_AUDIO_PLAYBACK_WIN_NUM         1
219 +
220 +#define MV_AUDIO_WIN_CTRL_REG(win)        (0xA04 + ((win)<<3))
221 +#define MV_AUDIO_WIN_BASE_REG(win)        (0xA00 + ((win)<<3))
222 +
223 +struct mv88fx_snd_platform_data {
224 +       u8  i2c_bus_no;
225 +       u16 i2c_address;
226 +       u32 spdif_rec;
227 +       u32 spdif_play;
228 +       u32 i2s_rec;
229 +       u32 i2s_play;
230 +       u32 tclk;
231 +       u32 base_offset;
232 +       struct mbus_dram_target_info *dram;
233 +};
234 +
235 +struct mv88fx_snd_stream {
236 +       struct snd_pcm_substream *substream;
237 +       struct device          *dev;
238 +       int    direction;            /* playback or capture */
239 +       #define PLAYBACK        0
240 +       #define CAPTURE         1
241 +       unsigned int    dig_mode;    /* i2s,spdif,both */
242 +       #define I2S             1
243 +       #define SPDIF           2
244 +       int stereo;                  /* mono, stereo */
245 +       int mono_mode;               /* both mono, left mono, right mono */
246 +       #define MONO_BOTH       0
247 +       #define MONO_LEFT       1
248 +       #define MONO_RIGHT      2
249 +       int clock_src;
250 +       #define DCO_CLOCK       0
251 +       #define SPCR_CLOCK      1
252 +       #define EXTERN_CLOCK    2
253 +       int rate;
254 +       int stat_mem;                /* Channel status source*/
255 +       int format;
256 +       #define SAMPLE_32IN32   0
257 +       #define SAMPLE_24IN32   1
258 +       #define SAMPLE_20IN32   2
259 +       #define SAMPLE_16IN32   3
260 +       #define SAMPLE_16IN16   4
261 +       unsigned int  dma_addr;
262 +       unsigned int  dma_size;
263 +       unsigned int  period_size;
264 +       unsigned int  spdif_status[4]; /* SPDIF status */
265 +       unsigned char *area;           /* virtual pointer */
266 +       dma_addr_t    addr;            /* physical address */
267 +};
268 +
269 +struct mv88fx_snd_chip {
270 +       struct mv88fx_snd_stream *stream[2];          /* run time values*/
271 +       struct mv88fx_snd_stream *stream_defaults[2]; /* default values*/
272 +       spinlock_t      reg_lock;       /* Register access spinlock */
273 +       struct resource *res;           /* resource for IRQ and base*/
274 +       void __iomem    *base;          /* Audio base address of the host */
275 +       unsigned int    audio_offset;   /* Offset to audio base register
276 +                                        * from internal base register */
277 +       int irq;
278 +       int loopback;                   /* When Loopback is enabled, playback
279 +                                        * data is looped back to be recorded */
280 +       int ch_stat_valid;              /* Playback SPDIF channel validity bit
281 +                                        * value when REG selected */
282 +       int burst;                      /* DMA Burst Size */
283 +
284 +       #define SPDIF_MEM_STAT         0
285 +       #define SPDIF_REG_STAT         1
286 +       unsigned int dco_ctrl_offst;
287 +       int     pcm_mode;               /* pcm, nonpcm*/
288 +       #define PCM             0
289 +       #define NON_PCM         1
290 +       int     stereo;
291 +};
292 +
293 +#define MV88FX_SND_MIN_PERIODS         8
294 +#define MV88FX_SND_MAX_PERIODS         16
295 +#define        MV88FX_SND_MIN_PERIOD_BYTES     0x4000
296 +#define        MV88FX_SND_MAX_PERIOD_BYTES     0x4000
297 +
298 +#endif /* __LINUX_MV88FX_SND_H */
299 diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
300 index b1749bc..9fc88d8 100644
301 --- a/sound/soc/Kconfig
302 +++ b/sound/soc/Kconfig
303 @@ -36,6 +36,7 @@ source "sound/soc/s3c24xx/Kconfig"
304  source "sound/soc/s6000/Kconfig"
305  source "sound/soc/sh/Kconfig"
306  source "sound/soc/txx9/Kconfig"
307 +source "sound/soc/kirkwood/Kconfig"
308  
309  # Supported codecs
310  source "sound/soc/codecs/Kconfig"
311 diff --git a/sound/soc/Makefile b/sound/soc/Makefile
312 index 0c5eac0..664850d 100644
313 --- a/sound/soc/Makefile
314 +++ b/sound/soc/Makefile
315 @@ -14,3 +14,4 @@ obj-$(CONFIG_SND_SOC) += s3c24xx/
316  obj-$(CONFIG_SND_SOC)  += s6000/
317  obj-$(CONFIG_SND_SOC)  += sh/
318  obj-$(CONFIG_SND_SOC)  += txx9/
319 +obj-$(CONFIG_SND_SOC)  += kirkwood/
320 diff --git a/sound/soc/kirkwood/Kconfig b/sound/soc/kirkwood/Kconfig
321 new file mode 100644
322 index 0000000..d6a7e2f
323 --- /dev/null
324 +++ b/sound/soc/kirkwood/Kconfig
325 @@ -0,0 +1,29 @@
326 +config SND_MV88FX_SOC
327 +       tristate "SoC Audio for the Marvell 88FX chip"
328 +       depends on ARCH_KIRKWOOD
329 +       help
330 +         Say Y or M if you want to add support for codecs attached to
331 +         the MV88FX I2S or SPD interface. You will also need
332 +         to select the audio interfaces to support below.
333 +
334 +choice
335 +       prompt "Audio Interface"
336 +       default SND_MV88FX_SOC_I2S
337 +       depends on SND_MV88FX_SOC
338 +
339 +config SND_MV88FX_SOC_I2S
340 +       bool "I2S"
341 +
342 +config SND_MV88FX_SOC_SPDIF
343 +       bool "SPDIF"
344 +
345 +endchoice
346 +
347 +choice
348 +       prompt "Codec IC"
349 +       default SND_SOC_CS42L51
350 +       depends on SND_MV88FX_SOC
351 +
352 +config SND_SOC_CS42L51
353 +       bool "CS42L51"
354 +endchoice
355 diff --git a/sound/soc/kirkwood/Makefile b/sound/soc/kirkwood/Makefile
356 new file mode 100644
357 index 0000000..57674ad
358 --- /dev/null
359 +++ b/sound/soc/kirkwood/Makefile
360 @@ -0,0 +1,7 @@
361 +
362 +snd-soc-kirkwood-objs := kirkwood_pcm.o kirkwood_audio_hal.o
363 +ifdef CONFIG_SND_SOC_CS42L51
364 +snd-soc-kirkwood-objs += cs42l51.o
365 +endif
366 +
367 +obj-$(CONFIG_SND_MV88FX_SOC) += snd-soc-kirkwood.o
368 diff --git a/sound/soc/kirkwood/cs42l51.c b/sound/soc/kirkwood/cs42l51.c
369 new file mode 100644
370 index 0000000..f5a22f9
371 --- /dev/null
372 +++ b/sound/soc/kirkwood/cs42l51.c
373 @@ -0,0 +1,304 @@
374 +/*
375 + *
376 + *     Marvell Orion Alsa Sound driver
377 + *
378 + *     Author: Maen Suleiman
379 + *     Copyright (C) 2008 Marvell Ltd.
380 + *
381 + *
382 + * This program is free software; you can redistribute it and/or modify
383 + * it under the terms of the GNU General Public License version 2 as
384 + * published by the Free Software Foundation.
385 + *
386 + */
387 +#include <linux/ioport.h>
388 +#include <linux/platform_device.h>
389 +#include <linux/init.h>
390 +#include <linux/slab.h>
391 +#include <linux/version.h>
392 +#include <linux/i2c.h>
393 +#include <sound/core.h>
394 +#include <sound/initval.h>
395 +#include <sound/control.h>
396 +#include <sound/pcm.h>
397 +#include <sound/asoundef.h>
398 +#include <sound/asound.h>
399 +
400 +#include "cs42l51.h"
401 +
402 +/* FIXME: This code is not written in driver module style. This is written as
403 + *        helper for SOC driver */
404 +
405 +struct i2c_client *client;
406 +
407 +static int cs42l51_add_i2c_device(unsigned char i2c_bus_no,
408 +                                 unsigned short i2c_add)
409 +{
410 +       struct i2c_board_info info;
411 +       struct i2c_adapter *adapter;
412 +
413 +       memset(&info, 0, sizeof(struct i2c_board_info));
414 +       info.addr = i2c_add;
415 +       strlcpy(info.type, "cs42l51", I2C_NAME_SIZE);
416 +
417 +       adapter = i2c_get_adapter(i2c_bus_no);
418 +       if (!adapter) {
419 +               snd_printk("can't get i2c adapter\n");
420 +               return -ENODEV;
421 +       }
422 +
423 +       client = i2c_new_device(adapter, &info);
424 +       i2c_put_adapter(adapter);
425 +       if (!client) {
426 +               snd_printk("can't add i2c device\n");
427 +               return -ENODEV;
428 +       }
429 +
430 +       return 0;
431 +}
432 +
433 +void cs42l51_del_i2c_device(void)
434 +{
435 +       if (client)
436 +               i2c_unregister_device(client);
437 +       client = NULL;
438 +}
439 +
440 +/*
441 + * offset: Register offset to start reading with
442 + * buf   : Pointer to the buffer to store the read data
443 + * num   : Number of registers to read
444 + *
445 + * Returns -ve errorno else number of registers read
446 + */
447 +
448 +int cs42l51_reg_read(unsigned char offset, unsigned char *buf, int num)
449 +{
450 +       int ret = 0;
451 +
452 +       /* Set autoincrement bit */
453 +       offset |= CODEC_INCR_ADDR;
454 +
455 +       /* Send register offset */
456 +       ret = i2c_master_send(client, &offset, 1);
457 +       if (ret != 1) {
458 +               snd_printd("Could not write register offset\n");
459 +               return 0;
460 +       }
461 +
462 +       return i2c_master_recv(client, buf, num);
463 +}
464 +
465 +/*
466 + * offset: Register offset to write
467 + * data  : Data to be written
468 + *
469 + * Returns -ve errorno else number of registers written (=1)
470 + */
471 +
472 +int cs42l51_reg_write(unsigned char offset, unsigned char data)
473 +{
474 +       int ret = 0;
475 +       unsigned char buf[2];
476 +
477 +       buf[0] = offset;
478 +       buf[1] = data;
479 +
480 +       /* Send register offset & data */
481 +       ret = i2c_master_send(client, &buf[0], 2);
482 +
483 +       return (ret == 2) ? 1 : ret;
484 +}
485 +
486 +int codec_init(int adc_mode, int digital_if_format,
487 +              unsigned char i2c_bus_no, unsigned short i2c_add)
488 +{
489 +       unsigned char reg_data;
490 +
491 +       if (cs42l51_add_i2c_device(i2c_bus_no, i2c_add))
492 +               return 1;
493 +
494 +       if (cs42l51_reg_read(CODEC_ID_REG, &reg_data, 1) < 0)
495 +               goto codec_init_error;
496 +
497 +       if (CODEC_CHIP_ID != (reg_data >> 3) ||
498 +           CODEC_REV_ID  != (reg_data & 0x7)) {
499 +               snd_printd("Error: Invalid Cirrus Logic chip/rev ID!\n");
500 +               return 1;
501 +       }
502 +
503 +       if (cs42l51_reg_read(CODEC_IF_CTRL_REG, &reg_data, 1) < 0)
504 +               goto codec_init_error;
505 +
506 +       reg_data = (reg_data & ~(0x7<<3)) | (digital_if_format << 3);
507 +
508 +       if (LEFT_JUSTIFIED_MODE == adc_mode)
509 +               reg_data &= (~0x4);
510 +       else
511 +               reg_data |= 0x4;
512 +
513 +       if (cs42l51_reg_write(CODEC_IF_CTRL_REG, reg_data) < 0)
514 +               goto codec_init_error;
515 +
516 +       return 0;
517 +
518 +codec_init_error:
519 +       snd_printd("I2C error\n");
520 +       return 1;
521 +}
522 +
523 +/*
524 + * Initialize the audio decoder.
525 + */
526 +
527 +int cs42l51_init(int adc_mode, int digital_if_format, int rec,
528 +                unsigned char i2c_bus_no, unsigned short i2c_add)
529 +{
530 +       if (codec_init(adc_mode, digital_if_format, i2c_bus_no, i2c_add)) {
531 +               snd_printk("Error: Audio Codec init failed\n");
532 +               return 1;
533 +       }
534 +
535 +       /* Use the signal processor */
536 +       if (cs42l51_reg_write(0x9, 0x40) < 0)
537 +               goto error;
538 +
539 +       /* Unmute PCM-A & PCM-B and set default */
540 +       if (cs42l51_reg_write(0x10, 0x60) < 0)
541 +               goto error;
542 +       if (cs42l51_reg_write(0x11, 0x60) < 0)
543 +               goto error;
544 +
545 +       /* default for AOUTx */
546 +       if (cs42l51_reg_write(0x16, 0x05) < 0)
547 +               goto error;
548 +       if (cs42l51_reg_write(0x17, 0x05) < 0)
549 +               goto error;
550 +
551 +       /* swap channels */
552 +       if (cs42l51_reg_write(0x18, 0xff) < 0)
553 +               goto error;
554 +
555 +       /* MIC Power Control: power down mIC in channel B, power on channel A
556 +        * Recommended seq. in datasheet:
557 +        *  1. Enable the PDN bit
558 +        *  2. Enable power-down for the selected channels
559 +        *  3. Disable the PDN bit */
560 +
561 +       /* Note: Tested for mono recording only */
562 +       if (!rec) {
563 +               /* Enable power down */
564 +               if (cs42l51_reg_write(0x2, 0x11) < 0)
565 +                       goto error;
566 +
567 +               /* No record - Power down both channels */
568 +               if (cs42l51_reg_write(0x2, 0x17) < 0)
569 +                       goto error;
570 +
571 +               /* Disable power down */
572 +               if (cs42l51_reg_write(0x2, 0x16) < 0)
573 +                       goto error;
574 +       } else {
575 +               if (rec == 2) {
576 +                       /* Setreo recording - by default both channels are up */
577 +
578 +                       /* MIC In channel selection - Select channel 3
579 +                        *                            unmute both channels */
580 +                       if (cs42l51_reg_write(0x7, 0xF0) < 0)
581 +                               goto error;
582 +
583 +                       /* Power up mic pre-amplifier for both channels */
584 +                       if (cs42l51_reg_write(0x3, 0xA0) < 0)
585 +                               goto error;
586 +               } else {
587 +                       /* Enable power down */
588 +                       if (cs42l51_reg_write(0x2, 0x11) < 0)
589 +                               goto error;
590 +
591 +                       /* Mono recording - Power down Channel B */
592 +                       if (cs42l51_reg_write(0x2, 0x15) < 0)
593 +                               goto error;
594 +
595 +                       /* Disable power down */
596 +                       if (cs42l51_reg_write(0x2, 0x14) < 0)
597 +                               goto error;
598 +
599 +                       /* MIC In channel selection - Select channel 3
600 +                        *                            Mute Channel B */
601 +                       if (cs42l51_reg_write(0x7, 0xF2) < 0)
602 +                               goto error;
603 +
604 +                       /* Power down mic pre-amplifier for Channel B*/
605 +                       if (cs42l51_reg_write(0x3, 0xA8) < 0)
606 +                               goto error;
607 +               }
608 +       }
609 +
610 +       return 0;
611 +error:
612 +       snd_printk("I2C error\n");
613 +       return 1;
614 +}
615 +
616 +#define AUD_NUM_VOLUME_STEPS  (40)
617 +static unsigned char auddec_volume_mapping[AUD_NUM_VOLUME_STEPS] =
618 +{
619 +       0x19,   0xB2,   0xB7,   0xBD,   0xC3,   0xC9,   0xCF,   0xD5,
620 +       0xD8,   0xE1,   0xE7,   0xED,   0xF3,   0xF9,   0xFF,   0x00,
621 +       0x01,   0x02,   0x03,   0x04,   0x05,   0x06,   0x07,   0x08,
622 +       0x09,   0x0A,   0x0B,   0x0C,   0x0D,   0x0E,   0x0F,   0x10,
623 +       0x11,   0x12,   0x13,   0x14,   0x15,   0x16,   0x17,   0x18
624 +};
625 +
626 +
627 +/*
628 + * Get the audio decoder volume for both channels.
629 + * 0 is lowest volume, AUD_NUM_VOLUME_STEPS-1 is the highest volume.
630 + */
631 +
632 +void cs42l51_vol_get(unsigned char *vol_list)
633 +{
634 +       unsigned char reg_data[2];
635 +       unsigned char i, vol_idx = 0;
636 +
637 +       if (cs42l51_reg_read(0x16 + vol_idx, reg_data, 2) < 0) {
638 +               snd_printd("I2C error\n");
639 +               snd_printk("Couldn't get volume\n");
640 +               return;
641 +       }
642 +
643 +       for (; vol_idx < 2; vol_idx++) {
644 +               /* Look for the index that mapps to this dB value.  */
645 +               for (i = 0; i < AUD_NUM_VOLUME_STEPS; i++) {
646 +                       if (reg_data[vol_idx] == auddec_volume_mapping[i])
647 +                               break;
648 +                       if ((auddec_volume_mapping[i] >
649 +                             auddec_volume_mapping[AUD_NUM_VOLUME_STEPS-1])
650 +                           && (reg_data[vol_idx] > auddec_volume_mapping[i])
651 +                           && (reg_data[vol_idx] < auddec_volume_mapping[i+1]))
652 +                               break;
653 +               }
654 +               vol_list[vol_idx] = i;
655 +       }
656 +}
657 +
658 +/*
659 + * Set the audio decoder volume for both channels.
660 + * 0 is lowest volume, AUD_NUM_VOLUME_STEPS-1 is the highest volume.
661 + */
662 +void cs42l51_vol_set(unsigned char *vol_list)
663 +{
664 +       unsigned int  vol_idx;
665 +
666 +       for (vol_idx = 0; vol_idx < 2; vol_idx++) {
667 +               if (vol_list[vol_idx] >= AUD_NUM_VOLUME_STEPS)
668 +                       vol_list[vol_idx] = AUD_NUM_VOLUME_STEPS - 1;
669 +
670 +               if (cs42l51_reg_write(0x16 + vol_idx,
671 +                   auddec_volume_mapping[vol_list[vol_idx]]) < 0) {
672 +                       snd_printd("I2C error\n");
673 +                       snd_printk("Couldn't set volume\n");
674 +                       return;
675 +               }
676 +       }
677 +}
678 diff --git a/sound/soc/kirkwood/cs42l51.h b/sound/soc/kirkwood/cs42l51.h
679 new file mode 100644
680 index 0000000..f4e7951
681 --- /dev/null
682 +++ b/sound/soc/kirkwood/cs42l51.h
683 @@ -0,0 +1,59 @@
684 +/*
685 + * Audio codec CS42L51 data definition file
686 + */
687 +
688 +#ifndef _CS42L51_H_
689 +#define _CS42L51_H_
690 +
691 +#define CODEC_CHIP_ID   0x1B
692 +#define CODEC_REV_ID    0x1
693 +
694 +#define CODEC_ID_REG                    0x1
695 +#define CODEC_IF_CTRL_REG               0x4
696 +#define CODEC_ADC_INPUT_INV_MUTE_REG    0x7
697 +#define CODEC_DAC_OUTPUT_CTRL_REG       0x8
698 +#define CODEC_DAC_CTRL_REG              0x9
699 +#define CODEC_PGAA_VOL_CTRL_REG         0xa
700 +#define CODEC_TONE_CTRL_REG             0x15
701 +#define CODEC_VOL_OUTA_CTRL_REG         0x16
702 +
703 +/* Set bit # 7 to 1 to get into auto incremental addressing mode */
704 +#define CODEC_INCR_ADDR                 0x80
705 +
706 +#define FALSE 0
707 +#define TRUE  1
708 +
709 +/* Selects the digital interface format used for the data in on SDIN. */
710 +enum dac_digital_if_format {
711 +       L_JUSTIFIED_UP_TO_24_BIT,
712 +       I2S_UP_TO_24_BIT,
713 +       R_JUSTIFIED_UP_TO_24_BIT,
714 +       R_JUSTIFIED_20_BIT,
715 +       R_JUSTIFIED_18_BIT,
716 +       R_JUSTIFIED_16_BIT
717 +
718 +};
719 +
720 +/* Selects either the I2S or Left-Justified digital interface format for the
721 +   data on SDOUT. */
722 +enum adc_mode {
723 +       LEFT_JUSTIFIED_MODE,
724 +       I2S_MODE
725 +};
726 +
727 +/* Initialize the Cirrus Logic device */
728 +int cs42l51_init(int adc_mode, int digital_if_format, int rec,
729 +                unsigned char i2c_bus_no, unsigned short i2c_add);
730 +
731 +/* Function to control output volume (playback) */
732 +void cs42l51_vol_get(unsigned char *vol_list);
733 +void cs42l51_vol_set(unsigned char *vol_list);
734 +
735 +/* Function to access the Cirrus Logic CODEC registers */
736 +int cs42l51_reg_read(unsigned char offset, unsigned char *buf, int num);
737 +int cs42l51_reg_write(unsigned char offset, unsigned char data);
738 +
739 +
740 +void cs42l51_del_i2c_device(void);
741 +#endif  /* _CS42L51_H_ */
742 +
743 diff --git a/sound/soc/kirkwood/kirkwood_audio_hal.c b/sound/soc/kirkwood/kirkwood_audio_hal.c
744 new file mode 100644
745 index 0000000..28305e3
746 --- /dev/null
747 +++ b/sound/soc/kirkwood/kirkwood_audio_hal.c
748 @@ -0,0 +1,821 @@
749 +/*
750 + * Sound driver for Marvell Kirkwood family SOCs
751 + *
752 + * This program is free software; you can redistribute it and/or
753 + * modify it under the terms of the GNU General Public License
754 + * as published by the Free Software Foundation; either version 2
755 + * of the License, or (at your option) any later version.
756 + *
757 + * This program is distributed in the hope that it will be useful,
758 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
759 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
760 + * GNU General Public License for more details.
761 + *
762 + * You should have received a copy of the GNU General Public License
763 + * along with this program; if not, write to the Free Software
764 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
765 + */
766 +
767 +#include <linux/io.h>
768 +#include <sound/core.h>
769 +#include <sound/pcm.h>
770 +#include <linux/spinlock.h>
771 +#include <linux/mv88fx_audio.h>
772 +#include "kirkwood_audio_hal.h"
773 +
774 +static void mv_audio_init(void __iomem *base);
775 +static void audio_setup_wins(void __iomem *base,
776 +                            struct mbus_dram_target_info *dram);
777 +static int set_window_as_per_baseadd(void __iomem *base, unsigned int baseadd,
778 +                                    unsigned int audio_offset, int win_num);
779 +
780 +/* Clocks Control and Status related*/
781 +static int mv_audio_dco_ctrl_set(struct mv_audio_freq_data *dcoCtrl,
782 +                         void __iomem *base);
783 +
784 +/* Audio PlayBack related*/
785 +static int mv_audio_playback_control_set(void __iomem *base, unsigned int
786 +                        audio_offset, struct mv_audio_playback_ctrl *ctrl);
787 +
788 +/* Audio SPDIF PlayBack related*/
789 +static void mv_spdif_playback_ctrl_set(void __iomem *base,
790 +                                       struct mv_spdif_playback_ctrl *ctrl);
791 +
792 +/* Audio I2S PlayBack related*/
793 +static int mv_i2s_playback_ctrl_set(void __iomem *base,
794 +                               struct mv_i2s_playback_ctrl *ctrl);
795 +
796 +/* Audio Recording*/
797 +static int  mv_audio_record_control_set(struct mv_audio_record_ctrl *ctrl,
798 +                               unsigned int audio_offset, void __iomem *base);
799 +
800 +/* SPDIF Recording Related*/
801 +static int spdif_record_tclock_set(void __iomem *base, unsigned int tclk);
802 +
803 +/* I2S Recording Related*/
804 +static int mv_i2s_record_cntrl_set(struct mv_i2s_record_ctrl *ctrl,
805 +                                  void __iomem *base);
806 +
807 +static inline int audio_burst_bytes_num_get(int burst)
808 +{
809 +       switch (burst) {
810 +       case AUDIO_32BYTE_BURST:
811 +               return 32;
812 +       case AUDIO_128BYTE_BURST:
813 +               return 128;
814 +       default:
815 +               return 0xffffffff;
816 +       }
817 +}
818 +
819 +int mv88fx_snd_hw_init(struct snd_card *card)
820 +{
821 +       void __iomem *base = chip->base;
822 +       struct mv88fx_snd_platform_data *platform_data =
823 +        card->dev->platform_data;
824 +
825 +       if (platform_data->i2s_rec || platform_data->i2s_play)
826 +               if (codec_init(I2S_MODE, I2S_UP_TO_24_BIT,
827 +                   platform_data->i2s_rec, platform_data->i2c_bus_no,
828 +                   platform_data->i2c_address)) {
829 +                       snd_printk("Initializing CS42L51 failed\n");
830 +                       return 1;
831 +       }
832 +
833 +       writel(0xffffffff, (base + MV_AUDIO_INT_CAUSE_REG));
834 +       writel(0, (base + MV_AUDIO_INT_MASK_REG));
835 +       writel(0, (base + MV_AUDIO_SPDIF_REC_INT_CAUSE_MASK_REG));
836 +
837 +       mv_audio_init(base);
838 +
839 +       audio_setup_wins(base, platform_data->dram);
840 +
841 +       /* Disable all playback/recording */
842 +       writel(readl(base + MV_AUDIO_PLAYBACK_CTRL_REG) &
843 +              (~(APCR_PLAY_I2S_ENABLE_MASK | APCR_PLAY_SPDIF_ENABLE_MASK)),
844 +              (base + MV_AUDIO_PLAYBACK_CTRL_REG));
845 +
846 +       writel(readl(base + MV_AUDIO_RECORD_CTRL_REG) &
847 +              (~(ARCR_RECORD_SPDIF_EN_MASK | ARCR_RECORD_I2S_EN_MASK)),
848 +              (base + MV_AUDIO_RECORD_CTRL_REG));
849 +
850 +       if (spdif_record_tclock_set(base, platform_data->tclk)) {
851 +               snd_printk("Marvell ALSA driver ERR. SPDIF clock set failed\n");
852 +               return 1;
853 +       }
854 +
855 +       return 0;
856 +}
857 +
858 +int mv88fx_snd_hw_playback_set(struct mv88fx_snd_chip *chip)
859 +{
860 +       struct mv88fx_snd_stream *audio_stream = chip->stream[PLAYBACK];
861 +       struct snd_pcm_substream *substream = audio_stream->substream;
862 +       struct snd_pcm_runtime *runtime = substream->runtime;
863 +
864 +       struct mv_audio_playback_ctrl   pcm_play_ctrl;
865 +       struct mv_i2s_playback_ctrl    i2s_play_ctrl;
866 +       struct mv_spdif_playback_ctrl  spdif_play_ctrl;
867 +       struct mv_audio_freq_data      dco_ctrl;
868 +
869 +       dco_ctrl.offset = chip->dco_ctrl_offst;
870 +
871 +       switch (audio_stream->rate) {
872 +       case 44100:
873 +               dco_ctrl.baseFreq = AUDIO_FREQ_44_1KH;
874 +               break;
875 +       case 48000:
876 +               dco_ctrl.baseFreq = AUDIO_FREQ_48KH;
877 +               break;
878 +       case 96000:
879 +               dco_ctrl.baseFreq = AUDIO_FREQ_96KH;
880 +               break;
881 +       default:
882 +               snd_printk("Requested rate %d is not supported\n",
883 +                          runtime->rate); return -1;
884 +       }
885 +
886 +       pcm_play_ctrl.burst = (chip->burst == 128) ? AUDIO_128BYTE_BURST :
887 +                                                    AUDIO_32BYTE_BURST;
888 +
889 +       pcm_play_ctrl.loopBack = chip->loopback;
890 +
891 +       if (audio_stream->stereo) {
892 +               pcm_play_ctrl.monoMode = AUDIO_PLAY_MONO_OFF;
893 +       } else {
894 +               switch (audio_stream->mono_mode) {
895 +               case MONO_LEFT:
896 +                       pcm_play_ctrl.monoMode = AUDIO_PLAY_LEFT_MONO;
897 +                       break;
898 +               case MONO_RIGHT:
899 +                       pcm_play_ctrl.monoMode = AUDIO_PLAY_RIGHT_MONO;
900 +                       break;
901 +               case MONO_BOTH:
902 +               default:
903 +                       pcm_play_ctrl.monoMode = AUDIO_PLAY_BOTH_MONO;
904 +                       break;
905 +               }
906 +       }
907 +
908 +       if (audio_stream->format == SAMPLE_16IN16) {
909 +               pcm_play_ctrl.sampleSize = SAMPLE_16BIT;
910 +               i2s_play_ctrl.sampleSize = SAMPLE_16BIT;
911 +       } else if (audio_stream->format == SAMPLE_24IN32) {
912 +               pcm_play_ctrl.sampleSize = SAMPLE_24BIT;
913 +               i2s_play_ctrl.sampleSize = SAMPLE_24BIT;
914 +       } else if (audio_stream->format == SAMPLE_32IN32) {
915 +               pcm_play_ctrl.sampleSize = SAMPLE_32BIT;
916 +               i2s_play_ctrl.sampleSize = SAMPLE_32BIT;
917 +       } else {
918 +               snd_printk("Requested format %d is not supported\n",
919 +                          runtime->format);
920 +               return -1;
921 +       }
922 +
923 +       /* buffer and period sizes in frame */
924 +       pcm_play_ctrl.bufferPhyBase = audio_stream->dma_addr;
925 +       pcm_play_ctrl.bufferSize = audio_stream->dma_size;
926 +       pcm_play_ctrl.intByteCount = audio_stream->period_size;
927 +
928 +       /* I2S playback streem stuff */
929 +       /*i2s_play_ctrl.sampleSize = pcm_play_ctrl.sampleSize;*/
930 +       i2s_play_ctrl.justification = I2S_JUSTIFIED;
931 +       i2s_play_ctrl.sendLastFrame = 0;
932 +
933 +       spdif_play_ctrl.nonPcm = FALSE;
934 +
935 +       spdif_play_ctrl.validity = chip->ch_stat_valid;
936 +
937 +       if (audio_stream->stat_mem) {
938 +               spdif_play_ctrl.userBitsFromMemory = TRUE;
939 +               spdif_play_ctrl.validityFromMemory = TRUE;
940 +               spdif_play_ctrl.blockStartInternally = FALSE;
941 +       } else {
942 +               spdif_play_ctrl.userBitsFromMemory = FALSE;
943 +               spdif_play_ctrl.validityFromMemory = FALSE;
944 +               spdif_play_ctrl.blockStartInternally = TRUE;
945 +       }
946 +
947 +       /* If this is non-PCM sound, mute I2S channel */
948 +       spin_lock_irq(&chip->reg_lock);
949 +
950 +       if (!(readl(chip->base + MV_AUDIO_PLAYBACK_CTRL_REG) &
951 +             (APCR_PLAY_I2S_ENABLE_MASK | APCR_PLAY_SPDIF_ENABLE_MASK))) {
952 +
953 +               if (mv_audio_dco_ctrl_set(&dco_ctrl, chip->base)) {
954 +                       snd_printk("Failed to initialize DCO clock control.\n");
955 +                       goto error;
956 +               }
957 +       }
958 +
959 +       if (audio_stream->clock_src == DCO_CLOCK)
960 +               while ((readl(chip->base + MV_AUDIO_SPCR_DCO_STATUS_REG) &
961 +               ASDSR_DCO_LOCK_MASK) == 0)
962 +                       cpu_relax();
963 +       else if (audio_stream->clock_src == SPCR_CLOCK)
964 +               while ((readl(chip->base + MV_AUDIO_SPCR_DCO_STATUS_REG) &
965 +               ASDSR_SPCR_LOCK_MASK) == 0)
966 +                       cpu_relax();
967 +
968 +       if (mv_audio_playback_control_set(chip->base, chip->audio_offset,
969 +                                       &pcm_play_ctrl)) {
970 +               snd_printk("Failed to initialize PCM playback control.\n");
971 +               goto error;
972 +       }
973 +
974 +       if (mv_i2s_playback_ctrl_set(chip->base, &i2s_play_ctrl)) {
975 +               snd_printk("Failed to initialize I2S playback control.\n");
976 +               goto error;
977 +       }
978 +
979 +       mv_spdif_playback_ctrl_set(chip->base, &spdif_play_ctrl);
980 +
981 +       spin_unlock_irq(&chip->reg_lock);
982 +
983 +       return 0;
984 +error:
985 +       spin_unlock_irq(&chip->reg_lock);
986 +       return -1;
987 +}
988 +
989 +int mv88fx_snd_hw_capture_set(struct mv88fx_snd_chip *chip)
990 +{
991 +       struct mv88fx_snd_stream *audio_stream = chip->stream[CAPTURE];
992 +       struct snd_pcm_substream *substream = audio_stream->substream;
993 +       struct snd_pcm_runtime *runtime = substream->runtime;
994 +
995 +       struct mv_audio_record_ctrl pcm_rec_ctrl;
996 +       struct mv_i2s_record_ctrl   i2s_rec_ctrl;
997 +       struct mv_audio_freq_data   dco_ctrl;
998 +
999 +       dco_ctrl.offset = chip->dco_ctrl_offst;
1000 +
1001 +       switch (audio_stream->rate) {
1002 +       case 44100:
1003 +               dco_ctrl.baseFreq = AUDIO_FREQ_44_1KH;
1004 +               break;
1005 +       case 48000:
1006 +               dco_ctrl.baseFreq = AUDIO_FREQ_48KH;
1007 +               break;
1008 +       case 96000:
1009 +               dco_ctrl.baseFreq = AUDIO_FREQ_96KH;
1010 +               break;
1011 +       default:
1012 +               snd_printk("Requested rate %d is not supported\n",
1013 +                          runtime->rate); return -1;
1014 +       }
1015 +
1016 +       pcm_rec_ctrl.burst = (chip->burst == 128) ? AUDIO_128BYTE_BURST :
1017 +                                                   AUDIO_32BYTE_BURST;
1018 +
1019 +       if (audio_stream->format == SAMPLE_16IN16) {
1020 +               pcm_rec_ctrl.sampleSize = SAMPLE_16BIT;
1021 +       } else if (audio_stream->format == SAMPLE_24IN32) {
1022 +               pcm_rec_ctrl.sampleSize = SAMPLE_24BIT;
1023 +       } else if (audio_stream->format == SAMPLE_32IN32) {
1024 +               pcm_rec_ctrl.sampleSize = SAMPLE_32BIT;
1025 +       } else {
1026 +               snd_printk("Requested format %d is not supported\n",
1027 +                          runtime->format);
1028 +               return -1;
1029 +       }
1030 +
1031 +       /* If request for tereo record comes on the boards that doesn't
1032 +        * support stereo recording */
1033 +       if ((!chip->stereo) && audio_stream->stereo) {
1034 +               snd_printk("Stereo recording is not supported\n");
1035 +               return -1;
1036 +       }
1037 +
1038 +       pcm_rec_ctrl.mono = (audio_stream->stereo) ? FALSE : TRUE;
1039 +
1040 +       if (pcm_rec_ctrl.mono) {
1041 +               switch (audio_stream->mono_mode) {
1042 +               case MONO_LEFT:
1043 +                       pcm_rec_ctrl.monoChannel = AUDIO_REC_LEFT_MONO;
1044 +                       break;
1045 +               default:
1046 +               case MONO_RIGHT:
1047 +                       pcm_rec_ctrl.monoChannel = AUDIO_REC_RIGHT_MONO;
1048 +                       break;
1049 +               }
1050 +
1051 +       } else {
1052 +               pcm_rec_ctrl.monoChannel = AUDIO_REC_LEFT_MONO;
1053 +       }
1054 +
1055 +
1056 +       pcm_rec_ctrl.bufferPhyBase = audio_stream->dma_addr;
1057 +       pcm_rec_ctrl.bufferSize = audio_stream->dma_size;
1058 +
1059 +       pcm_rec_ctrl.intByteCount = audio_stream->period_size;
1060 +
1061 +       /* I2S record streem stuff */
1062 +       i2s_rec_ctrl.sample = pcm_rec_ctrl.sampleSize;
1063 +       i2s_rec_ctrl.justf = I2S_JUSTIFIED;
1064 +
1065 +       spin_lock_irq(&chip->reg_lock);
1066 +
1067 +       /* set clock only if record is not enabled*/
1068 +       if (!(readl(chip->base + MV_AUDIO_RECORD_CTRL_REG) &
1069 +            (ARCR_RECORD_SPDIF_EN_MASK | ARCR_RECORD_I2S_EN_MASK))) {
1070 +
1071 +               if (mv_audio_dco_ctrl_set(&dco_ctrl, chip->base)) {
1072 +                       snd_printk("Failed to initialize DCO clock control.\n");
1073 +                       return -1;
1074 +               }
1075 +       }
1076 +
1077 +       if (mv_audio_record_control_set(&pcm_rec_ctrl, chip->audio_offset,
1078 +                                       chip->base)) {
1079 +               snd_printk("Failed to initialize PCM record control.\n");
1080 +               return -1;
1081 +       }
1082 +
1083 +       if (mv_i2s_record_cntrl_set(&i2s_rec_ctrl, chip->base)) {
1084 +               snd_printk("Failed to initialize I2S record control.\n");
1085 +               return -1;
1086 +       }
1087 +       spin_unlock_irq(&chip->reg_lock);
1088 +
1089 +       return 0;
1090 +}
1091 +
1092 +static void mv_audio_init(void __iomem *base)
1093 +{
1094 +       int timeout = 10000000;
1095 +       unsigned int reg_data;
1096 +
1097 +       reg_data = readl(base + 0x1200);
1098 +       reg_data &= (~(0x333FF8));
1099 +       reg_data |= 0x111D18;
1100 +
1101 +       writel(reg_data, base + 0x1200);
1102 +
1103 +       do {
1104 +               timeout--;
1105 +       } while (timeout);
1106 +
1107 +       reg_data = readl(base + 0x1200);
1108 +       reg_data &= (~(0x333FF8));
1109 +       reg_data |= 0x111D18;
1110 +
1111 +       writel(reg_data, base + 0x1200);
1112 +}
1113 +
1114 +static void audio_setup_wins(void __iomem *base,
1115 +                            struct mbus_dram_target_info *dram)
1116 +{
1117 +       int win_num;
1118 +
1119 +       /* First disable and clear windows */
1120 +       for (win_num = 0; win_num < MV_AUDIO_MAX_ADDR_DECODE_WIN; win_num++) {
1121 +               writel(0, base + MV_AUDIO_WIN_CTRL_REG(win_num));
1122 +               writel(0, base + MV_AUDIO_WIN_BASE_REG(win_num));
1123 +       }
1124 +
1125 +       /* Setup windows for DDR */
1126 +       for (win_num = 0; win_num < MV_AUDIO_MAX_ADDR_DECODE_WIN; win_num++) {
1127 +               /* We will set the Window to DRAM_CS1 in default */
1128 +               struct mbus_dram_window *cs = &dram->cs[1];
1129 +
1130 +               writel(cs->base & 0xffff0000,
1131 +                      base + MV_AUDIO_WIN_BASE_REG(win_num));
1132 +               writel(((cs->size - 1) & 0xffff0000) |
1133 +                      (cs->mbus_attr << 8) |
1134 +                      (dram->mbus_dram_target_id << 4) | 1,
1135 +                       base + MV_AUDIO_WIN_CTRL_REG(win_num));
1136 +       }
1137 +}
1138 +
1139 +#define MV_BOARD_TCLK_133MHZ    133333333
1140 +#define MV_BOARD_TCLK_150MHZ    150000000
1141 +#define MV_BOARD_TCLK_166MHZ    166666667
1142 +#define MV_BOARD_TCLK_200MHZ    200000000
1143 +
1144 +static int spdif_record_tclock_set(void __iomem *base, unsigned int tclk)
1145 +{
1146 +       unsigned int reg_data;
1147 +
1148 +       reg_data = readl(base + MV_AUDIO_SPDIF_REC_GEN_REG);
1149 +
1150 +       switch (tclk) {
1151 +       case MV_BOARD_TCLK_133MHZ:
1152 +               reg_data |= ASRGR_CORE_CLK_FREQ_133MHZ;
1153 +               break;
1154 +       case MV_BOARD_TCLK_150MHZ:
1155 +               reg_data |= ASRGR_CORE_CLK_FREQ_150MHZ;
1156 +               break;
1157 +       case MV_BOARD_TCLK_166MHZ:
1158 +               reg_data |= ASRGR_CORE_CLK_FREQ_166MHZ;
1159 +               break;
1160 +       case MV_BOARD_TCLK_200MHZ:
1161 +               reg_data |= ASRGR_CORE_CLK_FREQ_200MHZ;
1162 +               break;
1163 +       default:
1164 +               snd_printk("Not supported core clock %d\n", tclk);
1165 +               return 1;
1166 +       }
1167 +
1168 +       writel(reg_data, base + MV_AUDIO_SPDIF_REC_GEN_REG);
1169 +
1170 +       return 0;
1171 +}
1172 +
1173 +static int  mv_audio_record_control_set(struct mv_audio_record_ctrl *ctrl,
1174 +                               unsigned int audio_offset, void __iomem *base)
1175 +{
1176 +       unsigned int reg, buff_start, buff_end;
1177 +       unsigned int win_base, win_size;
1178 +
1179 +       if (ctrl->monoChannel > AUDIO_REC_RIGHT_MONO) {
1180 +               snd_printk("Error: Illegal monoChannel %x\n",
1181 +                          ctrl->monoChannel);
1182 +
1183 +               return 1;
1184 +       }
1185 +
1186 +       if ((ctrl->burst != AUDIO_32BYTE_BURST) &&
1187 +           (ctrl->burst != AUDIO_128BYTE_BURST)) {
1188 +               snd_printk("Error: Illegal burst %x\n",
1189 +                          ctrl->burst);
1190 +
1191 +               return 1;
1192 +       }
1193 +
1194 +       if (ctrl->bufferPhyBase & (MV_AUDIO_BUFFER_MIN_ALIGN - 1)) {
1195 +               snd_printk("Error bufferPhyBase is not aligned to 0x%x"\
1196 +                         " bytes\n", MV_AUDIO_BUFFER_MIN_ALIGN);
1197 +
1198 +               return 1;
1199 +       }
1200 +
1201 +       if ((ctrl->bufferSize <= audio_burst_bytes_num_get(ctrl->burst)) |
1202 +           (ctrl->bufferSize & (audio_burst_bytes_num_get(ctrl->burst) - 1)) ||
1203 +           (ctrl->bufferSize > AUDIO_REG_TO_SIZE(APBBCR_SIZE_MAX))) {
1204 +               snd_printk("Error bufferSize smaller than or not multiple "\
1205 +                         "of 0x%x bytes or larger than 0x%x\n",
1206 +                         audio_burst_bytes_num_get(ctrl->burst),
1207 +                         AUDIO_REG_TO_SIZE(APBBCR_SIZE_MAX));
1208 +
1209 +               return 1;
1210 +       }
1211 +
1212 +       reg = readl(base + MV_AUDIO_RECORD_CTRL_REG);
1213 +       reg &= ~(ARCR_RECORD_BURST_SIZE_MASK | ARCR_RECORDED_MONO_CHNL_MASK |
1214 +                ARCR_RECORD_SAMPLE_SIZE_MASK);
1215 +
1216 +       switch (ctrl->sampleSize) {
1217 +       case SAMPLE_16BIT:
1218 +       case SAMPLE_16BIT_NON_COMPACT:
1219 +       case SAMPLE_20BIT:
1220 +       case SAMPLE_24BIT:
1221 +       case SAMPLE_32BIT:
1222 +               reg |= ctrl->sampleSize << ARCR_RECORD_SAMPLE_SIZE_OFFS;
1223 +               break;
1224 +       default:
1225 +               snd_printk("Error: Illegal sampleSize %x\n",
1226 +                          ctrl->sampleSize);
1227 +
1228 +               return 1;
1229 +       }
1230 +
1231 +       reg |= ctrl->burst << ARCR_RECORD_BURST_SIZE_OFFS;
1232 +       reg |= ctrl->monoChannel << ARCR_RECORDED_MONO_CHNL_OFFS;
1233 +
1234 +       if (ctrl->mono)
1235 +               reg |= ARCR_RECORD_MONO_MASK;
1236 +       else
1237 +               reg &= (~ARCR_RECORD_MONO_MASK);
1238 +
1239 +       writel(reg, base + MV_AUDIO_RECORD_CTRL_REG);
1240 +
1241 +       /* Get the details of the Record address window*/
1242 +       win_base = readl(base + MV_AUDIO_WIN_BASE_REG(MV_AUDIO_RECORD_WIN_NUM));
1243 +       win_size = readl(base + MV_AUDIO_WIN_CTRL_REG(MV_AUDIO_RECORD_WIN_NUM));
1244 +
1245 +       /* Window size bits are 31:16. Where size =
1246 +        * (2 ^ no of ones) * 64 KB. e.g. 0x0FF says 16MB */
1247 +       win_size = ((win_size >> 16) + 1) << 16;
1248 +
1249 +       buff_start = ctrl->bufferPhyBase;
1250 +       buff_end   = buff_start + ctrl->bufferSize - 1;
1251 +
1252 +       /* If buffer address is not within window boundries then try to set a
1253 +        * new value to the Record window by geting the target of where the
1254 +        * buffer exist, if the buffer is within the window of the new target
1255 +        * then set the Record window to that target else return Fail
1256 +        */
1257 +
1258 +       if (!(((buff_start >= win_base) &&
1259 +            (buff_start <= (win_base + win_size - 1))) ||
1260 +            ((buff_end >= win_base) &&
1261 +            (buff_end <= (win_base + win_size - 1))))) {
1262 +               snd_printd("Audio record buffer is not within window");
1263 +
1264 +               /* Set the window for the buffer that user require
1265 +                  for the palyback\recording window to the target window */
1266 +               if (set_window_as_per_baseadd(base, ctrl->bufferPhyBase,
1267 +                               audio_offset, MV_AUDIO_RECORD_WIN_NUM)) {
1268 +                       snd_printk("Playback buffer (%#x) is not "
1269 +                                 "within a valid target\n",
1270 +                                 ctrl->bufferPhyBase);
1271 +                       return 1;
1272 +               }
1273 +       }
1274 +
1275 +       /* Set the interrupt byte count */
1276 +       reg = ctrl->intByteCount & ARBCI_BYTE_COUNT_MASK;
1277 +       writel(reg, base + MV_AUDIO_RECORD_BYTE_CNTR_INT_REG);
1278 +
1279 +       writel(ctrl->bufferPhyBase, base + MV_AUDIO_RECORD_START_ADDR_REG);
1280 +       writel(AUDIO_SIZE_TO_REG(ctrl->bufferSize),
1281 +              base + MV_AUDIO_RECORD_BUFF_SIZE_REG);
1282 +
1283 +
1284 +       return 0;
1285 +}
1286 +
1287 +static int mv_i2s_record_cntrl_set(struct mv_i2s_record_ctrl *ctrl,
1288 +                                  void __iomem *base)
1289 +{
1290 +       unsigned int reg;
1291 +
1292 +       reg = readl(base + MV_AUDIO_I2S_REC_CTRL_REG);
1293 +       reg &= ~(AIRCR_I2S_RECORD_JUSTF_MASK|AIRCR_I2S_SAMPLE_SIZE_MASK);
1294 +
1295 +       switch (ctrl->justf) {
1296 +       case I2S_JUSTIFIED:
1297 +       case LEFT_JUSTIFIED:
1298 +       case RIGHT_JUSTIFIED:
1299 +       case RISE_BIT_CLCK_JUSTIFIED:
1300 +               reg |= ctrl->justf << AIRCR_I2S_RECORD_JUSTF_OFFS;
1301 +               break;
1302 +       default:
1303 +               return 1;
1304 +       }
1305 +
1306 +       reg |= ctrl->sample << AIRCR_I2S_SAMPLE_SIZE_OFFS;
1307 +
1308 +       writel(reg, base + MV_AUDIO_I2S_REC_CTRL_REG);
1309 +       return 0;
1310 +}
1311 +
1312 +/* We trust the value set in the window registers and don't check them.
1313 + * As there is some value already present in the register, we assume
1314 + * base and size are aligned */
1315 +
1316 +static int set_window_as_per_baseadd(void __iomem *base, unsigned int baseadd,
1317 +                                    unsigned int audio_offset, int win_num)
1318 +{
1319 +       int dram_cs, win;
1320 +       unsigned int win_base, win_size, size;
1321 +       unsigned char dram_attr[4] = {0x0E, 0x0D, 0x0B, 0x07};
1322 +
1323 +       /* Base passed is Audio base address. Audio base address is
1324 +        * Internal register base address + audio_offset */
1325 +       void __iomem *internal_reg_base = base - audio_offset;
1326 +
1327 +       for (dram_cs = 0; dram_cs < 4; dram_cs++) {
1328 +               win_base = readl(internal_reg_base + 0x1500 + (8 * dram_cs));
1329 +               win_size = readl(internal_reg_base + 0x1504 + (8 * dram_cs));
1330 +
1331 +               /* skip if window is disabled */
1332 +               if (!(win_size & 1))
1333 +                       continue;
1334 +
1335 +               /* Window size bits are 31:24. Where size =
1336 +                * (2 ^ no of ones) * 16 MB. e.g. 0x0F says 256MB */
1337 +               size = ((win_size >> 24) + 1) << 24;
1338 +
1339 +               if ((baseadd >= win_base) && (baseadd < (win_base + size))) {
1340 +                       snd_printd("DRAM window %d set for %s window",
1341 +                                 dram_cs, win_num ? "plaback" : "record");
1342 +                       writel(win_base,
1343 +                       base + MV_AUDIO_WIN_BASE_REG(win_num));
1344 +
1345 +                       /* DRAM window ctrl regs are bit different than Audio
1346 +                        * Set size, attribute and target ID */
1347 +                       win_size = ((size - 1) & 0xffff0000) | 1;
1348 +                       win_size |= (dram_attr[dram_cs] << 8); /* Atribute */
1349 +                       win_size &= (~(0xF << 4));             /* Target ID */
1350 +
1351 +                       writel(win_size,
1352 +                       base + MV_AUDIO_WIN_CTRL_REG(win_num));
1353 +                       snd_printd("win_base 0x%08x\twin_size 0x%08x",
1354 +                                 win_base, win_size);
1355 +                       return 0;
1356 +               }
1357 +       }
1358 +
1359 +       for (win = 0; win < 8; win++) {
1360 +               win_base = readl(internal_reg_base + 0x2004 + (0x10 * win));
1361 +               win_size = readl(internal_reg_base + 0x2008 + (0x10 * win));
1362 +
1363 +               /* skip if window is disabled */
1364 +               if (!(win_size & 1))
1365 +                       continue;
1366 +
1367 +               /* Window size bits are 31:16. Where size =
1368 +                * (2 ^ no of ones) * 64 KB. e.g. 0x0FF says 16MB */
1369 +               size = ((win_size >> 16) + 1) << 16;
1370 +               if ((baseadd >= win_base) && (baseadd < (win_base + size))) {
1371 +                       snd_printd("CPU window %d set for %s window",
1372 +                                 win_base, win_num ? "plaback" : "record");
1373 +                       writel(win_base,
1374 +                       base + MV_AUDIO_WIN_BASE_REG(win_num));
1375 +                       writel(win_size,
1376 +                       base + MV_AUDIO_WIN_CTRL_REG(win_num));
1377 +                       return 0;
1378 +               }
1379 +       }
1380 +
1381 +       return 1;
1382 +}
1383 +
1384 +static int mv_audio_playback_control_set(void __iomem *base, unsigned int
1385 +                        audio_offset, struct mv_audio_playback_ctrl *ctrl)
1386 +{
1387 +       unsigned int reg, buff_start, buff_end;
1388 +       unsigned int win_base, win_size;
1389 +
1390 +       if (ctrl->monoMode >= AUDIO_PLAY_OTHER_MONO) {
1391 +               snd_printk("Error: Illegal monoMode %x\n", ctrl->monoMode);
1392 +               return 1;
1393 +       }
1394 +
1395 +       if ((ctrl->burst != AUDIO_32BYTE_BURST) &&
1396 +           (ctrl->burst != AUDIO_128BYTE_BURST)) {
1397 +               snd_printk("Error: Illegal burst %x\n", ctrl->burst);
1398 +               return 1;
1399 +       }
1400 +
1401 +       if (ctrl->bufferPhyBase & (MV_AUDIO_BUFFER_MIN_ALIGN - 1)) {
1402 +               snd_printk("Error, bufferPhyBase is not aligned to 0x%x "\
1403 +                         "bytes\n", MV_AUDIO_BUFFER_MIN_ALIGN);
1404 +               return 1;
1405 +       }
1406 +
1407 +       if ((ctrl->bufferSize <= audio_burst_bytes_num_get(ctrl->burst)) ||
1408 +           (ctrl->bufferSize & (audio_burst_bytes_num_get(ctrl->burst) - 1)) ||
1409 +           (ctrl->bufferSize > AUDIO_REG_TO_SIZE(APBBCR_SIZE_MAX))) {
1410 +               snd_printk("Error, bufferSize smaller than or not multiple "\
1411 +                         "of 0x%x bytes or larger than 0x%x",
1412 +                         audio_burst_bytes_num_get(ctrl->burst),
1413 +                         AUDIO_REG_TO_SIZE(APBBCR_SIZE_MAX));
1414 +               return 1;
1415 +       }
1416 +
1417 +       reg = readl(base + MV_AUDIO_PLAYBACK_CTRL_REG);
1418 +       reg &= ~(APCR_PLAY_BURST_SIZE_MASK | APCR_LOOPBACK_MASK |
1419 +                APCR_PLAY_MONO_MASK | APCR_PLAY_SAMPLE_SIZE_MASK);
1420 +       reg |= ctrl->burst << APCR_PLAY_BURST_SIZE_OFFS;
1421 +       reg |= ctrl->loopBack << APCR_LOOPBACK_OFFS;
1422 +       reg |= ctrl->monoMode << APCR_PLAY_MONO_OFFS;
1423 +       reg |= ctrl->sampleSize << APCR_PLAY_SAMPLE_SIZE_OFFS;
1424 +       writel(reg, base + MV_AUDIO_PLAYBACK_CTRL_REG);
1425 +
1426 +       /* Get the details of the Playback address window*/
1427 +       win_base = readl(base +
1428 +                        MV_AUDIO_WIN_BASE_REG(MV_AUDIO_PLAYBACK_WIN_NUM));
1429 +       win_size = readl(base +
1430 +                        MV_AUDIO_WIN_CTRL_REG(MV_AUDIO_PLAYBACK_WIN_NUM));
1431 +
1432 +       /* Window size bits are 31:16. Where size =
1433 +        * (2 ^ no of ones) * 64 KB. e.g. 0x0FF says 16MB */
1434 +       win_size = ((win_size >> 16) + 1) << 16;
1435 +
1436 +       buff_start = ctrl->bufferPhyBase;
1437 +       buff_end   = buff_start + ctrl->bufferSize - 1;
1438 +
1439 +       /* If Playback window is not enabled or buffer address is not within
1440 +        * window boundries then try to set a new value to the Playback window*/
1441 +
1442 +       if (!(((buff_start >= win_base) &&
1443 +            (buff_start <= (win_base + win_size - 1))) ||
1444 +            ((buff_end >= win_base) &&
1445 +            (buff_end <= (win_base + win_size - 1))))) {
1446 +               snd_printd("Audio playback buffer is not within window\n");
1447 +
1448 +               /* Set the window for the buffer that user require
1449 +                  for the palyback\recording window to the target window */
1450 +               if (set_window_as_per_baseadd(base, ctrl->bufferPhyBase,
1451 +                               audio_offset, MV_AUDIO_PLAYBACK_WIN_NUM)) {
1452 +                       snd_printk("Record buffer (%#x) is not "
1453 +                                 "within a valid target\n",
1454 +                                 ctrl->bufferPhyBase);
1455 +                       return 1;
1456 +               }
1457 +       }
1458 +
1459 +       /* Set the interrupt byte count */
1460 +       reg = ctrl->intByteCount & APBCI_BYTE_COUNT_MASK;
1461 +       writel(reg, base + MV_AUDIO_PLAYBACK_BYTE_CNTR_INT_REG);
1462 +
1463 +       writel(ctrl->bufferPhyBase,
1464 +              base + MV_AUDIO_PLAYBACK_BUFF_START_REG);
1465 +       writel(AUDIO_SIZE_TO_REG(ctrl->bufferSize),
1466 +              base + MV_AUDIO_PLAYBACK_BUFF_SIZE_REG);
1467 +
1468 +       return 0;
1469 +}
1470 +
1471 +static int mv_i2s_playback_ctrl_set(void __iomem *base,
1472 +                                   struct mv_i2s_playback_ctrl *ctrl)
1473 +{
1474 +       unsigned int reg_data;
1475 +
1476 +       reg_data = readl(base + MV_AUDIO_I2S_PLAY_CTRL_REG);
1477 +       reg_data &= ~(AIPCR_I2S_PB_JUSTF_MASK | AIPCR_I2S_PB_SAMPLE_SIZE_MASK);
1478 +
1479 +       if (ctrl->sampleSize > SAMPLE_16BIT) {
1480 +               snd_printk("Illigal sample size\n");
1481 +               return 1;
1482 +       }
1483 +
1484 +       reg_data |= ctrl->sampleSize << AIPCR_I2S_PB_SAMPLE_SIZE_OFFS;
1485 +
1486 +       if (ctrl->sendLastFrame)
1487 +               reg_data |= AIPCR_I2S_SEND_LAST_FRM_MASK;
1488 +       else
1489 +               reg_data &= ~AIPCR_I2S_SEND_LAST_FRM_MASK;
1490 +
1491 +       switch (ctrl->justification) {
1492 +       case I2S_JUSTIFIED:
1493 +       case LEFT_JUSTIFIED:
1494 +       case RIGHT_JUSTIFIED:
1495 +               reg_data |= ctrl->justification << AIPCR_I2S_PB_JUSTF_OFFS;
1496 +               break;
1497 +       default:
1498 +               snd_printk("Illigal justification value\n");
1499 +               return 1;
1500 +       }
1501 +
1502 +       writel(reg_data, base + MV_AUDIO_I2S_PLAY_CTRL_REG);
1503 +
1504 +       return 0;
1505 +}
1506 +
1507 +static void mv_spdif_playback_ctrl_set(void __iomem *base,
1508 +                                       struct mv_spdif_playback_ctrl *ctrl)
1509 +{
1510 +       unsigned int reg_data;
1511 +
1512 +       reg_data = readl(base + MV_AUDIO_SPDIF_PLAY_CTRL_REG);
1513 +
1514 +       if (ctrl->blockStartInternally)
1515 +               reg_data |= ASPCR_SPDIF_BLOCK_START_MASK;
1516 +       else
1517 +               reg_data &= ~ASPCR_SPDIF_BLOCK_START_MASK;
1518 +
1519 +       if (ctrl->validityFromMemory)
1520 +               reg_data |= ASPCR_SPDIF_PB_EN_MEM_VALIDITY_MASK;
1521 +       else
1522 +               reg_data &= ~ASPCR_SPDIF_PB_EN_MEM_VALIDITY_MASK;
1523 +
1524 +       if (ctrl->userBitsFromMemory)
1525 +               reg_data |= ASPCR_SPDIF_PB_MEM_USR_EN_MASK;
1526 +       else
1527 +               reg_data &= ~ASPCR_SPDIF_PB_MEM_USR_EN_MASK;
1528 +
1529 +       if (ctrl->validity)
1530 +               reg_data |= ASPCR_SPDIF_PB_REG_VALIDITY_MASK;
1531 +       else
1532 +               reg_data &= ~ASPCR_SPDIF_PB_REG_VALIDITY_MASK;
1533 +
1534 +       if (ctrl->nonPcm)
1535 +               reg_data |= ASPCR_SPDIF_PB_NONPCM_MASK;
1536 +       else
1537 +               reg_data &= ~ASPCR_SPDIF_PB_NONPCM_MASK;
1538 +
1539 +       writel(reg_data, base + MV_AUDIO_SPDIF_PLAY_CTRL_REG);
1540 +}
1541 +
1542 +static int mv_audio_dco_ctrl_set(struct mv_audio_freq_data *dcoCtrl,
1543 +                                void __iomem *base)
1544 +{
1545 +       unsigned int reg;
1546 +
1547 +       /* Check parameters*/
1548 +       if (dcoCtrl->baseFreq > AUDIO_FREQ_96KH) {
1549 +               snd_printk("dcoCtrl->baseFreq value (0x%x) invalid\n",
1550 +                          dcoCtrl->baseFreq);
1551 +               return 1;
1552 +       }
1553 +
1554 +       if ((dcoCtrl->offset > 0xFD0) || (dcoCtrl->offset < 0x20)) {
1555 +               snd_printk("dcoCtrl->offset value (0x%x) invalid\n",
1556 +                          dcoCtrl->baseFreq);
1557 +               return 1;
1558 +       }
1559 +
1560 +       reg = readl(base + MV_AUDIO_DCO_CTRL_REG);
1561 +
1562 +       reg &= ~(ADCR_DCO_CTRL_FS_MASK | ADCR_DCO_CTRL_OFFSET_MASK);
1563 +       reg |= ((dcoCtrl->baseFreq << ADCR_DCO_CTRL_FS_OFFS)  |
1564 +               (dcoCtrl->offset << ADCR_DCO_CTRL_OFFSET_OFFS));
1565 +
1566 +       writel(reg, base + MV_AUDIO_DCO_CTRL_REG);
1567 +
1568 +       return 0;
1569 +}
1570 diff --git a/sound/soc/kirkwood/kirkwood_audio_hal.h b/sound/soc/kirkwood/kirkwood_audio_hal.h
1571 new file mode 100644
1572 index 0000000..ce08102
1573 --- /dev/null
1574 +++ b/sound/soc/kirkwood/kirkwood_audio_hal.h
1575 @@ -0,0 +1,109 @@
1576 +/*
1577 + * Sound driver data definition file for Marvell Kirkwood family SOCs
1578 + */
1579 +
1580 +#ifndef __AUDIO_HAL_H
1581 +#define __AUDIO_HAL_H
1582 +
1583 +#include "kirkwood_audio_regs.h"
1584 +
1585 +#ifdef CONFIG_SND_SOC_CS42L51
1586 +#include "cs42l51.h"
1587 +
1588 +#define codec_init           cs42l51_init
1589 +#define codec_vol_get        cs42l51_vol_get
1590 +#define codec_vol_set        cs42l51_vol_set
1591 +#define codec_del_i2c_device cs42l51_del_i2c_device
1592 +#endif
1593 +
1594 +#define CODEC_I2C_BUS_NO 0
1595 +#define CODEC_I2C_ADD    0x4A
1596 +
1597 +/*********************************/
1598 +/* General enums and structures */
1599 +/*******************************/
1600 +/* Type of Audio operations*/
1601 +enum mv_audio_operation {
1602 +       AUDIO_PLAYBACK = 0,
1603 +       AUDIO_RECORD = 1
1604 +};
1605 +
1606 +struct mv_audio_freq_data{
1607 +       int baseFreq; /* Control FS, selects the base frequency
1608 +                      * of the DCO */
1609 +       u32 offset;   /* Offset control in which each step equals to
1610 +                      * 0.9536 ppm */
1611 +};
1612 +
1613 +
1614 +/***********************************/
1615 +/* Play Back related structures   */
1616 +/*********************************/
1617 +
1618 +struct mv_audio_playback_ctrl {
1619 +       int          burst;         /* Specifies the Burst Size of the DMA */
1620 +       bool         loopBack;      /* When Loopback is enabled, playback data
1621 +                                    * is looped back to be recorded */
1622 +       int          monoMode;      /* Mono Mode is used */
1623 +       unsigned int bufferPhyBase; /* Physical Address of DMA buffer */
1624 +       unsigned int bufferSize;    /* Size of DMA buffer */
1625 +       unsigned int intByteCount;  /* Number of bytes after which an
1626 +                                    * interrupt will be issued.*/
1627 +       int    sampleSize;          /* Playback Sample Size*/
1628 +};
1629 +
1630 +struct mv_spdif_playback_ctrl {
1631 +       bool nonPcm;                /* PCM or non-PCM mode*/
1632 +       bool validity;              /* Validity bit value when using
1633 +                                    * registers (userBitsFromMemory=0) */
1634 +       bool underrunData;          /* If true send last frame on mute/pause/
1635 +                                    * underrun otherwise send 24 binary */
1636 +       bool userBitsFromMemory;    /* otherwise from intenal registers */
1637 +       bool validityFromMemory;    /* otherwise from internal registers */
1638 +       bool blockStartInternally;  /* When user and valid bits are form
1639 +                                    * registers then this bit should be zero */
1640 +};
1641 +
1642 +struct mv_i2s_playback_ctrl {
1643 +       int  sampleSize;
1644 +       int  justification;
1645 +       bool sendLastFrame; /* If true send last frame on
1646 +                            * mute/pause/underrun
1647 +                            * otherwise send 64 binary*/
1648 +};
1649 +
1650 +
1651 +/*********************************/
1652 +/* Recording  related structures */
1653 +/*********************************/
1654 +
1655 +struct mv_audio_record_ctrl {
1656 +       int  burst;          /* Recording DMA Burst Size */
1657 +       int  sampleSize;     /*Recording Sample Size */
1658 +       bool mono;           /* If true then recording mono else
1659 +                             * recording stereo */
1660 +       int  monoChannel;    /* Left or right moono */
1661 +       u32  bufferPhyBase;  /* Physical Address of DMA buffer */
1662 +       u32  bufferSize;     /* Size of DMA buffer */
1663 +
1664 +       u32  intByteCount;   /* Number of bytes after which an
1665 +                             * interrupt will be issued.*/
1666 +
1667 +};
1668 +
1669 +struct mv_i2s_record_ctrl {
1670 +       int  sample; /* I2S Recording Sample Size*/
1671 +       int  justf;
1672 +};
1673 +
1674 +/******************/
1675 +/* Functions API */
1676 +/****************/
1677 +
1678 +extern struct mv88fx_snd_chip *chip;
1679 +
1680 +int mv88fx_snd_hw_init(struct snd_card *card);
1681 +int mv88fx_snd_hw_capture_set(struct mv88fx_snd_chip *chip);
1682 +int mv88fx_snd_hw_playback_set(struct mv88fx_snd_chip *chip);
1683 +
1684 +#endif
1685 diff --git a/sound/soc/kirkwood/kirkwood_audio_regs.h b/sound/soc/kirkwood/kirkwood_audio_regs.h
1686 new file mode 100644
1687 index 0000000..1d3df15
1688 --- /dev/null
1689 +++ b/sound/soc/kirkwood/kirkwood_audio_regs.h
1690 @@ -0,0 +1,310 @@
1691 +/*
1692 + * Audio registers for Marvell Kirkwood family SOCs
1693 + */
1694 +
1695 +#ifndef __KW_AUDIO_REGS_H
1696 +#define __KW_AUDIO_REGS_H
1697 +
1698 +enum mv_audio_freq {
1699 +       AUDIO_FREQ_44_1KH = 0,        /* 11.2896Mhz */
1700 +       AUDIO_FREQ_48KH = 1,          /* 12.288Mhz */
1701 +       AUDIO_FREQ_96KH = 2,          /* 24.576Mhz */
1702 +       AUDIO_FREQ_LOWER_44_1KH = 3 , /* Lower than 11.2896MHz */
1703 +       AUDIO_FREQ_HIGHER_96KH = 4,   /* Higher than 24.576MHz */
1704 +       AUDIO_FREQ_OTHER = 7,         /* Other frequency */
1705 +};
1706 +
1707 +enum mv_audio_burst_size {
1708 +       AUDIO_32BYTE_BURST = 1,
1709 +       AUDIO_128BYTE_BURST = 2,
1710 +};
1711 +
1712 +enum mv_audio_playback_mono {
1713 +       AUDIO_PLAY_MONO_OFF = 0,
1714 +       AUDIO_PLAY_LEFT_MONO = 1,
1715 +       AUDIO_PLAY_RIGHT_MONO = 2,
1716 +       AUDIO_PLAY_BOTH_MONO = 3,
1717 +       AUDIO_PLAY_OTHER_MONO = 4
1718 +};
1719 +
1720 +enum mv_audio_record_mono {
1721 +       AUDIO_REC_LEFT_MONO = 0,
1722 +       AUDIO_REC_RIGHT_MONO = 1,
1723 +};
1724 +
1725 +enum mv_audio_sample_size {
1726 +       SAMPLE_32BIT = 0,
1727 +       SAMPLE_24BIT = 1,
1728 +       SAMPLE_20BIT = 2,
1729 +       SAMPLE_16BIT = 3,
1730 +       SAMPLE_16BIT_NON_COMPACT = 7
1731 +};
1732 +
1733 +enum mv_audio_i2s_justification {
1734 +       LEFT_JUSTIFIED = 0,
1735 +       I2S_JUSTIFIED = 5,
1736 +       RISE_BIT_CLCK_JUSTIFIED = 7,
1737 +       RIGHT_JUSTIFIED = 8,
1738 +};
1739 +
1740 +#define APBBCR_SIZE_MAX                    0x3FFFFF
1741 +#define APBBCR_SIZE_SHIFT                  0x2
1742 +
1743 +#define AUDIO_REG_TO_SIZE(reg)             (((reg) + 1) << APBBCR_SIZE_SHIFT)
1744 +#define AUDIO_SIZE_TO_REG(size)            (((size) >> APBBCR_SIZE_SHIFT) - 1)
1745 +
1746 +#define MV_AUDIO_BUFFER_MIN_ALIGN          0x8
1747 +
1748 +/********************/
1749 +/* Clocking Control*/
1750 +/*******************/
1751 +
1752 +#define MV_AUDIO_DCO_CTRL_REG              0x1204
1753 +#define MV_AUDIO_SPCR_DCO_STATUS_REG       0x120c
1754 +#define MV_AUDIO_SAMPLE_CNTR_CTRL_REG      0x1220
1755 +#define MV_AUDIO_PLAYBACK_SAMPLE_CNTR_REG  0x1224
1756 +#define MV_AUDIO_RECORD_SAMPLE_CNTR_REG    0x1228
1757 +#define MV_AUDIO_CLOCK_CTRL_REG            0x1230
1758 +
1759 +/* MV_AUDIO_DCO_CTRL_REG */
1760 +#define ADCR_DCO_CTRL_FS_OFFS              0
1761 +#define ADCR_DCO_CTRL_FS_MASK              (0x3 << ADCR_DCO_CTRL_FS_OFFS)
1762 +#define ADCR_DCO_CTRL_FS_44_1KHZ           (0x0 << ADCR_DCO_CTRL_FS_OFFS)
1763 +#define ADCR_DCO_CTRL_FS_48KHZ             (0x1 << ADCR_DCO_CTRL_FS_OFFS)
1764 +#define ADCR_DCO_CTRL_FS_96KHZ             (0x2 << ADCR_DCO_CTRL_FS_OFFS)
1765 +
1766 +
1767 +#define ADCR_DCO_CTRL_OFFSET_OFFS          2
1768 +#define ADCR_DCO_CTRL_OFFSET_MASK          (0xfff << ADCR_DCO_CTRL_OFFSET_OFFS)
1769 +
1770 +/* MV_AUDIO_SPCR_DCO_STATUS_REG */
1771 +#define ASDSR_SPCR_CTRLFS_OFFS             0
1772 +#define ASDSR_SPCR_CTRLFS_MASK             (0x7 << ASDSR_SPCR_CTRLFS_OFFS)
1773 +#define ASDSR_SPCR_CTRLFS_44_1KHZ          (0x0 << ASDSR_SPCR_CTRLFS_OFFS)
1774 +#define ASDSR_SPCR_CTRLFS_48KHZ            (0x1 << ASDSR_SPCR_CTRLFS_OFFS)
1775 +#define ASDSR_SPCR_CTRLFS_96KHZ            (0x2 << ASDSR_SPCR_CTRLFS_OFFS)
1776 +#define ASDSR_SPCR_CTRLFS_44_1KHZ_LESS     (0x3 << ASDSR_SPCR_CTRLFS_OFFS)
1777 +#define ASDSR_SPCR_CTRLFS_96KHZ_MORE       (0x4 << ASDSR_SPCR_CTRLFS_OFFS)
1778 +#define ASDSR_SPCR_CTRLFS_OTHER            (0x7 << ASDSR_SPCR_CTRLFS_OFFS)
1779 +
1780 +
1781 +#define ASDSR_SPCR_CTRLOFFSET_OFFS         3
1782 +#define ASDSR_SPCR_CTRLOFFSET_MASK         (0xfff << ASDSR_SPCR_CTRLOFFSET_OFFS)
1783 +
1784 +#define ASDSR_SPCR_LOCK_OFFS               15
1785 +#define ASDSR_SPCR_LOCK_MASK               (0x1 << ASDSR_SPCR_LOCK_OFFS)
1786 +
1787 +#define ASDSR_DCO_LOCK_OFFS                16
1788 +#define ASDSR_DCO_LOCK_MASK                (0x1 << ASDSR_DCO_LOCK_OFFS)
1789 +
1790 +#define ASDSR_PLL_LOCK_OFFS                17
1791 +#define ASDSR_PLL_LOCK_MASK                (0x1 << ASDSR_PLL_LOCK_OFFS)
1792 +
1793 +/*MV_AUDIO_SAMPLE_CNTR_CTRL_REG */
1794 +
1795 +#define ASCCR_CLR_PLAY_CNTR_OFFS           9
1796 +#define ASCCR_CLR_PLAY_CNTR_MASK           (0x1 << ASCCR_CLR_PLAY_CNTR_OFFS)
1797 +
1798 +#define ASCCR_CLR_REC_CNTR_OFFS            8
1799 +#define ASCCR_CLR_REC_CNTR_MASK            (0x1 << ASCCR_CLR_REC_CNTR_OFFS)
1800 +
1801 +#define ASCCR_ACTIVE_PLAY_CNTR_OFFS        1
1802 +#define ASCCR_ACTIVE_PLAY_CNTR_MASK        (0x1 << ASCCR_ACTIVE_PLAY_CNTR_OFFS)
1803 +
1804 +#define ASCCR_ACTIVE_REC_CNTR_OFFS         0
1805 +#define ASCCR_ACTIVE_REC_CNTR_MASK         (0x1 << ASCCR_ACTIVE_REC_CNTR_OFFS)
1806 +
1807 +/* MV_AUDIO_CLOCK_CTRL_REG */
1808 +#define ACCR_MCLK_SOURCE_OFFS              0
1809 +#define ACCR_MCLK_SOURCE_MASK              (0x3 << ACCR_MCLK_SOURCE_OFFS)
1810 +#define ACCR_MCLK_SOURCE_DCO               (0x0 << ACCR_MCLK_SOURCE_OFFS)
1811 +#define ACCR_MCLK_SOURCE_SPCR              (0x2 << ACCR_MCLK_SOURCE_OFFS)
1812 +#define ACCR_MCLK_SOURCE_EXT               (0x3 << ACCR_MCLK_SOURCE_OFFS)
1813 +
1814 +
1815 +/*********************/
1816 +/* Interrupts       */
1817 +/*******************/
1818 +#define MV_AUDIO_ERROR_CAUSE_REG            0x1300
1819 +#define MV_AUDIO_ERROR_MASK_REG             0x1304
1820 +#define MV_AUDIO_INT_CAUSE_REG              0x1308
1821 +#define MV_AUDIO_INT_MASK_REG               0x130C
1822 +#define MV_AUDIO_RECORD_BYTE_CNTR_INT_REG   0x1310
1823 +#define MV_AUDIO_PLAYBACK_BYTE_CNTR_INT_REG 0x1314
1824 +
1825 +/* MV_AUDIO_INT_CAUSE_REG*/
1826 +#define AICR_RECORD_BYTES_INT               (0x1 << 13)
1827 +#define AICR_PLAY_BYTES_INT                 (0x1 << 14)
1828 +
1829 +#define ARBCI_BYTE_COUNT_MASK               0xFFFFFF
1830 +#define APBCI_BYTE_COUNT_MASK               0xFFFFFF
1831 +
1832 +/*********************/
1833 +/* Audio Playback   */
1834 +/*******************/
1835 +/* General */
1836 +#define MV_AUDIO_PLAYBACK_CTRL_REG           0x1100
1837 +#define MV_AUDIO_PLAYBACK_BUFF_START_REG     0x1104
1838 +#define MV_AUDIO_PLAYBACK_BUFF_SIZE_REG      0x1108
1839 +#define MV_AUDIO_PLAYBACK_BUFF_BYTE_CNTR_REG 0x110c
1840 +
1841 +/* SPDIF */
1842 +#define MV_AUDIO_SPDIF_PLAY_CTRL_REG         0x2204
1843 +#define MV_AUDIO_SPDIF_PLAY_CH_STATUS_LEFT_REG(ind) \
1844 +       (0x2280 + (ind << 2))
1845 +#define MV_AUDIO_SPDIF_PLAY_CH_STATUS_RIGHT_REG(ind) \
1846 +       (0x22a0 + (ind << 2))
1847 +#define MV_AUDIO_SPDIF_PLAY_USR_BITS_LEFT_REG(ind) \
1848 +       (0x22c0 + (ind << 2))
1849 +#define MV_AUDIO_SPDIF_PLAY_USR_BITS_RIGHT_REG(ind) \
1850 +       (0x22e0 + (ind << 2))
1851 +
1852 +/* I2S */
1853 +#define MV_AUDIO_I2S_PLAY_CTRL_REG           0x2508
1854 +
1855 +
1856 +/* MV_AUDIO_PLAYBACK_CTRL_REG */
1857 +#define APCR_PLAY_SAMPLE_SIZE_OFFS  0
1858 +#define APCR_PLAY_SAMPLE_SIZE_MASK  (0x7 << APCR_PLAY_SAMPLE_SIZE_OFFS)
1859 +
1860 +#define APCR_PLAY_I2S_ENABLE_OFFS   3
1861 +#define APCR_PLAY_I2S_ENABLE_MASK   (0x1 << APCR_PLAY_I2S_ENABLE_OFFS)
1862 +
1863 +#define APCR_PLAY_SPDIF_ENABLE_OFFS 4
1864 +#define APCR_PLAY_SPDIF_ENABLE_MASK (0x1 << APCR_PLAY_SPDIF_ENABLE_OFFS)
1865 +
1866 +#define APCR_PLAY_MONO_OFFS         5
1867 +#define APCR_PLAY_MONO_MASK         (0x3 << APCR_PLAY_MONO_OFFS)
1868 +
1869 +#define APCR_PLAY_I2S_MUTE_OFFS     7
1870 +#define APCR_PLAY_I2S_MUTE_MASK     (0x1 << APCR_PLAY_I2S_MUTE_OFFS)
1871 +
1872 +#define APCR_PLAY_SPDIF_MUTE_OFFS   8
1873 +#define APCR_PLAY_SPDIF_MUTE_MASK   (0x1 << APCR_PLAY_SPDIF_MUTE_OFFS)
1874 +
1875 +#define APCR_PLAY_PAUSE_OFFS        9
1876 +#define APCR_PLAY_PAUSE_MASK        (0x1 << APCR_PLAY_PAUSE_OFFS)
1877 +
1878 +#define APCR_LOOPBACK_OFFS          10
1879 +#define APCR_LOOPBACK_MASK          (0x1 << APCR_LOOPBACK_OFFS)
1880 +
1881 +#define APCR_PLAY_BURST_SIZE_OFFS   11
1882 +#define APCR_PLAY_BURST_SIZE_MASK   (0x3 << APCR_PLAY_BURST_SIZE_OFFS)
1883 +
1884 +#define APCR_PLAY_BUSY_OFFS         16
1885 +#define APCR_PLAY_BUSY_MASK         (0x1 << APCR_PLAY_BUSY_OFFS)
1886 +
1887 +/* MV_AUDIO_PLAYBACK_BUFF_BYTE_CNTR_REG */
1888 +#define APBBCR_SIZE_MAX             0x3FFFFF
1889 +#define APBBCR_SIZE_SHIFT           0x2
1890 +
1891 +
1892 +/* MV_AUDIO_SPDIF_PLAY_CTRL_REG */
1893 +#define ASPCR_SPDIF_BLOCK_START_OFFS  0x0
1894 +#define ASPCR_SPDIF_BLOCK_START_MASK  (0x1 << ASPCR_SPDIF_BLOCK_START_OFFS)
1895 +
1896 +#define ASPCR_SPDIF_PB_EN_MEM_VALIDITY_OFFS  0x1
1897 +#define ASPCR_SPDIF_PB_EN_MEM_VALIDITY_MASK  (0x1 << \
1898 +                                       ASPCR_SPDIF_PB_EN_MEM_VALIDITY_OFFS)
1899 +
1900 +#define ASPCR_SPDIF_PB_MEM_USR_EN_OFFS 0x2
1901 +#define ASPCR_SPDIF_PB_MEM_USR_EN_MASK (0x1 << ASPCR_SPDIF_PB_MEM_USR_EN_OFFS)
1902 +
1903 +#define ASPCR_SPDIF_UNDERRUN_DATA_OFFS 0x5
1904 +#define ASPCR_SPDIF_UNDERRUN_DATA_MASK (0x1 << ASPCR_SPDIF_UNDERRUN_DATA_OFFS)
1905 +
1906 +#define ASPCR_SPDIF_PB_REG_VALIDITY_OFFS 16
1907 +#define ASPCR_SPDIF_PB_REG_VALIDITY_MASK (0x1 << \
1908 +                                       ASPCR_SPDIF_PB_REG_VALIDITY_OFFS)
1909 +
1910 +#define ASPCR_SPDIF_PB_NONPCM_OFFS     17
1911 +#define ASPCR_SPDIF_PB_NONPCM_MASK     (0x1 << ASPCR_SPDIF_PB_NONPCM_OFFS)
1912 +
1913 +
1914 +/* MV_AUDIO_I2S_PLAY_CTRL_REG */
1915 +#define AIPCR_I2S_SEND_LAST_FRM_OFFS   23
1916 +#define AIPCR_I2S_SEND_LAST_FRM_MASK   (1 << AIPCR_I2S_SEND_LAST_FRM_OFFS)
1917 +
1918 +#define AIPCR_I2S_PB_JUSTF_OFFS        26
1919 +#define AIPCR_I2S_PB_JUSTF_MASK        (0xf << AIPCR_I2S_PB_JUSTF_OFFS)
1920 +
1921 +#define AIPCR_I2S_PB_SAMPLE_SIZE_OFFS  30
1922 +#define AIPCR_I2S_PB_SAMPLE_SIZE_MASK  (0x3 << AIPCR_I2S_PB_SAMPLE_SIZE_OFFS)
1923 +
1924 +/*********************/
1925 +/* Audio Recordnig  */
1926 +/*******************/
1927 +/* General */
1928 +#define MV_AUDIO_RECORD_CTRL_REG             0x1000
1929 +#define MV_AUDIO_RECORD_START_ADDR_REG       0x1004
1930 +#define MV_AUDIO_RECORD_BUFF_SIZE_REG        0x1008
1931 +#define MV_AUDIO_RECORD_BUF_BYTE_CNTR_REG    0x100C
1932 +
1933 +/* SPDIF */
1934 +#define MV_AUDIO_SPDIF_REC_GEN_REG            0x2004
1935 +#define MV_AUDIO_SPDIF_REC_INT_CAUSE_MASK_REG 0x2008
1936 +#define MV_AUDIO_SPDIF_REC_CH_STATUS_LEFT_REG(ind) \
1937 +       (0x2180 + ((ind) << 2))
1938 +#define MV_AUDIO_SPDIF_REC_CH_STATUS_RIGHT_REG(ind) \
1939 +       (0x21a0 + ((ind) << 2))
1940 +#define MV_AUDIO_SPDIF_REC_USR_BITS_LEFT_REG(ind) \
1941 +       (0x21c0 + ((ind) << 2))
1942 +#define MV_AUDIO_SPDIF_REC_USR_BITS_RIGHT_REG(ind) \
1943 +       (0x21e0 + ((ind) << 2))
1944 +
1945 +/* I2S */
1946 +#define MV_AUDIO_I2S_REC_CTRL_REG            0x2408
1947 +
1948 +
1949 +/* MV_AUDIO_RECORD_CTRL_REG*/
1950 +#define ARCR_RECORD_SAMPLE_SIZE_OFFS 0
1951 +#define ARCR_RECORD_SAMPLE_SIZE_MASK (0x7 << ARCR_RECORD_SAMPLE_SIZE_OFFS)
1952 +
1953 +#define ARCR_RECORDED_MONO_CHNL_OFFS 3
1954 +#define ARCR_RECORDED_MONO_CHNL_MASK (0x1 << ARCR_RECORDED_MONO_CHNL_OFFS)
1955 +
1956 +#define ARCR_RECORD_MONO_OFFS        4
1957 +#define ARCR_RECORD_MONO_MASK        (0x1 << ARCR_RECORD_MONO_OFFS)
1958 +
1959 +#define ARCR_RECORD_BURST_SIZE_OFFS  5
1960 +#define ARCR_RECORD_BURST_SIZE_MASK  (0x3 << ARCR_RECORD_BURST_SIZE_OFFS)
1961 +
1962 +#define ARCR_RECORD_MUTE_OFFS        8
1963 +#define ARCR_RECORD_MUTE_MASK        (0x1 << ARCR_RECORD_MUTE_OFFS)
1964 +
1965 +#define ARCR_RECORD_PAUSE_OFFS       9
1966 +#define ARCR_RECORD_PAUSE_MASK       (0x1 << ARCR_RECORD_PAUSE_OFFS)
1967 +
1968 +#define ARCR_RECORD_I2S_EN_OFFS      10
1969 +#define ARCR_RECORD_I2S_EN_MASK      (0x1 << ARCR_RECORD_I2S_EN_OFFS)
1970 +
1971 +#define ARCR_RECORD_SPDIF_EN_OFFS    11
1972 +#define ARCR_RECORD_SPDIF_EN_MASK    (0x1 << ARCR_RECORD_SPDIF_EN_OFFS)
1973 +
1974 +
1975 +/* MV_AUDIO_SPDIF_REC_GEN_REG*/
1976 +#define ASRGR_CORE_CLK_FREQ_OFFS     1
1977 +#define ASRGR_CORE_CLK_FREQ_MASK     (0x3 << ASRGR_CORE_CLK_FREQ_OFFS)
1978 +#define ASRGR_CORE_CLK_FREQ_133MHZ   (0x0 << ASRGR_CORE_CLK_FREQ_OFFS)
1979 +#define ASRGR_CORE_CLK_FREQ_150MHZ   (0x1 << ASRGR_CORE_CLK_FREQ_OFFS)
1980 +#define ASRGR_CORE_CLK_FREQ_166MHZ   (0x2 << ASRGR_CORE_CLK_FREQ_OFFS)
1981 +#define ASRGR_CORE_CLK_FREQ_200MHZ   (0x3 << ASRGR_CORE_CLK_FREQ_OFFS)
1982 +
1983 +#define ASRGR_VALID_PCM_INFO_OFFS    7
1984 +#define ASRGR_VALID_PCM_INFO_MASK    (0x1 << ASRGR_VALID_PCM_INFO_OFFS)
1985 +
1986 +#define ASRGR_SAMPLE_FREQ_OFFS       8
1987 +#define ASRGR_SAMPLE_FREQ_MASK       (0xf << ASRGR_SAMPLE_FREQ_OFFS)
1988 +
1989 +#define ASRGR_NON_PCM_OFFS           14
1990 +#define ASRGR_NON_PCM_MASK           (1 << ASRGR_NON_PCM_OFFS)
1991 +
1992 +/* MV_AUDIO_I2S_REC_CTRL_REG*/
1993 +#define AIRCR_I2S_RECORD_JUSTF_OFFS  26
1994 +#define AIRCR_I2S_RECORD_JUSTF_MASK  (0xf << AIRCR_I2S_RECORD_JUSTF_OFFS)
1995 +
1996 +#define AIRCR_I2S_SAMPLE_SIZE_OFFS   30
1997 +#define AIRCR_I2S_SAMPLE_SIZE_MASK   (0x3 << AIRCR_I2S_SAMPLE_SIZE_OFFS)
1998 +
1999 +#endif /* __KW_AUDIO_REGS_H */
2000 +
2001 diff --git a/sound/soc/kirkwood/kirkwood_pcm.c b/sound/soc/kirkwood/kirkwood_pcm.c
2002 new file mode 100644
2003 index 0000000..ed35851
2004 --- /dev/null
2005 +++ b/sound/soc/kirkwood/kirkwood_pcm.c
2006 @@ -0,0 +1,1505 @@
2007 +/*
2008 + *
2009 + *     Marvell Orion Alsa Sound driver
2010 + *
2011 + *     Author: Maen Suleiman
2012 + *     Copyright (C) 2008 Marvell Ltd.
2013 + *
2014 + *
2015 + * This program is free software; you can redistribute it and/or modify
2016 + * it under the terms of the GNU General Public License version 2 as
2017 + * published by the Free Software Foundation.
2018 + *
2019 + */
2020 +
2021 +#include <linux/interrupt.h>
2022 +#include <linux/dma-mapping.h>
2023 +#include <linux/platform_device.h>
2024 +#include <linux/mv88fx_audio.h>
2025 +
2026 +#include <sound/core.h>
2027 +#include <sound/control.h>
2028 +#include <sound/pcm.h>
2029 +#include <sound/asoundef.h>
2030 +
2031 +#include "kirkwood_audio_hal.h"
2032 +
2033 +struct mv88fx_snd_chip *chip;
2034 +
2035 +static int test_memory(struct mbus_dram_target_info *dram_info,
2036 +                       unsigned int base, unsigned int size)
2037 +{
2038 +       unsigned int i;
2039 +
2040 +       for (i = 0; i <= dram_info->num_cs; i++) {
2041 +
2042 +               /* check if we get to end */
2043 +               if ((dram_info->cs[i].base == 0) &&
2044 +                   (dram_info->cs[i].size == 0))
2045 +                       break;
2046 +
2047 +               /* check if we fit into one memory window only */
2048 +               if ((base >= dram_info->cs[i].base) &&
2049 +                   ((base + size) <= dram_info->cs[i].base +
2050 +                                     dram_info->cs[i].size))
2051 +                       return 1;
2052 +       }
2053 +
2054 +       return 0;
2055 +}
2056 +
2057 +static void devdma_hw_free(struct device *dev, struct snd_pcm_substream
2058 +                          *substream)
2059 +{
2060 +       struct snd_pcm_runtime *runtime = substream->runtime;
2061 +       struct snd_dma_buffer *buf = runtime->dma_buffer_p;
2062 +
2063 +       if (runtime->dma_area == NULL)
2064 +               return;
2065 +
2066 +       if (buf != &substream->dma_buffer)
2067 +               kfree(runtime->dma_buffer_p);
2068 +
2069 +       snd_pcm_set_runtime_buffer(substream, NULL);
2070 +}
2071 +
2072 +static int devdma_hw_alloc(struct device *dev, struct snd_pcm_substream
2073 +                          *substream, size_t size)
2074 +{
2075 +       struct snd_pcm_runtime *runtime = substream->runtime;
2076 +       struct snd_dma_buffer *buf = runtime->dma_buffer_p;
2077 +       struct mv88fx_snd_stream *audio_stream =
2078 +              snd_pcm_substream_chip(substream);
2079 +
2080 +       int ret = 0;
2081 +
2082 +       if (buf) {
2083 +               if (buf->bytes >= size) {
2084 +                       snd_printd("buf->bytes >= size\n");
2085 +                       goto out;
2086 +               }
2087 +               devdma_hw_free(dev, substream);
2088 +       }
2089 +
2090 +       if (substream->dma_buffer.area != NULL &&
2091 +           substream->dma_buffer.bytes >= size) {
2092 +               buf = &substream->dma_buffer;
2093 +       } else {
2094 +               buf = kmalloc(sizeof(struct snd_dma_buffer), GFP_KERNEL);
2095 +               if (!buf) {
2096 +                       snd_printk("buf == NULL\n");
2097 +                       goto nomem;
2098 +               }
2099 +
2100 +               buf->dev.type = SNDRV_DMA_TYPE_DEV;
2101 +               buf->dev.dev = dev;
2102 +               buf->area = audio_stream->area;
2103 +               buf->addr = audio_stream->addr;
2104 +               buf->bytes = size;
2105 +               buf->private_data = NULL;
2106 +
2107 +               if (!buf->area) {
2108 +                       snd_printk("buf->area == NULL\n");
2109 +                       goto free;
2110 +               }
2111 +       }
2112 +
2113 +       snd_pcm_set_runtime_buffer(substream, buf);
2114 +       ret = 1;
2115 +out:
2116 +       runtime->dma_bytes = size;
2117 +       return ret;
2118 +
2119 +free:
2120 +       kfree(buf);
2121 +nomem:
2122 +       return -ENOMEM;
2123 +}
2124 +
2125 +static int devdma_mmap(struct device *dev, struct snd_pcm_substream *substream,
2126 +                       struct vm_area_struct *vma)
2127 +{
2128 +       struct snd_pcm_runtime *runtime = substream->runtime;
2129 +       return dma_mmap_coherent(dev, vma, runtime->dma_area,
2130 +                     runtime->dma_addr, runtime->dma_bytes);
2131 +}
2132 +
2133 +/*
2134 + * hw preparation for spdif
2135 + */
2136 +
2137 +static int mv88fx_snd_spdif_mask_info(struct snd_kcontrol *kcontrol,
2138 +                                     struct snd_ctl_elem_info *uinfo)
2139 +{
2140 +       uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
2141 +       uinfo->count = 1;
2142 +       return 0;
2143 +}
2144 +
2145 +static int mv88fx_snd_spdif_mask_get(struct snd_kcontrol *kcontrol,
2146 +                                    struct snd_ctl_elem_value *ucontrol)
2147 +{
2148 +       ucontrol->value.iec958.status[0] = 0xff;
2149 +       ucontrol->value.iec958.status[1] = 0xff;
2150 +       ucontrol->value.iec958.status[2] = 0xff;
2151 +       ucontrol->value.iec958.status[3] = 0xff;
2152 +       return 0;
2153 +}
2154 +
2155 +static struct snd_kcontrol_new mv88fx_snd_spdif_mask = {
2156 +       .access = SNDRV_CTL_ELEM_ACCESS_READ,
2157 +       .iface  = SNDRV_CTL_ELEM_IFACE_PCM,
2158 +       .name   = SNDRV_CTL_NAME_IEC958("", PLAYBACK, CON_MASK),
2159 +       .info   = mv88fx_snd_spdif_mask_info,
2160 +       .get    = mv88fx_snd_spdif_mask_get,
2161 +};
2162 +
2163 +static int mv88fx_snd_spdif_stream_info(struct snd_kcontrol *kcontrol,
2164 +                                       struct snd_ctl_elem_info *uinfo)
2165 +{
2166 +       uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
2167 +       uinfo->count = 1;
2168 +       return 0;
2169 +}
2170 +
2171 +static int mv88fx_snd_spdif_stream_get(struct snd_kcontrol *kcontrol,
2172 +                                      struct snd_ctl_elem_value *ucontrol)
2173 +{
2174 +       struct mv88fx_snd_chip *chip = snd_kcontrol_chip(kcontrol);
2175 +       int i, word;
2176 +
2177 +       spin_lock_irq(&chip->reg_lock);
2178 +
2179 +       for (word = 0; word < 4; word++) {
2180 +               chip->stream[PLAYBACK]->spdif_status[word] =
2181 +               readl(chip->base +
2182 +               MV_AUDIO_SPDIF_PLAY_CH_STATUS_LEFT_REG(word));
2183 +
2184 +               for (i = 0; i < 4; i++)
2185 +                       ucontrol->value.iec958.status[word + i] =
2186 +                       (chip->stream[PLAYBACK]->spdif_status[word] >>
2187 +                        (i * 8)) & 0xff;
2188 +       }
2189 +
2190 +       spin_unlock_irq(&chip->reg_lock);
2191 +       return 0;
2192 +}
2193 +
2194 +static int mv88fx_snd_spdif_stream_put(struct snd_kcontrol *kcontrol,
2195 +                                      struct snd_ctl_elem_value *ucontrol)
2196 +{
2197 +       struct mv88fx_snd_chip *chip = snd_kcontrol_chip(kcontrol);
2198 +       int i, change = 0, word;
2199 +
2200 +       spin_lock_irq(&chip->reg_lock);
2201 +
2202 +       for (word = 0; word < 4; word++) {
2203 +               for (i = 0; i < 4; i++) {
2204 +                       chip->stream[PLAYBACK]->spdif_status[word] |=
2205 +                       ucontrol->value.iec958.status[word + i] << (i * 8);
2206 +               }
2207 +
2208 +               writel(chip->stream[PLAYBACK]->spdif_status[word],
2209 +               chip->base + MV_AUDIO_SPDIF_PLAY_CH_STATUS_LEFT_REG(word));
2210 +
2211 +               writel(chip->stream[PLAYBACK]->spdif_status[word],
2212 +               chip->base + MV_AUDIO_SPDIF_PLAY_CH_STATUS_RIGHT_REG(word));
2213 +       }
2214 +
2215 +       if (chip->stream[PLAYBACK]->spdif_status[0] & IEC958_AES0_NONAUDIO)
2216 +               chip->pcm_mode = NON_PCM;
2217 +
2218 +       spin_unlock_irq(&chip->reg_lock);
2219 +
2220 +       return change;
2221 +}
2222 +
2223 +static struct snd_kcontrol_new mv88fx_snd_spdif_stream = {
2224 +       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
2225 +                 SNDRV_CTL_ELEM_ACCESS_INACTIVE,
2226 +       .iface  = SNDRV_CTL_ELEM_IFACE_PCM,
2227 +       .name   = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PCM_STREAM),
2228 +       .info   = mv88fx_snd_spdif_stream_info,
2229 +       .get    = mv88fx_snd_spdif_stream_get,
2230 +       .put    = mv88fx_snd_spdif_stream_put
2231 +};
2232 +
2233 +
2234 +static int mv88fx_snd_spdif_default_info(struct snd_kcontrol *kcontrol,
2235 +                                        struct snd_ctl_elem_info *uinfo)
2236 +{
2237 +       uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
2238 +       uinfo->count = 1;
2239 +       return 0;
2240 +}
2241 +
2242 +static int mv88fx_snd_spdif_default_get(struct snd_kcontrol *kcontrol,
2243 +                                       struct snd_ctl_elem_value *ucontrol)
2244 +{
2245 +       struct mv88fx_snd_chip *chip = snd_kcontrol_chip(kcontrol);
2246 +       int i, word;
2247 +
2248 +       spin_lock_irq(&chip->reg_lock);
2249 +
2250 +       for (word = 0; word < 4; word++) {
2251 +               chip->stream_defaults[PLAYBACK]->spdif_status[word] =
2252 +               readl(chip->base +
2253 +               MV_AUDIO_SPDIF_PLAY_CH_STATUS_LEFT_REG(word));
2254 +
2255 +               for (i = 0; i < 4; i++)
2256 +                       ucontrol->value.iec958.status[word + i] =
2257 +                       (chip->stream_defaults[PLAYBACK]->spdif_status[word] >>
2258 +                        (i * 8)) & 0xff;
2259 +       }
2260 +
2261 +       spin_unlock_irq(&chip->reg_lock);
2262 +
2263 +       return 0;
2264 +}
2265 +
2266 +static int mv88fx_snd_spdif_default_put(struct snd_kcontrol *kcontrol,
2267 +                                       struct snd_ctl_elem_value *ucontrol)
2268 +{
2269 +       struct mv88fx_snd_chip *chip = snd_kcontrol_chip(kcontrol);
2270 +       int i, change = 0, word;
2271 +
2272 +       spin_lock_irq(&chip->reg_lock);
2273 +
2274 +       for (word = 0; word < 4; word++) {
2275 +               for (i = 0; i < 4; i++) {
2276 +                       chip->stream_defaults[PLAYBACK]->spdif_status[word] |=
2277 +                       ucontrol->value.iec958.status[word + i] << (i * 8);
2278 +               }
2279 +
2280 +               writel(chip->stream_defaults[PLAYBACK]->spdif_status[word],
2281 +               chip->base + MV_AUDIO_SPDIF_PLAY_CH_STATUS_LEFT_REG(word));
2282 +
2283 +               writel(chip->stream_defaults[PLAYBACK]->spdif_status[word],
2284 +               chip->base + MV_AUDIO_SPDIF_PLAY_CH_STATUS_RIGHT_REG(word));
2285 +       }
2286 +
2287 +       if (chip->stream_defaults[PLAYBACK]->spdif_status[0] &
2288 +           IEC958_AES0_NONAUDIO)
2289 +               chip->pcm_mode = NON_PCM;
2290 +
2291 +       spin_unlock_irq(&chip->reg_lock);
2292 +
2293 +       return change;
2294 +}
2295 +
2296 +/* static struct snd_kcontrol_new mv88fx_snd_spdif_default __devinitdata = */
2297 +static struct snd_kcontrol_new mv88fx_snd_spdif_default = {
2298 +       .iface = SNDRV_CTL_ELEM_IFACE_PCM,
2299 +       .name  = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
2300 +       .info  = mv88fx_snd_spdif_default_info,
2301 +       .get   = mv88fx_snd_spdif_default_get,
2302 +       .put   = mv88fx_snd_spdif_default_put
2303 +};
2304 +
2305 +unsigned char mv88fx_snd_vol[2];
2306 +
2307 +static int mv88fx_snd_mixer_vol_info(struct snd_kcontrol *kcontrol,
2308 +                                    struct snd_ctl_elem_info *uinfo)
2309 +{
2310 +       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2311 +       uinfo->count = 2;
2312 +       uinfo->value.integer.min = 0;
2313 +       uinfo->value.integer.max = 39;
2314 +       return 0;
2315 +}
2316 +
2317 +static int mv88fx_snd_mixer_vol_get(struct snd_kcontrol *kcontrol,
2318 +                                   struct snd_ctl_elem_value *ucontrol)
2319 +{
2320 +       codec_vol_get(mv88fx_snd_vol);
2321 +
2322 +       ucontrol->value.integer.value[0] = (long)mv88fx_snd_vol[0];
2323 +       ucontrol->value.integer.value[1] = (long)mv88fx_snd_vol[1];
2324 +
2325 +       return 0;
2326 +}
2327 +
2328 +static int mv88fx_snd_mixer_vol_put(struct snd_kcontrol *kcontrol,
2329 +                                   struct snd_ctl_elem_value *ucontrol)
2330 +{
2331 +       mv88fx_snd_vol[0] = (unsigned char)ucontrol->value.integer.value[0];
2332 +       mv88fx_snd_vol[1] = (unsigned char)ucontrol->value.integer.value[1];
2333 +
2334 +       codec_vol_set(mv88fx_snd_vol);
2335 +
2336 +       return 0;
2337 +}
2338 +
2339 +static struct snd_kcontrol_new mv88fx_snd_dac_vol = {
2340 +       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2341 +       .name  = "Playback DAC Volume",
2342 +       .info  = mv88fx_snd_mixer_vol_info,
2343 +       .get   = mv88fx_snd_mixer_vol_get,
2344 +       .put   = mv88fx_snd_mixer_vol_put
2345 +};
2346 +
2347 +struct mv88fx_snd_mixer_enum {
2348 +       char **names; /* enum names*/
2349 +       int  *values; /* values to be updated*/
2350 +       int  count;   /* number of elements */
2351 +       void *rec;    /* field to be updated*/
2352 +};
2353 +
2354 +int mv88fx_snd_mixer_enum_info(struct snd_kcontrol *kcontrol,
2355 +                               struct snd_ctl_elem_info *uinfo)
2356 +{
2357 +       struct mv88fx_snd_mixer_enum *mixer_enum =
2358 +       (struct mv88fx_snd_mixer_enum *)kcontrol->private_value;
2359 +
2360 +       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2361 +       uinfo->count = 1;
2362 +       uinfo->value.enumerated.items = mixer_enum->count;
2363 +
2364 +       if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2365 +               uinfo->value.enumerated.item--;
2366 +
2367 +       strcpy(uinfo->value.enumerated.name,
2368 +                       mixer_enum->names[uinfo->value.enumerated.item]);
2369 +
2370 +       return 0;
2371 +}
2372 +
2373 +int mv88fx_snd_mixer_enum_get(struct snd_kcontrol *kcontrol,
2374 +                              struct snd_ctl_elem_value *ucontrol)
2375 +{
2376 +       struct mv88fx_snd_mixer_enum *mixer_enum =
2377 +       (struct mv88fx_snd_mixer_enum *)kcontrol->private_value;
2378 +       int i;
2379 +       unsigned int val;
2380 +
2381 +       val = *(unsigned int *)mixer_enum->rec;
2382 +
2383 +       for (i = 0; i < mixer_enum->count; i++) {
2384 +
2385 +               if (val == (unsigned int)mixer_enum->values[i]) {
2386 +                       ucontrol->value.enumerated.item[0] = i;
2387 +                       break;
2388 +               }
2389 +       }
2390 +
2391 +       return 0;
2392 +}
2393 +
2394 +int mv88fx_snd_mixer_enum_put(struct snd_kcontrol *kcontrol,
2395 +                              struct snd_ctl_elem_value *ucontrol)
2396 +{
2397 +       unsigned int val, *rec;
2398 +       struct mv88fx_snd_mixer_enum *mixer_enum =
2399 +       (struct mv88fx_snd_mixer_enum *)kcontrol->private_value;
2400 +       int i;
2401 +
2402 +       rec = (unsigned int *)mixer_enum->rec;
2403 +       val = ucontrol->value.enumerated.item[0];
2404 +
2405 +       if (val < 0)
2406 +               val = 0;
2407 +       if (val > mixer_enum->count)
2408 +               val = mixer_enum->count;
2409 +
2410 +       for (i = 0; i < mixer_enum->count; i++) {
2411 +
2412 +               if (val ==  i) {
2413 +                       *rec = (unsigned int)mixer_enum->values[i];
2414 +                       break;
2415 +               }
2416 +       }
2417 +
2418 +       return 0;
2419 +}
2420 +
2421 +#define MV88FX_PCM_MIXER_ENUM(xname, xindex, value) \
2422 +{ .iface         = SNDRV_CTL_ELEM_IFACE_MIXER, \
2423 +  .name          = xname, \
2424 +  .index         = xindex, \
2425 +  .info          = mv88fx_snd_mixer_enum_info, \
2426 +  .get           = mv88fx_snd_mixer_enum_get, \
2427 +  .put           = mv88fx_snd_mixer_enum_put, \
2428 +  .private_value = (unsigned long)value, \
2429 +}
2430 +
2431 +char *playback_src_mixer_names[] = {"SPDIF", "I2S", "SPDIF And I2S"};
2432 +int playback_src_mixer_values[] = { SPDIF, I2S, (SPDIF | I2S)};
2433 +
2434 +struct mv88fx_snd_mixer_enum playback_src_mixer        = {
2435 +       .names  = playback_src_mixer_names,
2436 +       .values = playback_src_mixer_values,
2437 +       .count  = 3,
2438 +};
2439 +
2440 +char *playback_mono_mixer_names[] = {"Mono Both", "Mono Left", "Mono Right"};
2441 +int playback_mono_mixer_values[] = { MONO_BOTH, MONO_LEFT, MONO_RIGHT};
2442 +
2443 +struct mv88fx_snd_mixer_enum playback_mono_mixer = {
2444 +       .names  = playback_mono_mixer_names,
2445 +       .values = playback_mono_mixer_values,
2446 +       .count  = 3,
2447 +};
2448 +
2449 +char *capture_src_mixer_names[] = {"SPDIF", "I2S"};
2450 +int capture_src_mixer_values[] = { SPDIF, I2S};
2451 +
2452 +struct mv88fx_snd_mixer_enum capture_src_mixer = {
2453 +       .names  = capture_src_mixer_names,
2454 +       .values = capture_src_mixer_values,
2455 +       .count  = 2,
2456 +};
2457 +
2458 +char *capture_mono_mixer_names[] = {"Mono Left", "Mono Right"};
2459 +int capture_mono_mixer_values[] = { MONO_LEFT, MONO_RIGHT};
2460 +
2461 +struct mv88fx_snd_mixer_enum capture_mono_mixer        = {
2462 +       .names  = capture_mono_mixer_names,
2463 +       .values = capture_mono_mixer_values,
2464 +       .count  = 2,
2465 +};
2466 +
2467 +static struct snd_kcontrol_new mv88fx_snd_mixers[] = {
2468 +       MV88FX_PCM_MIXER_ENUM("Playback output type", 0, &playback_src_mixer),
2469 +
2470 +       MV88FX_PCM_MIXER_ENUM("Playback mono type", 0, &playback_mono_mixer),
2471 +
2472 +       MV88FX_PCM_MIXER_ENUM("Capture input Type", 0, &capture_src_mixer),
2473 +
2474 +       MV88FX_PCM_MIXER_ENUM("Capture mono type", 0, &capture_mono_mixer),
2475 +};
2476 +
2477 +#define        PLAYBACK_MIX_INDX       0
2478 +#define PLAYBACK_MONO_MIX_INDX  1
2479 +#define CAPTURE_MIX_INDX        2
2480 +#define        CAPTURE_MONO_MIX_INDX   3
2481 +
2482 +static int mv88fx_snd_ctrl_new(struct snd_card *card)
2483 +{
2484 +       struct mv88fx_snd_platform_data *pdata = card->dev->platform_data;
2485 +       int err = 0;
2486 +
2487 +       playback_src_mixer.rec = &chip->stream_defaults[PLAYBACK]->dig_mode;
2488 +       playback_mono_mixer.rec = &chip->stream_defaults[PLAYBACK]->mono_mode;
2489 +
2490 +       capture_src_mixer.rec = &chip->stream_defaults[CAPTURE]->dig_mode;
2491 +       capture_mono_mixer.rec = &chip->stream_defaults[CAPTURE]->mono_mode;
2492 +
2493 +       if ((pdata->i2s_play) && (pdata->spdif_play)) {
2494 +               err = snd_ctl_add(card,
2495 +                     snd_ctl_new1(&mv88fx_snd_mixers[PLAYBACK_MIX_INDX],
2496 +                     chip));
2497 +               if (err < 0)
2498 +                       return err;
2499 +       }
2500 +
2501 +       err = snd_ctl_add(card,
2502 +             snd_ctl_new1(&mv88fx_snd_mixers[PLAYBACK_MONO_MIX_INDX], chip));
2503 +       if (err < 0)
2504 +               return err;
2505 +
2506 +       if ((pdata->i2s_rec) && (pdata->spdif_rec)) {
2507 +               err = snd_ctl_add(card,
2508 +               snd_ctl_new1(&mv88fx_snd_mixers[CAPTURE_MIX_INDX], chip));
2509 +               if (err < 0)
2510 +                       return err;
2511 +       }
2512 +
2513 +       err = snd_ctl_add(card, snd_ctl_new1(
2514 +               &mv88fx_snd_mixers[CAPTURE_MONO_MIX_INDX], chip));
2515 +       if (err < 0)
2516 +               return err;
2517 +
2518 +       if (pdata->i2s_play) {
2519 +               err = snd_ctl_add(card, snd_ctl_new1(&mv88fx_snd_dac_vol,
2520 +                                 chip));
2521 +               if (err < 0)
2522 +                       return err;
2523 +       }
2524 +
2525 +       err = snd_ctl_add(card, snd_ctl_new1(&mv88fx_snd_spdif_mask,
2526 +                         chip));
2527 +       if (err < 0)
2528 +               return err;
2529 +
2530 +       err = snd_ctl_add(card, snd_ctl_new1(&mv88fx_snd_spdif_default,
2531 +                         chip));
2532 +       if (err < 0)
2533 +               return err;
2534 +
2535 +       err = snd_ctl_add(card, snd_ctl_new1(&mv88fx_snd_spdif_stream,
2536 +                         chip));
2537 +       return err;
2538 +}
2539 +
2540 +static struct snd_pcm_hardware mv88fx_snd_capture_hw = {
2541 +       .info = (SNDRV_PCM_INFO_INTERLEAVED |
2542 +                SNDRV_PCM_INFO_MMAP |
2543 +                SNDRV_PCM_INFO_MMAP_VALID |
2544 +                SNDRV_PCM_INFO_BLOCK_TRANSFER |
2545 +                SNDRV_PCM_INFO_PAUSE),
2546 +
2547 +       .formats = (SNDRV_PCM_FMTBIT_S16_LE |
2548 +                   SNDRV_PCM_FMTBIT_S24_LE |
2549 +                   SNDRV_PCM_FMTBIT_S32_LE),
2550 +
2551 +       .rates = (SNDRV_PCM_RATE_44100 |
2552 +                 SNDRV_PCM_RATE_48000 |
2553 +                 SNDRV_PCM_RATE_96000),
2554 +
2555 +       .rate_min = 44100,
2556 +       .rate_max = 96000,
2557 +       .channels_min = 1,
2558 +       .channels_max = 2,
2559 +       .buffer_bytes_max = (16*1024*1024),
2560 +       .period_bytes_min = MV88FX_SND_MIN_PERIOD_BYTES,
2561 +       .period_bytes_max = MV88FX_SND_MAX_PERIOD_BYTES,
2562 +       .periods_min = MV88FX_SND_MIN_PERIODS,
2563 +       .periods_max = MV88FX_SND_MAX_PERIODS,
2564 +       .fifo_size = 0,
2565 +};
2566 +
2567 +static int mv88fx_snd_capture_open(struct snd_pcm_substream *substream)
2568 +{
2569 +       int err;
2570 +
2571 +       chip->stream_defaults[CAPTURE]->substream = substream;
2572 +       chip->stream_defaults[CAPTURE]->direction = CAPTURE;
2573 +       substream->private_data = chip->stream_defaults[CAPTURE];
2574 +       substream->runtime->hw = mv88fx_snd_capture_hw;
2575 +
2576 +       if (chip->stream_defaults[CAPTURE]->dig_mode & SPDIF)
2577 +               substream->runtime->hw.formats &= ~SNDRV_PCM_FMTBIT_S32_LE;
2578 +
2579 +       /* check if playback is already running with specific rate */
2580 +       if (chip->stream[PLAYBACK]->rate) {
2581 +               switch (chip->stream[PLAYBACK]->rate) {
2582 +               case 44100:
2583 +                       substream->runtime->hw.rates = SNDRV_PCM_RATE_44100;
2584 +                       break;
2585 +               case 48000:
2586 +                       substream->runtime->hw.rates = SNDRV_PCM_RATE_48000;
2587 +                       break;
2588 +               case 96000:
2589 +                       substream->runtime->hw.rates = SNDRV_PCM_RATE_96000;
2590 +                       break;
2591 +               }
2592 +       }
2593 +
2594 +       err = snd_pcm_hw_constraint_minmax(substream->runtime,
2595 +                                          SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
2596 +                                          chip->burst * 2,
2597 +                                          AUDIO_REG_TO_SIZE(APBBCR_SIZE_MAX));
2598 +       if (err < 0)
2599 +               return err;
2600 +
2601 +       err = snd_pcm_hw_constraint_step(substream->runtime, 0,
2602 +                                        SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
2603 +                                        chip->burst);
2604 +       if (err < 0)
2605 +               return err;
2606 +
2607 +       err = snd_pcm_hw_constraint_step(substream->runtime, 0,
2608 +                                        SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
2609 +                                        chip->burst);
2610 +       if (err < 0)
2611 +               return err;
2612 +
2613 +       err = snd_pcm_hw_constraint_minmax(substream->runtime,
2614 +                                          SNDRV_PCM_HW_PARAM_PERIODS,
2615 +                                          MV88FX_SND_MIN_PERIODS,
2616 +                                          MV88FX_SND_MAX_PERIODS);
2617 +       if (err < 0)
2618 +               return err;
2619 +
2620 +       err = snd_pcm_hw_constraint_integer(substream->runtime,
2621 +                                           SNDRV_PCM_HW_PARAM_PERIODS);
2622 +       if (err < 0)
2623 +               return err;
2624 +
2625 +       return 0;
2626 +}
2627 +
2628 +static int mv88fx_snd_capture_close(struct snd_pcm_substream *substream)
2629 +{
2630 +       chip->stream_defaults[CAPTURE]->substream = NULL;
2631 +       memset(chip->stream[CAPTURE], 0, sizeof(struct mv88fx_snd_stream));
2632 +
2633 +       return 0;
2634 +}
2635 +
2636 +static int mv88fx_snd_capture_hw_params(struct snd_pcm_substream *substream,
2637 +                                       struct snd_pcm_hw_params *params)
2638 +{
2639 +       struct mv88fx_snd_stream *audio_stream =
2640 +                                 snd_pcm_substream_chip(substream);
2641 +
2642 +       return devdma_hw_alloc(audio_stream->dev, substream,
2643 +                              params_buffer_bytes(params));
2644 +}
2645 +
2646 +static int mv88fx_snd_capture_hw_free(struct snd_pcm_substream *substream)
2647 +{
2648 +       struct mv88fx_snd_stream *audio_stream =
2649 +                                snd_pcm_substream_chip(substream);
2650 +
2651 +       /*
2652 +        * Clear out the DMA and any allocated buffers.
2653 +        */
2654 +       devdma_hw_free(audio_stream->dev, substream);
2655 +       return 0;
2656 +}
2657 +
2658 +static int mv88fx_snd_capture_prepare(struct snd_pcm_substream *substream)
2659 +{
2660 +       struct snd_pcm_runtime *runtime = substream->runtime;
2661 +
2662 +       struct mv88fx_snd_stream *audio_stream =
2663 +                                 snd_pcm_substream_chip(substream);
2664 +
2665 +       audio_stream->rate = runtime->rate;
2666 +       audio_stream->stereo = (runtime->channels == 1) ? 0 : 1;
2667 +
2668 +       if (runtime->format == SNDRV_PCM_FORMAT_S16_LE) {
2669 +               audio_stream->format = SAMPLE_16IN16;
2670 +       } else if (runtime->format == SNDRV_PCM_FORMAT_S24_LE) {
2671 +               audio_stream->format = SAMPLE_24IN32;
2672 +       } else if (runtime->format == SNDRV_PCM_FORMAT_S32_LE) {
2673 +               audio_stream->format = SAMPLE_32IN32;
2674 +       } else {
2675 +               snd_printk("Requested format %d is not supported\n",
2676 +                               runtime->format);
2677 +               return -1;
2678 +       }
2679 +
2680 +       /* buffer and period sizes in frame */
2681 +       audio_stream->dma_addr = runtime->dma_addr;
2682 +       audio_stream->dma_size = frames_to_bytes(runtime, runtime->buffer_size);
2683 +       audio_stream->period_size =
2684 +                                frames_to_bytes(runtime, runtime->period_size);
2685 +
2686 +       memcpy(chip->stream[CAPTURE], chip->stream_defaults[CAPTURE],
2687 +              sizeof(struct mv88fx_snd_stream));
2688 +
2689 +       return mv88fx_snd_hw_capture_set(chip);
2690 +}
2691 +
2692 +static int mv88fx_snd_capture_trigger(struct snd_pcm_substream *substream,
2693 +                                     int cmd)
2694 +{
2695 +       struct mv88fx_snd_stream *audio_stream =
2696 +                                snd_pcm_substream_chip(substream);
2697 +       int result = 0;
2698 +       unsigned int reg_data;
2699 +
2700 +       spin_lock(chip->reg_lock);
2701 +       switch (cmd) {
2702 +       case SNDRV_PCM_TRIGGER_START:
2703 +               /* FIXME: should check if busy before */
2704 +
2705 +               /* make sure the dma in pause state*/
2706 +               reg_data = readl(chip->base + MV_AUDIO_RECORD_CTRL_REG);
2707 +               reg_data |= ARCR_RECORD_PAUSE_MASK;
2708 +               writel(reg_data, chip->base + MV_AUDIO_RECORD_CTRL_REG);
2709 +
2710 +               /* enable interrupt */
2711 +               reg_data = readl(chip->base + MV_AUDIO_INT_MASK_REG);
2712 +               reg_data |= AICR_RECORD_BYTES_INT;
2713 +               writel(reg_data, chip->base + MV_AUDIO_INT_MASK_REG);
2714 +
2715 +               reg_data = readl(chip->base + MV_AUDIO_RECORD_CTRL_REG);
2716 +
2717 +               /* enable dma */
2718 +               if (audio_stream->dig_mode & I2S)
2719 +                       reg_data |= ARCR_RECORD_I2S_EN_MASK;
2720 +
2721 +               if (audio_stream->dig_mode & SPDIF)
2722 +                       reg_data |= ARCR_RECORD_SPDIF_EN_MASK;
2723 +
2724 +               /* start dma */
2725 +               reg_data &= (~ARCR_RECORD_PAUSE_MASK);
2726 +               writel(reg_data, chip->base + MV_AUDIO_RECORD_CTRL_REG);
2727 +               break;
2728 +
2729 +       case SNDRV_PCM_TRIGGER_STOP:
2730 +
2731 +               /* make sure the dma in pause state */
2732 +               reg_data = readl(chip->base + MV_AUDIO_RECORD_CTRL_REG);
2733 +               reg_data |= ARCR_RECORD_PAUSE_MASK;
2734 +               writel(reg_data, chip->base + MV_AUDIO_RECORD_CTRL_REG);
2735 +
2736 +               /* disable interrupt */
2737 +               reg_data = readl(chip->base + MV_AUDIO_INT_MASK_REG);
2738 +               reg_data &= (~AICR_RECORD_BYTES_INT);
2739 +               writel(reg_data, chip->base + MV_AUDIO_INT_MASK_REG);
2740 +
2741 +               /* always stop both I2S and SPDIF */
2742 +               reg_data = readl(chip->base + MV_AUDIO_RECORD_CTRL_REG);
2743 +               reg_data &= (~(ARCR_RECORD_I2S_EN_MASK |
2744 +                              ARCR_RECORD_SPDIF_EN_MASK));
2745 +               writel(reg_data, chip->base + MV_AUDIO_RECORD_CTRL_REG);
2746 +
2747 +               /* FIXME: should check if busy after */
2748 +
2749 +               break;
2750 +
2751 +       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
2752 +       case SNDRV_PCM_TRIGGER_SUSPEND:
2753 +               reg_data = readl(chip->base + MV_AUDIO_RECORD_CTRL_REG);
2754 +               reg_data |= ARCR_RECORD_PAUSE_MASK;
2755 +               writel(reg_data, chip->base + MV_AUDIO_RECORD_CTRL_REG);
2756 +               break;
2757 +
2758 +       case SNDRV_PCM_TRIGGER_RESUME:
2759 +       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
2760 +               reg_data = readl(chip->base + MV_AUDIO_RECORD_CTRL_REG);
2761 +               reg_data &= (~ARCR_RECORD_PAUSE_MASK);
2762 +               writel(reg_data, chip->base + MV_AUDIO_RECORD_CTRL_REG);
2763 +               break;
2764 +
2765 +       default:
2766 +               result = -EINVAL;
2767 +               break;
2768 +       }
2769 +
2770 +       spin_unlock(&chip->reg_lock);
2771 +       return result;
2772 +}
2773 +
2774 +static snd_pcm_uframes_t mv88fx_snd_capture_pointer(struct snd_pcm_substream
2775 +                                                   *substream)
2776 +{
2777 +       return bytes_to_frames(substream->runtime,
2778 +       (ssize_t)readl(chip->base + MV_AUDIO_RECORD_BUF_BYTE_CNTR_REG));
2779 +}
2780 +
2781 +int mv88fx_snd_capture_mmap(struct snd_pcm_substream *substream,
2782 +                           struct vm_area_struct *vma)
2783 +{
2784 +       return devdma_mmap(NULL, substream, vma);
2785 +}
2786 +
2787 +static struct snd_pcm_ops mv88fx_snd_capture_ops = {
2788 +       .open      = mv88fx_snd_capture_open,
2789 +       .close     = mv88fx_snd_capture_close,
2790 +       .ioctl     = snd_pcm_lib_ioctl,
2791 +       .hw_params = mv88fx_snd_capture_hw_params,
2792 +       .hw_free   = mv88fx_snd_capture_hw_free,
2793 +       .prepare   = mv88fx_snd_capture_prepare,
2794 +       .trigger   = mv88fx_snd_capture_trigger,
2795 +       .pointer   = mv88fx_snd_capture_pointer,
2796 +       .mmap      = mv88fx_snd_capture_mmap,
2797 +};
2798 +
2799 +struct snd_pcm_hardware mv88fx_snd_playback_hw = {
2800 +       .info = (SNDRV_PCM_INFO_INTERLEAVED |
2801 +                SNDRV_PCM_INFO_MMAP |
2802 +                SNDRV_PCM_INFO_MMAP_VALID |
2803 +                SNDRV_PCM_INFO_BLOCK_TRANSFER |
2804 +                SNDRV_PCM_INFO_PAUSE),
2805 +       .formats = (SNDRV_PCM_FMTBIT_S16_LE |
2806 +                   SNDRV_PCM_FMTBIT_S24_LE |
2807 +                   SNDRV_PCM_FMTBIT_S32_LE),
2808 +       .rates = (SNDRV_PCM_RATE_44100 |
2809 +                 SNDRV_PCM_RATE_48000 |
2810 +                 SNDRV_PCM_RATE_96000),
2811 +
2812 +       .rate_min = 44100,
2813 +       .rate_max = 96000,
2814 +       .channels_min = 1,
2815 +       .channels_max = 2,
2816 +       .buffer_bytes_max = (16*1024*1024),
2817 +       .period_bytes_min = MV88FX_SND_MIN_PERIOD_BYTES,
2818 +       .period_bytes_max = MV88FX_SND_MAX_PERIOD_BYTES,
2819 +       .periods_min = MV88FX_SND_MIN_PERIODS,
2820 +       .periods_max = MV88FX_SND_MAX_PERIODS,
2821 +       .fifo_size = 0,
2822 +};
2823 +
2824 +int mv88fx_snd_playback_open(struct snd_pcm_substream *substream)
2825 +{
2826 +       int err = 0;
2827 +
2828 +       chip->stream_defaults[PLAYBACK]->substream = substream;
2829 +       chip->stream_defaults[PLAYBACK]->direction = PLAYBACK;
2830 +       substream->private_data = chip->stream_defaults[PLAYBACK];
2831 +       substream->runtime->hw = mv88fx_snd_playback_hw;
2832 +
2833 +       if (chip->stream_defaults[PLAYBACK]->dig_mode & SPDIF)
2834 +               substream->runtime->hw.formats &= ~SNDRV_PCM_FMTBIT_S32_LE;
2835 +
2836 +       /* check if capture is already running with specific rate */
2837 +       if (chip->stream[CAPTURE]->rate) {
2838 +               switch (chip->stream[CAPTURE]->rate) {
2839 +               case 44100:
2840 +                       substream->runtime->hw.rates = SNDRV_PCM_RATE_44100;
2841 +                       break;
2842 +               case 48000:
2843 +                       substream->runtime->hw.rates = SNDRV_PCM_RATE_48000;
2844 +                       break;
2845 +               case 96000:
2846 +                       substream->runtime->hw.rates = SNDRV_PCM_RATE_96000;
2847 +                       break;
2848 +
2849 +               }
2850 +       }
2851 +
2852 +       err = snd_pcm_hw_constraint_minmax(substream->runtime,
2853 +                                          SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
2854 +                                          chip->burst * 2,
2855 +                                          AUDIO_REG_TO_SIZE(APBBCR_SIZE_MAX));
2856 +       if (err < 0)
2857 +               return err;
2858 +
2859 +       err = snd_pcm_hw_constraint_step(substream->runtime, 0,
2860 +                                        SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
2861 +                                        chip->burst);
2862 +       if (err < 0)
2863 +               return err;
2864 +
2865 +       err = snd_pcm_hw_constraint_step(substream->runtime, 0,
2866 +                                        SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
2867 +                                        chip->burst);
2868 +       if (err < 0)
2869 +               return err;
2870 +
2871 +       err = snd_pcm_hw_constraint_minmax(substream->runtime,
2872 +                                          SNDRV_PCM_HW_PARAM_PERIODS,
2873 +                                          MV88FX_SND_MIN_PERIODS,
2874 +                                          MV88FX_SND_MAX_PERIODS);
2875 +       if (err < 0)
2876 +               return err;
2877 +
2878 +       err = snd_pcm_hw_constraint_integer(substream->runtime,
2879 +                                           SNDRV_PCM_HW_PARAM_PERIODS);
2880 +
2881 +       if (err < 0)
2882 +               return err;
2883 +
2884 +       return 0;
2885 +}
2886 +
2887 +int mv88fx_snd_playback_close(struct snd_pcm_substream *substream)
2888 +{
2889 +       int i;
2890 +
2891 +       chip->stream_defaults[PLAYBACK]->substream = NULL;
2892 +       chip->pcm_mode = PCM;
2893 +
2894 +       for (i = 0; i < 4; i++) {
2895 +               chip->stream_defaults[PLAYBACK]->spdif_status[i] = 0;
2896 +               chip->stream[PLAYBACK]->spdif_status[i] = 0;
2897 +
2898 +               writel(chip->stream_defaults[PLAYBACK]->spdif_status[i],
2899 +                      chip->base + MV_AUDIO_SPDIF_PLAY_CH_STATUS_LEFT_REG(i));
2900 +               writel(chip->stream_defaults[PLAYBACK]->spdif_status[i],
2901 +                      chip->base + MV_AUDIO_SPDIF_PLAY_CH_STATUS_RIGHT_REG(i));
2902 +       }
2903 +
2904 +       memset(chip->stream[PLAYBACK], 0, sizeof(struct mv88fx_snd_stream));
2905 +
2906 +       return 0;
2907 +}
2908 +
2909 +int mv88fx_snd_playback_hw_params(struct snd_pcm_substream *substream,
2910 +                                        struct snd_pcm_hw_params *params)
2911 +{
2912 +       struct mv88fx_snd_stream *audio_stream =
2913 +                                snd_pcm_substream_chip(substream);
2914 +
2915 +       return devdma_hw_alloc(audio_stream->dev, substream,
2916 +                       params_buffer_bytes(params));
2917 +}
2918 +
2919 +int mv88fx_snd_playback_hw_free(struct snd_pcm_substream *substream)
2920 +{
2921 +       struct mv88fx_snd_stream *audio_stream =
2922 +                                snd_pcm_substream_chip(substream);
2923 +
2924 +       /*
2925 +        * Clear out the DMA and any allocated buffers.
2926 +        */
2927 +       devdma_hw_free(audio_stream->dev, substream);
2928 +       return 0;
2929 +}
2930 +
2931 +int mv88fx_snd_playback_prepare(struct snd_pcm_substream *substream)
2932 +{
2933 +       struct snd_pcm_runtime *runtime = substream->runtime;
2934 +
2935 +       struct mv88fx_snd_stream *audio_stream =
2936 +                                 snd_pcm_substream_chip(substream);
2937 +
2938 +       if ((audio_stream->dig_mode == I2S) &&
2939 +           (chip->pcm_mode == NON_PCM))
2940 +               return -1;
2941 +
2942 +       audio_stream->rate = runtime->rate;
2943 +       audio_stream->stereo = (runtime->channels == 1) ? 0 : 1;
2944 +
2945 +       if (runtime->format == SNDRV_PCM_FORMAT_S16_LE) {
2946 +               audio_stream->format = SAMPLE_16IN16;
2947 +       } else if (runtime->format == SNDRV_PCM_FORMAT_S24_LE) {
2948 +               audio_stream->format = SAMPLE_24IN32;
2949 +       } else if (runtime->format == SNDRV_PCM_FORMAT_S32_LE) {
2950 +               audio_stream->format = SAMPLE_32IN32;
2951 +       } else {
2952 +               snd_printk("Requested format %d is not supported\n",
2953 +                               runtime->format);
2954 +               return -1;
2955 +       }
2956 +
2957 +       /* buffer and period sizes in frame */
2958 +       audio_stream->dma_addr = runtime->dma_addr;
2959 +       audio_stream->dma_size = frames_to_bytes(runtime, runtime->buffer_size);
2960 +       audio_stream->period_size =
2961 +                                frames_to_bytes(runtime, runtime->period_size);
2962 +
2963 +       memcpy(chip->stream[PLAYBACK], chip->stream_defaults[PLAYBACK],
2964 +              sizeof(struct mv88fx_snd_stream));
2965 +
2966 +       return mv88fx_snd_hw_playback_set(chip);
2967 +}
2968 +
2969 +int mv88fx_snd_playback_trigger(struct snd_pcm_substream *substream,
2970 +                                      int cmd)
2971 +{
2972 +       struct mv88fx_snd_stream *audio_stream =
2973 +                                snd_pcm_substream_chip(substream);
2974 +       int result = 0;
2975 +       unsigned int reg_data;
2976 +
2977 +       spin_lock(chip->reg_lock);
2978 +       switch (cmd) {
2979 +       case SNDRV_PCM_TRIGGER_START:
2980 +               /* enable interrupt */
2981 +               reg_data = readl(chip->base + MV_AUDIO_INT_MASK_REG);
2982 +               reg_data |= AICR_PLAY_BYTES_INT;
2983 +               writel(reg_data, chip->base + MV_AUDIO_INT_MASK_REG);
2984 +
2985 +               /* make sure the dma in pause state*/
2986 +               reg_data = readl(chip->base +
2987 +                                MV_AUDIO_PLAYBACK_CTRL_REG);
2988 +               reg_data |= APCR_PLAY_PAUSE_MASK;
2989 +               writel(reg_data, chip->base +
2990 +                                MV_AUDIO_PLAYBACK_CTRL_REG);
2991 +
2992 +               /* enable dma */
2993 +               if ((audio_stream->dig_mode & I2S) &&
2994 +                   (chip->pcm_mode == PCM))
2995 +                       reg_data |= APCR_PLAY_I2S_ENABLE_MASK;
2996 +
2997 +               if (audio_stream->dig_mode & SPDIF)
2998 +                       reg_data |= APCR_PLAY_SPDIF_ENABLE_MASK;
2999 +
3000 +               /* start dma */
3001 +               reg_data &= (~APCR_PLAY_PAUSE_MASK);
3002 +               writel(reg_data, chip->base + MV_AUDIO_PLAYBACK_CTRL_REG);
3003 +
3004 +               break;
3005 +
3006 +       case SNDRV_PCM_TRIGGER_STOP:
3007 +
3008 +               /* disable interrupt */
3009 +               reg_data = readl(chip->base + MV_AUDIO_INT_MASK_REG);
3010 +               reg_data &= (~AICR_PLAY_BYTES_INT);
3011 +               writel(reg_data, chip->base + MV_AUDIO_INT_MASK_REG);
3012 +
3013 +               /* make sure the dma in pause state*/
3014 +               reg_data = readl(chip->base +
3015 +                                MV_AUDIO_PLAYBACK_CTRL_REG);
3016 +               reg_data |= APCR_PLAY_PAUSE_MASK;
3017 +
3018 +               /* always stop both I2S and SPDIF*/
3019 +               reg_data &= (~(APCR_PLAY_I2S_ENABLE_MASK |
3020 +                              APCR_PLAY_SPDIF_ENABLE_MASK));
3021 +               writel(reg_data, chip->base +
3022 +                                MV_AUDIO_PLAYBACK_CTRL_REG);
3023 +
3024 +               /* check if busy twice*/
3025 +               while (readl(chip->base + MV_AUDIO_PLAYBACK_CTRL_REG) &
3026 +               APCR_PLAY_BUSY_MASK)
3027 +                       cpu_relax();
3028 +               while (readl(chip->base + MV_AUDIO_PLAYBACK_CTRL_REG) &
3029 +               APCR_PLAY_BUSY_MASK)
3030 +                       cpu_relax();
3031 +               break;
3032 +
3033 +       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
3034 +       case SNDRV_PCM_TRIGGER_SUSPEND:
3035 +               reg_data = readl(chip->base +
3036 +                                MV_AUDIO_PLAYBACK_CTRL_REG);
3037 +               reg_data |= APCR_PLAY_PAUSE_MASK;
3038 +               writel(reg_data, chip->base +
3039 +                                MV_AUDIO_PLAYBACK_CTRL_REG);
3040 +               break;
3041 +
3042 +       case SNDRV_PCM_TRIGGER_RESUME:
3043 +       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
3044 +               reg_data = readl(chip->base +
3045 +                                MV_AUDIO_PLAYBACK_CTRL_REG);
3046 +               reg_data &= (~APCR_PLAY_PAUSE_MASK);
3047 +               writel(reg_data, chip->base +
3048 +                                MV_AUDIO_PLAYBACK_CTRL_REG);
3049 +
3050 +               break;
3051 +
3052 +       default:
3053 +               result = -EINVAL;
3054 +       }
3055 +
3056 +       spin_unlock(&chip->reg_lock);
3057 +       return result;
3058 +}
3059 +
3060 +
3061 +snd_pcm_uframes_t mv88fx_snd_playback_pointer(struct snd_pcm_substream
3062 +                                                    *substream)
3063 +{
3064 +       return bytes_to_frames(substream->runtime,
3065 +       (ssize_t)readl(chip->base + MV_AUDIO_PLAYBACK_BUFF_BYTE_CNTR_REG));
3066 +}
3067 +
3068 +int mv88fx_snd_playback_mmap(struct snd_pcm_substream *substream,
3069 +                            struct vm_area_struct *vma)
3070 +{
3071 +       return devdma_mmap(NULL, substream, vma);
3072 +}
3073 +
3074 +
3075 +struct snd_pcm_ops mv88fx_snd_playback_ops = {
3076 +       .open      = mv88fx_snd_playback_open,
3077 +       .close     = mv88fx_snd_playback_close,
3078 +       .ioctl     = snd_pcm_lib_ioctl,
3079 +       .hw_params = mv88fx_snd_playback_hw_params,
3080 +       .hw_free   = mv88fx_snd_playback_hw_free,
3081 +       .prepare   = mv88fx_snd_playback_prepare,
3082 +       .trigger   = mv88fx_snd_playback_trigger,
3083 +       .pointer   = mv88fx_snd_playback_pointer,
3084 +       .mmap      = mv88fx_snd_playback_mmap,
3085 +};
3086 +
3087 +int __init mv88fx_snd_pcm_new(struct snd_card *card)
3088 +{
3089 +       struct snd_pcm *pcm;
3090 +       struct mv88fx_snd_platform_data *pdata = card->dev->platform_data;
3091 +       int err, i;
3092 +
3093 +       snd_printd("card->dev=0x%x\n", (unsigned int)card->dev);
3094 +
3095 +       err = snd_pcm_new(card, "Marvell mv88fx_snd IEC958 and I2S", 0, 1, 1,
3096 +                         &pcm);
3097 +       if (err < 0)
3098 +               return err;
3099 +
3100 +       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
3101 +                       &mv88fx_snd_playback_ops);
3102 +
3103 +       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
3104 +                       &mv88fx_snd_capture_ops);
3105 +
3106 +       if ((pdata->i2s_play) && (pdata->spdif_play))
3107 +               chip->stream_defaults[PLAYBACK]->dig_mode = (SPDIF | I2S);
3108 +       else if (pdata->i2s_play)
3109 +               chip->stream_defaults[PLAYBACK]->dig_mode = I2S;
3110 +       else if (pdata->spdif_play)
3111 +               chip->stream_defaults[PLAYBACK]->dig_mode = SPDIF;
3112 +       else
3113 +               chip->stream_defaults[PLAYBACK]->dig_mode = 0;
3114 +
3115 +       chip->stream_defaults[PLAYBACK]->mono_mode = MONO_BOTH;
3116 +       chip->pcm_mode = PCM;
3117 +       chip->stream_defaults[PLAYBACK]->stat_mem = 0;
3118 +       chip->stream_defaults[PLAYBACK]->clock_src = DCO_CLOCK;
3119 +
3120 +       if (pdata->i2s_rec)
3121 +               chip->stream_defaults[CAPTURE]->dig_mode = I2S;
3122 +       else if (pdata->spdif_rec)
3123 +               chip->stream_defaults[CAPTURE]->dig_mode = SPDIF;
3124 +       else
3125 +               chip->stream_defaults[CAPTURE]->dig_mode = 0;
3126 +
3127 +       chip->stream_defaults[CAPTURE]->mono_mode = MONO_LEFT;
3128 +       chip->pcm_mode = PCM;
3129 +       chip->stream_defaults[CAPTURE]->stat_mem = 0;
3130 +       chip->stream_defaults[CAPTURE]->clock_src = DCO_CLOCK;
3131 +
3132 +       for (i = 0; i < 4; i++) {
3133 +               chip->stream_defaults[PLAYBACK]->spdif_status[i] = 0;
3134 +               chip->stream[PLAYBACK]->spdif_status[i] = 0;
3135 +
3136 +               writel(chip->stream_defaults[PLAYBACK]->spdif_status[i],
3137 +                      chip->base + MV_AUDIO_SPDIF_PLAY_CH_STATUS_LEFT_REG(i));
3138 +
3139 +               writel(chip->stream_defaults[PLAYBACK]->spdif_status[i],
3140 +                      chip->base + MV_AUDIO_SPDIF_PLAY_CH_STATUS_RIGHT_REG(i));
3141 +
3142 +               writel(0, chip->base +
3143 +                         MV_AUDIO_SPDIF_PLAY_USR_BITS_LEFT_REG(i));
3144 +
3145 +               writel(0, chip->base +
3146 +                         MV_AUDIO_SPDIF_PLAY_USR_BITS_RIGHT_REG(i));
3147 +       }
3148 +
3149 +       pcm->private_data = chip;
3150 +       pcm->info_flags = 0;
3151 +       strcpy(pcm->name, "Marvell mv88fx_snd IEC958 and I2S");
3152 +
3153 +       return 0;
3154 +}
3155 +
3156 +irqreturn_t mv88fx_snd_interrupt(int irq, void *dev_id)
3157 +{
3158 +       struct mv88fx_snd_chip *chip = dev_id;
3159 +       struct mv88fx_snd_stream *play_stream = chip->stream_defaults[PLAYBACK];
3160 +       struct mv88fx_snd_stream *capture_stream =
3161 +                                               chip->stream_defaults[CAPTURE];
3162 +
3163 +       unsigned int status, mask;
3164 +
3165 +       spin_lock(&chip->reg_lock);
3166 +
3167 +       /* read the active interrupt */
3168 +       mask = readl(chip->base + MV_AUDIO_INT_MASK_REG);
3169 +       status = readl(chip->base + MV_AUDIO_INT_CAUSE_REG) & mask;
3170 +
3171 +       do {
3172 +               if (status & ~(AICR_RECORD_BYTES_INT|AICR_PLAY_BYTES_INT)) {
3173 +                       spin_unlock(&chip->reg_lock);
3174 +                       snd_BUG(); /* FIXME: should enable error interrupts*/
3175 +                       return IRQ_NONE;
3176 +               }
3177 +
3178 +               /* acknowledge interrupt */
3179 +               writel(status, chip->base + MV_AUDIO_INT_CAUSE_REG);
3180 +
3181 +               /* This is record event */
3182 +               if (status & AICR_RECORD_BYTES_INT)
3183 +                       snd_pcm_period_elapsed(capture_stream->substream);
3184 +
3185 +               /* This is play event */
3186 +               if (status & AICR_PLAY_BYTES_INT)
3187 +                       snd_pcm_period_elapsed(play_stream->substream);
3188 +
3189 +               /* read the active interrupt */
3190 +               mask = readl(chip->base + MV_AUDIO_INT_MASK_REG);
3191 +               status = readl(chip->base + MV_AUDIO_INT_CAUSE_REG) & mask;
3192 +       } while (status);
3193 +
3194 +       spin_unlock(&chip->reg_lock);
3195 +
3196 +       return IRQ_HANDLED;
3197 +}
3198 +
3199 +void mv88fx_snd_free(struct snd_card *card)
3200 +{
3201 +       struct mv88fx_snd_chip *chip = card->private_data;
3202 +
3203 +       /* free irq */
3204 +       free_irq(chip->irq, (void *)chip);
3205 +
3206 +       snd_printd("chip->res =0x%x\n", (unsigned int)chip->res);
3207 +
3208 +       if (chip->base)
3209 +               iounmap(chip->base);
3210 +
3211 +       if (chip->res)
3212 +               release_resource(chip->res);
3213 +
3214 +       chip->res = NULL;
3215 +
3216 +       /* Free memory allocated for streems */
3217 +       if (chip->stream_defaults[PLAYBACK]->area)
3218 +               dma_free_coherent(card->dev,
3219 +                        MV88FX_SND_MAX_PERIODS * MV88FX_SND_MAX_PERIOD_BYTES,
3220 +                        chip->stream_defaults[PLAYBACK]->area,
3221 +                        chip->stream_defaults[PLAYBACK]->addr);
3222 +
3223 +       if (chip->stream_defaults[CAPTURE]->area)
3224 +               dma_free_coherent(card->dev,
3225 +                        MV88FX_SND_MAX_PERIODS * MV88FX_SND_MAX_PERIOD_BYTES,
3226 +                        chip->stream_defaults[CAPTURE]->area,
3227 +                        chip->stream_defaults[CAPTURE]->addr);
3228 +
3229 +       kfree(chip->stream_defaults[PLAYBACK]);
3230 +       chip->stream_defaults[PLAYBACK] = NULL;
3231 +
3232 +       kfree(chip->stream[PLAYBACK]);
3233 +       chip->stream[PLAYBACK] = NULL;
3234 +
3235 +       kfree(chip->stream_defaults[CAPTURE]);
3236 +       chip->stream_defaults[CAPTURE] = NULL;
3237 +
3238 +       kfree(chip->stream[CAPTURE]);
3239 +       chip->stream[CAPTURE] = NULL;
3240 +
3241 +       chip = NULL;
3242 +}
3243 +
3244 +int mv88fx_snd_probe(struct platform_device *dev)
3245 +{
3246 +       int err = 0, irq = NO_IRQ;
3247 +       struct snd_card *card = NULL;
3248 +       struct resource *r = NULL;
3249 +       static struct snd_device_ops ops = {
3250 +               .dev_free =     NULL,
3251 +       };
3252 +       struct mv88fx_snd_platform_data *pdata = NULL;
3253 +
3254 +       err = snd_card_create(-1, "mv88fx_snd", THIS_MODULE,
3255 +                      sizeof(struct mv88fx_snd_chip), &card);
3256 +
3257 +       if (err) {
3258 +               snd_printk("snd_card_create failed\n");
3259 +               return err;
3260 +       }
3261 +
3262 +       card->dev = &dev->dev;
3263 +       chip = card->private_data;
3264 +       card->private_free = mv88fx_snd_free;
3265 +
3266 +       pdata = (struct mv88fx_snd_platform_data *)dev->dev.platform_data;
3267 +
3268 +       if (pdata->i2s_rec == 2 || pdata->spdif_rec == 2)
3269 +               chip->stereo = 1;
3270 +       else
3271 +               chip->stereo = 0;
3272 +
3273 +       chip->audio_offset = pdata->base_offset;
3274 +
3275 +       r = platform_get_resource(dev, IORESOURCE_MEM, 0);
3276 +       if (!r) {
3277 +               snd_printk("platform_get_resource failed\n");
3278 +               err = -ENXIO;
3279 +               goto error;
3280 +       }
3281 +
3282 +       snd_printd("chip->res =0x%x\n", (unsigned int)chip->res);
3283 +
3284 +       r = request_mem_region(r->start, SZ_16K, MV88FX_AUDIO_NAME);
3285 +       if (!r) {
3286 +               snd_printk("request_mem_region failed\n");
3287 +               err = -EBUSY;
3288 +               goto error;
3289 +       }
3290 +       chip->res = r;
3291 +
3292 +       chip->base = ioremap(r->start, SZ_16K);
3293 +
3294 +       if (!chip->base) {
3295 +               snd_printk("ioremap failed\n");
3296 +               err = -ENOMEM;
3297 +               goto error;
3298 +       }
3299 +
3300 +       snd_printd("chip->base=0x%x r->start0x%x\n",
3301 +                        (unsigned int)chip->base, r->start);
3302 +
3303 +       irq = platform_get_irq(dev, 0);
3304 +       if (irq == NO_IRQ) {
3305 +               snd_printk("platform_get_irq failed\n");
3306 +               err = -ENXIO;
3307 +               goto error;
3308 +       }
3309 +
3310 +       snd_printd("card = 0x%x dev 0x%x\n",
3311 +                        (unsigned int)card, (unsigned int)dev);
3312 +       strncpy(card->driver, dev->dev.driver->name, sizeof(card->driver));
3313 +
3314 +       /* Allocate memory for our device */
3315 +       chip->stream_defaults[PLAYBACK] =
3316 +                         kzalloc(sizeof(struct mv88fx_snd_stream), GFP_KERNEL);
3317 +
3318 +       if (chip->stream_defaults[PLAYBACK] == NULL) {
3319 +               snd_printk("kzalloc failed for default playback\n");
3320 +               err = -ENOMEM;
3321 +               goto error;
3322 +       }
3323 +
3324 +       chip->stream_defaults[PLAYBACK]->direction = PLAYBACK;
3325 +       chip->stream_defaults[PLAYBACK]->dev = card->dev;
3326 +
3327 +       chip->stream[PLAYBACK] = kzalloc(sizeof(struct mv88fx_snd_stream),
3328 +                                        GFP_KERNEL);
3329 +
3330 +       if (chip->stream[PLAYBACK] == NULL) {
3331 +               snd_printk("kzalloc failed for runtime playback\n");
3332 +               err = -ENOMEM;
3333 +               goto error;
3334 +       }
3335 +
3336 +       chip->stream_defaults[CAPTURE] =
3337 +                        kzalloc(sizeof(struct mv88fx_snd_stream), GFP_KERNEL);
3338 +
3339 +       if (chip->stream_defaults[CAPTURE] == NULL) {
3340 +               snd_printk("kzalloc failed for capture\n");
3341 +               err = -ENOMEM;
3342 +               goto error;
3343 +       }
3344 +
3345 +       chip->stream_defaults[CAPTURE]->direction = CAPTURE;
3346 +       chip->stream_defaults[CAPTURE]->dev = card->dev;
3347 +
3348 +       chip->stream[CAPTURE] = kzalloc(sizeof(struct mv88fx_snd_stream),
3349 +                                       GFP_KERNEL);
3350 +
3351 +       if (chip->stream[CAPTURE] == NULL) {
3352 +               snd_printk("kzalloc failed for runtime capture\n");
3353 +               err = -ENOMEM;
3354 +               goto error;
3355 +       }
3356 +
3357 +       chip->irq = irq;
3358 +       chip->stream_defaults[PLAYBACK]->area =
3359 +       dma_alloc_coherent(&dev->dev,
3360 +                          MV88FX_SND_MAX_PERIODS * MV88FX_SND_MAX_PERIOD_BYTES,
3361 +                          &chip->stream_defaults[PLAYBACK]->addr,
3362 +                          GFP_KERNEL);
3363 +
3364 +       if (!chip->stream_defaults[PLAYBACK]->area) {
3365 +               snd_printk("dma_alloc_coherent failed for playback buffer\n");
3366 +               err = -ENOMEM;
3367 +               goto error;
3368 +       }
3369 +
3370 +       if (0 == test_memory(pdata->dram,
3371 +         (unsigned int)chip->stream_defaults[PLAYBACK]->addr,
3372 +         (unsigned int)MV88FX_SND_MAX_PERIODS * MV88FX_SND_MAX_PERIOD_BYTES)) {
3373 +
3374 +               snd_printk("error: playback buffer not in one memory window\n");
3375 +               err = -ENOMEM;
3376 +               goto error;
3377 +       }
3378 +
3379 +       chip->stream_defaults[CAPTURE]->area =
3380 +       dma_alloc_coherent(&dev->dev,
3381 +                          MV88FX_SND_MAX_PERIODS * MV88FX_SND_MAX_PERIOD_BYTES,
3382 +                          &chip->stream_defaults[CAPTURE]->addr,
3383 +                          GFP_KERNEL);
3384 +
3385 +       if (!chip->stream_defaults[CAPTURE]->area) {
3386 +               snd_printk("dma_alloc_coherent failed for capture buffer\n");
3387 +               err = -ENOMEM;
3388 +               goto error;
3389 +       }
3390 +
3391 +       if (0 == test_memory(pdata->dram,
3392 +         (unsigned int)chip->stream_defaults[CAPTURE]->addr,
3393 +         (unsigned int)MV88FX_SND_MAX_PERIODS * MV88FX_SND_MAX_PERIOD_BYTES)) {
3394 +
3395 +               snd_printk("error: playback buffer not in one memory window\n");
3396 +               err = -ENOMEM;
3397 +               goto error;
3398 +       }
3399 +
3400 +       if (request_irq(chip->irq, mv88fx_snd_interrupt, 0, MV88FX_AUDIO_NAME,
3401 +           (void *)chip)) {
3402 +
3403 +               snd_printk("Unable to grab IRQ %d\n", chip->irq);
3404 +               err = -ENOMEM;
3405 +               goto error;
3406 +       }
3407 +
3408 +       chip->ch_stat_valid = 1;
3409 +       chip->burst = 128;
3410 +       chip->loopback = 0;
3411 +       chip->dco_ctrl_offst = 0x800;
3412 +
3413 +       err = mv88fx_snd_hw_init(card);
3414 +       if (err) {
3415 +               snd_printk("mv88fx_snd_hw_init failed\n");
3416 +               err = -ENOMEM;
3417 +               goto error;
3418 +       }
3419 +
3420 +       /* Set default values */
3421 +       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
3422 +       if (err < 0) {
3423 +               snd_printk("Creating chip device failed.\n");
3424 +               err = -ENOMEM;
3425 +               goto error;
3426 +       }
3427 +
3428 +       /* create pcm devices */
3429 +       err = mv88fx_snd_pcm_new(card);
3430 +       if (err < 0) {
3431 +               snd_printk("Creating PCM device failed.\n");
3432 +               err = -ENOMEM;
3433 +               goto error;
3434 +       }
3435 +       /* create controll interfaces & switches */
3436 +       err = mv88fx_snd_ctrl_new(card);
3437 +       if (err < 0) {
3438 +               snd_printk("Creating non-PCM device failed.\n");
3439 +               err = -ENOMEM;
3440 +               goto error;
3441 +       }
3442 +
3443 +       strcpy(card->driver, "mv88fx_snd");
3444 +       strcpy(card->shortname, "Marvell mv88fx_snd");
3445 +       sprintf(card->longname, "Marvell mv88fx_snd ALSA driver");
3446 +
3447 +       err = snd_card_register(card);
3448 +       if (err < 0) {
3449 +               snd_printk("Card registeration failed.\n");
3450 +               err = -ENOMEM;
3451 +               goto error;
3452 +       }
3453 +
3454 +       /* if (dma_set_mask(&dev->dev, 0xFFFFFFUL) < 0) { */
3455 +       if (dma_set_mask(&dev->dev, 0xFFFFFFFFUL) < 0) {
3456 +               snd_printk("Could not set DMA mask\n");
3457 +               goto error;
3458 +       }
3459 +
3460 +       platform_set_drvdata(dev, card);
3461 +       return 0;
3462 +error:
3463 +       if (card)
3464 +               snd_card_free(card);
3465 +       platform_set_drvdata(dev, NULL);
3466 +       return err;
3467 +}
3468 +
3469 +int mv88fx_snd_remove(struct platform_device *dev)
3470 +{
3471 +       struct snd_card *card = platform_get_drvdata(dev);
3472 +
3473 +       if (card)
3474 +               snd_card_free(card);
3475 +
3476 +       /* FIXME: Once "../codecs/cs42l51.c" is fixed to behave as a module
3477 +        *        this should be removed */
3478 +       codec_del_i2c_device();
3479 +
3480 +       platform_set_drvdata(dev, NULL);
3481 +       return 0;
3482 +}
3483 +
3484 +#define mv88fx_snd_resume     NULL
3485 +#define mv88fx_snd_suspend    NULL
3486 +
3487 +struct platform_driver mv88fx_snd_driver = {
3488 +       .probe   = mv88fx_snd_probe,
3489 +       .remove  = mv88fx_snd_remove,
3490 +       .suspend = mv88fx_snd_suspend,
3491 +       .resume  = mv88fx_snd_resume,
3492 +       .driver  = { .name = MV88FX_AUDIO_NAME,},
3493 +};
3494 +
3495 +int __init mv88fx_snd_init(void)
3496 +{
3497 +       return platform_driver_register(&mv88fx_snd_driver);
3498 +}
3499 +
3500 +void __exit mv88fx_snd_exit(void)
3501 +{
3502 +       platform_driver_unregister(&mv88fx_snd_driver);
3503 +}
3504 +
3505 +MODULE_AUTHOR("Maen Suleiman <maen@marvell.com>");
3506 +MODULE_DESCRIPTION("Marvell MV88Fx Alsa Sound driver");
3507 +MODULE_LICENSE("GPL");
3508 +
3509 +module_init(mv88fx_snd_init);
3510 +module_exit(mv88fx_snd_exit);
3511 +
3512 -- 
3513 1.6.5.2
3514