aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc
diff options
context:
space:
mode:
authorArjan van de Ven <arjan@linux.intel.com>2008-10-17 12:20:26 -0400
committerArjan van de Ven <arjan@linux.intel.com>2008-10-17 12:20:26 -0400
commit651dab4264e4ba0e563f5ff56f748127246e9065 (patch)
tree016630974bdcb00fe529b673f96d389e0fd6dc94 /sound/soc
parent40b8606253552109815786e5d4b0de98782d31f5 (diff)
parent2e532d68a2b3e2aa6b19731501222069735c741c (diff)
Merge commit 'linus/master' into merge-linus
Conflicts: arch/x86/kvm/i8254.c
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/Kconfig2
-rw-r--r--sound/soc/Makefile2
-rw-r--r--sound/soc/at32/at32-pcm.c5
-rw-r--r--sound/soc/at32/playpaq_wm8510.c7
-rw-r--r--sound/soc/at91/Kconfig17
-rw-r--r--sound/soc/at91/Makefile5
-rw-r--r--sound/soc/at91/at91-ssc.c4
-rw-r--r--sound/soc/at91/eti_b1_wm8731.c348
-rw-r--r--sound/soc/blackfin/Kconfig101
-rw-r--r--sound/soc/blackfin/Makefile21
-rw-r--r--sound/soc/blackfin/bf5xx-ac97-pcm.c457
-rw-r--r--sound/soc/blackfin/bf5xx-ac97-pcm.h29
-rw-r--r--sound/soc/blackfin/bf5xx-ac97.c406
-rw-r--r--sound/soc/blackfin/bf5xx-ac97.h36
-rw-r--r--sound/soc/blackfin/bf5xx-ad1980.c113
-rw-r--r--sound/soc/blackfin/bf5xx-ad73311.c240
-rw-r--r--sound/soc/blackfin/bf5xx-i2s-pcm.c288
-rw-r--r--sound/soc/blackfin/bf5xx-i2s-pcm.h29
-rw-r--r--sound/soc/blackfin/bf5xx-i2s.c311
-rw-r--r--sound/soc/blackfin/bf5xx-i2s.h14
-rw-r--r--sound/soc/blackfin/bf5xx-sport.c1032
-rw-r--r--sound/soc/blackfin/bf5xx-sport.h194
-rw-r--r--sound/soc/blackfin/bf5xx-ssm2602.c186
-rw-r--r--sound/soc/codecs/Kconfig100
-rw-r--r--sound/soc/codecs/Makefile26
-rw-r--r--sound/soc/codecs/ac97.c3
-rw-r--r--sound/soc/codecs/ad1980.c308
-rw-r--r--sound/soc/codecs/ad1980.h23
-rw-r--r--sound/soc/codecs/ad73311.c107
-rw-r--r--sound/soc/codecs/ad73311.h90
-rw-r--r--sound/soc/codecs/ak4535.c117
-rw-r--r--sound/soc/codecs/ak4535.h1
-rw-r--r--sound/soc/codecs/cs4270.c103
-rw-r--r--sound/soc/codecs/ssm2602.c775
-rw-r--r--sound/soc/codecs/ssm2602.h130
-rw-r--r--sound/soc/codecs/tlv320aic23.c714
-rw-r--r--sound/soc/codecs/tlv320aic23.h122
-rw-r--r--sound/soc/codecs/tlv320aic26.c520
-rw-r--r--sound/soc/codecs/tlv320aic26.h96
-rw-r--r--sound/soc/codecs/tlv320aic3x.c113
-rw-r--r--sound/soc/codecs/tlv320aic3x.h3
-rw-r--r--sound/soc/codecs/uda1380.c116
-rw-r--r--sound/soc/codecs/uda1380.h1
-rw-r--r--sound/soc/codecs/wm8510.c221
-rw-r--r--sound/soc/codecs/wm8510.h2
-rw-r--r--sound/soc/codecs/wm8580.c1053
-rw-r--r--sound/soc/codecs/wm8580.h42
-rw-r--r--sound/soc/codecs/wm8731.c179
-rw-r--r--sound/soc/codecs/wm8731.h2
-rw-r--r--sound/soc/codecs/wm8750.c178
-rw-r--r--sound/soc/codecs/wm8750.h2
-rw-r--r--sound/soc/codecs/wm8753.c181
-rw-r--r--sound/soc/codecs/wm8753.h5
-rw-r--r--sound/soc/codecs/wm8900.c1541
-rw-r--r--sound/soc/codecs/wm8900.h64
-rw-r--r--sound/soc/codecs/wm8903.c1813
-rw-r--r--sound/soc/codecs/wm8903.h1463
-rw-r--r--sound/soc/codecs/wm8971.c941
-rw-r--r--sound/soc/codecs/wm8971.h64
-rw-r--r--sound/soc/codecs/wm8990.c110
-rw-r--r--sound/soc/codecs/wm8990.h1
-rw-r--r--sound/soc/codecs/wm9712.c3
-rw-r--r--sound/soc/codecs/wm9713.c37
-rw-r--r--sound/soc/davinci/davinci-evm.c3
-rw-r--r--sound/soc/davinci/davinci-i2s.c4
-rw-r--r--sound/soc/davinci/davinci-i2s.h2
-rw-r--r--sound/soc/davinci/davinci-pcm.c2
-rw-r--r--sound/soc/davinci/davinci-pcm.h2
-rw-r--r--sound/soc/fsl/Kconfig10
-rw-r--r--sound/soc/fsl/Makefile5
-rw-r--r--sound/soc/fsl/mpc5200_psc_i2s.c884
-rw-r--r--sound/soc/fsl/mpc8610_hpcd.c26
-rw-r--r--sound/soc/fsl/soc-of-simple.c171
-rw-r--r--sound/soc/omap/Kconfig8
-rw-r--r--sound/soc/omap/Makefile2
-rw-r--r--sound/soc/omap/n810.c7
-rw-r--r--sound/soc/omap/omap-mcbsp.c181
-rw-r--r--sound/soc/omap/omap-mcbsp.h16
-rw-r--r--sound/soc/omap/omap-pcm.c4
-rw-r--r--sound/soc/omap/osk5912.c232
-rw-r--r--sound/soc/pxa/Kconfig3
-rw-r--r--sound/soc/pxa/corgi.c41
-rw-r--r--sound/soc/pxa/em-x270.c2
-rw-r--r--sound/soc/pxa/poodle.c7
-rw-r--r--sound/soc/pxa/pxa2xx-ac97.c282
-rw-r--r--sound/soc/pxa/pxa2xx-i2s.c67
-rw-r--r--sound/soc/pxa/pxa2xx-pcm.c265
-rw-r--r--sound/soc/pxa/pxa2xx-pcm.h15
-rw-r--r--sound/soc/pxa/spitz.c63
-rw-r--r--sound/soc/pxa/tosa.c6
-rw-r--r--sound/soc/s3c24xx/neo1973_wm8753.c96
-rw-r--r--sound/soc/soc-core.c143
-rw-r--r--sound/soc/soc-dapm.c152
93 files changed, 16078 insertions, 1840 deletions
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index f743530add8f..4dfda6674bec 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -5,6 +5,7 @@
5menuconfig SND_SOC 5menuconfig SND_SOC
6 tristate "ALSA for SoC audio support" 6 tristate "ALSA for SoC audio support"
7 select SND_PCM 7 select SND_PCM
8 select AC97_BUS if SND_SOC_AC97_BUS
8 ---help--- 9 ---help---
9 10
10 If you want ASoC support, you should say Y here and also to the 11 If you want ASoC support, you should say Y here and also to the
@@ -31,6 +32,7 @@ source "sound/soc/sh/Kconfig"
31source "sound/soc/fsl/Kconfig" 32source "sound/soc/fsl/Kconfig"
32source "sound/soc/davinci/Kconfig" 33source "sound/soc/davinci/Kconfig"
33source "sound/soc/omap/Kconfig" 34source "sound/soc/omap/Kconfig"
35source "sound/soc/blackfin/Kconfig"
34 36
35# Supported codecs 37# Supported codecs
36source "sound/soc/codecs/Kconfig" 38source "sound/soc/codecs/Kconfig"
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index 933a66d30804..d849349f2c66 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -2,4 +2,4 @@ snd-soc-core-objs := soc-core.o soc-dapm.o
2 2
3obj-$(CONFIG_SND_SOC) += snd-soc-core.o 3obj-$(CONFIG_SND_SOC) += snd-soc-core.o
4obj-$(CONFIG_SND_SOC) += codecs/ at32/ at91/ pxa/ s3c24xx/ sh/ fsl/ davinci/ 4obj-$(CONFIG_SND_SOC) += codecs/ at32/ at91/ pxa/ s3c24xx/ sh/ fsl/ davinci/
5obj-$(CONFIG_SND_SOC) += omap/ au1x/ 5obj-$(CONFIG_SND_SOC) += omap/ au1x/ blackfin/
diff --git a/sound/soc/at32/at32-pcm.c b/sound/soc/at32/at32-pcm.c
index 435f1daf177c..c83584f989a9 100644
--- a/sound/soc/at32/at32-pcm.c
+++ b/sound/soc/at32/at32-pcm.c
@@ -434,7 +434,8 @@ static int at32_pcm_suspend(struct platform_device *pdev,
434 params = prtd->params; 434 params = prtd->params;
435 435
436 /* Disable the PDC and save the PDC registers */ 436 /* Disable the PDC and save the PDC registers */
437 ssc_writex(params->ssc->regs, PDC_PTCR, params->mask->pdc_disable); 437 ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
438 params->mask->pdc_disable);
438 439
439 prtd->pdc_xpr_save = ssc_readx(params->ssc->regs, params->pdc->xpr); 440 prtd->pdc_xpr_save = ssc_readx(params->ssc->regs, params->pdc->xpr);
440 prtd->pdc_xcr_save = ssc_readx(params->ssc->regs, params->pdc->xcr); 441 prtd->pdc_xcr_save = ssc_readx(params->ssc->regs, params->pdc->xcr);
@@ -464,7 +465,7 @@ static int at32_pcm_resume(struct platform_device *pdev,
464 ssc_writex(params->ssc->regs, params->pdc->xnpr, prtd->pdc_xnpr_save); 465 ssc_writex(params->ssc->regs, params->pdc->xnpr, prtd->pdc_xnpr_save);
465 ssc_writex(params->ssc->regs, params->pdc->xncr, prtd->pdc_xncr_save); 466 ssc_writex(params->ssc->regs, params->pdc->xncr, prtd->pdc_xncr_save);
466 467
467 ssc_writex(params->ssc->regs, PDC_PTCR, params->mask->pdc_enable); 468 ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR, params->mask->pdc_enable);
468 return 0; 469 return 0;
469} 470}
470#else /* CONFIG_PM */ 471#else /* CONFIG_PM */
diff --git a/sound/soc/at32/playpaq_wm8510.c b/sound/soc/at32/playpaq_wm8510.c
index 3f326219f1ec..98a2d5826a85 100644
--- a/sound/soc/at32/playpaq_wm8510.c
+++ b/sound/soc/at32/playpaq_wm8510.c
@@ -377,6 +377,7 @@ static struct snd_soc_machine snd_soc_machine_playpaq = {
377 377
378 378
379static struct wm8510_setup_data playpaq_wm8510_setup = { 379static struct wm8510_setup_data playpaq_wm8510_setup = {
380 .i2c_bus = 0,
380 .i2c_address = 0x1a, 381 .i2c_address = 0x1a,
381}; 382};
382 383
@@ -405,7 +406,6 @@ static int __init playpaq_asoc_init(void)
405 ssc = ssc_request(0); 406 ssc = ssc_request(0);
406 if (IS_ERR(ssc)) { 407 if (IS_ERR(ssc)) {
407 ret = PTR_ERR(ssc); 408 ret = PTR_ERR(ssc);
408 ssc = NULL;
409 goto err_ssc; 409 goto err_ssc;
410 } 410 }
411 ssc_p->ssc = ssc; 411 ssc_p->ssc = ssc;
@@ -476,10 +476,7 @@ err_pll0:
476 _gclk0 = NULL; 476 _gclk0 = NULL;
477 } 477 }
478err_gclk0: 478err_gclk0:
479 if (ssc != NULL) { 479 ssc_free(ssc);
480 ssc_free(ssc);
481 ssc = NULL;
482 }
483err_ssc: 480err_ssc:
484 return ret; 481 return ret;
485} 482}
diff --git a/sound/soc/at91/Kconfig b/sound/soc/at91/Kconfig
index 905186502e00..85a883299c2e 100644
--- a/sound/soc/at91/Kconfig
+++ b/sound/soc/at91/Kconfig
@@ -8,20 +8,3 @@ config SND_AT91_SOC
8 8
9config SND_AT91_SOC_SSC 9config SND_AT91_SOC_SSC
10 tristate 10 tristate
11
12config SND_AT91_SOC_ETI_B1_WM8731
13 tristate "SoC Audio support for WM8731-based Endrelia ETI-B1 boards"
14 depends on SND_AT91_SOC && (MACH_ETI_B1 || MACH_ETI_C1)
15 select SND_AT91_SOC_SSC
16 select SND_SOC_WM8731
17 help
18 Say Y if you want to add support for SoC audio on WM8731-based
19 Endrelia Technologies Inc ETI-B1 or ETI-C1 boards.
20
21config SND_AT91_SOC_ETI_SLAVE
22 bool "Run codec in slave Mode on Endrelia boards"
23 depends on SND_AT91_SOC_ETI_B1_WM8731
24 default n
25 help
26 Say Y if you want to run with the AT91 SSC generating the BCLK
27 and LRC signals on Endrelia boards.
diff --git a/sound/soc/at91/Makefile b/sound/soc/at91/Makefile
index f23da17cc328..b817f11df286 100644
--- a/sound/soc/at91/Makefile
+++ b/sound/soc/at91/Makefile
@@ -4,8 +4,3 @@ snd-soc-at91-ssc-objs := at91-ssc.o
4 4
5obj-$(CONFIG_SND_AT91_SOC) += snd-soc-at91.o 5obj-$(CONFIG_SND_AT91_SOC) += snd-soc-at91.o
6obj-$(CONFIG_SND_AT91_SOC_SSC) += snd-soc-at91-ssc.o 6obj-$(CONFIG_SND_AT91_SOC_SSC) += snd-soc-at91-ssc.o
7
8# AT91 Machine Support
9snd-soc-eti-b1-wm8731-objs := eti_b1_wm8731.o
10
11obj-$(CONFIG_SND_AT91_SOC_ETI_B1_WM8731) += snd-soc-eti-b1-wm8731.o
diff --git a/sound/soc/at91/at91-ssc.c b/sound/soc/at91/at91-ssc.c
index 5d44515e62e0..1b61cc461261 100644
--- a/sound/soc/at91/at91-ssc.c
+++ b/sound/soc/at91/at91-ssc.c
@@ -5,7 +5,7 @@
5 * Endrelia Technologies Inc. 5 * Endrelia Technologies Inc.
6 * 6 *
7 * Based on pxa2xx Platform drivers by 7 * Based on pxa2xx Platform drivers by
8 * Liam Girdwood <liam.girdwood@wolfsonmicro.com> 8 * Liam Girdwood <lrg@slimlogic.co.uk>
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify it 10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the 11 * under the terms of the GNU General Public License as published by the
@@ -408,7 +408,7 @@ static int at91_ssc_hw_params(struct snd_pcm_substream *substream,
408 dma_params->pdc_xfer_size = 4; 408 dma_params->pdc_xfer_size = 4;
409 break; 409 break;
410 default: 410 default:
411 printk(KERN_WARNING "at91-ssc: unsupported PCM format"); 411 printk(KERN_WARNING "at91-ssc: unsupported PCM format\n");
412 return -EINVAL; 412 return -EINVAL;
413 } 413 }
414 414
diff --git a/sound/soc/at91/eti_b1_wm8731.c b/sound/soc/at91/eti_b1_wm8731.c
deleted file mode 100644
index b81d6b2cfa1d..000000000000
--- a/sound/soc/at91/eti_b1_wm8731.c
+++ /dev/null
@@ -1,348 +0,0 @@
1/*
2 * eti_b1_wm8731 -- SoC audio for AT91RM9200-based Endrelia ETI_B1 board.
3 *
4 * Author: Frank Mandarino <fmandarino@endrelia.com>
5 * Endrelia Technologies Inc.
6 * Created: Mar 29, 2006
7 *
8 * Based on corgi.c by:
9 *
10 * Copyright 2005 Wolfson Microelectronics PLC.
11 * Copyright 2005 Openedhand Ltd.
12 *
13 * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
14 * Richard Purdie <richard@openedhand.com>
15 *
16 * This program is free software; you can redistribute it and/or modify it
17 * under the terms of the GNU General Public License as published by the
18 * Free Software Foundation; either version 2 of the License, or (at your
19 * option) any later version.
20 *
21 */
22
23#include <linux/module.h>
24#include <linux/moduleparam.h>
25#include <linux/kernel.h>
26#include <linux/clk.h>
27#include <linux/timer.h>
28#include <linux/interrupt.h>
29#include <linux/platform_device.h>
30#include <sound/core.h>
31#include <sound/pcm.h>
32#include <sound/soc.h>
33#include <sound/soc-dapm.h>
34
35#include <mach/hardware.h>
36#include <mach/gpio.h>
37
38#include "../codecs/wm8731.h"
39#include "at91-pcm.h"
40#include "at91-ssc.h"
41
42#if 0
43#define DBG(x...) printk(KERN_INFO "eti_b1_wm8731: " x)
44#else
45#define DBG(x...)
46#endif
47
48static struct clk *pck1_clk;
49static struct clk *pllb_clk;
50
51
52static int eti_b1_startup(struct snd_pcm_substream *substream)
53{
54 struct snd_soc_pcm_runtime *rtd = substream->private_data;
55 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
56 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
57 int ret;
58
59 /* cpu clock is the AT91 master clock sent to the SSC */
60 ret = snd_soc_dai_set_sysclk(cpu_dai, AT91_SYSCLK_MCK,
61 60000000, SND_SOC_CLOCK_IN);
62 if (ret < 0)
63 return ret;
64
65 /* codec system clock is supplied by PCK1, set to 12MHz */
66 ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK,
67 12000000, SND_SOC_CLOCK_IN);
68 if (ret < 0)
69 return ret;
70
71 /* Start PCK1 clock. */
72 clk_enable(pck1_clk);
73 DBG("pck1 started\n");
74
75 return 0;
76}
77
78static void eti_b1_shutdown(struct snd_pcm_substream *substream)
79{
80 /* Stop PCK1 clock. */
81 clk_disable(pck1_clk);
82 DBG("pck1 stopped\n");
83}
84
85static int eti_b1_hw_params(struct snd_pcm_substream *substream,
86 struct snd_pcm_hw_params *params)
87{
88 struct snd_soc_pcm_runtime *rtd = substream->private_data;
89 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
90 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
91 int ret;
92
93#ifdef CONFIG_SND_AT91_SOC_ETI_SLAVE
94 unsigned int rate;
95 int cmr_div, period;
96
97 /* set codec DAI configuration */
98 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
99 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
100 if (ret < 0)
101 return ret;
102
103 /* set cpu DAI configuration */
104 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
105 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
106 if (ret < 0)
107 return ret;
108
109 /*
110 * The SSC clock dividers depend on the sample rate. The CMR.DIV
111 * field divides the system master clock MCK to drive the SSC TK
112 * signal which provides the codec BCLK. The TCMR.PERIOD and
113 * RCMR.PERIOD fields further divide the BCLK signal to drive
114 * the SSC TF and RF signals which provide the codec DACLRC and
115 * ADCLRC clocks.
116 *
117 * The dividers were determined through trial and error, where a
118 * CMR.DIV value is chosen such that the resulting BCLK value is
119 * divisible, or almost divisible, by (2 * sample rate), and then
120 * the TCMR.PERIOD or RCMR.PERIOD is BCLK / (2 * sample rate) - 1.
121 */
122 rate = params_rate(params);
123
124 switch (rate) {
125 case 8000:
126 cmr_div = 25; /* BCLK = 60MHz/(2*25) = 1.2MHz */
127 period = 74; /* LRC = BCLK/(2*(74+1)) = 8000Hz */
128 break;
129 case 32000:
130 cmr_div = 7; /* BCLK = 60MHz/(2*7) ~= 4.28571428MHz */
131 period = 66; /* LRC = BCLK/(2*(66+1)) = 31982.942Hz */
132 break;
133 case 48000:
134 cmr_div = 13; /* BCLK = 60MHz/(2*13) ~= 2.3076923MHz */
135 period = 23; /* LRC = BCLK/(2*(23+1)) = 48076.923Hz */
136 break;
137 default:
138 printk(KERN_WARNING "unsupported rate %d on ETI-B1 board\n", rate);
139 return -EINVAL;
140 }
141
142 /* set the MCK divider for BCLK */
143 ret = snd_soc_dai_set_clkdiv(cpu_dai, AT91SSC_CMR_DIV, cmr_div);
144 if (ret < 0)
145 return ret;
146
147 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
148 /* set the BCLK divider for DACLRC */
149 ret = snd_soc_dai_set_clkdiv(cpu_dai,
150 AT91SSC_TCMR_PERIOD, period);
151 } else {
152 /* set the BCLK divider for ADCLRC */
153 ret = snd_soc_dai_set_clkdiv(cpu_dai,
154 AT91SSC_RCMR_PERIOD, period);
155 }
156 if (ret < 0)
157 return ret;
158
159#else /* CONFIG_SND_AT91_SOC_ETI_SLAVE */
160 /*
161 * Codec in Master Mode.
162 */
163
164 /* set codec DAI configuration */
165 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
166 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
167 if (ret < 0)
168 return ret;
169
170 /* set cpu DAI configuration */
171 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
172 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
173 if (ret < 0)
174 return ret;
175
176#endif /* CONFIG_SND_AT91_SOC_ETI_SLAVE */
177
178 return 0;
179}
180
181static struct snd_soc_ops eti_b1_ops = {
182 .startup = eti_b1_startup,
183 .hw_params = eti_b1_hw_params,
184 .shutdown = eti_b1_shutdown,
185};
186
187
188static const struct snd_soc_dapm_widget eti_b1_dapm_widgets[] = {
189 SND_SOC_DAPM_MIC("Int Mic", NULL),
190 SND_SOC_DAPM_SPK("Ext Spk", NULL),
191};
192
193static const struct snd_soc_dapm_route intercon[] = {
194
195 /* speaker connected to LHPOUT */
196 {"Ext Spk", NULL, "LHPOUT"},
197
198 /* mic is connected to Mic Jack, with WM8731 Mic Bias */
199 {"MICIN", NULL, "Mic Bias"},
200 {"Mic Bias", NULL, "Int Mic"},
201};
202
203/*
204 * Logic for a wm8731 as connected on a Endrelia ETI-B1 board.
205 */
206static int eti_b1_wm8731_init(struct snd_soc_codec *codec)
207{
208 DBG("eti_b1_wm8731_init() called\n");
209
210 /* Add specific widgets */
211 snd_soc_dapm_new_controls(codec, eti_b1_dapm_widgets,
212 ARRAY_SIZE(eti_b1_dapm_widgets));
213
214 /* Set up specific audio path interconnects */
215 snd_soc_dapm_add_route(codec, intercon, ARRAY_SIZE(intercon));
216
217 /* not connected */
218 snd_soc_dapm_disable_pin(codec, "RLINEIN");
219 snd_soc_dapm_disable_pin(codec, "LLINEIN");
220
221 /* always connected */
222 snd_soc_dapm_enable_pin(codec, "Int Mic");
223 snd_soc_dapm_enable_pin(codec, "Ext Spk");
224
225 snd_soc_dapm_sync(codec);
226
227 return 0;
228}
229
230static struct snd_soc_dai_link eti_b1_dai = {
231 .name = "WM8731",
232 .stream_name = "WM8731 PCM",
233 .cpu_dai = &at91_ssc_dai[1],
234 .codec_dai = &wm8731_dai,
235 .init = eti_b1_wm8731_init,
236 .ops = &eti_b1_ops,
237};
238
239static struct snd_soc_machine snd_soc_machine_eti_b1 = {
240 .name = "ETI_B1_WM8731",
241 .dai_link = &eti_b1_dai,
242 .num_links = 1,
243};
244
245static struct wm8731_setup_data eti_b1_wm8731_setup = {
246 .i2c_address = 0x1a,
247};
248
249static struct snd_soc_device eti_b1_snd_devdata = {
250 .machine = &snd_soc_machine_eti_b1,
251 .platform = &at91_soc_platform,
252 .codec_dev = &soc_codec_dev_wm8731,
253 .codec_data = &eti_b1_wm8731_setup,
254};
255
256static struct platform_device *eti_b1_snd_device;
257
258static int __init eti_b1_init(void)
259{
260 int ret;
261 struct at91_ssc_periph *ssc = eti_b1_dai.cpu_dai->private_data;
262
263 if (!request_mem_region(AT91RM9200_BASE_SSC1, SZ_16K, "soc-audio")) {
264 DBG("SSC1 memory region is busy\n");
265 return -EBUSY;
266 }
267
268 ssc->base = ioremap(AT91RM9200_BASE_SSC1, SZ_16K);
269 if (!ssc->base) {
270 DBG("SSC1 memory ioremap failed\n");
271 ret = -ENOMEM;
272 goto fail_release_mem;
273 }
274
275 ssc->pid = AT91RM9200_ID_SSC1;
276
277 eti_b1_snd_device = platform_device_alloc("soc-audio", -1);
278 if (!eti_b1_snd_device) {
279 DBG("platform device allocation failed\n");
280 ret = -ENOMEM;
281 goto fail_io_unmap;
282 }
283
284 platform_set_drvdata(eti_b1_snd_device, &eti_b1_snd_devdata);
285 eti_b1_snd_devdata.dev = &eti_b1_snd_device->dev;
286
287 ret = platform_device_add(eti_b1_snd_device);
288 if (ret) {
289 DBG("platform device add failed\n");
290 platform_device_put(eti_b1_snd_device);
291 goto fail_io_unmap;
292 }
293
294 at91_set_A_periph(AT91_PIN_PB6, 0); /* TF1 */
295 at91_set_A_periph(AT91_PIN_PB7, 0); /* TK1 */
296 at91_set_A_periph(AT91_PIN_PB8, 0); /* TD1 */
297 at91_set_A_periph(AT91_PIN_PB9, 0); /* RD1 */
298/* at91_set_A_periph(AT91_PIN_PB10, 0);*/ /* RK1 */
299 at91_set_A_periph(AT91_PIN_PB11, 0); /* RF1 */
300
301 /*
302 * Set PCK1 parent to PLLB and its rate to 12 Mhz.
303 */
304 pllb_clk = clk_get(NULL, "pllb");
305 pck1_clk = clk_get(NULL, "pck1");
306
307 clk_set_parent(pck1_clk, pllb_clk);
308 clk_set_rate(pck1_clk, 12000000);
309
310 DBG("MCLK rate %luHz\n", clk_get_rate(pck1_clk));
311
312 /* assign the GPIO pin to PCK1 */
313 at91_set_B_periph(AT91_PIN_PA24, 0);
314
315#ifdef CONFIG_SND_AT91_SOC_ETI_SLAVE
316 printk(KERN_INFO "eti_b1_wm8731: Codec in Slave Mode\n");
317#else
318 printk(KERN_INFO "eti_b1_wm8731: Codec in Master Mode\n");
319#endif
320 return ret;
321
322fail_io_unmap:
323 iounmap(ssc->base);
324fail_release_mem:
325 release_mem_region(AT91RM9200_BASE_SSC1, SZ_16K);
326 return ret;
327}
328
329static void __exit eti_b1_exit(void)
330{
331 struct at91_ssc_periph *ssc = eti_b1_dai.cpu_dai->private_data;
332
333 clk_put(pck1_clk);
334 clk_put(pllb_clk);
335
336 platform_device_unregister(eti_b1_snd_device);
337
338 iounmap(ssc->base);
339 release_mem_region(AT91RM9200_BASE_SSC1, SZ_16K);
340}
341
342module_init(eti_b1_init);
343module_exit(eti_b1_exit);
344
345/* Module information */
346MODULE_AUTHOR("Frank Mandarino <fmandarino@endrelia.com>");
347MODULE_DESCRIPTION("ALSA SoC ETI-B1-WM8731");
348MODULE_LICENSE("GPL");
diff --git a/sound/soc/blackfin/Kconfig b/sound/soc/blackfin/Kconfig
new file mode 100644
index 000000000000..dc006206f622
--- /dev/null
+++ b/sound/soc/blackfin/Kconfig
@@ -0,0 +1,101 @@
1config SND_BF5XX_I2S
2 tristate "SoC I2S Audio for the ADI BF5xx chip"
3 depends on BLACKFIN && SND_SOC
4 help
5 Say Y or M if you want to add support for codecs attached to
6 the Blackfin SPORT (synchronous serial ports) interface in I2S
7 mode (supports single stereo In/Out).
8 You will also need to select the audio interfaces to support below.
9
10config SND_BF5XX_SOC_SSM2602
11 tristate "SoC SSM2602 Audio support for BF52x ezkit"
12 depends on SND_BF5XX_I2S
13 select SND_BF5XX_SOC_I2S
14 select SND_SOC_SSM2602
15 select I2C
16 select I2C_BLACKFIN_TWI
17 help
18 Say Y if you want to add support for SoC audio on BF527-EZKIT.
19
20config SND_BF5XX_SOC_AD73311
21 tristate "SoC AD73311 Audio support for Blackfin"
22 depends on SND_BF5XX_I2S
23 select SND_BF5XX_SOC_I2S
24 select SND_SOC_AD73311
25 help
26 Say Y if you want to add support for AD73311 codec on Blackfin.
27
28config SND_BFIN_AD73311_SE
29 int "PF pin for AD73311L Chip Select"
30 depends on SND_BF5XX_SOC_AD73311
31 default 4
32 help
33 Enter the GPIO used to control AD73311's SE pin. Acceptable
34 values are 0 to 7
35
36config SND_BF5XX_AC97
37 tristate "SoC AC97 Audio for the ADI BF5xx chip"
38 depends on BLACKFIN && SND_SOC
39 help
40 Say Y or M if you want to add support for codecs attached to
41 the Blackfin SPORT (synchronous serial ports) interface in slot 16
42 mode (pseudo AC97 interface).
43 You will also need to select the audio interfaces to support below.
44
45 Note:
46 AC97 codecs which do not implment the slot-16 mode will not function
47 properly with this driver. This driver is known to work with the
48 Analog Devices line of AC97 codecs.
49
50config SND_MMAP_SUPPORT
51 bool "Enable MMAP Support"
52 depends on SND_BF5XX_AC97
53 default y
54 help
55 Say y if you want AC97 driver to support mmap mode.
56 We introduce an intermediate buffer to simulate mmap.
57
58config SND_BF5XX_SOC_SPORT
59 tristate
60
61config SND_BF5XX_SOC_I2S
62 tristate
63 select SND_BF5XX_SOC_SPORT
64
65config SND_BF5XX_SOC_AC97
66 tristate
67 select AC97_BUS
68 select SND_SOC_AC97_BUS
69 select SND_BF5XX_SOC_SPORT
70
71config SND_BF5XX_SOC_AD1980
72 tristate "SoC AD1980/1 Audio support for BF5xx"
73 depends on SND_BF5XX_AC97
74 select SND_BF5XX_SOC_AC97
75 select SND_SOC_AD1980
76 help
77 Say Y if you want to add support for SoC audio on BF5xx STAMP/EZKIT.
78
79config SND_BF5XX_SPORT_NUM
80 int "Set a SPORT for Sound chip"
81 depends on (SND_BF5XX_I2S || SND_BF5XX_AC97)
82 range 0 3 if BF54x
83 range 0 1 if (BF53x || BF561)
84 default 0
85 help
86 Set the correct SPORT for sound chip.
87
88config SND_BF5XX_HAVE_COLD_RESET
89 bool "BOARD has COLD Reset GPIO"
90 depends on SND_BF5XX_AC97
91 default y if BFIN548_EZKIT
92 default n if !BFIN548_EZKIT
93
94config SND_BF5XX_RESET_GPIO_NUM
95 int "Set a GPIO for cold reset"
96 depends on SND_BF5XX_HAVE_COLD_RESET
97 range 0 159
98 default 19 if BFIN548_EZKIT
99 default 5 if BFIN537_STAMP
100 help
101 Set the correct GPIO for RESET the sound chip.
diff --git a/sound/soc/blackfin/Makefile b/sound/soc/blackfin/Makefile
new file mode 100644
index 000000000000..97bb37a6359c
--- /dev/null
+++ b/sound/soc/blackfin/Makefile
@@ -0,0 +1,21 @@
1# Blackfin Platform Support
2snd-bf5xx-ac97-objs := bf5xx-ac97-pcm.o
3snd-bf5xx-i2s-objs := bf5xx-i2s-pcm.o
4snd-soc-bf5xx-sport-objs := bf5xx-sport.o
5snd-soc-bf5xx-ac97-objs := bf5xx-ac97.o
6snd-soc-bf5xx-i2s-objs := bf5xx-i2s.o
7
8obj-$(CONFIG_SND_BF5XX_AC97) += snd-bf5xx-ac97.o
9obj-$(CONFIG_SND_BF5XX_I2S) += snd-bf5xx-i2s.o
10obj-$(CONFIG_SND_BF5XX_SOC_SPORT) += snd-soc-bf5xx-sport.o
11obj-$(CONFIG_SND_BF5XX_SOC_AC97) += snd-soc-bf5xx-ac97.o
12obj-$(CONFIG_SND_BF5XX_SOC_I2S) += snd-soc-bf5xx-i2s.o
13
14# Blackfin Machine Support
15snd-ad1980-objs := bf5xx-ad1980.o
16snd-ssm2602-objs := bf5xx-ssm2602.o
17snd-ad73311-objs := bf5xx-ad73311.o
18
19obj-$(CONFIG_SND_BF5XX_SOC_AD1980) += snd-ad1980.o
20obj-$(CONFIG_SND_BF5XX_SOC_SSM2602) += snd-ssm2602.o
21obj-$(CONFIG_SND_BF5XX_SOC_AD73311) += snd-ad73311.o
diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.c b/sound/soc/blackfin/bf5xx-ac97-pcm.c
new file mode 100644
index 000000000000..25e50d2ea1ec
--- /dev/null
+++ b/sound/soc/blackfin/bf5xx-ac97-pcm.c
@@ -0,0 +1,457 @@
1/*
2 * File: sound/soc/blackfin/bf5xx-ac97-pcm.c
3 * Author: Cliff Cai <Cliff.Cai@analog.com>
4 *
5 * Created: Tue June 06 2008
6 * Description: DMA Driver for AC97 sound chip
7 *
8 * Modified:
9 * Copyright 2008 Analog Devices Inc.
10 *
11 * Bugs: Enter bugs at http://blackfin.uclinux.org/
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see the file COPYING, or write
25 * to the Free Software Foundation, Inc.,
26 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 */
28
29#include <linux/module.h>
30#include <linux/init.h>
31#include <linux/platform_device.h>
32#include <linux/slab.h>
33#include <linux/dma-mapping.h>
34
35#include <sound/core.h>
36#include <sound/pcm.h>
37#include <sound/pcm_params.h>
38#include <sound/soc.h>
39
40#include <asm/dma.h>
41
42#include "bf5xx-ac97-pcm.h"
43#include "bf5xx-ac97.h"
44#include "bf5xx-sport.h"
45
46#if defined(CONFIG_SND_MMAP_SUPPORT)
47static void bf5xx_mmap_copy(struct snd_pcm_substream *substream,
48 snd_pcm_uframes_t count)
49{
50 struct snd_pcm_runtime *runtime = substream->runtime;
51 struct sport_device *sport = runtime->private_data;
52 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
53 bf5xx_pcm_to_ac97(
54 (struct ac97_frame *)sport->tx_dma_buf + sport->tx_pos,
55 (__u32 *)runtime->dma_area + sport->tx_pos, count);
56 sport->tx_pos += runtime->period_size;
57 if (sport->tx_pos >= runtime->buffer_size)
58 sport->tx_pos %= runtime->buffer_size;
59 sport->tx_delay_pos = sport->tx_pos;
60 } else {
61 bf5xx_ac97_to_pcm(
62 (struct ac97_frame *)sport->rx_dma_buf + sport->rx_pos,
63 (__u32 *)runtime->dma_area + sport->rx_pos, count);
64 sport->rx_pos += runtime->period_size;
65 if (sport->rx_pos >= runtime->buffer_size)
66 sport->rx_pos %= runtime->buffer_size;
67 }
68}
69#endif
70
71static void bf5xx_dma_irq(void *data)
72{
73 struct snd_pcm_substream *pcm = data;
74#if defined(CONFIG_SND_MMAP_SUPPORT)
75 struct snd_pcm_runtime *runtime = pcm->runtime;
76 struct sport_device *sport = runtime->private_data;
77 bf5xx_mmap_copy(pcm, runtime->period_size);
78 if (pcm->stream == SNDRV_PCM_STREAM_PLAYBACK) {
79 if (sport->once == 0) {
80 snd_pcm_period_elapsed(pcm);
81 bf5xx_mmap_copy(pcm, runtime->period_size);
82 sport->once = 1;
83 }
84 }
85#endif
86 snd_pcm_period_elapsed(pcm);
87}
88
89/* The memory size for pure pcm data is 128*1024 = 0x20000 bytes.
90 * The total rx/tx buffer is for ac97 frame to hold all pcm data
91 * is 0x20000 * sizeof(struct ac97_frame) / 4.
92 */
93#ifdef CONFIG_SND_MMAP_SUPPORT
94static const struct snd_pcm_hardware bf5xx_pcm_hardware = {
95 .info = SNDRV_PCM_INFO_INTERLEAVED |
96 SNDRV_PCM_INFO_MMAP |
97 SNDRV_PCM_INFO_MMAP_VALID |
98 SNDRV_PCM_INFO_BLOCK_TRANSFER,
99#else
100static const struct snd_pcm_hardware bf5xx_pcm_hardware = {
101 .info = SNDRV_PCM_INFO_INTERLEAVED |
102 SNDRV_PCM_INFO_BLOCK_TRANSFER,
103#endif
104 .formats = SNDRV_PCM_FMTBIT_S16_LE,
105 .period_bytes_min = 32,
106 .period_bytes_max = 0x10000,
107 .periods_min = 1,
108 .periods_max = PAGE_SIZE/32,
109 .buffer_bytes_max = 0x20000, /* 128 kbytes */
110 .fifo_size = 16,
111};
112
113static int bf5xx_pcm_hw_params(struct snd_pcm_substream *substream,
114 struct snd_pcm_hw_params *params)
115{
116 size_t size = bf5xx_pcm_hardware.buffer_bytes_max
117 * sizeof(struct ac97_frame) / 4;
118
119 snd_pcm_lib_malloc_pages(substream, size);
120
121 return 0;
122}
123
124static int bf5xx_pcm_hw_free(struct snd_pcm_substream *substream)
125{
126 struct snd_pcm_runtime *runtime = substream->runtime;
127
128 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
129 memset(runtime->dma_area, 0, runtime->buffer_size);
130 snd_pcm_lib_free_pages(substream);
131 return 0;
132}
133
134static int bf5xx_pcm_prepare(struct snd_pcm_substream *substream)
135{
136 struct snd_pcm_runtime *runtime = substream->runtime;
137 struct sport_device *sport = runtime->private_data;
138
139 /* An intermediate buffer is introduced for implementing mmap for
140 * SPORT working in TMD mode(include AC97).
141 */
142#if defined(CONFIG_SND_MMAP_SUPPORT)
143 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
144 sport_set_tx_callback(sport, bf5xx_dma_irq, substream);
145 sport_config_tx_dma(sport, sport->tx_dma_buf, runtime->periods,
146 runtime->period_size * sizeof(struct ac97_frame));
147 } else {
148 sport_set_rx_callback(sport, bf5xx_dma_irq, substream);
149 sport_config_rx_dma(sport, sport->rx_dma_buf, runtime->periods,
150 runtime->period_size * sizeof(struct ac97_frame));
151 }
152#else
153 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
154 sport_set_tx_callback(sport, bf5xx_dma_irq, substream);
155 sport_config_tx_dma(sport, runtime->dma_area, runtime->periods,
156 runtime->period_size * sizeof(struct ac97_frame));
157 } else {
158 sport_set_rx_callback(sport, bf5xx_dma_irq, substream);
159 sport_config_rx_dma(sport, runtime->dma_area, runtime->periods,
160 runtime->period_size * sizeof(struct ac97_frame));
161 }
162#endif
163 return 0;
164}
165
166static int bf5xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
167{
168 struct snd_pcm_runtime *runtime = substream->runtime;
169 struct sport_device *sport = runtime->private_data;
170 int ret = 0;
171
172 pr_debug("%s enter\n", __func__);
173 switch (cmd) {
174 case SNDRV_PCM_TRIGGER_START:
175 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
176 bf5xx_mmap_copy(substream, runtime->period_size);
177 snd_pcm_period_elapsed(substream);
178 sport->tx_delay_pos = 0;
179 sport_tx_start(sport);
180 }
181 else
182 sport_rx_start(sport);
183 break;
184 case SNDRV_PCM_TRIGGER_STOP:
185 case SNDRV_PCM_TRIGGER_SUSPEND:
186 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
187 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
188#if defined(CONFIG_SND_MMAP_SUPPORT)
189 sport->tx_pos = 0;
190#endif
191 sport_tx_stop(sport);
192 } else {
193#if defined(CONFIG_SND_MMAP_SUPPORT)
194 sport->rx_pos = 0;
195#endif
196 sport_rx_stop(sport);
197 }
198 break;
199 default:
200 ret = -EINVAL;
201 }
202 return ret;
203}
204
205static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream)
206{
207 struct snd_pcm_runtime *runtime = substream->runtime;
208 struct sport_device *sport = runtime->private_data;
209 unsigned int curr;
210
211#if defined(CONFIG_SND_MMAP_SUPPORT)
212 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
213 curr = sport->tx_delay_pos;
214 else
215 curr = sport->rx_pos;
216#else
217
218 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
219 curr = sport_curr_offset_tx(sport) / sizeof(struct ac97_frame);
220 else
221 curr = sport_curr_offset_rx(sport) / sizeof(struct ac97_frame);
222
223#endif
224 return curr;
225}
226
227static int bf5xx_pcm_open(struct snd_pcm_substream *substream)
228{
229 struct snd_pcm_runtime *runtime = substream->runtime;
230 int ret;
231
232 pr_debug("%s enter\n", __func__);
233 snd_soc_set_runtime_hwparams(substream, &bf5xx_pcm_hardware);
234
235 ret = snd_pcm_hw_constraint_integer(runtime,
236 SNDRV_PCM_HW_PARAM_PERIODS);
237 if (ret < 0)
238 goto out;
239
240 if (sport_handle != NULL)
241 runtime->private_data = sport_handle;
242 else {
243 pr_err("sport_handle is NULL\n");
244 return -1;
245 }
246 return 0;
247
248 out:
249 return ret;
250}
251
252static int bf5xx_pcm_close(struct snd_pcm_substream *substream)
253{
254 struct snd_pcm_runtime *runtime = substream->runtime;
255 struct sport_device *sport = runtime->private_data;
256
257 pr_debug("%s enter\n", __func__);
258 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
259 sport->once = 0;
260 memset(sport->tx_dma_buf, 0, runtime->buffer_size * sizeof(struct ac97_frame));
261 } else
262 memset(sport->rx_dma_buf, 0, runtime->buffer_size * sizeof(struct ac97_frame));
263
264 return 0;
265}
266
267#ifdef CONFIG_SND_MMAP_SUPPORT
268static int bf5xx_pcm_mmap(struct snd_pcm_substream *substream,
269 struct vm_area_struct *vma)
270{
271 struct snd_pcm_runtime *runtime = substream->runtime;
272 size_t size = vma->vm_end - vma->vm_start;
273 vma->vm_start = (unsigned long)runtime->dma_area;
274 vma->vm_end = vma->vm_start + size;
275 vma->vm_flags |= VM_SHARED;
276 return 0 ;
277}
278#else
279static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel,
280 snd_pcm_uframes_t pos,
281 void __user *buf, snd_pcm_uframes_t count)
282{
283 struct snd_pcm_runtime *runtime = substream->runtime;
284
285 pr_debug("%s copy pos:0x%lx count:0x%lx\n",
286 substream->stream ? "Capture" : "Playback", pos, count);
287
288 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
289 bf5xx_pcm_to_ac97(
290 (struct ac97_frame *)runtime->dma_area + pos,
291 buf, count);
292 else
293 bf5xx_ac97_to_pcm(
294 (struct ac97_frame *)runtime->dma_area + pos,
295 buf, count);
296 return 0;
297}
298#endif
299
300struct snd_pcm_ops bf5xx_pcm_ac97_ops = {
301 .open = bf5xx_pcm_open,
302 .close = bf5xx_pcm_close,
303 .ioctl = snd_pcm_lib_ioctl,
304 .hw_params = bf5xx_pcm_hw_params,
305 .hw_free = bf5xx_pcm_hw_free,
306 .prepare = bf5xx_pcm_prepare,
307 .trigger = bf5xx_pcm_trigger,
308 .pointer = bf5xx_pcm_pointer,
309#ifdef CONFIG_SND_MMAP_SUPPORT
310 .mmap = bf5xx_pcm_mmap,
311#else
312 .copy = bf5xx_pcm_copy,
313#endif
314};
315
316static int bf5xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
317{
318 struct snd_pcm_substream *substream = pcm->streams[stream].substream;
319 struct snd_dma_buffer *buf = &substream->dma_buffer;
320 size_t size = bf5xx_pcm_hardware.buffer_bytes_max
321 * sizeof(struct ac97_frame) / 4;
322
323 buf->dev.type = SNDRV_DMA_TYPE_DEV;
324 buf->dev.dev = pcm->card->dev;
325 buf->private_data = NULL;
326 buf->area = dma_alloc_coherent(pcm->card->dev, size,
327 &buf->addr, GFP_KERNEL);
328 if (!buf->area) {
329 pr_err("Failed to allocate dma memory\n");
330 pr_err("Please increase uncached DMA memory region\n");
331 return -ENOMEM;
332 }
333 buf->bytes = size;
334
335 pr_debug("%s, area:%p, size:0x%08lx\n", __func__,
336 buf->area, buf->bytes);
337
338 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
339 sport_handle->tx_buf = buf->area;
340 else
341 sport_handle->rx_buf = buf->area;
342
343/*
344 * Need to allocate local buffer when enable
345 * MMAP for SPORT working in TMD mode (include AC97).
346 */
347#if defined(CONFIG_SND_MMAP_SUPPORT)
348 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
349 if (!sport_handle->tx_dma_buf) {
350 sport_handle->tx_dma_buf = dma_alloc_coherent(NULL, \
351 size, &sport_handle->tx_dma_phy, GFP_KERNEL);
352 if (!sport_handle->tx_dma_buf) {
353 pr_err("Failed to allocate memory for tx dma \
354 buf - Please increase uncached DMA \
355 memory region\n");
356 return -ENOMEM;
357 } else
358 memset(sport_handle->tx_dma_buf, 0, size);
359 } else
360 memset(sport_handle->tx_dma_buf, 0, size);
361 } else {
362 if (!sport_handle->rx_dma_buf) {
363 sport_handle->rx_dma_buf = dma_alloc_coherent(NULL, \
364 size, &sport_handle->rx_dma_phy, GFP_KERNEL);
365 if (!sport_handle->rx_dma_buf) {
366 pr_err("Failed to allocate memory for rx dma \
367 buf - Please increase uncached DMA \
368 memory region\n");
369 return -ENOMEM;
370 } else
371 memset(sport_handle->rx_dma_buf, 0, size);
372 } else
373 memset(sport_handle->rx_dma_buf, 0, size);
374 }
375#endif
376 return 0;
377}
378
379static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
380{
381 struct snd_pcm_substream *substream;
382 struct snd_dma_buffer *buf;
383 int stream;
384#if defined(CONFIG_SND_MMAP_SUPPORT)
385 size_t size = bf5xx_pcm_hardware.buffer_bytes_max *
386 sizeof(struct ac97_frame) / 4;
387#endif
388 for (stream = 0; stream < 2; stream++) {
389 substream = pcm->streams[stream].substream;
390 if (!substream)
391 continue;
392
393 buf = &substream->dma_buffer;
394 if (!buf->area)
395 continue;
396 dma_free_coherent(NULL, buf->bytes, buf->area, 0);
397 buf->area = NULL;
398#if defined(CONFIG_SND_MMAP_SUPPORT)
399 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
400 if (sport_handle->tx_dma_buf)
401 dma_free_coherent(NULL, size, \
402 sport_handle->tx_dma_buf, 0);
403 sport_handle->tx_dma_buf = NULL;
404 } else {
405
406 if (sport_handle->rx_dma_buf)
407 dma_free_coherent(NULL, size, \
408 sport_handle->rx_dma_buf, 0);
409 sport_handle->rx_dma_buf = NULL;
410 }
411#endif
412 }
413 if (sport_handle)
414 sport_done(sport_handle);
415}
416
417static u64 bf5xx_pcm_dmamask = DMA_32BIT_MASK;
418
419int bf5xx_pcm_ac97_new(struct snd_card *card, struct snd_soc_dai *dai,
420 struct snd_pcm *pcm)
421{
422 int ret = 0;
423
424 pr_debug("%s enter\n", __func__);
425 if (!card->dev->dma_mask)
426 card->dev->dma_mask = &bf5xx_pcm_dmamask;
427 if (!card->dev->coherent_dma_mask)
428 card->dev->coherent_dma_mask = DMA_32BIT_MASK;
429
430 if (dai->playback.channels_min) {
431 ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
432 SNDRV_PCM_STREAM_PLAYBACK);
433 if (ret)
434 goto out;
435 }
436
437 if (dai->capture.channels_min) {
438 ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
439 SNDRV_PCM_STREAM_CAPTURE);
440 if (ret)
441 goto out;
442 }
443 out:
444 return ret;
445}
446
447struct snd_soc_platform bf5xx_ac97_soc_platform = {
448 .name = "bf5xx-audio",
449 .pcm_ops = &bf5xx_pcm_ac97_ops,
450 .pcm_new = bf5xx_pcm_ac97_new,
451 .pcm_free = bf5xx_pcm_free_dma_buffers,
452};
453EXPORT_SYMBOL_GPL(bf5xx_ac97_soc_platform);
454
455MODULE_AUTHOR("Cliff Cai");
456MODULE_DESCRIPTION("ADI Blackfin AC97 PCM DMA module");
457MODULE_LICENSE("GPL");
diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.h b/sound/soc/blackfin/bf5xx-ac97-pcm.h
new file mode 100644
index 000000000000..350125a0ae21
--- /dev/null
+++ b/sound/soc/blackfin/bf5xx-ac97-pcm.h
@@ -0,0 +1,29 @@
1/*
2 * linux/sound/arm/bf5xx-ac97-pcm.h -- ALSA PCM interface for the Blackfin
3 *
4 * Copyright 2007 Analog Device Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#ifndef _BF5XX_AC97_PCM_H
12#define _BF5XX_AC97_PCM_H
13
14struct bf5xx_pcm_dma_params {
15 char *name; /* stream identifier */
16};
17
18struct bf5xx_gpio {
19 u32 sys;
20 u32 rx;
21 u32 tx;
22 u32 clk;
23 u32 frm;
24};
25
26/* platform data */
27extern struct snd_soc_platform bf5xx_ac97_soc_platform;
28
29#endif
diff --git a/sound/soc/blackfin/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c
new file mode 100644
index 000000000000..5e5aafb6485f
--- /dev/null
+++ b/sound/soc/blackfin/bf5xx-ac97.c
@@ -0,0 +1,406 @@
1/*
2 * bf5xx-ac97.c -- AC97 support for the ADI blackfin chip.
3 *
4 * Author: Roy Huang
5 * Created: 11th. June 2007
6 * Copyright: Analog Device Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/init.h>
14#include <linux/module.h>
15#include <linux/platform_device.h>
16#include <linux/interrupt.h>
17#include <linux/wait.h>
18#include <linux/delay.h>
19
20#include <sound/core.h>
21#include <sound/pcm.h>
22#include <sound/ac97_codec.h>
23#include <sound/initval.h>
24#include <sound/soc.h>
25
26#include <asm/irq.h>
27#include <asm/portmux.h>
28#include <linux/mutex.h>
29#include <linux/gpio.h>
30
31#include "bf5xx-sport.h"
32#include "bf5xx-ac97.h"
33
34#if defined(CONFIG_BF54x)
35#define PIN_REQ_SPORT_0 {P_SPORT0_TFS, P_SPORT0_DTPRI, P_SPORT0_TSCLK, \
36 P_SPORT0_RFS, P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0}
37
38#define PIN_REQ_SPORT_1 {P_SPORT1_TFS, P_SPORT1_DTPRI, P_SPORT1_TSCLK, \
39 P_SPORT1_RFS, P_SPORT1_DRPRI, P_SPORT1_RSCLK, 0}
40
41#define PIN_REQ_SPORT_2 {P_SPORT2_TFS, P_SPORT2_DTPRI, P_SPORT2_TSCLK, \
42 P_SPORT2_RFS, P_SPORT2_DRPRI, P_SPORT2_RSCLK, 0}
43
44#define PIN_REQ_SPORT_3 {P_SPORT3_TFS, P_SPORT3_DTPRI, P_SPORT3_TSCLK, \
45 P_SPORT3_RFS, P_SPORT3_DRPRI, P_SPORT3_RSCLK, 0}
46#else
47#define PIN_REQ_SPORT_0 {P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS, \
48 P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0}
49
50#define PIN_REQ_SPORT_1 {P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS, \
51 P_SPORT1_DRPRI, P_SPORT1_RSCLK, 0}
52#endif
53
54static int *cmd_count;
55static int sport_num = CONFIG_SND_BF5XX_SPORT_NUM;
56
57#if defined(CONFIG_BF54x)
58static struct sport_param sport_params[4] = {
59 {
60 .dma_rx_chan = CH_SPORT0_RX,
61 .dma_tx_chan = CH_SPORT0_TX,
62 .err_irq = IRQ_SPORT0_ERR,
63 .regs = (struct sport_register *)SPORT0_TCR1,
64 },
65 {
66 .dma_rx_chan = CH_SPORT1_RX,
67 .dma_tx_chan = CH_SPORT1_TX,
68 .err_irq = IRQ_SPORT1_ERR,
69 .regs = (struct sport_register *)SPORT1_TCR1,
70 },
71 {
72 .dma_rx_chan = CH_SPORT2_RX,
73 .dma_tx_chan = CH_SPORT2_TX,
74 .err_irq = IRQ_SPORT2_ERR,
75 .regs = (struct sport_register *)SPORT2_TCR1,
76 },
77 {
78 .dma_rx_chan = CH_SPORT3_RX,
79 .dma_tx_chan = CH_SPORT3_TX,
80 .err_irq = IRQ_SPORT3_ERR,
81 .regs = (struct sport_register *)SPORT3_TCR1,
82 }
83};
84#else
85static struct sport_param sport_params[2] = {
86 {
87 .dma_rx_chan = CH_SPORT0_RX,
88 .dma_tx_chan = CH_SPORT0_TX,
89 .err_irq = IRQ_SPORT0_ERROR,
90 .regs = (struct sport_register *)SPORT0_TCR1,
91 },
92 {
93 .dma_rx_chan = CH_SPORT1_RX,
94 .dma_tx_chan = CH_SPORT1_TX,
95 .err_irq = IRQ_SPORT1_ERROR,
96 .regs = (struct sport_register *)SPORT1_TCR1,
97 }
98};
99#endif
100
101void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u32 *src, \
102 size_t count)
103{
104 while (count--) {
105 dst->ac97_tag = TAG_VALID | TAG_PCM;
106 (dst++)->ac97_pcm = *src++;
107 }
108}
109EXPORT_SYMBOL(bf5xx_pcm_to_ac97);
110
111void bf5xx_ac97_to_pcm(const struct ac97_frame *src, __u32 *dst, \
112 size_t count)
113{
114 while (count--)
115 *(dst++) = (src++)->ac97_pcm;
116}
117EXPORT_SYMBOL(bf5xx_ac97_to_pcm);
118
119static unsigned int sport_tx_curr_frag(struct sport_device *sport)
120{
121 return sport->tx_curr_frag = sport_curr_offset_tx(sport) / \
122 sport->tx_fragsize;
123}
124
125static void enqueue_cmd(struct snd_ac97 *ac97, __u16 addr, __u16 data)
126{
127 struct sport_device *sport = sport_handle;
128 int nextfrag = sport_tx_curr_frag(sport);
129 struct ac97_frame *nextwrite;
130
131 sport_incfrag(sport, &nextfrag, 1);
132
133 nextwrite = (struct ac97_frame *)(sport->tx_buf + \
134 nextfrag * sport->tx_fragsize);
135 pr_debug("sport->tx_buf:%p, nextfrag:0x%x nextwrite:%p, cmd_count:%d\n",
136 sport->tx_buf, nextfrag, nextwrite, cmd_count[nextfrag]);
137 nextwrite[cmd_count[nextfrag]].ac97_tag |= TAG_CMD;
138 nextwrite[cmd_count[nextfrag]].ac97_addr = addr;
139 nextwrite[cmd_count[nextfrag]].ac97_data = data;
140 ++cmd_count[nextfrag];
141 pr_debug("ac97_sport: Inserting %02x/%04x into fragment %d\n",
142 addr >> 8, data, nextfrag);
143}
144
145static unsigned short bf5xx_ac97_read(struct snd_ac97 *ac97,
146 unsigned short reg)
147{
148 struct ac97_frame out_frame[2], in_frame[2];
149
150 pr_debug("%s enter 0x%x\n", __func__, reg);
151
152 /* When dma descriptor is enabled, the register should not be read */
153 if (sport_handle->tx_run || sport_handle->rx_run) {
154 pr_err("Could you send a mail to cliff.cai@analog.com "
155 "to report this?\n");
156 return -EFAULT;
157 }
158
159 memset(&out_frame, 0, 2 * sizeof(struct ac97_frame));
160 memset(&in_frame, 0, 2 * sizeof(struct ac97_frame));
161 out_frame[0].ac97_tag = TAG_VALID | TAG_CMD;
162 out_frame[0].ac97_addr = ((reg << 8) | 0x8000);
163 sport_send_and_recv(sport_handle, (unsigned char *)&out_frame,
164 (unsigned char *)&in_frame,
165 2 * sizeof(struct ac97_frame));
166 return in_frame[1].ac97_data;
167}
168
169void bf5xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
170 unsigned short val)
171{
172 pr_debug("%s enter 0x%x:0x%04x\n", __func__, reg, val);
173
174 if (sport_handle->tx_run) {
175 enqueue_cmd(ac97, (reg << 8), val); /* write */
176 enqueue_cmd(ac97, (reg << 8) | 0x8000, 0); /* read back */
177 } else {
178 struct ac97_frame frame;
179 memset(&frame, 0, sizeof(struct ac97_frame));
180 frame.ac97_tag = TAG_VALID | TAG_CMD;
181 frame.ac97_addr = (reg << 8);
182 frame.ac97_data = val;
183 sport_send_and_recv(sport_handle, (unsigned char *)&frame, \
184 NULL, sizeof(struct ac97_frame));
185 }
186}
187
188static void bf5xx_ac97_warm_reset(struct snd_ac97 *ac97)
189{
190#if defined(CONFIG_BF54x) || defined(CONFIG_BF561) || \
191 (defined(BF537_FAMILY) && (CONFIG_SND_BF5XX_SPORT_NUM == 1))
192
193#define CONCAT(a, b, c) a ## b ## c
194#define BFIN_SPORT_RFS(x) CONCAT(P_SPORT, x, _RFS)
195
196 u16 per = BFIN_SPORT_RFS(CONFIG_SND_BF5XX_SPORT_NUM);
197 u16 gpio = P_IDENT(BFIN_SPORT_RFS(CONFIG_SND_BF5XX_SPORT_NUM));
198
199 pr_debug("%s enter\n", __func__);
200
201 peripheral_free(per);
202 gpio_request(gpio, "bf5xx-ac97");
203 gpio_direction_output(gpio, 1);
204 udelay(2);
205 gpio_set_value(gpio, 0);
206 udelay(1);
207 gpio_free(gpio);
208 peripheral_request(per, "soc-audio");
209#else
210 pr_info("%s: Not implemented\n", __func__);
211#endif
212}
213
214static void bf5xx_ac97_cold_reset(struct snd_ac97 *ac97)
215{
216#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
217 pr_debug("%s enter\n", __func__);
218
219 /* It is specified for bf548-ezkit */
220 gpio_set_value(CONFIG_SND_BF5XX_RESET_GPIO_NUM, 0);
221 /* Keep reset pin low for 1 ms */
222 mdelay(1);
223 gpio_set_value(CONFIG_SND_BF5XX_RESET_GPIO_NUM, 1);
224 /* Wait for bit clock recover */
225 mdelay(1);
226#else
227 pr_info("%s: Not implemented\n", __func__);
228#endif
229}
230
231struct snd_ac97_bus_ops soc_ac97_ops = {
232 .read = bf5xx_ac97_read,
233 .write = bf5xx_ac97_write,
234 .warm_reset = bf5xx_ac97_warm_reset,
235 .reset = bf5xx_ac97_cold_reset,
236};
237EXPORT_SYMBOL_GPL(soc_ac97_ops);
238
239#ifdef CONFIG_PM
240static int bf5xx_ac97_suspend(struct platform_device *pdev,
241 struct snd_soc_dai *dai)
242{
243 struct sport_device *sport =
244 (struct sport_device *)dai->private_data;
245
246 pr_debug("%s : sport %d\n", __func__, dai->id);
247 if (!dai->active)
248 return 0;
249 if (dai->capture.active)
250 sport_rx_stop(sport);
251 if (dai->playback.active)
252 sport_tx_stop(sport);
253 return 0;
254}
255
256static int bf5xx_ac97_resume(struct platform_device *pdev,
257 struct snd_soc_dai *dai)
258{
259 int ret;
260 struct sport_device *sport =
261 (struct sport_device *)dai->private_data;
262
263 pr_debug("%s : sport %d\n", __func__, dai->id);
264 if (!dai->active)
265 return 0;
266
267 ret = sport_set_multichannel(sport_handle, 16, 0x1F, 1);
268 if (ret) {
269 pr_err("SPORT is busy!\n");
270 return -EBUSY;
271 }
272
273 ret = sport_config_rx(sport_handle, IRFS, 0xF, 0, (16*16-1));
274 if (ret) {
275 pr_err("SPORT is busy!\n");
276 return -EBUSY;
277 }
278
279 ret = sport_config_tx(sport_handle, ITFS, 0xF, 0, (16*16-1));
280 if (ret) {
281 pr_err("SPORT is busy!\n");
282 return -EBUSY;
283 }
284
285 if (dai->capture.active)
286 sport_rx_start(sport);
287 if (dai->playback.active)
288 sport_tx_start(sport);
289 return 0;
290}
291
292#else
293#define bf5xx_ac97_suspend NULL
294#define bf5xx_ac97_resume NULL
295#endif
296
297static int bf5xx_ac97_probe(struct platform_device *pdev,
298 struct snd_soc_dai *dai)
299{
300 int ret;
301#if defined(CONFIG_BF54x)
302 u16 sport_req[][7] = {PIN_REQ_SPORT_0, PIN_REQ_SPORT_1,
303 PIN_REQ_SPORT_2, PIN_REQ_SPORT_3};
304#else
305 u16 sport_req[][7] = {PIN_REQ_SPORT_0, PIN_REQ_SPORT_1};
306#endif
307 cmd_count = (int *)get_zeroed_page(GFP_KERNEL);
308 if (cmd_count == NULL)
309 return -ENOMEM;
310
311 if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) {
312 pr_err("Requesting Peripherals failed\n");
313 return -EFAULT;
314 }
315
316#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
317 /* Request PB3 as reset pin */
318 if (gpio_request(CONFIG_SND_BF5XX_RESET_GPIO_NUM, "SND_AD198x RESET")) {
319 pr_err("Failed to request GPIO_%d for reset\n",
320 CONFIG_SND_BF5XX_RESET_GPIO_NUM);
321 peripheral_free_list(&sport_req[sport_num][0]);
322 return -1;
323 }
324 gpio_direction_output(CONFIG_SND_BF5XX_RESET_GPIO_NUM, 1);
325#endif
326 sport_handle = sport_init(&sport_params[sport_num], 2, \
327 sizeof(struct ac97_frame), NULL);
328 if (!sport_handle) {
329 peripheral_free_list(&sport_req[sport_num][0]);
330#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
331 gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM);
332#endif
333 return -ENODEV;
334 }
335 /*SPORT works in TDM mode to simulate AC97 transfers*/
336 ret = sport_set_multichannel(sport_handle, 16, 0x1F, 1);
337 if (ret) {
338 pr_err("SPORT is busy!\n");
339 kfree(sport_handle);
340 peripheral_free_list(&sport_req[sport_num][0]);
341#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
342 gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM);
343#endif
344 return -EBUSY;
345 }
346
347 ret = sport_config_rx(sport_handle, IRFS, 0xF, 0, (16*16-1));
348 if (ret) {
349 pr_err("SPORT is busy!\n");
350 kfree(sport_handle);
351 peripheral_free_list(&sport_req[sport_num][0]);
352#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
353 gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM);
354#endif
355 return -EBUSY;
356 }
357
358 ret = sport_config_tx(sport_handle, ITFS, 0xF, 0, (16*16-1));
359 if (ret) {
360 pr_err("SPORT is busy!\n");
361 kfree(sport_handle);
362 peripheral_free_list(&sport_req[sport_num][0]);
363#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
364 gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM);
365#endif
366 return -EBUSY;
367 }
368 return 0;
369}
370
371static void bf5xx_ac97_remove(struct platform_device *pdev,
372 struct snd_soc_dai *dai)
373{
374 free_page((unsigned long)cmd_count);
375 cmd_count = NULL;
376#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
377 gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM);
378#endif
379}
380
381struct snd_soc_dai bfin_ac97_dai = {
382 .name = "bf5xx-ac97",
383 .id = 0,
384 .type = SND_SOC_DAI_AC97,
385 .probe = bf5xx_ac97_probe,
386 .remove = bf5xx_ac97_remove,
387 .suspend = bf5xx_ac97_suspend,
388 .resume = bf5xx_ac97_resume,
389 .playback = {
390 .stream_name = "AC97 Playback",
391 .channels_min = 2,
392 .channels_max = 2,
393 .rates = SNDRV_PCM_RATE_48000,
394 .formats = SNDRV_PCM_FMTBIT_S16_LE, },
395 .capture = {
396 .stream_name = "AC97 Capture",
397 .channels_min = 2,
398 .channels_max = 2,
399 .rates = SNDRV_PCM_RATE_48000,
400 .formats = SNDRV_PCM_FMTBIT_S16_LE, },
401};
402EXPORT_SYMBOL_GPL(bfin_ac97_dai);
403
404MODULE_AUTHOR("Roy Huang");
405MODULE_DESCRIPTION("AC97 driver for ADI Blackfin");
406MODULE_LICENSE("GPL");
diff --git a/sound/soc/blackfin/bf5xx-ac97.h b/sound/soc/blackfin/bf5xx-ac97.h
new file mode 100644
index 000000000000..3f77cc558dc0
--- /dev/null
+++ b/sound/soc/blackfin/bf5xx-ac97.h
@@ -0,0 +1,36 @@
1/*
2 * linux/sound/arm/bf5xx-ac97.h
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#ifndef _BF5XX_AC97_H
10#define _BF5XX_AC97_H
11
12extern struct snd_ac97_bus_ops bf5xx_ac97_ops;
13extern struct snd_ac97 *ac97;
14/* Frame format in memory, only support stereo currently */
15struct ac97_frame {
16 u16 ac97_tag; /* slot 0 */
17 u16 ac97_addr; /* slot 1 */
18 u16 ac97_data; /* slot 2 */
19 u32 ac97_pcm; /* slot 3 and 4: left and right pcm data */
20} __attribute__ ((packed));
21
22#define TAG_VALID 0x8000
23#define TAG_CMD 0x6000
24#define TAG_PCM_LEFT 0x1000
25#define TAG_PCM_RIGHT 0x0800
26#define TAG_PCM (TAG_PCM_LEFT | TAG_PCM_RIGHT)
27
28extern struct snd_soc_dai bfin_ac97_dai;
29
30void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u32 *src, \
31 size_t count);
32
33void bf5xx_ac97_to_pcm(const struct ac97_frame *src, __u32 *dst, \
34 size_t count);
35
36#endif
diff --git a/sound/soc/blackfin/bf5xx-ad1980.c b/sound/soc/blackfin/bf5xx-ad1980.c
new file mode 100644
index 000000000000..124425d22320
--- /dev/null
+++ b/sound/soc/blackfin/bf5xx-ad1980.c
@@ -0,0 +1,113 @@
1/*
2 * File: sound/soc/blackfin/bf5xx-ad1980.c
3 * Author: Cliff Cai <Cliff.Cai@analog.com>
4 *
5 * Created: Tue June 06 2008
6 * Description: Board driver for AD1980/1 audio codec
7 *
8 * Modified:
9 * Copyright 2008 Analog Devices Inc.
10 *
11 * Bugs: Enter bugs at http://blackfin.uclinux.org/
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see the file COPYING, or write
25 * to the Free Software Foundation, Inc.,
26 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 */
28
29#include <linux/module.h>
30#include <linux/moduleparam.h>
31#include <linux/device.h>
32#include <asm/dma.h>
33
34#include <sound/core.h>
35#include <sound/pcm.h>
36#include <sound/soc.h>
37
38#include <linux/gpio.h>
39#include <asm/portmux.h>
40
41#include "../codecs/ad1980.h"
42#include "bf5xx-sport.h"
43#include "bf5xx-ac97-pcm.h"
44#include "bf5xx-ac97.h"
45
46static struct snd_soc_machine bf5xx_board;
47
48static int bf5xx_board_startup(struct snd_pcm_substream *substream)
49{
50 struct snd_soc_pcm_runtime *rtd = substream->private_data;
51 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
52
53 pr_debug("%s enter\n", __func__);
54 cpu_dai->private_data = sport_handle;
55 return 0;
56}
57
58static struct snd_soc_ops bf5xx_board_ops = {
59 .startup = bf5xx_board_startup,
60};
61
62static struct snd_soc_dai_link bf5xx_board_dai = {
63 .name = "AC97",
64 .stream_name = "AC97 HiFi",
65 .cpu_dai = &bfin_ac97_dai,
66 .codec_dai = &ad1980_dai,
67 .ops = &bf5xx_board_ops,
68};
69
70static struct snd_soc_machine bf5xx_board = {
71 .name = "bf5xx-board",
72 .dai_link = &bf5xx_board_dai,
73 .num_links = 1,
74};
75
76static struct snd_soc_device bf5xx_board_snd_devdata = {
77 .machine = &bf5xx_board,
78 .platform = &bf5xx_ac97_soc_platform,
79 .codec_dev = &soc_codec_dev_ad1980,
80};
81
82static struct platform_device *bf5xx_board_snd_device;
83
84static int __init bf5xx_board_init(void)
85{
86 int ret;
87
88 bf5xx_board_snd_device = platform_device_alloc("soc-audio", -1);
89 if (!bf5xx_board_snd_device)
90 return -ENOMEM;
91
92 platform_set_drvdata(bf5xx_board_snd_device, &bf5xx_board_snd_devdata);
93 bf5xx_board_snd_devdata.dev = &bf5xx_board_snd_device->dev;
94 ret = platform_device_add(bf5xx_board_snd_device);
95
96 if (ret)
97 platform_device_put(bf5xx_board_snd_device);
98
99 return ret;
100}
101
102static void __exit bf5xx_board_exit(void)
103{
104 platform_device_unregister(bf5xx_board_snd_device);
105}
106
107module_init(bf5xx_board_init);
108module_exit(bf5xx_board_exit);
109
110/* Module information */
111MODULE_AUTHOR("Cliff Cai");
112MODULE_DESCRIPTION("ALSA SoC AD1980/1 BF5xx board");
113MODULE_LICENSE("GPL");
diff --git a/sound/soc/blackfin/bf5xx-ad73311.c b/sound/soc/blackfin/bf5xx-ad73311.c
new file mode 100644
index 000000000000..622c9b909532
--- /dev/null
+++ b/sound/soc/blackfin/bf5xx-ad73311.c
@@ -0,0 +1,240 @@
1/*
2 * File: sound/soc/blackfin/bf5xx-ad73311.c
3 * Author: Cliff Cai <Cliff.Cai@analog.com>
4 *
5 * Created: Thur Sep 25 2008
6 * Description: Board driver for ad73311 sound chip
7 *
8 * Modified:
9 * Copyright 2008 Analog Devices Inc.
10 *
11 * Bugs: Enter bugs at http://blackfin.uclinux.org/
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see the file COPYING, or write
25 * to the Free Software Foundation, Inc.,
26 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 */
28
29#include <linux/module.h>
30#include <linux/moduleparam.h>
31#include <linux/device.h>
32#include <linux/delay.h>
33#include <linux/gpio.h>
34
35#include <sound/core.h>
36#include <sound/pcm.h>
37#include <sound/soc.h>
38#include <sound/soc-dapm.h>
39#include <sound/pcm_params.h>
40
41#include <asm/blackfin.h>
42#include <asm/cacheflush.h>
43#include <asm/irq.h>
44#include <asm/dma.h>
45#include <asm/portmux.h>
46
47#include "../codecs/ad73311.h"
48#include "bf5xx-sport.h"
49#include "bf5xx-i2s-pcm.h"
50#include "bf5xx-i2s.h"
51
52#if CONFIG_SND_BF5XX_SPORT_NUM == 0
53#define bfin_write_SPORT_TCR1 bfin_write_SPORT0_TCR1
54#define bfin_read_SPORT_TCR1 bfin_read_SPORT0_TCR1
55#define bfin_write_SPORT_TCR2 bfin_write_SPORT0_TCR2
56#define bfin_write_SPORT_TX16 bfin_write_SPORT0_TX16
57#define bfin_read_SPORT_STAT bfin_read_SPORT0_STAT
58#else
59#define bfin_write_SPORT_TCR1 bfin_write_SPORT1_TCR1
60#define bfin_read_SPORT_TCR1 bfin_read_SPORT1_TCR1
61#define bfin_write_SPORT_TCR2 bfin_write_SPORT1_TCR2
62#define bfin_write_SPORT_TX16 bfin_write_SPORT1_TX16
63#define bfin_read_SPORT_STAT bfin_read_SPORT1_STAT
64#endif
65
66#define GPIO_SE CONFIG_SND_BFIN_AD73311_SE
67
68static struct snd_soc_machine bf5xx_ad73311;
69
70static int snd_ad73311_startup(void)
71{
72 pr_debug("%s enter\n", __func__);
73
74 /* Pull up SE pin on AD73311L */
75 gpio_set_value(GPIO_SE, 1);
76 return 0;
77}
78
79static int snd_ad73311_configure(void)
80{
81 unsigned short ctrl_regs[6];
82 unsigned short status = 0;
83 int count = 0;
84
85 /* DMCLK = MCLK = 16.384 MHz
86 * SCLK = DMCLK/8 = 2.048 MHz
87 * Sample Rate = DMCLK/2048 = 8 KHz
88 */
89 ctrl_regs[0] = AD_CONTROL | AD_WRITE | CTRL_REG_B | REGB_MCDIV(0) | \
90 REGB_SCDIV(0) | REGB_DIRATE(0);
91 ctrl_regs[1] = AD_CONTROL | AD_WRITE | CTRL_REG_C | REGC_PUDEV | \
92 REGC_PUADC | REGC_PUDAC | REGC_PUREF | REGC_REFUSE ;
93 ctrl_regs[2] = AD_CONTROL | AD_WRITE | CTRL_REG_D | REGD_OGS(2) | \
94 REGD_IGS(2);
95 ctrl_regs[3] = AD_CONTROL | AD_WRITE | CTRL_REG_E | REGE_DA(0x1f);
96 ctrl_regs[4] = AD_CONTROL | AD_WRITE | CTRL_REG_F | REGF_SEEN ;
97 ctrl_regs[5] = AD_CONTROL | AD_WRITE | CTRL_REG_A | REGA_MODE_DATA;
98
99 local_irq_disable();
100 snd_ad73311_startup();
101 udelay(1);
102
103 bfin_write_SPORT_TCR1(TFSR);
104 bfin_write_SPORT_TCR2(0xF);
105 SSYNC();
106
107 /* SPORT Tx Register is a 8 x 16 FIFO, all the data can be put to
108 * FIFO before enable SPORT to transfer the data
109 */
110 for (count = 0; count < 6; count++)
111 bfin_write_SPORT_TX16(ctrl_regs[count]);
112 SSYNC();
113 bfin_write_SPORT_TCR1(bfin_read_SPORT_TCR1() | TSPEN);
114 SSYNC();
115
116 /* When TUVF is set, the data is already send out */
117 while (!(status & TUVF) && count++ < 10000) {
118 udelay(1);
119 status = bfin_read_SPORT_STAT();
120 SSYNC();
121 }
122 bfin_write_SPORT_TCR1(bfin_read_SPORT_TCR1() & ~TSPEN);
123 SSYNC();
124 local_irq_enable();
125
126 if (count == 10000) {
127 printk(KERN_ERR "ad73311: failed to configure codec\n");
128 return -1;
129 }
130 return 0;
131}
132
133static int bf5xx_probe(struct platform_device *pdev)
134{
135 int err;
136 if (gpio_request(GPIO_SE, "AD73311_SE")) {
137 printk(KERN_ERR "%s: Failed ro request GPIO_%d\n", __func__, GPIO_SE);
138 return -EBUSY;
139 }
140
141 gpio_direction_output(GPIO_SE, 0);
142
143 err = snd_ad73311_configure();
144 if (err < 0)
145 return -EFAULT;
146
147 return 0;
148}
149
150static int bf5xx_ad73311_startup(struct snd_pcm_substream *substream)
151{
152 struct snd_soc_pcm_runtime *rtd = substream->private_data;
153 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
154
155 pr_debug("%s enter\n", __func__);
156 cpu_dai->private_data = sport_handle;
157 return 0;
158}
159
160static int bf5xx_ad73311_hw_params(struct snd_pcm_substream *substream,
161 struct snd_pcm_hw_params *params)
162{
163 struct snd_soc_pcm_runtime *rtd = substream->private_data;
164 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
165 int ret = 0;
166
167 pr_debug("%s rate %d format %x\n", __func__, params_rate(params),
168 params_format(params));
169
170 /* set cpu DAI configuration */
171 ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
172 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
173 if (ret < 0)
174 return ret;
175
176 return 0;
177}
178
179
180static struct snd_soc_ops bf5xx_ad73311_ops = {
181 .startup = bf5xx_ad73311_startup,
182 .hw_params = bf5xx_ad73311_hw_params,
183};
184
185static struct snd_soc_dai_link bf5xx_ad73311_dai = {
186 .name = "ad73311",
187 .stream_name = "AD73311",
188 .cpu_dai = &bf5xx_i2s_dai,
189 .codec_dai = &ad73311_dai,
190 .ops = &bf5xx_ad73311_ops,
191};
192
193static struct snd_soc_machine bf5xx_ad73311 = {
194 .name = "bf5xx_ad73311",
195 .probe = bf5xx_probe,
196 .dai_link = &bf5xx_ad73311_dai,
197 .num_links = 1,
198};
199
200static struct snd_soc_device bf5xx_ad73311_snd_devdata = {
201 .machine = &bf5xx_ad73311,
202 .platform = &bf5xx_i2s_soc_platform,
203 .codec_dev = &soc_codec_dev_ad73311,
204};
205
206static struct platform_device *bf52x_ad73311_snd_device;
207
208static int __init bf5xx_ad73311_init(void)
209{
210 int ret;
211
212 pr_debug("%s enter\n", __func__);
213 bf52x_ad73311_snd_device = platform_device_alloc("soc-audio", -1);
214 if (!bf52x_ad73311_snd_device)
215 return -ENOMEM;
216
217 platform_set_drvdata(bf52x_ad73311_snd_device, &bf5xx_ad73311_snd_devdata);
218 bf5xx_ad73311_snd_devdata.dev = &bf52x_ad73311_snd_device->dev;
219 ret = platform_device_add(bf52x_ad73311_snd_device);
220
221 if (ret)
222 platform_device_put(bf52x_ad73311_snd_device);
223
224 return ret;
225}
226
227static void __exit bf5xx_ad73311_exit(void)
228{
229 pr_debug("%s enter\n", __func__);
230 platform_device_unregister(bf52x_ad73311_snd_device);
231}
232
233module_init(bf5xx_ad73311_init);
234module_exit(bf5xx_ad73311_exit);
235
236/* Module information */
237MODULE_AUTHOR("Cliff Cai");
238MODULE_DESCRIPTION("ALSA SoC AD73311 Blackfin");
239MODULE_LICENSE("GPL");
240
diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c
new file mode 100644
index 000000000000..61fccf925192
--- /dev/null
+++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c
@@ -0,0 +1,288 @@
1/*
2 * File: sound/soc/blackfin/bf5xx-i2s-pcm.c
3 * Author: Cliff Cai <Cliff.Cai@analog.com>
4 *
5 * Created: Tue June 06 2008
6 * Description: DMA driver for i2s codec
7 *
8 * Modified:
9 * Copyright 2008 Analog Devices Inc.
10 *
11 * Bugs: Enter bugs at http://blackfin.uclinux.org/
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see the file COPYING, or write
25 * to the Free Software Foundation, Inc.,
26 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 */
28
29#include <linux/module.h>
30#include <linux/init.h>
31#include <linux/platform_device.h>
32#include <linux/slab.h>
33#include <linux/dma-mapping.h>
34
35#include <sound/core.h>
36#include <sound/pcm.h>
37#include <sound/pcm_params.h>
38#include <sound/soc.h>
39
40#include <asm/dma.h>
41
42#include "bf5xx-i2s-pcm.h"
43#include "bf5xx-i2s.h"
44#include "bf5xx-sport.h"
45
46static void bf5xx_dma_irq(void *data)
47{
48 struct snd_pcm_substream *pcm = data;
49 snd_pcm_period_elapsed(pcm);
50}
51
52static const struct snd_pcm_hardware bf5xx_pcm_hardware = {
53 .info = SNDRV_PCM_INFO_INTERLEAVED |
54 SNDRV_PCM_INFO_MMAP |
55 SNDRV_PCM_INFO_MMAP_VALID |
56 SNDRV_PCM_INFO_BLOCK_TRANSFER,
57 .formats = SNDRV_PCM_FMTBIT_S16_LE |
58 SNDRV_PCM_FMTBIT_S24_LE |
59 SNDRV_PCM_FMTBIT_S32_LE,
60 .period_bytes_min = 32,
61 .period_bytes_max = 0x10000,
62 .periods_min = 1,
63 .periods_max = PAGE_SIZE/32,
64 .buffer_bytes_max = 0x20000, /* 128 kbytes */
65 .fifo_size = 16,
66};
67
68static int bf5xx_pcm_hw_params(struct snd_pcm_substream *substream,
69 struct snd_pcm_hw_params *params)
70{
71 size_t size = bf5xx_pcm_hardware.buffer_bytes_max;
72 snd_pcm_lib_malloc_pages(substream, size);
73
74 return 0;
75}
76
77static int bf5xx_pcm_hw_free(struct snd_pcm_substream *substream)
78{
79 snd_pcm_lib_free_pages(substream);
80
81 return 0;
82}
83
84static int bf5xx_pcm_prepare(struct snd_pcm_substream *substream)
85{
86 struct snd_pcm_runtime *runtime = substream->runtime;
87 struct sport_device *sport = runtime->private_data;
88 int period_bytes = frames_to_bytes(runtime, runtime->period_size);
89
90 pr_debug("%s enter\n", __func__);
91 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
92 sport_set_tx_callback(sport, bf5xx_dma_irq, substream);
93 sport_config_tx_dma(sport, runtime->dma_area,
94 runtime->periods, period_bytes);
95 } else {
96 sport_set_rx_callback(sport, bf5xx_dma_irq, substream);
97 sport_config_rx_dma(sport, runtime->dma_area,
98 runtime->periods, period_bytes);
99 }
100
101 return 0;
102}
103
104static int bf5xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
105{
106 struct snd_pcm_runtime *runtime = substream->runtime;
107 struct sport_device *sport = runtime->private_data;
108 int ret = 0;
109
110 pr_debug("%s enter\n", __func__);
111 switch (cmd) {
112 case SNDRV_PCM_TRIGGER_START:
113 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
114 sport_tx_start(sport);
115 else
116 sport_rx_start(sport);
117 break;
118 case SNDRV_PCM_TRIGGER_STOP:
119 case SNDRV_PCM_TRIGGER_SUSPEND:
120 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
121 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
122 sport_tx_stop(sport);
123 else
124 sport_rx_stop(sport);
125 break;
126 default:
127 ret = -EINVAL;
128 }
129
130 return ret;
131}
132
133static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream)
134{
135 struct snd_pcm_runtime *runtime = substream->runtime;
136 struct sport_device *sport = runtime->private_data;
137 unsigned int diff;
138 snd_pcm_uframes_t frames;
139 pr_debug("%s enter\n", __func__);
140 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
141 diff = sport_curr_offset_tx(sport);
142 frames = bytes_to_frames(substream->runtime, diff);
143 } else {
144 diff = sport_curr_offset_rx(sport);
145 frames = bytes_to_frames(substream->runtime, diff);
146 }
147 return frames;
148}
149
150static int bf5xx_pcm_open(struct snd_pcm_substream *substream)
151{
152 struct snd_pcm_runtime *runtime = substream->runtime;
153 int ret;
154
155 pr_debug("%s enter\n", __func__);
156 snd_soc_set_runtime_hwparams(substream, &bf5xx_pcm_hardware);
157
158 ret = snd_pcm_hw_constraint_integer(runtime, \
159 SNDRV_PCM_HW_PARAM_PERIODS);
160 if (ret < 0)
161 goto out;
162
163 if (sport_handle != NULL)
164 runtime->private_data = sport_handle;
165 else {
166 pr_err("sport_handle is NULL\n");
167 return -1;
168 }
169 return 0;
170
171 out:
172 return ret;
173}
174
175static int bf5xx_pcm_mmap(struct snd_pcm_substream *substream,
176 struct vm_area_struct *vma)
177{
178 struct snd_pcm_runtime *runtime = substream->runtime;
179 size_t size = vma->vm_end - vma->vm_start;
180 vma->vm_start = (unsigned long)runtime->dma_area;
181 vma->vm_end = vma->vm_start + size;
182 vma->vm_flags |= VM_SHARED;
183
184 return 0 ;
185}
186
187struct snd_pcm_ops bf5xx_pcm_i2s_ops = {
188 .open = bf5xx_pcm_open,
189 .ioctl = snd_pcm_lib_ioctl,
190 .hw_params = bf5xx_pcm_hw_params,
191 .hw_free = bf5xx_pcm_hw_free,
192 .prepare = bf5xx_pcm_prepare,
193 .trigger = bf5xx_pcm_trigger,
194 .pointer = bf5xx_pcm_pointer,
195 .mmap = bf5xx_pcm_mmap,
196};
197
198static int bf5xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
199{
200 struct snd_pcm_substream *substream = pcm->streams[stream].substream;
201 struct snd_dma_buffer *buf = &substream->dma_buffer;
202 size_t size = bf5xx_pcm_hardware.buffer_bytes_max;
203
204 buf->dev.type = SNDRV_DMA_TYPE_DEV;
205 buf->dev.dev = pcm->card->dev;
206 buf->private_data = NULL;
207 buf->area = dma_alloc_coherent(pcm->card->dev, size,
208 &buf->addr, GFP_KERNEL);
209 if (!buf->area) {
210 pr_err("Failed to allocate dma memory \
211 Please increase uncached DMA memory region\n");
212 return -ENOMEM;
213 }
214 buf->bytes = size;
215
216 pr_debug("%s, area:%p, size:0x%08lx\n", __func__,
217 buf->area, buf->bytes);
218
219 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
220 sport_handle->tx_buf = buf->area;
221 else
222 sport_handle->rx_buf = buf->area;
223
224 return 0;
225}
226
227static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
228{
229 struct snd_pcm_substream *substream;
230 struct snd_dma_buffer *buf;
231 int stream;
232
233 for (stream = 0; stream < 2; stream++) {
234 substream = pcm->streams[stream].substream;
235 if (!substream)
236 continue;
237
238 buf = &substream->dma_buffer;
239 if (!buf->area)
240 continue;
241 dma_free_coherent(NULL, buf->bytes, buf->area, 0);
242 buf->area = NULL;
243 }
244 if (sport_handle)
245 sport_done(sport_handle);
246}
247
248static u64 bf5xx_pcm_dmamask = DMA_32BIT_MASK;
249
250int bf5xx_pcm_i2s_new(struct snd_card *card, struct snd_soc_dai *dai,
251 struct snd_pcm *pcm)
252{
253 int ret = 0;
254
255 pr_debug("%s enter\n", __func__);
256 if (!card->dev->dma_mask)
257 card->dev->dma_mask = &bf5xx_pcm_dmamask;
258 if (!card->dev->coherent_dma_mask)
259 card->dev->coherent_dma_mask = DMA_32BIT_MASK;
260
261 if (dai->playback.channels_min) {
262 ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
263 SNDRV_PCM_STREAM_PLAYBACK);
264 if (ret)
265 goto out;
266 }
267
268 if (dai->capture.channels_min) {
269 ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
270 SNDRV_PCM_STREAM_CAPTURE);
271 if (ret)
272 goto out;
273 }
274 out:
275 return ret;
276}
277
278struct snd_soc_platform bf5xx_i2s_soc_platform = {
279 .name = "bf5xx-audio",
280 .pcm_ops = &bf5xx_pcm_i2s_ops,
281 .pcm_new = bf5xx_pcm_i2s_new,
282 .pcm_free = bf5xx_pcm_free_dma_buffers,
283};
284EXPORT_SYMBOL_GPL(bf5xx_i2s_soc_platform);
285
286MODULE_AUTHOR("Cliff Cai");
287MODULE_DESCRIPTION("ADI Blackfin I2S PCM DMA module");
288MODULE_LICENSE("GPL");
diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.h b/sound/soc/blackfin/bf5xx-i2s-pcm.h
new file mode 100644
index 000000000000..4d4609a97c59
--- /dev/null
+++ b/sound/soc/blackfin/bf5xx-i2s-pcm.h
@@ -0,0 +1,29 @@
1/*
2 * linux/sound/arm/bf5xx-i2s-pcm.h -- ALSA PCM interface for the Blackfin
3 *
4 * Copyright 2007 Analog Device Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#ifndef _BF5XX_I2S_PCM_H
12#define _BF5XX_I2S_PCM_H
13
14struct bf5xx_pcm_dma_params {
15 char *name; /* stream identifier */
16};
17
18struct bf5xx_gpio {
19 u32 sys;
20 u32 rx;
21 u32 tx;
22 u32 clk;
23 u32 frm;
24};
25
26/* platform data */
27extern struct snd_soc_platform bf5xx_i2s_soc_platform;
28
29#endif
diff --git a/sound/soc/blackfin/bf5xx-i2s.c b/sound/soc/blackfin/bf5xx-i2s.c
new file mode 100644
index 000000000000..827587f08180
--- /dev/null
+++ b/sound/soc/blackfin/bf5xx-i2s.c
@@ -0,0 +1,311 @@
1/*
2 * File: sound/soc/blackfin/bf5xx-i2s.c
3 * Author: Cliff Cai <Cliff.Cai@analog.com>
4 *
5 * Created: Tue June 06 2008
6 * Description: Blackfin I2S CPU DAI driver
7 *
8 * Modified:
9 * Copyright 2008 Analog Devices Inc.
10 *
11 * Bugs: Enter bugs at http://blackfin.uclinux.org/
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see the file COPYING, or write
25 * to the Free Software Foundation, Inc.,
26 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 */
28
29#include <linux/init.h>
30#include <linux/module.h>
31#include <linux/device.h>
32#include <linux/delay.h>
33#include <sound/core.h>
34#include <sound/pcm.h>
35#include <sound/pcm_params.h>
36#include <sound/initval.h>
37#include <sound/soc.h>
38
39#include <asm/irq.h>
40#include <asm/portmux.h>
41#include <linux/mutex.h>
42#include <linux/gpio.h>
43
44#include "bf5xx-sport.h"
45#include "bf5xx-i2s.h"
46
47struct bf5xx_i2s_port {
48 u16 tcr1;
49 u16 rcr1;
50 u16 tcr2;
51 u16 rcr2;
52 int counter;
53};
54
55static struct bf5xx_i2s_port bf5xx_i2s;
56static int sport_num = CONFIG_SND_BF5XX_SPORT_NUM;
57
58static struct sport_param sport_params[2] = {
59 {
60 .dma_rx_chan = CH_SPORT0_RX,
61 .dma_tx_chan = CH_SPORT0_TX,
62 .err_irq = IRQ_SPORT0_ERROR,
63 .regs = (struct sport_register *)SPORT0_TCR1,
64 },
65 {
66 .dma_rx_chan = CH_SPORT1_RX,
67 .dma_tx_chan = CH_SPORT1_TX,
68 .err_irq = IRQ_SPORT1_ERROR,
69 .regs = (struct sport_register *)SPORT1_TCR1,
70 }
71};
72
73static u16 sport_req[][7] = {
74 { P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
75 P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0},
76 { P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS,
77 P_SPORT1_DRPRI, P_SPORT1_RSCLK, 0},
78};
79
80static int bf5xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
81 unsigned int fmt)
82{
83 int ret = 0;
84
85 /* interface format:support I2S,slave mode */
86 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
87 case SND_SOC_DAIFMT_I2S:
88 bf5xx_i2s.tcr1 |= TFSR | TCKFE;
89 bf5xx_i2s.rcr1 |= RFSR | RCKFE;
90 bf5xx_i2s.tcr2 |= TSFSE;
91 bf5xx_i2s.rcr2 |= RSFSE;
92 break;
93 case SND_SOC_DAIFMT_DSP_A:
94 bf5xx_i2s.tcr1 |= TFSR;
95 bf5xx_i2s.rcr1 |= RFSR;
96 break;
97 case SND_SOC_DAIFMT_LEFT_J:
98 ret = -EINVAL;
99 break;
100 default:
101 ret = -EINVAL;
102 break;
103 }
104
105 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
106 case SND_SOC_DAIFMT_CBS_CFS:
107 ret = -EINVAL;
108 break;
109 case SND_SOC_DAIFMT_CBM_CFS:
110 ret = -EINVAL;
111 break;
112 case SND_SOC_DAIFMT_CBM_CFM:
113 break;
114 case SND_SOC_DAIFMT_CBS_CFM:
115 ret = -EINVAL;
116 break;
117 default:
118 ret = -EINVAL;
119 break;
120 }
121
122 return ret;
123}
124
125static int bf5xx_i2s_startup(struct snd_pcm_substream *substream)
126{
127 pr_debug("%s enter\n", __func__);
128
129 /*this counter is used for counting how many pcm streams are opened*/
130 bf5xx_i2s.counter++;
131 return 0;
132}
133
134static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream,
135 struct snd_pcm_hw_params *params)
136{
137 int ret = 0;
138
139 bf5xx_i2s.tcr2 &= ~0x1f;
140 bf5xx_i2s.rcr2 &= ~0x1f;
141 switch (params_format(params)) {
142 case SNDRV_PCM_FORMAT_S16_LE:
143 bf5xx_i2s.tcr2 |= 15;
144 bf5xx_i2s.rcr2 |= 15;
145 sport_handle->wdsize = 2;
146 break;
147 case SNDRV_PCM_FORMAT_S24_LE:
148 bf5xx_i2s.tcr2 |= 23;
149 bf5xx_i2s.rcr2 |= 23;
150 sport_handle->wdsize = 3;
151 break;
152 case SNDRV_PCM_FORMAT_S32_LE:
153 bf5xx_i2s.tcr2 |= 31;
154 bf5xx_i2s.rcr2 |= 31;
155 sport_handle->wdsize = 4;
156 break;
157 }
158
159 if (bf5xx_i2s.counter == 1) {
160 /*
161 * TX and RX are not independent,they are enabled at the
162 * same time, even if only one side is running. So, we
163 * need to configure both of them at the time when the first
164 * stream is opened.
165 *
166 * CPU DAI:slave mode.
167 */
168 ret = sport_config_rx(sport_handle, bf5xx_i2s.rcr1,
169 bf5xx_i2s.rcr2, 0, 0);
170 if (ret) {
171 pr_err("SPORT is busy!\n");
172 return -EBUSY;
173 }
174
175 ret = sport_config_tx(sport_handle, bf5xx_i2s.tcr1,
176 bf5xx_i2s.tcr2, 0, 0);
177 if (ret) {
178 pr_err("SPORT is busy!\n");
179 return -EBUSY;
180 }
181 }
182
183 return 0;
184}
185
186static void bf5xx_i2s_shutdown(struct snd_pcm_substream *substream)
187{
188 pr_debug("%s enter\n", __func__);
189 bf5xx_i2s.counter--;
190}
191
192static int bf5xx_i2s_probe(struct platform_device *pdev,
193 struct snd_soc_dai *dai)
194{
195 pr_debug("%s enter\n", __func__);
196 if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) {
197 pr_err("Requesting Peripherals failed\n");
198 return -EFAULT;
199 }
200
201 /* request DMA for SPORT */
202 sport_handle = sport_init(&sport_params[sport_num], 4, \
203 2 * sizeof(u32), NULL);
204 if (!sport_handle) {
205 peripheral_free_list(&sport_req[sport_num][0]);
206 return -ENODEV;
207 }
208
209 return 0;
210}
211
212static void bf5xx_i2s_remove(struct platform_device *pdev,
213 struct snd_soc_dai *dai)
214{
215 pr_debug("%s enter\n", __func__);
216 peripheral_free_list(&sport_req[sport_num][0]);
217}
218
219#ifdef CONFIG_PM
220static int bf5xx_i2s_suspend(struct platform_device *dev,
221 struct snd_soc_dai *dai)
222{
223 struct sport_device *sport =
224 (struct sport_device *)dai->private_data;
225
226 pr_debug("%s : sport %d\n", __func__, dai->id);
227 if (!dai->active)
228 return 0;
229 if (dai->capture.active)
230 sport_rx_stop(sport);
231 if (dai->playback.active)
232 sport_tx_stop(sport);
233 return 0;
234}
235
236static int bf5xx_i2s_resume(struct platform_device *pdev,
237 struct snd_soc_dai *dai)
238{
239 int ret;
240 struct sport_device *sport =
241 (struct sport_device *)dai->private_data;
242
243 pr_debug("%s : sport %d\n", __func__, dai->id);
244 if (!dai->active)
245 return 0;
246
247 ret = sport_config_rx(sport_handle, RFSR | RCKFE, RSFSE|0x1f, 0, 0);
248 if (ret) {
249 pr_err("SPORT is busy!\n");
250 return -EBUSY;
251 }
252
253 ret = sport_config_tx(sport_handle, TFSR | TCKFE, TSFSE|0x1f, 0, 0);
254 if (ret) {
255 pr_err("SPORT is busy!\n");
256 return -EBUSY;
257 }
258
259 if (dai->capture.active)
260 sport_rx_start(sport);
261 if (dai->playback.active)
262 sport_tx_start(sport);
263 return 0;
264}
265
266#else
267#define bf5xx_i2s_suspend NULL
268#define bf5xx_i2s_resume NULL
269#endif
270
271#define BF5XX_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
272 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \
273 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | \
274 SNDRV_PCM_RATE_96000)
275
276#define BF5XX_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |\
277 SNDRV_PCM_FMTBIT_S32_LE)
278
279struct snd_soc_dai bf5xx_i2s_dai = {
280 .name = "bf5xx-i2s",
281 .id = 0,
282 .type = SND_SOC_DAI_I2S,
283 .probe = bf5xx_i2s_probe,
284 .remove = bf5xx_i2s_remove,
285 .suspend = bf5xx_i2s_suspend,
286 .resume = bf5xx_i2s_resume,
287 .playback = {
288 .channels_min = 1,
289 .channels_max = 2,
290 .rates = BF5XX_I2S_RATES,
291 .formats = BF5XX_I2S_FORMATS,},
292 .capture = {
293 .channels_min = 1,
294 .channels_max = 2,
295 .rates = BF5XX_I2S_RATES,
296 .formats = BF5XX_I2S_FORMATS,},
297 .ops = {
298 .startup = bf5xx_i2s_startup,
299 .shutdown = bf5xx_i2s_shutdown,
300 .hw_params = bf5xx_i2s_hw_params,},
301 .dai_ops = {
302 .set_fmt = bf5xx_i2s_set_dai_fmt,
303 },
304};
305EXPORT_SYMBOL_GPL(bf5xx_i2s_dai);
306
307/* Module information */
308MODULE_AUTHOR("Cliff Cai");
309MODULE_DESCRIPTION("I2S driver for ADI Blackfin");
310MODULE_LICENSE("GPL");
311
diff --git a/sound/soc/blackfin/bf5xx-i2s.h b/sound/soc/blackfin/bf5xx-i2s.h
new file mode 100644
index 000000000000..7107d1a0b06b
--- /dev/null
+++ b/sound/soc/blackfin/bf5xx-i2s.h
@@ -0,0 +1,14 @@
1/*
2 * linux/sound/arm/bf5xx-i2s.h
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#ifndef _BF5XX_I2S_H
10#define _BF5XX_I2S_H
11
12extern struct snd_soc_dai bf5xx_i2s_dai;
13
14#endif
diff --git a/sound/soc/blackfin/bf5xx-sport.c b/sound/soc/blackfin/bf5xx-sport.c
new file mode 100644
index 000000000000..3b99e484d555
--- /dev/null
+++ b/sound/soc/blackfin/bf5xx-sport.c
@@ -0,0 +1,1032 @@
1/*
2 * File: bf5xx_sport.c
3 * Based on:
4 * Author: Roy Huang <roy.huang@analog.com>
5 *
6 * Created: Tue Sep 21 10:52:42 CEST 2004
7 * Description:
8 * Blackfin SPORT Driver
9 *
10 * Copyright 2004-2007 Analog Devices Inc.
11 *
12 * Bugs: Enter bugs at http://blackfin.uclinux.org/
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, see the file COPYING, or write
26 * to the Free Software Foundation, Inc.,
27 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28 */
29
30#include <linux/kernel.h>
31#include <linux/slab.h>
32#include <linux/delay.h>
33#include <linux/dma-mapping.h>
34#include <linux/gpio.h>
35#include <linux/bug.h>
36#include <asm/portmux.h>
37#include <asm/dma.h>
38#include <asm/blackfin.h>
39#include <asm/cacheflush.h>
40
41#include "bf5xx-sport.h"
42/* delay between frame sync pulse and first data bit in multichannel mode */
43#define FRAME_DELAY (1<<12)
44
45struct sport_device *sport_handle;
46EXPORT_SYMBOL(sport_handle);
47/* note: multichannel is in units of 8 channels,
48 * tdm_count is # channels NOT / 8 ! */
49int sport_set_multichannel(struct sport_device *sport,
50 int tdm_count, u32 mask, int packed)
51{
52 pr_debug("%s tdm_count=%d mask:0x%08x packed=%d\n", __func__,
53 tdm_count, mask, packed);
54
55 if ((sport->regs->tcr1 & TSPEN) || (sport->regs->rcr1 & RSPEN))
56 return -EBUSY;
57
58 if (tdm_count & 0x7)
59 return -EINVAL;
60
61 if (tdm_count > 32)
62 return -EINVAL; /* Only support less than 32 channels now */
63
64 if (tdm_count) {
65 sport->regs->mcmc1 = ((tdm_count>>3)-1) << 12;
66 sport->regs->mcmc2 = FRAME_DELAY | MCMEN | \
67 (packed ? (MCDTXPE|MCDRXPE) : 0);
68
69 sport->regs->mtcs0 = mask;
70 sport->regs->mrcs0 = mask;
71 sport->regs->mtcs1 = 0;
72 sport->regs->mrcs1 = 0;
73 sport->regs->mtcs2 = 0;
74 sport->regs->mrcs2 = 0;
75 sport->regs->mtcs3 = 0;
76 sport->regs->mrcs3 = 0;
77 } else {
78 sport->regs->mcmc1 = 0;
79 sport->regs->mcmc2 = 0;
80
81 sport->regs->mtcs0 = 0;
82 sport->regs->mrcs0 = 0;
83 }
84
85 sport->regs->mtcs1 = 0; sport->regs->mtcs2 = 0; sport->regs->mtcs3 = 0;
86 sport->regs->mrcs1 = 0; sport->regs->mrcs2 = 0; sport->regs->mrcs3 = 0;
87
88 SSYNC();
89
90 return 0;
91}
92EXPORT_SYMBOL(sport_set_multichannel);
93
94int sport_config_rx(struct sport_device *sport, unsigned int rcr1,
95 unsigned int rcr2, unsigned int clkdiv, unsigned int fsdiv)
96{
97 if ((sport->regs->tcr1 & TSPEN) || (sport->regs->rcr1 & RSPEN))
98 return -EBUSY;
99
100 sport->regs->rcr1 = rcr1;
101 sport->regs->rcr2 = rcr2;
102 sport->regs->rclkdiv = clkdiv;
103 sport->regs->rfsdiv = fsdiv;
104
105 SSYNC();
106
107 return 0;
108}
109EXPORT_SYMBOL(sport_config_rx);
110
111int sport_config_tx(struct sport_device *sport, unsigned int tcr1,
112 unsigned int tcr2, unsigned int clkdiv, unsigned int fsdiv)
113{
114 if ((sport->regs->tcr1 & TSPEN) || (sport->regs->rcr1 & RSPEN))
115 return -EBUSY;
116
117 sport->regs->tcr1 = tcr1;
118 sport->regs->tcr2 = tcr2;
119 sport->regs->tclkdiv = clkdiv;
120 sport->regs->tfsdiv = fsdiv;
121
122 SSYNC();
123
124 return 0;
125}
126EXPORT_SYMBOL(sport_config_tx);
127
128static void setup_desc(struct dmasg *desc, void *buf, int fragcount,
129 size_t fragsize, unsigned int cfg,
130 unsigned int x_count, unsigned int ycount, size_t wdsize)
131{
132
133 int i;
134
135 for (i = 0; i < fragcount; ++i) {
136 desc[i].next_desc_addr = (unsigned long)&(desc[i + 1]);
137 desc[i].start_addr = (unsigned long)buf + i*fragsize;
138 desc[i].cfg = cfg;
139 desc[i].x_count = x_count;
140 desc[i].x_modify = wdsize;
141 desc[i].y_count = ycount;
142 desc[i].y_modify = wdsize;
143 }
144
145 /* make circular */
146 desc[fragcount-1].next_desc_addr = (unsigned long)desc;
147
148 pr_debug("setup desc: desc0=%p, next0=%lx, desc1=%p,"
149 "next1=%lx\nx_count=%x,y_count=%x,addr=0x%lx,cfs=0x%x\n",
150 &(desc[0]), desc[0].next_desc_addr,
151 &(desc[1]), desc[1].next_desc_addr,
152 desc[0].x_count, desc[0].y_count,
153 desc[0].start_addr, desc[0].cfg);
154}
155
156static int sport_start(struct sport_device *sport)
157{
158 enable_dma(sport->dma_rx_chan);
159 enable_dma(sport->dma_tx_chan);
160 sport->regs->rcr1 |= RSPEN;
161 sport->regs->tcr1 |= TSPEN;
162 SSYNC();
163
164 return 0;
165}
166
167static int sport_stop(struct sport_device *sport)
168{
169 sport->regs->tcr1 &= ~TSPEN;
170 sport->regs->rcr1 &= ~RSPEN;
171 SSYNC();
172
173 disable_dma(sport->dma_rx_chan);
174 disable_dma(sport->dma_tx_chan);
175 return 0;
176}
177
178static inline int sport_hook_rx_dummy(struct sport_device *sport)
179{
180 struct dmasg *desc, temp_desc;
181 unsigned long flags;
182
183 BUG_ON(sport->dummy_rx_desc == NULL);
184 BUG_ON(sport->curr_rx_desc == sport->dummy_rx_desc);
185
186 /* Maybe the dummy buffer descriptor ring is damaged */
187 sport->dummy_rx_desc->next_desc_addr = \
188 (unsigned long)(sport->dummy_rx_desc+1);
189
190 local_irq_save(flags);
191 desc = (struct dmasg *)get_dma_next_desc_ptr(sport->dma_rx_chan);
192 /* Copy the descriptor which will be damaged to backup */
193 temp_desc = *desc;
194 desc->x_count = 0xa;
195 desc->y_count = 0;
196 desc->next_desc_addr = (unsigned long)(sport->dummy_rx_desc);
197 local_irq_restore(flags);
198 /* Waiting for dummy buffer descriptor is already hooked*/
199 while ((get_dma_curr_desc_ptr(sport->dma_rx_chan) -
200 sizeof(struct dmasg)) !=
201 (unsigned long)sport->dummy_rx_desc)
202 ;
203 sport->curr_rx_desc = sport->dummy_rx_desc;
204 /* Restore the damaged descriptor */
205 *desc = temp_desc;
206
207 return 0;
208}
209
210static inline int sport_rx_dma_start(struct sport_device *sport, int dummy)
211{
212 if (dummy) {
213 sport->dummy_rx_desc->next_desc_addr = \
214 (unsigned long) sport->dummy_rx_desc;
215 sport->curr_rx_desc = sport->dummy_rx_desc;
216 } else
217 sport->curr_rx_desc = sport->dma_rx_desc;
218
219 set_dma_next_desc_addr(sport->dma_rx_chan, \
220 (unsigned long)(sport->curr_rx_desc));
221 set_dma_x_count(sport->dma_rx_chan, 0);
222 set_dma_x_modify(sport->dma_rx_chan, 0);
223 set_dma_config(sport->dma_rx_chan, (DMAFLOW_LARGE | NDSIZE_9 | \
224 WDSIZE_32 | WNR));
225 set_dma_curr_addr(sport->dma_rx_chan, sport->curr_rx_desc->start_addr);
226 SSYNC();
227
228 return 0;
229}
230
231static inline int sport_tx_dma_start(struct sport_device *sport, int dummy)
232{
233 if (dummy) {
234 sport->dummy_tx_desc->next_desc_addr = \
235 (unsigned long) sport->dummy_tx_desc;
236 sport->curr_tx_desc = sport->dummy_tx_desc;
237 } else
238 sport->curr_tx_desc = sport->dma_tx_desc;
239
240 set_dma_next_desc_addr(sport->dma_tx_chan, \
241 (unsigned long)(sport->curr_tx_desc));
242 set_dma_x_count(sport->dma_tx_chan, 0);
243 set_dma_x_modify(sport->dma_tx_chan, 0);
244 set_dma_config(sport->dma_tx_chan,
245 (DMAFLOW_LARGE | NDSIZE_9 | WDSIZE_32));
246 set_dma_curr_addr(sport->dma_tx_chan, sport->curr_tx_desc->start_addr);
247 SSYNC();
248
249 return 0;
250}
251
252int sport_rx_start(struct sport_device *sport)
253{
254 unsigned long flags;
255 pr_debug("%s enter\n", __func__);
256 if (sport->rx_run)
257 return -EBUSY;
258 if (sport->tx_run) {
259 /* tx is running, rx is not running */
260 BUG_ON(sport->dma_rx_desc == NULL);
261 BUG_ON(sport->curr_rx_desc != sport->dummy_rx_desc);
262 local_irq_save(flags);
263 while ((get_dma_curr_desc_ptr(sport->dma_rx_chan) -
264 sizeof(struct dmasg)) !=
265 (unsigned long)sport->dummy_rx_desc)
266 ;
267 sport->dummy_rx_desc->next_desc_addr =
268 (unsigned long)(sport->dma_rx_desc);
269 local_irq_restore(flags);
270 sport->curr_rx_desc = sport->dma_rx_desc;
271 } else {
272 sport_tx_dma_start(sport, 1);
273 sport_rx_dma_start(sport, 0);
274 sport_start(sport);
275 }
276
277 sport->rx_run = 1;
278
279 return 0;
280}
281EXPORT_SYMBOL(sport_rx_start);
282
283int sport_rx_stop(struct sport_device *sport)
284{
285 pr_debug("%s enter\n", __func__);
286
287 if (!sport->rx_run)
288 return 0;
289 if (sport->tx_run) {
290 /* TX dma is still running, hook the dummy buffer */
291 sport_hook_rx_dummy(sport);
292 } else {
293 /* Both rx and tx dma will be stopped */
294 sport_stop(sport);
295 sport->curr_rx_desc = NULL;
296 sport->curr_tx_desc = NULL;
297 }
298
299 sport->rx_run = 0;
300
301 return 0;
302}
303EXPORT_SYMBOL(sport_rx_stop);
304
305static inline int sport_hook_tx_dummy(struct sport_device *sport)
306{
307 struct dmasg *desc, temp_desc;
308 unsigned long flags;
309
310 BUG_ON(sport->dummy_tx_desc == NULL);
311 BUG_ON(sport->curr_tx_desc == sport->dummy_tx_desc);
312
313 sport->dummy_tx_desc->next_desc_addr = \
314 (unsigned long)(sport->dummy_tx_desc+1);
315
316 /* Shorten the time on last normal descriptor */
317 local_irq_save(flags);
318 desc = (struct dmasg *)get_dma_next_desc_ptr(sport->dma_tx_chan);
319 /* Store the descriptor which will be damaged */
320 temp_desc = *desc;
321 desc->x_count = 0xa;
322 desc->y_count = 0;
323 desc->next_desc_addr = (unsigned long)(sport->dummy_tx_desc);
324 local_irq_restore(flags);
325 /* Waiting for dummy buffer descriptor is already hooked*/
326 while ((get_dma_curr_desc_ptr(sport->dma_tx_chan) - \
327 sizeof(struct dmasg)) != \
328 (unsigned long)sport->dummy_tx_desc)
329 ;
330 sport->curr_tx_desc = sport->dummy_tx_desc;
331 /* Restore the damaged descriptor */
332 *desc = temp_desc;
333
334 return 0;
335}
336
337int sport_tx_start(struct sport_device *sport)
338{
339 unsigned flags;
340 pr_debug("%s: tx_run:%d, rx_run:%d\n", __func__,
341 sport->tx_run, sport->rx_run);
342 if (sport->tx_run)
343 return -EBUSY;
344 if (sport->rx_run) {
345 BUG_ON(sport->dma_tx_desc == NULL);
346 BUG_ON(sport->curr_tx_desc != sport->dummy_tx_desc);
347 /* Hook the normal buffer descriptor */
348 local_irq_save(flags);
349 while ((get_dma_curr_desc_ptr(sport->dma_tx_chan) -
350 sizeof(struct dmasg)) !=
351 (unsigned long)sport->dummy_tx_desc)
352 ;
353 sport->dummy_tx_desc->next_desc_addr =
354 (unsigned long)(sport->dma_tx_desc);
355 local_irq_restore(flags);
356 sport->curr_tx_desc = sport->dma_tx_desc;
357 } else {
358
359 sport_tx_dma_start(sport, 0);
360 /* Let rx dma run the dummy buffer */
361 sport_rx_dma_start(sport, 1);
362 sport_start(sport);
363 }
364 sport->tx_run = 1;
365 return 0;
366}
367EXPORT_SYMBOL(sport_tx_start);
368
369int sport_tx_stop(struct sport_device *sport)
370{
371 if (!sport->tx_run)
372 return 0;
373 if (sport->rx_run) {
374 /* RX is still running, hook the dummy buffer */
375 sport_hook_tx_dummy(sport);
376 } else {
377 /* Both rx and tx dma stopped */
378 sport_stop(sport);
379 sport->curr_rx_desc = NULL;
380 sport->curr_tx_desc = NULL;
381 }
382
383 sport->tx_run = 0;
384
385 return 0;
386}
387EXPORT_SYMBOL(sport_tx_stop);
388
389static inline int compute_wdsize(size_t wdsize)
390{
391 switch (wdsize) {
392 case 1:
393 return WDSIZE_8;
394 case 2:
395 return WDSIZE_16;
396 case 4:
397 default:
398 return WDSIZE_32;
399 }
400}
401
402int sport_config_rx_dma(struct sport_device *sport, void *buf,
403 int fragcount, size_t fragsize)
404{
405 unsigned int x_count;
406 unsigned int y_count;
407 unsigned int cfg;
408 dma_addr_t addr;
409
410 pr_debug("%s buf:%p, frag:%d, fragsize:0x%lx\n", __func__, \
411 buf, fragcount, fragsize);
412
413 x_count = fragsize / sport->wdsize;
414 y_count = 0;
415
416 /* for fragments larger than 64k words we use 2d dma,
417 * denote fragecount as two numbers' mutliply and both of them
418 * are less than 64k.*/
419 if (x_count >= 0x10000) {
420 int i, count = x_count;
421
422 for (i = 16; i > 0; i--) {
423 x_count = 1 << i;
424 if ((count & (x_count - 1)) == 0) {
425 y_count = count >> i;
426 if (y_count < 0x10000)
427 break;
428 }
429 }
430 if (i == 0)
431 return -EINVAL;
432 }
433 pr_debug("%s(x_count:0x%x, y_count:0x%x)\n", __func__,
434 x_count, y_count);
435
436 if (sport->dma_rx_desc)
437 dma_free_coherent(NULL, sport->rx_desc_bytes,
438 sport->dma_rx_desc, 0);
439
440 /* Allocate a new descritor ring as current one. */
441 sport->dma_rx_desc = dma_alloc_coherent(NULL, \
442 fragcount * sizeof(struct dmasg), &addr, 0);
443 sport->rx_desc_bytes = fragcount * sizeof(struct dmasg);
444
445 if (!sport->dma_rx_desc) {
446 pr_err("Failed to allocate memory for rx desc\n");
447 return -ENOMEM;
448 }
449
450 sport->rx_buf = buf;
451 sport->rx_fragsize = fragsize;
452 sport->rx_frags = fragcount;
453
454 cfg = 0x7000 | DI_EN | compute_wdsize(sport->wdsize) | WNR | \
455 (DESC_ELEMENT_COUNT << 8); /* large descriptor mode */
456
457 if (y_count != 0)
458 cfg |= DMA2D;
459
460 setup_desc(sport->dma_rx_desc, buf, fragcount, fragsize,
461 cfg|DMAEN, x_count, y_count, sport->wdsize);
462
463 return 0;
464}
465EXPORT_SYMBOL(sport_config_rx_dma);
466
467int sport_config_tx_dma(struct sport_device *sport, void *buf, \
468 int fragcount, size_t fragsize)
469{
470 unsigned int x_count;
471 unsigned int y_count;
472 unsigned int cfg;
473 dma_addr_t addr;
474
475 pr_debug("%s buf:%p, fragcount:%d, fragsize:0x%lx\n",
476 __func__, buf, fragcount, fragsize);
477
478 x_count = fragsize/sport->wdsize;
479 y_count = 0;
480
481 /* for fragments larger than 64k words we use 2d dma,
482 * denote fragecount as two numbers' mutliply and both of them
483 * are less than 64k.*/
484 if (x_count >= 0x10000) {
485 int i, count = x_count;
486
487 for (i = 16; i > 0; i--) {
488 x_count = 1 << i;
489 if ((count & (x_count - 1)) == 0) {
490 y_count = count >> i;
491 if (y_count < 0x10000)
492 break;
493 }
494 }
495 if (i == 0)
496 return -EINVAL;
497 }
498 pr_debug("%s x_count:0x%x, y_count:0x%x\n", __func__,
499 x_count, y_count);
500
501
502 if (sport->dma_tx_desc) {
503 dma_free_coherent(NULL, sport->tx_desc_bytes, \
504 sport->dma_tx_desc, 0);
505 }
506
507 sport->dma_tx_desc = dma_alloc_coherent(NULL, \
508 fragcount * sizeof(struct dmasg), &addr, 0);
509 sport->tx_desc_bytes = fragcount * sizeof(struct dmasg);
510 if (!sport->dma_tx_desc) {
511 pr_err("Failed to allocate memory for tx desc\n");
512 return -ENOMEM;
513 }
514
515 sport->tx_buf = buf;
516 sport->tx_fragsize = fragsize;
517 sport->tx_frags = fragcount;
518 cfg = 0x7000 | DI_EN | compute_wdsize(sport->wdsize) | \
519 (DESC_ELEMENT_COUNT << 8); /* large descriptor mode */
520
521 if (y_count != 0)
522 cfg |= DMA2D;
523
524 setup_desc(sport->dma_tx_desc, buf, fragcount, fragsize,
525 cfg|DMAEN, x_count, y_count, sport->wdsize);
526
527 return 0;
528}
529EXPORT_SYMBOL(sport_config_tx_dma);
530
531/* setup dummy dma descriptor ring, which don't generate interrupts,
532 * the x_modify is set to 0 */
533static int sport_config_rx_dummy(struct sport_device *sport)
534{
535 struct dmasg *desc;
536 unsigned config;
537
538 pr_debug("%s entered\n", __func__);
539#if L1_DATA_A_LENGTH != 0
540 desc = (struct dmasg *) l1_data_sram_alloc(2 * sizeof(*desc));
541#else
542 {
543 dma_addr_t addr;
544 desc = dma_alloc_coherent(NULL, 2 * sizeof(*desc), &addr, 0);
545 }
546#endif
547 if (desc == NULL) {
548 pr_err("Failed to allocate memory for dummy rx desc\n");
549 return -ENOMEM;
550 }
551 memset(desc, 0, 2 * sizeof(*desc));
552 sport->dummy_rx_desc = desc;
553 desc->start_addr = (unsigned long)sport->dummy_buf;
554 config = DMAFLOW_LARGE | NDSIZE_9 | compute_wdsize(sport->wdsize)
555 | WNR | DMAEN;
556 desc->cfg = config;
557 desc->x_count = sport->dummy_count/sport->wdsize;
558 desc->x_modify = sport->wdsize;
559 desc->y_count = 0;
560 desc->y_modify = 0;
561 memcpy(desc+1, desc, sizeof(*desc));
562 desc->next_desc_addr = (unsigned long)(desc+1);
563 desc[1].next_desc_addr = (unsigned long)desc;
564 return 0;
565}
566
567static int sport_config_tx_dummy(struct sport_device *sport)
568{
569 struct dmasg *desc;
570 unsigned int config;
571
572 pr_debug("%s entered\n", __func__);
573
574#if L1_DATA_A_LENGTH != 0
575 desc = (struct dmasg *) l1_data_sram_alloc(2 * sizeof(*desc));
576#else
577 {
578 dma_addr_t addr;
579 desc = dma_alloc_coherent(NULL, 2 * sizeof(*desc), &addr, 0);
580 }
581#endif
582 if (!desc) {
583 pr_err("Failed to allocate memory for dummy tx desc\n");
584 return -ENOMEM;
585 }
586 memset(desc, 0, 2 * sizeof(*desc));
587 sport->dummy_tx_desc = desc;
588 desc->start_addr = (unsigned long)sport->dummy_buf + \
589 sport->dummy_count;
590 config = DMAFLOW_LARGE | NDSIZE_9 |
591 compute_wdsize(sport->wdsize) | DMAEN;
592 desc->cfg = config;
593 desc->x_count = sport->dummy_count/sport->wdsize;
594 desc->x_modify = sport->wdsize;
595 desc->y_count = 0;
596 desc->y_modify = 0;
597 memcpy(desc+1, desc, sizeof(*desc));
598 desc->next_desc_addr = (unsigned long)(desc+1);
599 desc[1].next_desc_addr = (unsigned long)desc;
600 return 0;
601}
602
603unsigned long sport_curr_offset_rx(struct sport_device *sport)
604{
605 unsigned long curr = get_dma_curr_addr(sport->dma_rx_chan);
606
607 return (unsigned char *)curr - sport->rx_buf;
608}
609EXPORT_SYMBOL(sport_curr_offset_rx);
610
611unsigned long sport_curr_offset_tx(struct sport_device *sport)
612{
613 unsigned long curr = get_dma_curr_addr(sport->dma_tx_chan);
614
615 return (unsigned char *)curr - sport->tx_buf;
616}
617EXPORT_SYMBOL(sport_curr_offset_tx);
618
619void sport_incfrag(struct sport_device *sport, int *frag, int tx)
620{
621 ++(*frag);
622 if (tx == 1 && *frag == sport->tx_frags)
623 *frag = 0;
624
625 if (tx == 0 && *frag == sport->rx_frags)
626 *frag = 0;
627}
628EXPORT_SYMBOL(sport_incfrag);
629
630void sport_decfrag(struct sport_device *sport, int *frag, int tx)
631{
632 --(*frag);
633 if (tx == 1 && *frag == 0)
634 *frag = sport->tx_frags;
635
636 if (tx == 0 && *frag == 0)
637 *frag = sport->rx_frags;
638}
639EXPORT_SYMBOL(sport_decfrag);
640
641static int sport_check_status(struct sport_device *sport,
642 unsigned int *sport_stat,
643 unsigned int *rx_stat,
644 unsigned int *tx_stat)
645{
646 int status = 0;
647
648 if (sport_stat) {
649 SSYNC();
650 status = sport->regs->stat;
651 if (status & (TOVF|TUVF|ROVF|RUVF))
652 sport->regs->stat = (status & (TOVF|TUVF|ROVF|RUVF));
653 SSYNC();
654 *sport_stat = status;
655 }
656
657 if (rx_stat) {
658 SSYNC();
659 status = get_dma_curr_irqstat(sport->dma_rx_chan);
660 if (status & (DMA_DONE|DMA_ERR))
661 clear_dma_irqstat(sport->dma_rx_chan);
662 SSYNC();
663 *rx_stat = status;
664 }
665
666 if (tx_stat) {
667 SSYNC();
668 status = get_dma_curr_irqstat(sport->dma_tx_chan);
669 if (status & (DMA_DONE|DMA_ERR))
670 clear_dma_irqstat(sport->dma_tx_chan);
671 SSYNC();
672 *tx_stat = status;
673 }
674
675 return 0;
676}
677
678int sport_dump_stat(struct sport_device *sport, char *buf, size_t len)
679{
680 int ret;
681
682 ret = snprintf(buf, len,
683 "sts: 0x%04x\n"
684 "rx dma %d sts: 0x%04x tx dma %d sts: 0x%04x\n",
685 sport->regs->stat,
686 sport->dma_rx_chan,
687 get_dma_curr_irqstat(sport->dma_rx_chan),
688 sport->dma_tx_chan,
689 get_dma_curr_irqstat(sport->dma_tx_chan));
690 buf += ret;
691 len -= ret;
692
693 ret += snprintf(buf, len,
694 "curr_rx_desc:0x%p, curr_tx_desc:0x%p\n"
695 "dma_rx_desc:0x%p, dma_tx_desc:0x%p\n"
696 "dummy_rx_desc:0x%p, dummy_tx_desc:0x%p\n",
697 sport->curr_rx_desc, sport->curr_tx_desc,
698 sport->dma_rx_desc, sport->dma_tx_desc,
699 sport->dummy_rx_desc, sport->dummy_tx_desc);
700
701 return ret;
702}
703
704static irqreturn_t rx_handler(int irq, void *dev_id)
705{
706 unsigned int rx_stat;
707 struct sport_device *sport = dev_id;
708
709 pr_debug("%s enter\n", __func__);
710 sport_check_status(sport, NULL, &rx_stat, NULL);
711 if (!(rx_stat & DMA_DONE))
712 pr_err("rx dma is already stopped\n");
713
714 if (sport->rx_callback) {
715 sport->rx_callback(sport->rx_data);
716 return IRQ_HANDLED;
717 }
718
719 return IRQ_NONE;
720}
721
722static irqreturn_t tx_handler(int irq, void *dev_id)
723{
724 unsigned int tx_stat;
725 struct sport_device *sport = dev_id;
726 pr_debug("%s enter\n", __func__);
727 sport_check_status(sport, NULL, NULL, &tx_stat);
728 if (!(tx_stat & DMA_DONE)) {
729 pr_err("tx dma is already stopped\n");
730 return IRQ_HANDLED;
731 }
732 if (sport->tx_callback) {
733 sport->tx_callback(sport->tx_data);
734 return IRQ_HANDLED;
735 }
736
737 return IRQ_NONE;
738}
739
740static irqreturn_t err_handler(int irq, void *dev_id)
741{
742 unsigned int status = 0;
743 struct sport_device *sport = dev_id;
744
745 pr_debug("%s\n", __func__);
746 if (sport_check_status(sport, &status, NULL, NULL)) {
747 pr_err("error checking status ??");
748 return IRQ_NONE;
749 }
750
751 if (status & (TOVF|TUVF|ROVF|RUVF)) {
752 pr_info("sport status error:%s%s%s%s\n",
753 status & TOVF ? " TOVF" : "",
754 status & TUVF ? " TUVF" : "",
755 status & ROVF ? " ROVF" : "",
756 status & RUVF ? " RUVF" : "");
757 if (status & TOVF || status & TUVF) {
758 disable_dma(sport->dma_tx_chan);
759 if (sport->tx_run)
760 sport_tx_dma_start(sport, 0);
761 else
762 sport_tx_dma_start(sport, 1);
763 enable_dma(sport->dma_tx_chan);
764 } else {
765 disable_dma(sport->dma_rx_chan);
766 if (sport->rx_run)
767 sport_rx_dma_start(sport, 0);
768 else
769 sport_rx_dma_start(sport, 1);
770 enable_dma(sport->dma_rx_chan);
771 }
772 }
773 status = sport->regs->stat;
774 if (status & (TOVF|TUVF|ROVF|RUVF))
775 sport->regs->stat = (status & (TOVF|TUVF|ROVF|RUVF));
776 SSYNC();
777
778 if (sport->err_callback)
779 sport->err_callback(sport->err_data);
780
781 return IRQ_HANDLED;
782}
783
784int sport_set_rx_callback(struct sport_device *sport,
785 void (*rx_callback)(void *), void *rx_data)
786{
787 BUG_ON(rx_callback == NULL);
788 sport->rx_callback = rx_callback;
789 sport->rx_data = rx_data;
790
791 return 0;
792}
793EXPORT_SYMBOL(sport_set_rx_callback);
794
795int sport_set_tx_callback(struct sport_device *sport,
796 void (*tx_callback)(void *), void *tx_data)
797{
798 BUG_ON(tx_callback == NULL);
799 sport->tx_callback = tx_callback;
800 sport->tx_data = tx_data;
801
802 return 0;
803}
804EXPORT_SYMBOL(sport_set_tx_callback);
805
806int sport_set_err_callback(struct sport_device *sport,
807 void (*err_callback)(void *), void *err_data)
808{
809 BUG_ON(err_callback == NULL);
810 sport->err_callback = err_callback;
811 sport->err_data = err_data;
812
813 return 0;
814}
815EXPORT_SYMBOL(sport_set_err_callback);
816
817struct sport_device *sport_init(struct sport_param *param, unsigned wdsize,
818 unsigned dummy_count, void *private_data)
819{
820 int ret;
821 struct sport_device *sport;
822 pr_debug("%s enter\n", __func__);
823 BUG_ON(param == NULL);
824 BUG_ON(wdsize == 0 || dummy_count == 0);
825 sport = kmalloc(sizeof(struct sport_device), GFP_KERNEL);
826 if (!sport) {
827 pr_err("Failed to allocate for sport device\n");
828 return NULL;
829 }
830
831 memset(sport, 0, sizeof(struct sport_device));
832 sport->dma_rx_chan = param->dma_rx_chan;
833 sport->dma_tx_chan = param->dma_tx_chan;
834 sport->err_irq = param->err_irq;
835 sport->regs = param->regs;
836 sport->private_data = private_data;
837
838 if (request_dma(sport->dma_rx_chan, "SPORT RX Data") == -EBUSY) {
839 pr_err("Failed to request RX dma %d\n", \
840 sport->dma_rx_chan);
841 goto __init_err1;
842 }
843 if (set_dma_callback(sport->dma_rx_chan, rx_handler, sport) != 0) {
844 pr_err("Failed to request RX irq %d\n", \
845 sport->dma_rx_chan);
846 goto __init_err2;
847 }
848
849 if (request_dma(sport->dma_tx_chan, "SPORT TX Data") == -EBUSY) {
850 pr_err("Failed to request TX dma %d\n", \
851 sport->dma_tx_chan);
852 goto __init_err2;
853 }
854
855 if (set_dma_callback(sport->dma_tx_chan, tx_handler, sport) != 0) {
856 pr_err("Failed to request TX irq %d\n", \
857 sport->dma_tx_chan);
858 goto __init_err3;
859 }
860
861 if (request_irq(sport->err_irq, err_handler, IRQF_SHARED, "SPORT err",
862 sport) < 0) {
863 pr_err("Failed to request err irq:%d\n", \
864 sport->err_irq);
865 goto __init_err3;
866 }
867
868 pr_err("dma rx:%d tx:%d, err irq:%d, regs:%p\n",
869 sport->dma_rx_chan, sport->dma_tx_chan,
870 sport->err_irq, sport->regs);
871
872 sport->wdsize = wdsize;
873 sport->dummy_count = dummy_count;
874
875#if L1_DATA_A_LENGTH != 0
876 sport->dummy_buf = l1_data_sram_alloc(dummy_count * 2);
877#else
878 sport->dummy_buf = kmalloc(dummy_count * 2, GFP_KERNEL);
879#endif
880 if (sport->dummy_buf == NULL) {
881 pr_err("Failed to allocate dummy buffer\n");
882 goto __error;
883 }
884
885 memset(sport->dummy_buf, 0, dummy_count * 2);
886 ret = sport_config_rx_dummy(sport);
887 if (ret) {
888 pr_err("Failed to config rx dummy ring\n");
889 goto __error;
890 }
891 ret = sport_config_tx_dummy(sport);
892 if (ret) {
893 pr_err("Failed to config tx dummy ring\n");
894 goto __error;
895 }
896
897 return sport;
898__error:
899 free_irq(sport->err_irq, sport);
900__init_err3:
901 free_dma(sport->dma_tx_chan);
902__init_err2:
903 free_dma(sport->dma_rx_chan);
904__init_err1:
905 kfree(sport);
906 return NULL;
907}
908EXPORT_SYMBOL(sport_init);
909
910void sport_done(struct sport_device *sport)
911{
912 if (sport == NULL)
913 return;
914
915 sport_stop(sport);
916 if (sport->dma_rx_desc)
917 dma_free_coherent(NULL, sport->rx_desc_bytes,
918 sport->dma_rx_desc, 0);
919 if (sport->dma_tx_desc)
920 dma_free_coherent(NULL, sport->tx_desc_bytes,
921 sport->dma_tx_desc, 0);
922
923#if L1_DATA_A_LENGTH != 0
924 l1_data_sram_free(sport->dummy_rx_desc);
925 l1_data_sram_free(sport->dummy_tx_desc);
926 l1_data_sram_free(sport->dummy_buf);
927#else
928 dma_free_coherent(NULL, 2*sizeof(struct dmasg),
929 sport->dummy_rx_desc, 0);
930 dma_free_coherent(NULL, 2*sizeof(struct dmasg),
931 sport->dummy_tx_desc, 0);
932 kfree(sport->dummy_buf);
933#endif
934 free_dma(sport->dma_rx_chan);
935 free_dma(sport->dma_tx_chan);
936 free_irq(sport->err_irq, sport);
937
938 kfree(sport);
939 sport = NULL;
940}
941EXPORT_SYMBOL(sport_done);
942/*
943* It is only used to send several bytes when dma is not enabled
944 * sport controller is configured but not enabled.
945 * Multichannel cannot works with pio mode */
946/* Used by ac97 to write and read codec register */
947int sport_send_and_recv(struct sport_device *sport, u8 *out_data, \
948 u8 *in_data, int len)
949{
950 unsigned short dma_config;
951 unsigned short status;
952 unsigned long flags;
953 unsigned long wait = 0;
954
955 pr_debug("%s enter, out_data:%p, in_data:%p len:%d\n", \
956 __func__, out_data, in_data, len);
957 pr_debug("tcr1:0x%04x, tcr2:0x%04x, tclkdiv:0x%04x, tfsdiv:0x%04x\n"
958 "mcmc1:0x%04x, mcmc2:0x%04x\n",
959 sport->regs->tcr1, sport->regs->tcr2,
960 sport->regs->tclkdiv, sport->regs->tfsdiv,
961 sport->regs->mcmc1, sport->regs->mcmc2);
962 flush_dcache_range((unsigned)out_data, (unsigned)(out_data + len));
963
964 /* Enable tx dma */
965 dma_config = (RESTART | WDSIZE_16 | DI_EN);
966 set_dma_start_addr(sport->dma_tx_chan, (unsigned long)out_data);
967 set_dma_x_count(sport->dma_tx_chan, len/2);
968 set_dma_x_modify(sport->dma_tx_chan, 2);
969 set_dma_config(sport->dma_tx_chan, dma_config);
970 enable_dma(sport->dma_tx_chan);
971
972 if (in_data != NULL) {
973 invalidate_dcache_range((unsigned)in_data, \
974 (unsigned)(in_data + len));
975 /* Enable rx dma */
976 dma_config = (RESTART | WDSIZE_16 | WNR | DI_EN);
977 set_dma_start_addr(sport->dma_rx_chan, (unsigned long)in_data);
978 set_dma_x_count(sport->dma_rx_chan, len/2);
979 set_dma_x_modify(sport->dma_rx_chan, 2);
980 set_dma_config(sport->dma_rx_chan, dma_config);
981 enable_dma(sport->dma_rx_chan);
982 }
983
984 local_irq_save(flags);
985 sport->regs->tcr1 |= TSPEN;
986 sport->regs->rcr1 |= RSPEN;
987 SSYNC();
988
989 status = get_dma_curr_irqstat(sport->dma_tx_chan);
990 while (status & DMA_RUN) {
991 udelay(1);
992 status = get_dma_curr_irqstat(sport->dma_tx_chan);
993 pr_debug("DMA status:0x%04x\n", status);
994 if (wait++ > 100)
995 goto __over;
996 }
997 status = sport->regs->stat;
998 wait = 0;
999
1000 while (!(status & TXHRE)) {
1001 pr_debug("sport status:0x%04x\n", status);
1002 udelay(1);
1003 status = *(unsigned short *)&sport->regs->stat;
1004 if (wait++ > 1000)
1005 goto __over;
1006 }
1007 /* Wait for the last byte sent out */
1008 udelay(20);
1009 pr_debug("sport status:0x%04x\n", status);
1010
1011__over:
1012 sport->regs->tcr1 &= ~TSPEN;
1013 sport->regs->rcr1 &= ~RSPEN;
1014 SSYNC();
1015 disable_dma(sport->dma_tx_chan);
1016 /* Clear the status */
1017 clear_dma_irqstat(sport->dma_tx_chan);
1018 if (in_data != NULL) {
1019 disable_dma(sport->dma_rx_chan);
1020 clear_dma_irqstat(sport->dma_rx_chan);
1021 }
1022 SSYNC();
1023 local_irq_restore(flags);
1024
1025 return 0;
1026}
1027EXPORT_SYMBOL(sport_send_and_recv);
1028
1029MODULE_AUTHOR("Roy Huang");
1030MODULE_DESCRIPTION("SPORT driver for ADI Blackfin");
1031MODULE_LICENSE("GPL");
1032
diff --git a/sound/soc/blackfin/bf5xx-sport.h b/sound/soc/blackfin/bf5xx-sport.h
new file mode 100644
index 000000000000..fcadcc081f7f
--- /dev/null
+++ b/sound/soc/blackfin/bf5xx-sport.h
@@ -0,0 +1,194 @@
1/*
2 * File: bf5xx_ac97_sport.h
3 * Based on:
4 * Author: Roy Huang <roy.huang@analog.com>
5 *
6 * Created:
7 * Description:
8 *
9 * Copyright 2004-2007 Analog Devices Inc.
10 *
11 * Bugs: Enter bugs at http://blackfin.uclinux.org/
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see the file COPYING, or write
25 * to the Free Software Foundation, Inc.,
26 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 */
28
29
30#ifndef __BF5XX_SPORT_H__
31#define __BF5XX_SPORT_H__
32
33#include <linux/types.h>
34#include <linux/wait.h>
35#include <linux/workqueue.h>
36#include <asm/dma.h>
37
38struct sport_register {
39 u16 tcr1; u16 reserved0;
40 u16 tcr2; u16 reserved1;
41 u16 tclkdiv; u16 reserved2;
42 u16 tfsdiv; u16 reserved3;
43 u32 tx;
44 u32 reserved_l0;
45 u32 rx;
46 u32 reserved_l1;
47 u16 rcr1; u16 reserved4;
48 u16 rcr2; u16 reserved5;
49 u16 rclkdiv; u16 reserved6;
50 u16 rfsdiv; u16 reserved7;
51 u16 stat; u16 reserved8;
52 u16 chnl; u16 reserved9;
53 u16 mcmc1; u16 reserved10;
54 u16 mcmc2; u16 reserved11;
55 u32 mtcs0;
56 u32 mtcs1;
57 u32 mtcs2;
58 u32 mtcs3;
59 u32 mrcs0;
60 u32 mrcs1;
61 u32 mrcs2;
62 u32 mrcs3;
63};
64
65#define DESC_ELEMENT_COUNT 9
66
67struct sport_device {
68 int dma_rx_chan;
69 int dma_tx_chan;
70 int err_irq;
71 struct sport_register *regs;
72
73 unsigned char *rx_buf;
74 unsigned char *tx_buf;
75 unsigned int rx_fragsize;
76 unsigned int tx_fragsize;
77 unsigned int rx_frags;
78 unsigned int tx_frags;
79 unsigned int wdsize;
80
81 /* for dummy dma transfer */
82 void *dummy_buf;
83 unsigned int dummy_count;
84
85 /* DMA descriptor ring head of current audio stream*/
86 struct dmasg *dma_rx_desc;
87 struct dmasg *dma_tx_desc;
88 unsigned int rx_desc_bytes;
89 unsigned int tx_desc_bytes;
90
91 unsigned int rx_run:1; /* rx is running */
92 unsigned int tx_run:1; /* tx is running */
93
94 struct dmasg *dummy_rx_desc;
95 struct dmasg *dummy_tx_desc;
96
97 struct dmasg *curr_rx_desc;
98 struct dmasg *curr_tx_desc;
99
100 int rx_curr_frag;
101 int tx_curr_frag;
102
103 unsigned int rcr1;
104 unsigned int rcr2;
105 int rx_tdm_count;
106
107 unsigned int tcr1;
108 unsigned int tcr2;
109 int tx_tdm_count;
110
111 void (*rx_callback)(void *data);
112 void *rx_data;
113 void (*tx_callback)(void *data);
114 void *tx_data;
115 void (*err_callback)(void *data);
116 void *err_data;
117 unsigned char *tx_dma_buf;
118 unsigned char *rx_dma_buf;
119#ifdef CONFIG_SND_MMAP_SUPPORT
120 dma_addr_t tx_dma_phy;
121 dma_addr_t rx_dma_phy;
122 int tx_pos;/*pcm sample count*/
123 int rx_pos;
124 unsigned int tx_buffer_size;
125 unsigned int rx_buffer_size;
126 int tx_delay_pos;
127 int once;
128#endif
129 void *private_data;
130};
131
132extern struct sport_device *sport_handle;
133
134struct sport_param {
135 int dma_rx_chan;
136 int dma_tx_chan;
137 int err_irq;
138 struct sport_register *regs;
139};
140
141struct sport_device *sport_init(struct sport_param *param, unsigned wdsize,
142 unsigned dummy_count, void *private_data);
143
144void sport_done(struct sport_device *sport);
145
146/* first use these ...*/
147
148/* note: multichannel is in units of 8 channels, tdm_count is number of channels
149 * NOT / 8 ! all channels are enabled by default */
150int sport_set_multichannel(struct sport_device *sport, int tdm_count,
151 u32 mask, int packed);
152
153int sport_config_rx(struct sport_device *sport,
154 unsigned int rcr1, unsigned int rcr2,
155 unsigned int clkdiv, unsigned int fsdiv);
156
157int sport_config_tx(struct sport_device *sport,
158 unsigned int tcr1, unsigned int tcr2,
159 unsigned int clkdiv, unsigned int fsdiv);
160
161/* ... then these: */
162
163/* buffer size (in bytes) == fragcount * fragsize_bytes */
164
165/* this is not a very general api, it sets the dma to 2d autobuffer mode */
166
167int sport_config_rx_dma(struct sport_device *sport, void *buf,
168 int fragcount, size_t fragsize_bytes);
169
170int sport_config_tx_dma(struct sport_device *sport, void *buf,
171 int fragcount, size_t fragsize_bytes);
172
173int sport_tx_start(struct sport_device *sport);
174int sport_tx_stop(struct sport_device *sport);
175int sport_rx_start(struct sport_device *sport);
176int sport_rx_stop(struct sport_device *sport);
177
178/* for use in interrupt handler */
179unsigned long sport_curr_offset_rx(struct sport_device *sport);
180unsigned long sport_curr_offset_tx(struct sport_device *sport);
181
182void sport_incfrag(struct sport_device *sport, int *frag, int tx);
183void sport_decfrag(struct sport_device *sport, int *frag, int tx);
184
185int sport_set_rx_callback(struct sport_device *sport,
186 void (*rx_callback)(void *), void *rx_data);
187int sport_set_tx_callback(struct sport_device *sport,
188 void (*tx_callback)(void *), void *tx_data);
189int sport_set_err_callback(struct sport_device *sport,
190 void (*err_callback)(void *), void *err_data);
191
192int sport_send_and_recv(struct sport_device *sport, u8 *out_data, \
193 u8 *in_data, int len);
194#endif /* BF53X_SPORT_H */
diff --git a/sound/soc/blackfin/bf5xx-ssm2602.c b/sound/soc/blackfin/bf5xx-ssm2602.c
new file mode 100644
index 000000000000..e15f67fd7769
--- /dev/null
+++ b/sound/soc/blackfin/bf5xx-ssm2602.c
@@ -0,0 +1,186 @@
1/*
2 * File: sound/soc/blackfin/bf5xx-ssm2602.c
3 * Author: Cliff Cai <Cliff.Cai@analog.com>
4 *
5 * Created: Tue June 06 2008
6 * Description: board driver for SSM2602 sound chip
7 *
8 * Modified:
9 * Copyright 2008 Analog Devices Inc.
10 *
11 * Bugs: Enter bugs at http://blackfin.uclinux.org/
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see the file COPYING, or write
25 * to the Free Software Foundation, Inc.,
26 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 */
28
29#include <linux/module.h>
30#include <linux/moduleparam.h>
31#include <linux/device.h>
32
33#include <sound/core.h>
34#include <sound/pcm.h>
35#include <sound/soc.h>
36#include <sound/soc-dapm.h>
37#include <sound/pcm_params.h>
38
39#include <asm/dma.h>
40#include <asm/portmux.h>
41#include <linux/gpio.h>
42#include "../codecs/ssm2602.h"
43#include "bf5xx-sport.h"
44#include "bf5xx-i2s-pcm.h"
45#include "bf5xx-i2s.h"
46
47static struct snd_soc_machine bf5xx_ssm2602;
48
49static int bf5xx_ssm2602_startup(struct snd_pcm_substream *substream)
50{
51 struct snd_soc_pcm_runtime *rtd = substream->private_data;
52 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
53
54 pr_debug("%s enter\n", __func__);
55 cpu_dai->private_data = sport_handle;
56 return 0;
57}
58
59static int bf5xx_ssm2602_hw_params(struct snd_pcm_substream *substream,
60 struct snd_pcm_hw_params *params)
61{
62 struct snd_soc_pcm_runtime *rtd = substream->private_data;
63 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
64 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
65 unsigned int clk = 0;
66 int ret = 0;
67
68 pr_debug("%s rate %d format %x\n", __func__, params_rate(params),
69 params_format(params));
70 /*
71 * If you are using a crystal source which frequency is not 12MHz
72 * then modify the below case statement with frequency of the crystal.
73 *
74 * If you are using the SPORT to generate clocking then this is
75 * where to do it.
76 */
77
78 switch (params_rate(params)) {
79 case 8000:
80 case 16000:
81 case 48000:
82 case 96000:
83 case 11025:
84 case 22050:
85 case 44100:
86 clk = 12000000;
87 break;
88 }
89
90 /*
91 * CODEC is master for BCLK and LRC in this configuration.
92 */
93
94 /* set codec DAI configuration */
95 ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
96 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
97 if (ret < 0)
98 return ret;
99 /* set cpu DAI configuration */
100 ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
101 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
102 if (ret < 0)
103 return ret;
104
105 ret = codec_dai->dai_ops.set_sysclk(codec_dai, SSM2602_SYSCLK, clk,
106 SND_SOC_CLOCK_IN);
107 if (ret < 0)
108 return ret;
109
110 return 0;
111}
112
113static struct snd_soc_ops bf5xx_ssm2602_ops = {
114 .startup = bf5xx_ssm2602_startup,
115 .hw_params = bf5xx_ssm2602_hw_params,
116};
117
118static struct snd_soc_dai_link bf5xx_ssm2602_dai = {
119 .name = "ssm2602",
120 .stream_name = "SSM2602",
121 .cpu_dai = &bf5xx_i2s_dai,
122 .codec_dai = &ssm2602_dai,
123 .ops = &bf5xx_ssm2602_ops,
124};
125
126/*
127 * SSM2602 2 wire address is determined by CSB
128 * state during powerup.
129 * low = 0x1a
130 * high = 0x1b
131 */
132
133static struct ssm2602_setup_data bf5xx_ssm2602_setup = {
134 .i2c_bus = 0,
135 .i2c_address = 0x1b,
136};
137
138static struct snd_soc_machine bf5xx_ssm2602 = {
139 .name = "bf5xx_ssm2602",
140 .dai_link = &bf5xx_ssm2602_dai,
141 .num_links = 1,
142};
143
144static struct snd_soc_device bf5xx_ssm2602_snd_devdata = {
145 .machine = &bf5xx_ssm2602,
146 .platform = &bf5xx_i2s_soc_platform,
147 .codec_dev = &soc_codec_dev_ssm2602,
148 .codec_data = &bf5xx_ssm2602_setup,
149};
150
151static struct platform_device *bf52x_ssm2602_snd_device;
152
153static int __init bf5xx_ssm2602_init(void)
154{
155 int ret;
156
157 pr_debug("%s enter\n", __func__);
158 bf52x_ssm2602_snd_device = platform_device_alloc("soc-audio", -1);
159 if (!bf52x_ssm2602_snd_device)
160 return -ENOMEM;
161
162 platform_set_drvdata(bf52x_ssm2602_snd_device,
163 &bf5xx_ssm2602_snd_devdata);
164 bf5xx_ssm2602_snd_devdata.dev = &bf52x_ssm2602_snd_device->dev;
165 ret = platform_device_add(bf52x_ssm2602_snd_device);
166
167 if (ret)
168 platform_device_put(bf52x_ssm2602_snd_device);
169
170 return ret;
171}
172
173static void __exit bf5xx_ssm2602_exit(void)
174{
175 pr_debug("%s enter\n", __func__);
176 platform_device_unregister(bf52x_ssm2602_snd_device);
177}
178
179module_init(bf5xx_ssm2602_init);
180module_exit(bf5xx_ssm2602_exit);
181
182/* Module information */
183MODULE_AUTHOR("Cliff Cai");
184MODULE_DESCRIPTION("ALSA SoC SSM2602 BF527-EZKIT");
185MODULE_LICENSE("GPL");
186
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 1db04a28a53d..38a0e3b620a7 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -1,32 +1,45 @@
1config SND_SOC_AC97_CODEC 1config SND_SOC_ALL_CODECS
2 tristate 2 tristate "Build all ASoC CODEC drivers"
3 select SND_AC97_CODEC 3 depends on I2C
4 4 select SPI
5config SND_SOC_AK4535 5 select SPI_MASTER
6 tristate 6 select SND_SOC_AD73311
7 7 select SND_SOC_AK4535
8config SND_SOC_UDA1380 8 select SND_SOC_CS4270
9 tristate 9 select SND_SOC_SSM2602
10 select SND_SOC_TLV320AIC23
11 select SND_SOC_TLV320AIC26
12 select SND_SOC_TLV320AIC3X
13 select SND_SOC_UDA1380
14 select SND_SOC_WM8510
15 select SND_SOC_WM8580
16 select SND_SOC_WM8731
17 select SND_SOC_WM8750
18 select SND_SOC_WM8753
19 select SND_SOC_WM8900
20 select SND_SOC_WM8903
21 select SND_SOC_WM8971
22 select SND_SOC_WM8990
23 help
24 Normally ASoC codec drivers are only built if a machine driver which
25 uses them is also built since they are only usable with a machine
26 driver. Selecting this option will allow these drivers to be built
27 without an explicit machine driver for test and development purposes.
10 28
11config SND_SOC_WM8510 29 If unsure select "N".
12 tristate
13 30
14config SND_SOC_WM8731
15 tristate
16 31
17config SND_SOC_WM8750 32config SND_SOC_AC97_CODEC
18 tristate
19
20config SND_SOC_WM8753
21 tristate 33 tristate
34 select SND_AC97_CODEC
22 35
23config SND_SOC_WM8990 36config SND_SOC_AD1980
24 tristate 37 tristate
25 38
26config SND_SOC_WM9712 39config SND_SOC_AD73311
27 tristate 40 tristate
28 41
29config SND_SOC_WM9713 42config SND_SOC_AK4535
30 tristate 43 tristate
31 44
32# Cirrus Logic CS4270 Codec 45# Cirrus Logic CS4270 Codec
@@ -47,6 +60,53 @@ config SND_SOC_CS4270_VD33_ERRATA
47 bool 60 bool
48 depends on SND_SOC_CS4270 61 depends on SND_SOC_CS4270
49 62
63config SND_SOC_SSM2602
64 tristate
65
66config SND_SOC_TLV320AIC23
67 tristate
68 depends on I2C
69
70config SND_SOC_TLV320AIC26
71 tristate "TI TLV320AIC26 Codec support" if SND_SOC_OF_SIMPLE
72 depends on SPI
73
50config SND_SOC_TLV320AIC3X 74config SND_SOC_TLV320AIC3X
51 tristate 75 tristate
52 depends on I2C 76 depends on I2C
77
78config SND_SOC_UDA1380
79 tristate
80
81config SND_SOC_WM8510
82 tristate
83
84config SND_SOC_WM8580
85 tristate
86
87config SND_SOC_WM8731
88 tristate
89
90config SND_SOC_WM8750
91 tristate
92
93config SND_SOC_WM8753
94 tristate
95
96config SND_SOC_WM8900
97 tristate
98
99config SND_SOC_WM8903
100 tristate
101
102config SND_SOC_WM8971
103 tristate
104
105config SND_SOC_WM8990
106 tristate
107
108config SND_SOC_WM9712
109 tristate
110
111config SND_SOC_WM9713
112 tristate
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index d7b97abcf729..90f0a585fc70 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -1,25 +1,43 @@
1snd-soc-ac97-objs := ac97.o 1snd-soc-ac97-objs := ac97.o
2snd-soc-ad1980-objs := ad1980.o
3snd-soc-ad73311-objs := ad73311.o
2snd-soc-ak4535-objs := ak4535.o 4snd-soc-ak4535-objs := ak4535.o
5snd-soc-cs4270-objs := cs4270.o
6snd-soc-ssm2602-objs := ssm2602.o
7snd-soc-tlv320aic23-objs := tlv320aic23.o
8snd-soc-tlv320aic26-objs := tlv320aic26.o
9snd-soc-tlv320aic3x-objs := tlv320aic3x.o
3snd-soc-uda1380-objs := uda1380.o 10snd-soc-uda1380-objs := uda1380.o
4snd-soc-wm8510-objs := wm8510.o 11snd-soc-wm8510-objs := wm8510.o
12snd-soc-wm8580-objs := wm8580.o
5snd-soc-wm8731-objs := wm8731.o 13snd-soc-wm8731-objs := wm8731.o
6snd-soc-wm8750-objs := wm8750.o 14snd-soc-wm8750-objs := wm8750.o
7snd-soc-wm8753-objs := wm8753.o 15snd-soc-wm8753-objs := wm8753.o
16snd-soc-wm8900-objs := wm8900.o
17snd-soc-wm8903-objs := wm8903.o
18snd-soc-wm8971-objs := wm8971.o
8snd-soc-wm8990-objs := wm8990.o 19snd-soc-wm8990-objs := wm8990.o
9snd-soc-wm9712-objs := wm9712.o 20snd-soc-wm9712-objs := wm9712.o
10snd-soc-wm9713-objs := wm9713.o 21snd-soc-wm9713-objs := wm9713.o
11snd-soc-cs4270-objs := cs4270.o
12snd-soc-tlv320aic3x-objs := tlv320aic3x.o
13 22
14obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o 23obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o
24obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o
25obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o
15obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o 26obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o
27obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o
28obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o
29obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o
30obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o
31obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o
16obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o 32obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o
17obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o 33obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o
34obj-$(CONFIG_SND_SOC_WM8580) += snd-soc-wm8580.o
18obj-$(CONFIG_SND_SOC_WM8731) += snd-soc-wm8731.o 35obj-$(CONFIG_SND_SOC_WM8731) += snd-soc-wm8731.o
19obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o 36obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o
20obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o 37obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o
38obj-$(CONFIG_SND_SOC_WM8900) += snd-soc-wm8900.o
39obj-$(CONFIG_SND_SOC_WM8903) += snd-soc-wm8903.o
40obj-$(CONFIG_SND_SOC_WM8971) += snd-soc-wm8971.o
21obj-$(CONFIG_SND_SOC_WM8990) += snd-soc-wm8990.o 41obj-$(CONFIG_SND_SOC_WM8990) += snd-soc-wm8990.o
22obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o 42obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o
23obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o 43obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o
24obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o
25obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c
index 61fd96ca7bc7..bd1ebdc6c86c 100644
--- a/sound/soc/codecs/ac97.c
+++ b/sound/soc/codecs/ac97.c
@@ -2,8 +2,7 @@
2 * ac97.c -- ALSA Soc AC97 codec support 2 * ac97.c -- ALSA Soc AC97 codec support
3 * 3 *
4 * Copyright 2005 Wolfson Microelectronics PLC. 4 * Copyright 2005 Wolfson Microelectronics PLC.
5 * Author: Liam Girdwood 5 * Author: Liam Girdwood <lrg@slimlogic.co.uk>
6 * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
7 * 6 *
8 * This program is free software; you can redistribute it and/or modify it 7 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the 8 * under the terms of the GNU General Public License as published by the
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c
new file mode 100644
index 000000000000..1397b8e06c0b
--- /dev/null
+++ b/sound/soc/codecs/ad1980.c
@@ -0,0 +1,308 @@
1/*
2 * ad1980.c -- ALSA Soc AD1980 codec support
3 *
4 * Copyright: Analog Device Inc.
5 * Author: Roy Huang <roy.huang@analog.com>
6 * Cliff Cai <cliff.cai@analog.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 */
13
14#include <linux/init.h>
15#include <linux/module.h>
16#include <linux/kernel.h>
17#include <linux/device.h>
18#include <sound/core.h>
19#include <sound/pcm.h>
20#include <sound/ac97_codec.h>
21#include <sound/initval.h>
22#include <sound/soc.h>
23#include <sound/soc-dapm.h>
24
25#include "ad1980.h"
26
27static unsigned int ac97_read(struct snd_soc_codec *codec,
28 unsigned int reg);
29static int ac97_write(struct snd_soc_codec *codec,
30 unsigned int reg, unsigned int val);
31
32/*
33 * AD1980 register cache
34 */
35static const u16 ad1980_reg[] = {
36 0x0090, 0x8000, 0x8000, 0x8000, /* 0 - 6 */
37 0x0000, 0x0000, 0x8008, 0x8008, /* 8 - e */
38 0x8808, 0x8808, 0x0000, 0x8808, /* 10 - 16 */
39 0x8808, 0x0000, 0x8000, 0x0000, /* 18 - 1e */
40 0x0000, 0x0000, 0x0000, 0x0000, /* 20 - 26 */
41 0x03c7, 0x0000, 0xbb80, 0xbb80, /* 28 - 2e */
42 0xbb80, 0xbb80, 0x0000, 0x8080, /* 30 - 36 */
43 0x8080, 0x2000, 0x0000, 0x0000, /* 38 - 3e */
44 0x0000, 0x0000, 0x0000, 0x0000, /* reserved */
45 0x0000, 0x0000, 0x0000, 0x0000, /* reserved */
46 0x0000, 0x0000, 0x0000, 0x0000, /* reserved */
47 0x0000, 0x0000, 0x0000, 0x0000, /* reserved */
48 0x8080, 0x0000, 0x0000, 0x0000, /* 60 - 66 */
49 0x0000, 0x0000, 0x0000, 0x0000, /* reserved */
50 0x0000, 0x0000, 0x1001, 0x0000, /* 70 - 76 */
51 0x0000, 0x0000, 0x4144, 0x5370 /* 78 - 7e */
52};
53
54static const char *ad1980_rec_sel[] = {"Mic", "CD", "NC", "AUX", "Line",
55 "Stereo Mix", "Mono Mix", "Phone"};
56
57static const struct soc_enum ad1980_cap_src =
58 SOC_ENUM_DOUBLE(AC97_REC_SEL, 8, 0, 7, ad1980_rec_sel);
59
60static const struct snd_kcontrol_new ad1980_snd_ac97_controls[] = {
61SOC_DOUBLE("Master Playback Volume", AC97_MASTER, 8, 0, 31, 1),
62SOC_SINGLE("Master Playback Switch", AC97_MASTER, 15, 1, 1),
63
64SOC_DOUBLE("Headphone Playback Volume", AC97_HEADPHONE, 8, 0, 31, 1),
65SOC_SINGLE("Headphone Playback Switch", AC97_HEADPHONE, 15, 1, 1),
66
67SOC_DOUBLE("PCM Playback Volume", AC97_PCM, 8, 0, 31, 1),
68SOC_SINGLE("PCM Playback Switch", AC97_PCM, 15, 1, 1),
69
70SOC_DOUBLE("PCM Capture Volume", AC97_REC_GAIN, 8, 0, 31, 0),
71SOC_SINGLE("PCM Capture Switch", AC97_REC_GAIN, 15, 1, 1),
72
73SOC_SINGLE("Mono Playback Volume", AC97_MASTER_MONO, 0, 31, 1),
74SOC_SINGLE("Mono Playback Switch", AC97_MASTER_MONO, 15, 1, 1),
75
76SOC_SINGLE("Phone Capture Volume", AC97_PHONE, 0, 31, 1),
77SOC_SINGLE("Phone Capture Switch", AC97_PHONE, 15, 1, 1),
78
79SOC_SINGLE("Mic Volume", AC97_MIC, 0, 31, 1),
80SOC_SINGLE("Mic Switch", AC97_MIC, 15, 1, 1),
81
82SOC_SINGLE("Stereo Mic Switch", AC97_AD_MISC, 6, 1, 0),
83SOC_DOUBLE("Line HP Swap Switch", AC97_AD_MISC, 10, 5, 1, 0),
84
85SOC_DOUBLE("Surround Playback Volume", AC97_SURROUND_MASTER, 8, 0, 31, 1),
86SOC_DOUBLE("Surround Playback Switch", AC97_SURROUND_MASTER, 15, 7, 1, 1),
87
88SOC_ENUM("Capture Source", ad1980_cap_src),
89
90SOC_SINGLE("Mic Boost Switch", AC97_MIC, 6, 1, 0),
91};
92
93/* add non dapm controls */
94static int ad1980_add_controls(struct snd_soc_codec *codec)
95{
96 int err, i;
97
98 for (i = 0; i < ARRAY_SIZE(ad1980_snd_ac97_controls); i++) {
99 err = snd_ctl_add(codec->card, snd_soc_cnew(
100 &ad1980_snd_ac97_controls[i], codec, NULL));
101 if (err < 0)
102 return err;
103 }
104 return 0;
105}
106
107static unsigned int ac97_read(struct snd_soc_codec *codec,
108 unsigned int reg)
109{
110 u16 *cache = codec->reg_cache;
111
112 switch (reg) {
113 case AC97_RESET:
114 case AC97_INT_PAGING:
115 case AC97_POWERDOWN:
116 case AC97_EXTENDED_STATUS:
117 case AC97_VENDOR_ID1:
118 case AC97_VENDOR_ID2:
119 return soc_ac97_ops.read(codec->ac97, reg);
120 default:
121 reg = reg >> 1;
122
123 if (reg >= (ARRAY_SIZE(ad1980_reg)))
124 return -EINVAL;
125
126 return cache[reg];
127 }
128}
129
130static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
131 unsigned int val)
132{
133 u16 *cache = codec->reg_cache;
134
135 soc_ac97_ops.write(codec->ac97, reg, val);
136 reg = reg >> 1;
137 if (reg < (ARRAY_SIZE(ad1980_reg)))
138 cache[reg] = val;
139
140 return 0;
141}
142
143struct snd_soc_dai ad1980_dai = {
144 .name = "AC97",
145 .playback = {
146 .stream_name = "Playback",
147 .channels_min = 2,
148 .channels_max = 2,
149 .rates = SNDRV_PCM_RATE_48000,
150 .formats = SNDRV_PCM_FMTBIT_S16_LE, },
151 .capture = {
152 .stream_name = "Capture",
153 .channels_min = 2,
154 .channels_max = 2,
155 .rates = SNDRV_PCM_RATE_48000,
156 .formats = SNDRV_PCM_FMTBIT_S16_LE, },
157};
158EXPORT_SYMBOL_GPL(ad1980_dai);
159
160static int ad1980_reset(struct snd_soc_codec *codec, int try_warm)
161{
162 u16 retry_cnt = 0;
163
164retry:
165 if (try_warm && soc_ac97_ops.warm_reset) {
166 soc_ac97_ops.warm_reset(codec->ac97);
167 if (ac97_read(codec, AC97_RESET) == 0x0090)
168 return 1;
169 }
170
171 soc_ac97_ops.reset(codec->ac97);
172 /* Set bit 16slot in register 74h, then every slot will has only 16
173 * bits. This command is sent out in 20bit mode, in which case the
174 * first nibble of data is eaten by the addr. (Tag is always 16 bit)*/
175 ac97_write(codec, AC97_AD_SERIAL_CFG, 0x9900);
176
177 if (ac97_read(codec, AC97_RESET) != 0x0090)
178 goto err;
179 return 0;
180
181err:
182 while (retry_cnt++ < 10)
183 goto retry;
184
185 printk(KERN_ERR "AD1980 AC97 reset failed\n");
186 return -EIO;
187}
188
189static int ad1980_soc_probe(struct platform_device *pdev)
190{
191 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
192 struct snd_soc_codec *codec;
193 int ret = 0;
194 u16 vendor_id2;
195
196 printk(KERN_INFO "AD1980 SoC Audio Codec\n");
197
198 socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
199 if (socdev->codec == NULL)
200 return -ENOMEM;
201 codec = socdev->codec;
202 mutex_init(&codec->mutex);
203
204 codec->reg_cache =
205 kzalloc(sizeof(u16) * ARRAY_SIZE(ad1980_reg), GFP_KERNEL);
206 if (codec->reg_cache == NULL) {
207 ret = -ENOMEM;
208 goto cache_err;
209 }
210 memcpy(codec->reg_cache, ad1980_reg, sizeof(u16) * \
211 ARRAY_SIZE(ad1980_reg));
212 codec->reg_cache_size = sizeof(u16) * ARRAY_SIZE(ad1980_reg);
213 codec->reg_cache_step = 2;
214 codec->name = "AD1980";
215 codec->owner = THIS_MODULE;
216 codec->dai = &ad1980_dai;
217 codec->num_dai = 1;
218 codec->write = ac97_write;
219 codec->read = ac97_read;
220 INIT_LIST_HEAD(&codec->dapm_widgets);
221 INIT_LIST_HEAD(&codec->dapm_paths);
222
223 ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);
224 if (ret < 0) {
225 printk(KERN_ERR "ad1980: failed to register AC97 codec\n");
226 goto codec_err;
227 }
228
229 /* register pcms */
230 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
231 if (ret < 0)
232 goto pcm_err;
233
234
235 ret = ad1980_reset(codec, 0);
236 if (ret < 0) {
237 printk(KERN_ERR "AC97 link error\n");
238 goto reset_err;
239 }
240
241 /* Read out vendor ID to make sure it is ad1980 */
242 if (ac97_read(codec, AC97_VENDOR_ID1) != 0x4144)
243 goto reset_err;
244
245 vendor_id2 = ac97_read(codec, AC97_VENDOR_ID2);
246
247 if (vendor_id2 != 0x5370) {
248 if (vendor_id2 != 0x5374)
249 goto reset_err;
250 else
251 printk(KERN_WARNING "ad1980: "
252 "Found AD1981 - only 2/2 IN/OUT Channels "
253 "supported\n");
254 }
255
256 ac97_write(codec, AC97_MASTER, 0x0000); /* unmute line out volume */
257 ac97_write(codec, AC97_PCM, 0x0000); /* unmute PCM out volume */
258 ac97_write(codec, AC97_REC_GAIN, 0x0000);/* unmute record volume */
259
260 ad1980_add_controls(codec);
261 ret = snd_soc_register_card(socdev);
262 if (ret < 0) {
263 printk(KERN_ERR "ad1980: failed to register card\n");
264 goto reset_err;
265 }
266
267 return 0;
268
269reset_err:
270 snd_soc_free_pcms(socdev);
271
272pcm_err:
273 snd_soc_free_ac97_codec(codec);
274
275codec_err:
276 kfree(codec->reg_cache);
277
278cache_err:
279 kfree(socdev->codec);
280 socdev->codec = NULL;
281 return ret;
282}
283
284static int ad1980_soc_remove(struct platform_device *pdev)
285{
286 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
287 struct snd_soc_codec *codec = socdev->codec;
288
289 if (codec == NULL)
290 return 0;
291
292 snd_soc_dapm_free(socdev);
293 snd_soc_free_pcms(socdev);
294 snd_soc_free_ac97_codec(codec);
295 kfree(codec->reg_cache);
296 kfree(codec);
297 return 0;
298}
299
300struct snd_soc_codec_device soc_codec_dev_ad1980 = {
301 .probe = ad1980_soc_probe,
302 .remove = ad1980_soc_remove,
303};
304EXPORT_SYMBOL_GPL(soc_codec_dev_ad1980);
305
306MODULE_DESCRIPTION("ASoC ad1980 driver");
307MODULE_AUTHOR("Roy Huang, Cliff Cai");
308MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/ad1980.h b/sound/soc/codecs/ad1980.h
new file mode 100644
index 000000000000..db6c8500d66b
--- /dev/null
+++ b/sound/soc/codecs/ad1980.h
@@ -0,0 +1,23 @@
1/*
2 * ad1980.h -- ad1980 Soc Audio driver
3 */
4
5#ifndef _AD1980_H
6#define _AD1980_H
7/* Bit definition of Power-Down Control/Status Register */
8#define ADC 0x0001
9#define DAC 0x0002
10#define ANL 0x0004
11#define REF 0x0008
12#define PR0 0x0100
13#define PR1 0x0200
14#define PR2 0x0400
15#define PR3 0x0800
16#define PR4 0x1000
17#define PR5 0x2000
18#define PR6 0x4000
19
20extern struct snd_soc_dai ad1980_dai;
21extern struct snd_soc_codec_device soc_codec_dev_ad1980;
22
23#endif
diff --git a/sound/soc/codecs/ad73311.c b/sound/soc/codecs/ad73311.c
new file mode 100644
index 000000000000..37af8607b00a
--- /dev/null
+++ b/sound/soc/codecs/ad73311.c
@@ -0,0 +1,107 @@
1/*
2 * ad73311.c -- ALSA Soc AD73311 codec support
3 *
4 * Copyright: Analog Device Inc.
5 * Author: Cliff Cai <cliff.cai@analog.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 *
12 * Revision history
13 * 25th Sep 2008 Initial version.
14 */
15
16#include <linux/init.h>
17#include <linux/module.h>
18#include <linux/version.h>
19#include <linux/kernel.h>
20#include <linux/device.h>
21#include <sound/core.h>
22#include <sound/pcm.h>
23#include <sound/ac97_codec.h>
24#include <sound/initval.h>
25#include <sound/soc.h>
26
27#include "ad73311.h"
28
29struct snd_soc_dai ad73311_dai = {
30 .name = "AD73311",
31 .playback = {
32 .stream_name = "Playback",
33 .channels_min = 1,
34 .channels_max = 1,
35 .rates = SNDRV_PCM_RATE_8000,
36 .formats = SNDRV_PCM_FMTBIT_S16_LE, },
37 .capture = {
38 .stream_name = "Capture",
39 .channels_min = 1,
40 .channels_max = 1,
41 .rates = SNDRV_PCM_RATE_8000,
42 .formats = SNDRV_PCM_FMTBIT_S16_LE, },
43};
44EXPORT_SYMBOL_GPL(ad73311_dai);
45
46static int ad73311_soc_probe(struct platform_device *pdev)
47{
48 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
49 struct snd_soc_codec *codec;
50 int ret = 0;
51
52 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
53 if (codec == NULL)
54 return -ENOMEM;
55 mutex_init(&codec->mutex);
56 codec->name = "AD73311";
57 codec->owner = THIS_MODULE;
58 codec->dai = &ad73311_dai;
59 codec->num_dai = 1;
60 socdev->codec = codec;
61 INIT_LIST_HEAD(&codec->dapm_widgets);
62 INIT_LIST_HEAD(&codec->dapm_paths);
63
64 /* register pcms */
65 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
66 if (ret < 0) {
67 printk(KERN_ERR "ad73311: failed to create pcms\n");
68 goto pcm_err;
69 }
70
71 ret = snd_soc_register_card(socdev);
72 if (ret < 0) {
73 printk(KERN_ERR "ad73311: failed to register card\n");
74 goto register_err;
75 }
76
77 return ret;
78
79register_err:
80 snd_soc_free_pcms(socdev);
81pcm_err:
82 kfree(socdev->codec);
83 socdev->codec = NULL;
84 return ret;
85}
86
87static int ad73311_soc_remove(struct platform_device *pdev)
88{
89 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
90 struct snd_soc_codec *codec = socdev->codec;
91
92 if (codec == NULL)
93 return 0;
94 snd_soc_free_pcms(socdev);
95 kfree(codec);
96 return 0;
97}
98
99struct snd_soc_codec_device soc_codec_dev_ad73311 = {
100 .probe = ad73311_soc_probe,
101 .remove = ad73311_soc_remove,
102};
103EXPORT_SYMBOL_GPL(soc_codec_dev_ad73311);
104
105MODULE_DESCRIPTION("ASoC ad73311 driver");
106MODULE_AUTHOR("Cliff Cai ");
107MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/ad73311.h b/sound/soc/codecs/ad73311.h
new file mode 100644
index 000000000000..507ce0c30edf
--- /dev/null
+++ b/sound/soc/codecs/ad73311.h
@@ -0,0 +1,90 @@
1/*
2 * File: sound/soc/codec/ad73311.h
3 * Based on:
4 * Author: Cliff Cai <cliff.cai@analog.com>
5 *
6 * Created: Thur Sep 25, 2008
7 * Description: definitions for AD73311 registers
8 *
9 *
10 * Modified:
11 * Copyright 2006 Analog Devices Inc.
12 *
13 * Bugs: Enter bugs at http://blackfin.uclinux.org/
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, see the file COPYING, or write
27 * to the Free Software Foundation, Inc.,
28 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
29 */
30
31#ifndef __AD73311_H__
32#define __AD73311_H__
33
34#define AD_CONTROL 0x8000
35#define AD_DATA 0x0000
36#define AD_READ 0x4000
37#define AD_WRITE 0x0000
38
39/* Control register A */
40#define CTRL_REG_A (0 << 8)
41
42#define REGA_MODE_PRO 0x00
43#define REGA_MODE_DATA 0x01
44#define REGA_MODE_MIXED 0x03
45#define REGA_DLB 0x04
46#define REGA_SLB 0x08
47#define REGA_DEVC(x) ((x & 0x7) << 4)
48#define REGA_RESET 0x80
49
50/* Control register B */
51#define CTRL_REG_B (1 << 8)
52
53#define REGB_DIRATE(x) (x & 0x3)
54#define REGB_SCDIV(x) ((x & 0x3) << 2)
55#define REGB_MCDIV(x) ((x & 0x7) << 4)
56#define REGB_CEE (1 << 7)
57
58/* Control register C */
59#define CTRL_REG_C (2 << 8)
60
61#define REGC_PUDEV (1 << 0)
62#define REGC_PUADC (1 << 3)
63#define REGC_PUDAC (1 << 4)
64#define REGC_PUREF (1 << 5)
65#define REGC_REFUSE (1 << 6)
66
67/* Control register D */
68#define CTRL_REG_D (3 << 8)
69
70#define REGD_IGS(x) (x & 0x7)
71#define REGD_RMOD (1 << 3)
72#define REGD_OGS(x) ((x & 0x7) << 4)
73#define REGD_MUTE (x << 7)
74
75/* Control register E */
76#define CTRL_REG_E (4 << 8)
77
78#define REGE_DA(x) (x & 0x1f)
79#define REGE_IBYP (1 << 5)
80
81/* Control register F */
82#define CTRL_REG_F (5 << 8)
83
84#define REGF_SEEN (1 << 5)
85#define REGF_INV (1 << 6)
86#define REGF_ALB (1 << 7)
87
88extern struct snd_soc_dai ad73311_dai;
89extern struct snd_soc_codec_device soc_codec_dev_ad73311;
90#endif
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c
index 7da9f467b7b8..2a89b5888e11 100644
--- a/sound/soc/codecs/ak4535.c
+++ b/sound/soc/codecs/ak4535.c
@@ -28,7 +28,6 @@
28 28
29#include "ak4535.h" 29#include "ak4535.h"
30 30
31#define AUDIO_NAME "ak4535"
32#define AK4535_VERSION "0.3" 31#define AK4535_VERSION "0.3"
33 32
34struct snd_soc_codec_device soc_codec_dev_ak4535; 33struct snd_soc_codec_device soc_codec_dev_ak4535;
@@ -535,87 +534,85 @@ static struct snd_soc_device *ak4535_socdev;
535 534
536#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 535#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
537 536
538#define I2C_DRIVERID_AK4535 0xfefe /* liam - need a proper id */ 537static int ak4535_i2c_probe(struct i2c_client *i2c,
539 538 const struct i2c_device_id *id)
540static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
541
542/* Magic definition of all other variables and things */
543I2C_CLIENT_INSMOD;
544
545static struct i2c_driver ak4535_i2c_driver;
546static struct i2c_client client_template;
547
548/* If the i2c layer weren't so broken, we could pass this kind of data
549 around */
550static int ak4535_codec_probe(struct i2c_adapter *adap, int addr, int kind)
551{ 539{
552 struct snd_soc_device *socdev = ak4535_socdev; 540 struct snd_soc_device *socdev = ak4535_socdev;
553 struct ak4535_setup_data *setup = socdev->codec_data;
554 struct snd_soc_codec *codec = socdev->codec; 541 struct snd_soc_codec *codec = socdev->codec;
555 struct i2c_client *i2c;
556 int ret; 542 int ret;
557 543
558 if (addr != setup->i2c_address)
559 return -ENODEV;
560
561 client_template.adapter = adap;
562 client_template.addr = addr;
563
564 i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
565 if (i2c == NULL)
566 return -ENOMEM;
567
568 i2c_set_clientdata(i2c, codec); 544 i2c_set_clientdata(i2c, codec);
569 codec->control_data = i2c; 545 codec->control_data = i2c;
570 546
571 ret = i2c_attach_client(i2c);
572 if (ret < 0) {
573 printk(KERN_ERR "failed to attach codec at addr %x\n", addr);
574 goto err;
575 }
576
577 ret = ak4535_init(socdev); 547 ret = ak4535_init(socdev);
578 if (ret < 0) { 548 if (ret < 0)
579 printk(KERN_ERR "failed to initialise AK4535\n"); 549 printk(KERN_ERR "failed to initialise AK4535\n");
580 goto err;
581 }
582 return ret;
583 550
584err:
585 kfree(i2c);
586 return ret; 551 return ret;
587} 552}
588 553
589static int ak4535_i2c_detach(struct i2c_client *client) 554static int ak4535_i2c_remove(struct i2c_client *client)
590{ 555{
591 struct snd_soc_codec *codec = i2c_get_clientdata(client); 556 struct snd_soc_codec *codec = i2c_get_clientdata(client);
592 i2c_detach_client(client);
593 kfree(codec->reg_cache); 557 kfree(codec->reg_cache);
594 kfree(client);
595 return 0; 558 return 0;
596} 559}
597 560
598static int ak4535_i2c_attach(struct i2c_adapter *adap) 561static const struct i2c_device_id ak4535_i2c_id[] = {
599{ 562 { "ak4535", 0 },
600 return i2c_probe(adap, &addr_data, ak4535_codec_probe); 563 { }
601} 564};
565MODULE_DEVICE_TABLE(i2c, ak4535_i2c_id);
602 566
603/* corgi i2c codec control layer */
604static struct i2c_driver ak4535_i2c_driver = { 567static struct i2c_driver ak4535_i2c_driver = {
605 .driver = { 568 .driver = {
606 .name = "AK4535 I2C Codec", 569 .name = "AK4535 I2C Codec",
607 .owner = THIS_MODULE, 570 .owner = THIS_MODULE,
608 }, 571 },
609 .id = I2C_DRIVERID_AK4535, 572 .probe = ak4535_i2c_probe,
610 .attach_adapter = ak4535_i2c_attach, 573 .remove = ak4535_i2c_remove,
611 .detach_client = ak4535_i2c_detach, 574 .id_table = ak4535_i2c_id,
612 .command = NULL,
613}; 575};
614 576
615static struct i2c_client client_template = { 577static int ak4535_add_i2c_device(struct platform_device *pdev,
616 .name = "AK4535", 578 const struct ak4535_setup_data *setup)
617 .driver = &ak4535_i2c_driver, 579{
618}; 580 struct i2c_board_info info;
581 struct i2c_adapter *adapter;
582 struct i2c_client *client;
583 int ret;
584
585 ret = i2c_add_driver(&ak4535_i2c_driver);
586 if (ret != 0) {
587 dev_err(&pdev->dev, "can't add i2c driver\n");
588 return ret;
589 }
590
591 memset(&info, 0, sizeof(struct i2c_board_info));
592 info.addr = setup->i2c_address;
593 strlcpy(info.type, "ak4535", I2C_NAME_SIZE);
594
595 adapter = i2c_get_adapter(setup->i2c_bus);
596 if (!adapter) {
597 dev_err(&pdev->dev, "can't get i2c adapter %d\n",
598 setup->i2c_bus);
599 goto err_driver;
600 }
601
602 client = i2c_new_device(adapter, &info);
603 i2c_put_adapter(adapter);
604 if (!client) {
605 dev_err(&pdev->dev, "can't add i2c device at 0x%x\n",
606 (unsigned int)info.addr);
607 goto err_driver;
608 }
609
610 return 0;
611
612err_driver:
613 i2c_del_driver(&ak4535_i2c_driver);
614 return -ENODEV;
615}
619#endif 616#endif
620 617
621static int ak4535_probe(struct platform_device *pdev) 618static int ak4535_probe(struct platform_device *pdev)
@@ -624,7 +621,7 @@ static int ak4535_probe(struct platform_device *pdev)
624 struct ak4535_setup_data *setup; 621 struct ak4535_setup_data *setup;
625 struct snd_soc_codec *codec; 622 struct snd_soc_codec *codec;
626 struct ak4535_priv *ak4535; 623 struct ak4535_priv *ak4535;
627 int ret = 0; 624 int ret;
628 625
629 printk(KERN_INFO "AK4535 Audio Codec %s", AK4535_VERSION); 626 printk(KERN_INFO "AK4535 Audio Codec %s", AK4535_VERSION);
630 627
@@ -646,17 +643,14 @@ static int ak4535_probe(struct platform_device *pdev)
646 INIT_LIST_HEAD(&codec->dapm_paths); 643 INIT_LIST_HEAD(&codec->dapm_paths);
647 644
648 ak4535_socdev = socdev; 645 ak4535_socdev = socdev;
646 ret = -ENODEV;
647
649#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 648#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
650 if (setup->i2c_address) { 649 if (setup->i2c_address) {
651 normal_i2c[0] = setup->i2c_address;
652 codec->hw_write = (hw_write_t)i2c_master_send; 650 codec->hw_write = (hw_write_t)i2c_master_send;
653 codec->hw_read = (hw_read_t)i2c_master_recv; 651 codec->hw_read = (hw_read_t)i2c_master_recv;
654 ret = i2c_add_driver(&ak4535_i2c_driver); 652 ret = ak4535_add_i2c_device(pdev, setup);
655 if (ret != 0)
656 printk(KERN_ERR "can't add i2c driver");
657 } 653 }
658#else
659 /* Add other interfaces here */
660#endif 654#endif
661 655
662 if (ret != 0) { 656 if (ret != 0) {
@@ -678,6 +672,7 @@ static int ak4535_remove(struct platform_device *pdev)
678 snd_soc_free_pcms(socdev); 672 snd_soc_free_pcms(socdev);
679 snd_soc_dapm_free(socdev); 673 snd_soc_dapm_free(socdev);
680#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 674#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
675 i2c_unregister_device(codec->control_data);
681 i2c_del_driver(&ak4535_i2c_driver); 676 i2c_del_driver(&ak4535_i2c_driver);
682#endif 677#endif
683 kfree(codec->private_data); 678 kfree(codec->private_data);
diff --git a/sound/soc/codecs/ak4535.h b/sound/soc/codecs/ak4535.h
index e9fe30e2c056..c7a58703ea39 100644
--- a/sound/soc/codecs/ak4535.h
+++ b/sound/soc/codecs/ak4535.h
@@ -37,6 +37,7 @@
37#define AK4535_CACHEREGNUM 0x10 37#define AK4535_CACHEREGNUM 0x10
38 38
39struct ak4535_setup_data { 39struct ak4535_setup_data {
40 int i2c_bus;
40 unsigned short i2c_address; 41 unsigned short i2c_address;
41}; 42};
42 43
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index 9deb8c74fdfd..0bbd94501d7e 100644
--- a/sound/soc/codecs/cs4270.c
+++ b/sound/soc/codecs/cs4270.c
@@ -490,34 +490,7 @@ static int cs4270_mute(struct snd_soc_dai *dai, int mute)
490 490
491#endif 491#endif
492 492
493static int cs4270_i2c_probe(struct i2c_adapter *adap, int addr, int kind); 493static int cs4270_i2c_probe(struct i2c_client *, const struct i2c_device_id *);
494
495/*
496 * Notify the driver that a new I2C bus has been found.
497 *
498 * This function is called for each I2C bus in the system. The function
499 * then asks the I2C subsystem to probe that bus at the addresses on which
500 * our device (the CS4270) could exist. If a device is found at one of
501 * those addresses, then our probe function (cs4270_i2c_probe) is called.
502 */
503static int cs4270_i2c_attach(struct i2c_adapter *adapter)
504{
505 return i2c_probe(adapter, &addr_data, cs4270_i2c_probe);
506}
507
508static int cs4270_i2c_detach(struct i2c_client *client)
509{
510 struct snd_soc_codec *codec = i2c_get_clientdata(client);
511
512 i2c_detach_client(client);
513 codec->control_data = NULL;
514
515 kfree(codec->reg_cache);
516 codec->reg_cache = NULL;
517
518 kfree(client);
519 return 0;
520}
521 494
522/* A list of non-DAPM controls that the CS4270 supports */ 495/* A list of non-DAPM controls that the CS4270 supports */
523static const struct snd_kcontrol_new cs4270_snd_controls[] = { 496static const struct snd_kcontrol_new cs4270_snd_controls[] = {
@@ -525,14 +498,19 @@ static const struct snd_kcontrol_new cs4270_snd_controls[] = {
525 CS4270_VOLA, CS4270_VOLB, 0, 0xFF, 1) 498 CS4270_VOLA, CS4270_VOLB, 0, 0xFF, 1)
526}; 499};
527 500
501static const struct i2c_device_id cs4270_id[] = {
502 {"cs4270", 0},
503 {}
504};
505MODULE_DEVICE_TABLE(i2c, cs4270_id);
506
528static struct i2c_driver cs4270_i2c_driver = { 507static struct i2c_driver cs4270_i2c_driver = {
529 .driver = { 508 .driver = {
530 .name = "CS4270 I2C", 509 .name = "CS4270 I2C",
531 .owner = THIS_MODULE, 510 .owner = THIS_MODULE,
532 }, 511 },
533 .id = I2C_DRIVERID_CS4270, 512 .id_table = cs4270_id,
534 .attach_adapter = cs4270_i2c_attach, 513 .probe = cs4270_i2c_probe,
535 .detach_client = cs4270_i2c_detach,
536}; 514};
537 515
538/* 516/*
@@ -561,11 +539,11 @@ static struct snd_soc_device *cs4270_socdev;
561 * Note: snd_soc_new_pcms() must be called before this function can be called, 539 * Note: snd_soc_new_pcms() must be called before this function can be called,
562 * because of snd_ctl_add(). 540 * because of snd_ctl_add().
563 */ 541 */
564static int cs4270_i2c_probe(struct i2c_adapter *adapter, int addr, int kind) 542static int cs4270_i2c_probe(struct i2c_client *i2c_client,
543 const struct i2c_device_id *id)
565{ 544{
566 struct snd_soc_device *socdev = cs4270_socdev; 545 struct snd_soc_device *socdev = cs4270_socdev;
567 struct snd_soc_codec *codec = socdev->codec; 546 struct snd_soc_codec *codec = socdev->codec;
568 struct i2c_client *i2c_client = NULL;
569 int i; 547 int i;
570 int ret = 0; 548 int ret = 0;
571 549
@@ -578,12 +556,6 @@ static int cs4270_i2c_probe(struct i2c_adapter *adapter, int addr, int kind)
578 556
579 /* Note: codec_dai->codec is NULL here */ 557 /* Note: codec_dai->codec is NULL here */
580 558
581 i2c_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
582 if (!i2c_client) {
583 printk(KERN_ERR "cs4270: could not allocate I2C client\n");
584 return -ENOMEM;
585 }
586
587 codec->reg_cache = kzalloc(CS4270_NUMREGS, GFP_KERNEL); 559 codec->reg_cache = kzalloc(CS4270_NUMREGS, GFP_KERNEL);
588 if (!codec->reg_cache) { 560 if (!codec->reg_cache) {
589 printk(KERN_ERR "cs4270: could not allocate register cache\n"); 561 printk(KERN_ERR "cs4270: could not allocate register cache\n");
@@ -591,13 +563,6 @@ static int cs4270_i2c_probe(struct i2c_adapter *adapter, int addr, int kind)
591 goto error; 563 goto error;
592 } 564 }
593 565
594 i2c_set_clientdata(i2c_client, codec);
595 strcpy(i2c_client->name, "CS4270");
596
597 i2c_client->driver = &cs4270_i2c_driver;
598 i2c_client->adapter = adapter;
599 i2c_client->addr = addr;
600
601 /* Verify that we have a CS4270 */ 566 /* Verify that we have a CS4270 */
602 567
603 ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID); 568 ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID);
@@ -612,18 +577,10 @@ static int cs4270_i2c_probe(struct i2c_adapter *adapter, int addr, int kind)
612 goto error; 577 goto error;
613 } 578 }
614 579
615 printk(KERN_INFO "cs4270: found device at I2C address %X\n", addr); 580 printk(KERN_INFO "cs4270: found device at I2C address %X\n",
581 i2c_client->addr);
616 printk(KERN_INFO "cs4270: hardware revision %X\n", ret & 0xF); 582 printk(KERN_INFO "cs4270: hardware revision %X\n", ret & 0xF);
617 583
618 /* Tell the I2C layer a new client has arrived */
619
620 ret = i2c_attach_client(i2c_client);
621 if (ret) {
622 printk(KERN_ERR "cs4270: could not attach codec, "
623 "I2C address %x, error code %i\n", addr, ret);
624 goto error;
625 }
626
627 codec->control_data = i2c_client; 584 codec->control_data = i2c_client;
628 codec->read = cs4270_read_reg_cache; 585 codec->read = cs4270_read_reg_cache;
629 codec->write = cs4270_i2c_write; 586 codec->write = cs4270_i2c_write;
@@ -648,20 +605,17 @@ static int cs4270_i2c_probe(struct i2c_adapter *adapter, int addr, int kind)
648 goto error; 605 goto error;
649 } 606 }
650 607
608 i2c_set_clientdata(i2c_client, codec);
609
651 return 0; 610 return 0;
652 611
653error: 612error:
654 if (codec->control_data) { 613 codec->control_data = NULL;
655 i2c_detach_client(i2c_client);
656 codec->control_data = NULL;
657 }
658 614
659 kfree(codec->reg_cache); 615 kfree(codec->reg_cache);
660 codec->reg_cache = NULL; 616 codec->reg_cache = NULL;
661 codec->reg_cache_size = 0; 617 codec->reg_cache_size = 0;
662 618
663 kfree(i2c_client);
664
665 return ret; 619 return ret;
666} 620}
667 621
@@ -727,7 +681,7 @@ static int cs4270_probe(struct platform_device *pdev)
727 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); 681 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
728 if (ret < 0) { 682 if (ret < 0) {
729 printk(KERN_ERR "cs4270: failed to create PCMs\n"); 683 printk(KERN_ERR "cs4270: failed to create PCMs\n");
730 return ret; 684 goto error_free_codec;
731 } 685 }
732 686
733#ifdef USE_I2C 687#ifdef USE_I2C
@@ -736,8 +690,7 @@ static int cs4270_probe(struct platform_device *pdev)
736 ret = i2c_add_driver(&cs4270_i2c_driver); 690 ret = i2c_add_driver(&cs4270_i2c_driver);
737 if (ret) { 691 if (ret) {
738 printk(KERN_ERR "cs4270: failed to attach driver"); 692 printk(KERN_ERR "cs4270: failed to attach driver");
739 snd_soc_free_pcms(socdev); 693 goto error_free_pcms;
740 return ret;
741 } 694 }
742 695
743 /* Did we find a CS4270 on the I2C bus? */ 696 /* Did we find a CS4270 on the I2C bus? */
@@ -759,10 +712,23 @@ static int cs4270_probe(struct platform_device *pdev)
759 ret = snd_soc_register_card(socdev); 712 ret = snd_soc_register_card(socdev);
760 if (ret < 0) { 713 if (ret < 0) {
761 printk(KERN_ERR "cs4270: failed to register card\n"); 714 printk(KERN_ERR "cs4270: failed to register card\n");
762 snd_soc_free_pcms(socdev); 715 goto error_del_driver;
763 return ret;
764 } 716 }
765 717
718 return 0;
719
720error_del_driver:
721#ifdef USE_I2C
722 i2c_del_driver(&cs4270_i2c_driver);
723
724error_free_pcms:
725#endif
726 snd_soc_free_pcms(socdev);
727
728error_free_codec:
729 kfree(socdev->codec);
730 socdev->codec = NULL;
731
766 return ret; 732 return ret;
767} 733}
768 734
@@ -773,8 +739,7 @@ static int cs4270_remove(struct platform_device *pdev)
773 snd_soc_free_pcms(socdev); 739 snd_soc_free_pcms(socdev);
774 740
775#ifdef USE_I2C 741#ifdef USE_I2C
776 if (socdev->codec->control_data) 742 i2c_del_driver(&cs4270_i2c_driver);
777 i2c_del_driver(&cs4270_i2c_driver);
778#endif 743#endif
779 744
780 kfree(socdev->codec); 745 kfree(socdev->codec);
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c
new file mode 100644
index 000000000000..44ef0dacd564
--- /dev/null
+++ b/sound/soc/codecs/ssm2602.c
@@ -0,0 +1,775 @@
1/*
2 * File: sound/soc/codecs/ssm2602.c
3 * Author: Cliff Cai <Cliff.Cai@analog.com>
4 *
5 * Created: Tue June 06 2008
6 * Description: Driver for ssm2602 sound chip
7 *
8 * Modified:
9 * Copyright 2008 Analog Devices Inc.
10 *
11 * Bugs: Enter bugs at http://blackfin.uclinux.org/
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see the file COPYING, or write
25 * to the Free Software Foundation, Inc.,
26 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 */
28
29#include <linux/module.h>
30#include <linux/moduleparam.h>
31#include <linux/init.h>
32#include <linux/delay.h>
33#include <linux/pm.h>
34#include <linux/i2c.h>
35#include <linux/platform_device.h>
36#include <sound/core.h>
37#include <sound/pcm.h>
38#include <sound/pcm_params.h>
39#include <sound/soc.h>
40#include <sound/soc-dapm.h>
41#include <sound/initval.h>
42
43#include "ssm2602.h"
44
45#define SSM2602_VERSION "0.1"
46
47struct snd_soc_codec_device soc_codec_dev_ssm2602;
48
49/* codec private data */
50struct ssm2602_priv {
51 unsigned int sysclk;
52 struct snd_pcm_substream *master_substream;
53 struct snd_pcm_substream *slave_substream;
54};
55
56/*
57 * ssm2602 register cache
58 * We can't read the ssm2602 register space when we are
59 * using 2 wire for device control, so we cache them instead.
60 * There is no point in caching the reset register
61 */
62static const u16 ssm2602_reg[SSM2602_CACHEREGNUM] = {
63 0x0017, 0x0017, 0x0079, 0x0079,
64 0x0000, 0x0000, 0x0000, 0x000a,
65 0x0000, 0x0000
66};
67
68/*
69 * read ssm2602 register cache
70 */
71static inline unsigned int ssm2602_read_reg_cache(struct snd_soc_codec *codec,
72 unsigned int reg)
73{
74 u16 *cache = codec->reg_cache;
75 if (reg == SSM2602_RESET)
76 return 0;
77 if (reg >= SSM2602_CACHEREGNUM)
78 return -1;
79 return cache[reg];
80}
81
82/*
83 * write ssm2602 register cache
84 */
85static inline void ssm2602_write_reg_cache(struct snd_soc_codec *codec,
86 u16 reg, unsigned int value)
87{
88 u16 *cache = codec->reg_cache;
89 if (reg >= SSM2602_CACHEREGNUM)
90 return;
91 cache[reg] = value;
92}
93
94/*
95 * write to the ssm2602 register space
96 */
97static int ssm2602_write(struct snd_soc_codec *codec, unsigned int reg,
98 unsigned int value)
99{
100 u8 data[2];
101
102 /* data is
103 * D15..D9 ssm2602 register offset
104 * D8...D0 register data
105 */
106 data[0] = (reg << 1) | ((value >> 8) & 0x0001);
107 data[1] = value & 0x00ff;
108
109 ssm2602_write_reg_cache(codec, reg, value);
110 if (codec->hw_write(codec->control_data, data, 2) == 2)
111 return 0;
112 else
113 return -EIO;
114}
115
116#define ssm2602_reset(c) ssm2602_write(c, SSM2602_RESET, 0)
117
118/*Appending several "None"s just for OSS mixer use*/
119static const char *ssm2602_input_select[] = {
120 "Line", "Mic", "None", "None", "None",
121 "None", "None", "None",
122};
123
124static const char *ssm2602_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"};
125
126static const struct soc_enum ssm2602_enum[] = {
127 SOC_ENUM_SINGLE(SSM2602_APANA, 2, 2, ssm2602_input_select),
128 SOC_ENUM_SINGLE(SSM2602_APDIGI, 1, 4, ssm2602_deemph),
129};
130
131static const struct snd_kcontrol_new ssm2602_snd_controls[] = {
132
133SOC_DOUBLE_R("Master Playback Volume", SSM2602_LOUT1V, SSM2602_ROUT1V,
134 0, 127, 0),
135SOC_DOUBLE_R("Master Playback ZC Switch", SSM2602_LOUT1V, SSM2602_ROUT1V,
136 7, 1, 0),
137
138SOC_DOUBLE_R("Capture Volume", SSM2602_LINVOL, SSM2602_RINVOL, 0, 31, 0),
139SOC_DOUBLE_R("Capture Switch", SSM2602_LINVOL, SSM2602_RINVOL, 7, 1, 1),
140
141SOC_SINGLE("Mic Boost (+20dB)", SSM2602_APANA, 0, 1, 0),
142SOC_SINGLE("Mic Switch", SSM2602_APANA, 1, 1, 1),
143
144SOC_SINGLE("Sidetone Playback Volume", SSM2602_APANA, 6, 3, 1),
145
146SOC_SINGLE("ADC High Pass Filter Switch", SSM2602_APDIGI, 0, 1, 1),
147SOC_SINGLE("Store DC Offset Switch", SSM2602_APDIGI, 4, 1, 0),
148
149SOC_ENUM("Capture Source", ssm2602_enum[0]),
150
151SOC_ENUM("Playback De-emphasis", ssm2602_enum[1]),
152};
153
154/* add non dapm controls */
155static int ssm2602_add_controls(struct snd_soc_codec *codec)
156{
157 int err, i;
158
159 for (i = 0; i < ARRAY_SIZE(ssm2602_snd_controls); i++) {
160 err = snd_ctl_add(codec->card,
161 snd_soc_cnew(&ssm2602_snd_controls[i], codec, NULL));
162 if (err < 0)
163 return err;
164 }
165
166 return 0;
167}
168
169/* Output Mixer */
170static const struct snd_kcontrol_new ssm2602_output_mixer_controls[] = {
171SOC_DAPM_SINGLE("Line Bypass Switch", SSM2602_APANA, 3, 1, 0),
172SOC_DAPM_SINGLE("Mic Sidetone Switch", SSM2602_APANA, 5, 1, 0),
173SOC_DAPM_SINGLE("HiFi Playback Switch", SSM2602_APANA, 4, 1, 0),
174};
175
176/* Input mux */
177static const struct snd_kcontrol_new ssm2602_input_mux_controls =
178SOC_DAPM_ENUM("Input Select", ssm2602_enum[0]);
179
180static const struct snd_soc_dapm_widget ssm2602_dapm_widgets[] = {
181SND_SOC_DAPM_MIXER("Output Mixer", SSM2602_PWR, 4, 1,
182 &ssm2602_output_mixer_controls[0],
183 ARRAY_SIZE(ssm2602_output_mixer_controls)),
184SND_SOC_DAPM_DAC("DAC", "HiFi Playback", SSM2602_PWR, 3, 1),
185SND_SOC_DAPM_OUTPUT("LOUT"),
186SND_SOC_DAPM_OUTPUT("LHPOUT"),
187SND_SOC_DAPM_OUTPUT("ROUT"),
188SND_SOC_DAPM_OUTPUT("RHPOUT"),
189SND_SOC_DAPM_ADC("ADC", "HiFi Capture", SSM2602_PWR, 2, 1),
190SND_SOC_DAPM_MUX("Input Mux", SND_SOC_NOPM, 0, 0, &ssm2602_input_mux_controls),
191SND_SOC_DAPM_PGA("Line Input", SSM2602_PWR, 0, 1, NULL, 0),
192SND_SOC_DAPM_MICBIAS("Mic Bias", SSM2602_PWR, 1, 1),
193SND_SOC_DAPM_INPUT("MICIN"),
194SND_SOC_DAPM_INPUT("RLINEIN"),
195SND_SOC_DAPM_INPUT("LLINEIN"),
196};
197
198static const struct snd_soc_dapm_route audio_conn[] = {
199 /* output mixer */
200 {"Output Mixer", "Line Bypass Switch", "Line Input"},
201 {"Output Mixer", "HiFi Playback Switch", "DAC"},
202 {"Output Mixer", "Mic Sidetone Switch", "Mic Bias"},
203
204 /* outputs */
205 {"RHPOUT", NULL, "Output Mixer"},
206 {"ROUT", NULL, "Output Mixer"},
207 {"LHPOUT", NULL, "Output Mixer"},
208 {"LOUT", NULL, "Output Mixer"},
209
210 /* input mux */
211 {"Input Mux", "Line", "Line Input"},
212 {"Input Mux", "Mic", "Mic Bias"},
213 {"ADC", NULL, "Input Mux"},
214
215 /* inputs */
216 {"Line Input", NULL, "LLINEIN"},
217 {"Line Input", NULL, "RLINEIN"},
218 {"Mic Bias", NULL, "MICIN"},
219};
220
221static int ssm2602_add_widgets(struct snd_soc_codec *codec)
222{
223 snd_soc_dapm_new_controls(codec, ssm2602_dapm_widgets,
224 ARRAY_SIZE(ssm2602_dapm_widgets));
225
226 snd_soc_dapm_add_routes(codec, audio_conn, ARRAY_SIZE(audio_conn));
227
228 snd_soc_dapm_new_widgets(codec);
229 return 0;
230}
231
232struct _coeff_div {
233 u32 mclk;
234 u32 rate;
235 u16 fs;
236 u8 sr:4;
237 u8 bosr:1;
238 u8 usb:1;
239};
240
241/* codec mclk clock divider coefficients */
242static const struct _coeff_div coeff_div[] = {
243 /* 48k */
244 {12288000, 48000, 256, 0x0, 0x0, 0x0},
245 {18432000, 48000, 384, 0x0, 0x1, 0x0},
246 {12000000, 48000, 250, 0x0, 0x0, 0x1},
247
248 /* 32k */
249 {12288000, 32000, 384, 0x6, 0x0, 0x0},
250 {18432000, 32000, 576, 0x6, 0x1, 0x0},
251 {12000000, 32000, 375, 0x6, 0x0, 0x1},
252
253 /* 8k */
254 {12288000, 8000, 1536, 0x3, 0x0, 0x0},
255 {18432000, 8000, 2304, 0x3, 0x1, 0x0},
256 {11289600, 8000, 1408, 0xb, 0x0, 0x0},
257 {16934400, 8000, 2112, 0xb, 0x1, 0x0},
258 {12000000, 8000, 1500, 0x3, 0x0, 0x1},
259
260 /* 96k */
261 {12288000, 96000, 128, 0x7, 0x0, 0x0},
262 {18432000, 96000, 192, 0x7, 0x1, 0x0},
263 {12000000, 96000, 125, 0x7, 0x0, 0x1},
264
265 /* 44.1k */
266 {11289600, 44100, 256, 0x8, 0x0, 0x0},
267 {16934400, 44100, 384, 0x8, 0x1, 0x0},
268 {12000000, 44100, 272, 0x8, 0x1, 0x1},
269
270 /* 88.2k */
271 {11289600, 88200, 128, 0xf, 0x0, 0x0},
272 {16934400, 88200, 192, 0xf, 0x1, 0x0},
273 {12000000, 88200, 136, 0xf, 0x1, 0x1},
274};
275
276static inline int get_coeff(int mclk, int rate)
277{
278 int i;
279
280 for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
281 if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk)
282 return i;
283 }
284 return i;
285}
286
287static int ssm2602_hw_params(struct snd_pcm_substream *substream,
288 struct snd_pcm_hw_params *params)
289{
290 u16 srate;
291 struct snd_soc_pcm_runtime *rtd = substream->private_data;
292 struct snd_soc_device *socdev = rtd->socdev;
293 struct snd_soc_codec *codec = socdev->codec;
294 struct ssm2602_priv *ssm2602 = codec->private_data;
295 u16 iface = ssm2602_read_reg_cache(codec, SSM2602_IFACE) & 0xfff3;
296 int i = get_coeff(ssm2602->sysclk, params_rate(params));
297
298 /*no match is found*/
299 if (i == ARRAY_SIZE(coeff_div))
300 return -EINVAL;
301
302 srate = (coeff_div[i].sr << 2) |
303 (coeff_div[i].bosr << 1) | coeff_div[i].usb;
304
305 ssm2602_write(codec, SSM2602_ACTIVE, 0);
306 ssm2602_write(codec, SSM2602_SRATE, srate);
307
308 /* bit size */
309 switch (params_format(params)) {
310 case SNDRV_PCM_FORMAT_S16_LE:
311 break;
312 case SNDRV_PCM_FORMAT_S20_3LE:
313 iface |= 0x0004;
314 break;
315 case SNDRV_PCM_FORMAT_S24_LE:
316 iface |= 0x0008;
317 break;
318 case SNDRV_PCM_FORMAT_S32_LE:
319 iface |= 0x000c;
320 break;
321 }
322 ssm2602_write(codec, SSM2602_IFACE, iface);
323 ssm2602_write(codec, SSM2602_ACTIVE, ACTIVE_ACTIVATE_CODEC);
324 return 0;
325}
326
327static int ssm2602_startup(struct snd_pcm_substream *substream)
328{
329 struct snd_soc_pcm_runtime *rtd = substream->private_data;
330 struct snd_soc_device *socdev = rtd->socdev;
331 struct snd_soc_codec *codec = socdev->codec;
332 struct ssm2602_priv *ssm2602 = codec->private_data;
333 struct snd_pcm_runtime *master_runtime;
334
335 /* The DAI has shared clocks so if we already have a playback or
336 * capture going then constrain this substream to match it.
337 */
338 if (ssm2602->master_substream) {
339 master_runtime = ssm2602->master_substream->runtime;
340 snd_pcm_hw_constraint_minmax(substream->runtime,
341 SNDRV_PCM_HW_PARAM_RATE,
342 master_runtime->rate,
343 master_runtime->rate);
344
345 snd_pcm_hw_constraint_minmax(substream->runtime,
346 SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
347 master_runtime->sample_bits,
348 master_runtime->sample_bits);
349
350 ssm2602->slave_substream = substream;
351 } else
352 ssm2602->master_substream = substream;
353
354 return 0;
355}
356
357static int ssm2602_pcm_prepare(struct snd_pcm_substream *substream)
358{
359 struct snd_soc_pcm_runtime *rtd = substream->private_data;
360 struct snd_soc_device *socdev = rtd->socdev;
361 struct snd_soc_codec *codec = socdev->codec;
362 /* set active */
363 ssm2602_write(codec, SSM2602_ACTIVE, ACTIVE_ACTIVATE_CODEC);
364
365 return 0;
366}
367
368static void ssm2602_shutdown(struct snd_pcm_substream *substream)
369{
370 struct snd_soc_pcm_runtime *rtd = substream->private_data;
371 struct snd_soc_device *socdev = rtd->socdev;
372 struct snd_soc_codec *codec = socdev->codec;
373 /* deactivate */
374 if (!codec->active)
375 ssm2602_write(codec, SSM2602_ACTIVE, 0);
376}
377
378static int ssm2602_mute(struct snd_soc_dai *dai, int mute)
379{
380 struct snd_soc_codec *codec = dai->codec;
381 u16 mute_reg = ssm2602_read_reg_cache(codec, SSM2602_APDIGI) & ~APDIGI_ENABLE_DAC_MUTE;
382 if (mute)
383 ssm2602_write(codec, SSM2602_APDIGI,
384 mute_reg | APDIGI_ENABLE_DAC_MUTE);
385 else
386 ssm2602_write(codec, SSM2602_APDIGI, mute_reg);
387 return 0;
388}
389
390static int ssm2602_set_dai_sysclk(struct snd_soc_dai *codec_dai,
391 int clk_id, unsigned int freq, int dir)
392{
393 struct snd_soc_codec *codec = codec_dai->codec;
394 struct ssm2602_priv *ssm2602 = codec->private_data;
395 switch (freq) {
396 case 11289600:
397 case 12000000:
398 case 12288000:
399 case 16934400:
400 case 18432000:
401 ssm2602->sysclk = freq;
402 return 0;
403 }
404 return -EINVAL;
405}
406
407static int ssm2602_set_dai_fmt(struct snd_soc_dai *codec_dai,
408 unsigned int fmt)
409{
410 struct snd_soc_codec *codec = codec_dai->codec;
411 u16 iface = 0;
412
413 /* set master/slave audio interface */
414 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
415 case SND_SOC_DAIFMT_CBM_CFM:
416 iface |= 0x0040;
417 break;
418 case SND_SOC_DAIFMT_CBS_CFS:
419 break;
420 default:
421 return -EINVAL;
422 }
423
424 /* interface format */
425 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
426 case SND_SOC_DAIFMT_I2S:
427 iface |= 0x0002;
428 break;
429 case SND_SOC_DAIFMT_RIGHT_J:
430 break;
431 case SND_SOC_DAIFMT_LEFT_J:
432 iface |= 0x0001;
433 break;
434 case SND_SOC_DAIFMT_DSP_A:
435 iface |= 0x0003;
436 break;
437 case SND_SOC_DAIFMT_DSP_B:
438 iface |= 0x0013;
439 break;
440 default:
441 return -EINVAL;
442 }
443
444 /* clock inversion */
445 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
446 case SND_SOC_DAIFMT_NB_NF:
447 break;
448 case SND_SOC_DAIFMT_IB_IF:
449 iface |= 0x0090;
450 break;
451 case SND_SOC_DAIFMT_IB_NF:
452 iface |= 0x0080;
453 break;
454 case SND_SOC_DAIFMT_NB_IF:
455 iface |= 0x0010;
456 break;
457 default:
458 return -EINVAL;
459 }
460
461 /* set iface */
462 ssm2602_write(codec, SSM2602_IFACE, iface);
463 return 0;
464}
465
466static int ssm2602_set_bias_level(struct snd_soc_codec *codec,
467 enum snd_soc_bias_level level)
468{
469 u16 reg = ssm2602_read_reg_cache(codec, SSM2602_PWR) & 0xff7f;
470
471 switch (level) {
472 case SND_SOC_BIAS_ON:
473 /* vref/mid, osc on, dac unmute */
474 ssm2602_write(codec, SSM2602_PWR, reg);
475 break;
476 case SND_SOC_BIAS_PREPARE:
477 break;
478 case SND_SOC_BIAS_STANDBY:
479 /* everything off except vref/vmid, */
480 ssm2602_write(codec, SSM2602_PWR, reg | PWR_CLK_OUT_PDN);
481 break;
482 case SND_SOC_BIAS_OFF:
483 /* everything off, dac mute, inactive */
484 ssm2602_write(codec, SSM2602_ACTIVE, 0);
485 ssm2602_write(codec, SSM2602_PWR, 0xffff);
486 break;
487
488 }
489 codec->bias_level = level;
490 return 0;
491}
492
493#define SSM2602_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
494 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
495 SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
496 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\
497 SNDRV_PCM_RATE_96000)
498
499struct snd_soc_dai ssm2602_dai = {
500 .name = "SSM2602",
501 .playback = {
502 .stream_name = "Playback",
503 .channels_min = 2,
504 .channels_max = 2,
505 .rates = SSM2602_RATES,
506 .formats = SNDRV_PCM_FMTBIT_S32_LE,},
507 .capture = {
508 .stream_name = "Capture",
509 .channels_min = 2,
510 .channels_max = 2,
511 .rates = SSM2602_RATES,
512 .formats = SNDRV_PCM_FMTBIT_S32_LE,},
513 .ops = {
514 .startup = ssm2602_startup,
515 .prepare = ssm2602_pcm_prepare,
516 .hw_params = ssm2602_hw_params,
517 .shutdown = ssm2602_shutdown,
518 },
519 .dai_ops = {
520 .digital_mute = ssm2602_mute,
521 .set_sysclk = ssm2602_set_dai_sysclk,
522 .set_fmt = ssm2602_set_dai_fmt,
523 }
524};
525EXPORT_SYMBOL_GPL(ssm2602_dai);
526
527static int ssm2602_suspend(struct platform_device *pdev, pm_message_t state)
528{
529 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
530 struct snd_soc_codec *codec = socdev->codec;
531
532 ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF);
533 return 0;
534}
535
536static int ssm2602_resume(struct platform_device *pdev)
537{
538 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
539 struct snd_soc_codec *codec = socdev->codec;
540 int i;
541 u8 data[2];
542 u16 *cache = codec->reg_cache;
543
544 /* Sync reg_cache with the hardware */
545 for (i = 0; i < ARRAY_SIZE(ssm2602_reg); i++) {
546 data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
547 data[1] = cache[i] & 0x00ff;
548 codec->hw_write(codec->control_data, data, 2);
549 }
550 ssm2602_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
551 ssm2602_set_bias_level(codec, codec->suspend_bias_level);
552 return 0;
553}
554
555/*
556 * initialise the ssm2602 driver
557 * register the mixer and dsp interfaces with the kernel
558 */
559static int ssm2602_init(struct snd_soc_device *socdev)
560{
561 struct snd_soc_codec *codec = socdev->codec;
562 int reg, ret = 0;
563
564 codec->name = "SSM2602";
565 codec->owner = THIS_MODULE;
566 codec->read = ssm2602_read_reg_cache;
567 codec->write = ssm2602_write;
568 codec->set_bias_level = ssm2602_set_bias_level;
569 codec->dai = &ssm2602_dai;
570 codec->num_dai = 1;
571 codec->reg_cache_size = sizeof(ssm2602_reg);
572 codec->reg_cache = kmemdup(ssm2602_reg, sizeof(ssm2602_reg),
573 GFP_KERNEL);
574 if (codec->reg_cache == NULL)
575 return -ENOMEM;
576
577 ssm2602_reset(codec);
578
579 /* register pcms */
580 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
581 if (ret < 0) {
582 pr_err("ssm2602: failed to create pcms\n");
583 goto pcm_err;
584 }
585 /*power on device*/
586 ssm2602_write(codec, SSM2602_ACTIVE, 0);
587 /* set the update bits */
588 reg = ssm2602_read_reg_cache(codec, SSM2602_LINVOL);
589 ssm2602_write(codec, SSM2602_LINVOL, reg | LINVOL_LRIN_BOTH);
590 reg = ssm2602_read_reg_cache(codec, SSM2602_RINVOL);
591 ssm2602_write(codec, SSM2602_RINVOL, reg | RINVOL_RLIN_BOTH);
592 reg = ssm2602_read_reg_cache(codec, SSM2602_LOUT1V);
593 ssm2602_write(codec, SSM2602_LOUT1V, reg | LOUT1V_LRHP_BOTH);
594 reg = ssm2602_read_reg_cache(codec, SSM2602_ROUT1V);
595 ssm2602_write(codec, SSM2602_ROUT1V, reg | ROUT1V_RLHP_BOTH);
596 /*select Line in as default input*/
597 ssm2602_write(codec, SSM2602_APANA,
598 APANA_ENABLE_MIC_BOOST2 | APANA_SELECT_DAC |
599 APANA_ENABLE_MIC_BOOST);
600 ssm2602_write(codec, SSM2602_PWR, 0);
601
602 ssm2602_add_controls(codec);
603 ssm2602_add_widgets(codec);
604 ret = snd_soc_register_card(socdev);
605 if (ret < 0) {
606 pr_err("ssm2602: failed to register card\n");
607 goto card_err;
608 }
609
610 return ret;
611
612card_err:
613 snd_soc_free_pcms(socdev);
614 snd_soc_dapm_free(socdev);
615pcm_err:
616 kfree(codec->reg_cache);
617 return ret;
618}
619
620static struct snd_soc_device *ssm2602_socdev;
621
622#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
623/*
624 * ssm2602 2 wire address is determined by GPIO5
625 * state during powerup.
626 * low = 0x1a
627 * high = 0x1b
628 */
629static int ssm2602_i2c_probe(struct i2c_client *i2c,
630 const struct i2c_device_id *id)
631{
632 struct snd_soc_device *socdev = ssm2602_socdev;
633 struct snd_soc_codec *codec = socdev->codec;
634 int ret;
635
636 i2c_set_clientdata(i2c, codec);
637 codec->control_data = i2c;
638
639 ret = ssm2602_init(socdev);
640 if (ret < 0)
641 pr_err("failed to initialise SSM2602\n");
642
643 return ret;
644}
645
646static int ssm2602_i2c_remove(struct i2c_client *client)
647{
648 struct snd_soc_codec *codec = i2c_get_clientdata(client);
649 kfree(codec->reg_cache);
650 return 0;
651}
652
653static const struct i2c_device_id ssm2602_i2c_id[] = {
654 { "ssm2602", 0 },
655 { }
656};
657MODULE_DEVICE_TABLE(i2c, ssm2602_i2c_id);
658/* corgi i2c codec control layer */
659static struct i2c_driver ssm2602_i2c_driver = {
660 .driver = {
661 .name = "SSM2602 I2C Codec",
662 .owner = THIS_MODULE,
663 },
664 .probe = ssm2602_i2c_probe,
665 .remove = ssm2602_i2c_remove,
666 .id_table = ssm2602_i2c_id,
667};
668
669static int ssm2602_add_i2c_device(struct platform_device *pdev,
670 const struct ssm2602_setup_data *setup)
671{
672 struct i2c_board_info info;
673 struct i2c_adapter *adapter;
674 struct i2c_client *client;
675 int ret;
676
677 ret = i2c_add_driver(&ssm2602_i2c_driver);
678 if (ret != 0) {
679 dev_err(&pdev->dev, "can't add i2c driver\n");
680 return ret;
681 }
682 memset(&info, 0, sizeof(struct i2c_board_info));
683 info.addr = setup->i2c_address;
684 strlcpy(info.type, "ssm2602", I2C_NAME_SIZE);
685 adapter = i2c_get_adapter(setup->i2c_bus);
686 if (!adapter) {
687 dev_err(&pdev->dev, "can't get i2c adapter %d\n",
688 setup->i2c_bus);
689 goto err_driver;
690 }
691 client = i2c_new_device(adapter, &info);
692 i2c_put_adapter(adapter);
693 if (!client) {
694 dev_err(&pdev->dev, "can't add i2c device at 0x%x\n",
695 (unsigned int)info.addr);
696 goto err_driver;
697 }
698 return 0;
699err_driver:
700 i2c_del_driver(&ssm2602_i2c_driver);
701 return -ENODEV;
702}
703#endif
704
705static int ssm2602_probe(struct platform_device *pdev)
706{
707 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
708 struct ssm2602_setup_data *setup;
709 struct snd_soc_codec *codec;
710 struct ssm2602_priv *ssm2602;
711 int ret = 0;
712
713 pr_info("ssm2602 Audio Codec %s", SSM2602_VERSION);
714
715 setup = socdev->codec_data;
716 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
717 if (codec == NULL)
718 return -ENOMEM;
719
720 ssm2602 = kzalloc(sizeof(struct ssm2602_priv), GFP_KERNEL);
721 if (ssm2602 == NULL) {
722 kfree(codec);
723 return -ENOMEM;
724 }
725
726 codec->private_data = ssm2602;
727 socdev->codec = codec;
728 mutex_init(&codec->mutex);
729 INIT_LIST_HEAD(&codec->dapm_widgets);
730 INIT_LIST_HEAD(&codec->dapm_paths);
731
732 ssm2602_socdev = socdev;
733#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
734 if (setup->i2c_address) {
735 codec->hw_write = (hw_write_t)i2c_master_send;
736 ret = ssm2602_add_i2c_device(pdev, setup);
737 }
738#else
739 /* other interfaces */
740#endif
741 return ret;
742}
743
744/* remove everything here */
745static int ssm2602_remove(struct platform_device *pdev)
746{
747 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
748 struct snd_soc_codec *codec = socdev->codec;
749
750 if (codec->control_data)
751 ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF);
752
753 snd_soc_free_pcms(socdev);
754 snd_soc_dapm_free(socdev);
755#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
756 i2c_unregister_device(codec->control_data);
757 i2c_del_driver(&ssm2602_i2c_driver);
758#endif
759 kfree(codec->private_data);
760 kfree(codec);
761
762 return 0;
763}
764
765struct snd_soc_codec_device soc_codec_dev_ssm2602 = {
766 .probe = ssm2602_probe,
767 .remove = ssm2602_remove,
768 .suspend = ssm2602_suspend,
769 .resume = ssm2602_resume,
770};
771EXPORT_SYMBOL_GPL(soc_codec_dev_ssm2602);
772
773MODULE_DESCRIPTION("ASoC ssm2602 driver");
774MODULE_AUTHOR("Cliff Cai");
775MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/ssm2602.h b/sound/soc/codecs/ssm2602.h
new file mode 100644
index 000000000000..f344e6d76e31
--- /dev/null
+++ b/sound/soc/codecs/ssm2602.h
@@ -0,0 +1,130 @@
1/*
2 * File: sound/soc/codecs/ssm2602.h
3 * Author: Cliff Cai <Cliff.Cai@analog.com>
4 *
5 * Created: Tue June 06 2008
6 *
7 * Modified:
8 * Copyright 2008 Analog Devices Inc.
9 *
10 * Bugs: Enter bugs at http://blackfin.uclinux.org/
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see the file COPYING, or write
24 * to the Free Software Foundation, Inc.,
25 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 */
27
28#ifndef _SSM2602_H
29#define _SSM2602_H
30
31/* SSM2602 Codec Register definitions */
32
33#define SSM2602_LINVOL 0x00
34#define SSM2602_RINVOL 0x01
35#define SSM2602_LOUT1V 0x02
36#define SSM2602_ROUT1V 0x03
37#define SSM2602_APANA 0x04
38#define SSM2602_APDIGI 0x05
39#define SSM2602_PWR 0x06
40#define SSM2602_IFACE 0x07
41#define SSM2602_SRATE 0x08
42#define SSM2602_ACTIVE 0x09
43#define SSM2602_RESET 0x0f
44
45/*SSM2602 Codec Register Field definitions
46 *(Mask value to extract the corresponding Register field)
47 */
48
49/*Left ADC Volume Control (SSM2602_REG_LEFT_ADC_VOL)*/
50#define LINVOL_LIN_VOL 0x01F /* Left Channel PGA Volume control */
51#define LINVOL_LIN_ENABLE_MUTE 0x080 /* Left Channel Input Mute */
52#define LINVOL_LRIN_BOTH 0x100 /* Left Channel Line Input Volume update */
53
54/*Right ADC Volume Control (SSM2602_REG_RIGHT_ADC_VOL)*/
55#define RINVOL_RIN_VOL 0x01F /* Right Channel PGA Volume control */
56#define RINVOL_RIN_ENABLE_MUTE 0x080 /* Right Channel Input Mute */
57#define RINVOL_RLIN_BOTH 0x100 /* Right Channel Line Input Volume update */
58
59/*Left DAC Volume Control (SSM2602_REG_LEFT_DAC_VOL)*/
60#define LOUT1V_LHP_VOL 0x07F /* Left Channel Headphone volume control */
61#define LOUT1V_ENABLE_LZC 0x080 /* Left Channel Zero cross detect enable */
62#define LOUT1V_LRHP_BOTH 0x100 /* Left Channel Headphone volume update */
63
64/*Right DAC Volume Control (SSM2602_REG_RIGHT_DAC_VOL)*/
65#define ROUT1V_RHP_VOL 0x07F /* Right Channel Headphone volume control */
66#define ROUT1V_ENABLE_RZC 0x080 /* Right Channel Zero cross detect enable */
67#define ROUT1V_RLHP_BOTH 0x100 /* Right Channel Headphone volume update */
68
69/*Analogue Audio Path Control (SSM2602_REG_ANALOGUE_PATH)*/
70#define APANA_ENABLE_MIC_BOOST 0x001 /* Primary Microphone Amplifier gain booster control */
71#define APANA_ENABLE_MIC_MUTE 0x002 /* Microphone Mute Control */
72#define APANA_ADC_IN_SELECT 0x004 /* Microphone/Line IN select to ADC (1=MIC, 0=Line In) */
73#define APANA_ENABLE_BYPASS 0x008 /* Line input bypass to line output */
74#define APANA_SELECT_DAC 0x010 /* Select DAC (1=Select DAC, 0=Don't Select DAC) */
75#define APANA_ENABLE_SIDETONE 0x020 /* Enable/Disable Side Tone */
76#define APANA_SIDETONE_ATTN 0x0C0 /* Side Tone Attenuation */
77#define APANA_ENABLE_MIC_BOOST2 0x100 /* Secondary Microphone Amplifier gain booster control */
78
79/*Digital Audio Path Control (SSM2602_REG_DIGITAL_PATH)*/
80#define APDIGI_ENABLE_ADC_HPF 0x001 /* Enable/Disable ADC Highpass Filter */
81#define APDIGI_DE_EMPHASIS 0x006 /* De-Emphasis Control */
82#define APDIGI_ENABLE_DAC_MUTE 0x008 /* DAC Mute Control */
83#define APDIGI_STORE_OFFSET 0x010 /* Store/Clear DC offset when HPF is disabled */
84
85/*Power Down Control (SSM2602_REG_POWER)
86 *(1=Enable PowerDown, 0=Disable PowerDown)
87 */
88#define PWR_LINE_IN_PDN 0x001 /* Line Input Power Down */
89#define PWR_MIC_PDN 0x002 /* Microphone Input & Bias Power Down */
90#define PWR_ADC_PDN 0x004 /* ADC Power Down */
91#define PWR_DAC_PDN 0x008 /* DAC Power Down */
92#define PWR_OUT_PDN 0x010 /* Outputs Power Down */
93#define PWR_OSC_PDN 0x020 /* Oscillator Power Down */
94#define PWR_CLK_OUT_PDN 0x040 /* CLKOUT Power Down */
95#define PWR_POWER_OFF 0x080 /* POWEROFF Mode */
96
97/*Digital Audio Interface Format (SSM2602_REG_DIGITAL_IFACE)*/
98#define IFACE_IFACE_FORMAT 0x003 /* Digital Audio input format control */
99#define IFACE_AUDIO_DATA_LEN 0x00C /* Audio Data word length control */
100#define IFACE_DAC_LR_POLARITY 0x010 /* Polarity Control for clocks in RJ,LJ and I2S modes */
101#define IFACE_DAC_LR_SWAP 0x020 /* Swap DAC data control */
102#define IFACE_ENABLE_MASTER 0x040 /* Enable/Disable Master Mode */
103#define IFACE_BCLK_INVERT 0x080 /* Bit Clock Inversion control */
104
105/*Sampling Control (SSM2602_REG_SAMPLING_CTRL)*/
106#define SRATE_ENABLE_USB_MODE 0x001 /* Enable/Disable USB Mode */
107#define SRATE_BOS_RATE 0x002 /* Base Over-Sampling rate */
108#define SRATE_SAMPLE_RATE 0x03C /* Clock setting condition (Sampling rate control) */
109#define SRATE_CORECLK_DIV2 0x040 /* Core Clock divider select */
110#define SRATE_CLKOUT_DIV2 0x080 /* Clock Out divider select */
111
112/*Active Control (SSM2602_REG_ACTIVE_CTRL)*/
113#define ACTIVE_ACTIVATE_CODEC 0x001 /* Activate Codec Digital Audio Interface */
114
115/*********************************************************************/
116
117#define SSM2602_CACHEREGNUM 10
118
119#define SSM2602_SYSCLK 0
120#define SSM2602_DAI 0
121
122struct ssm2602_setup_data {
123 int i2c_bus;
124 unsigned short i2c_address;
125};
126
127extern struct snd_soc_dai ssm2602_dai;
128extern struct snd_soc_codec_device soc_codec_dev_ssm2602;
129
130#endif
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c
new file mode 100644
index 000000000000..44308dac9e18
--- /dev/null
+++ b/sound/soc/codecs/tlv320aic23.c
@@ -0,0 +1,714 @@
1/*
2 * ALSA SoC TLV320AIC23 codec driver
3 *
4 * Author: Arun KS, <arunks@mistralsolutions.com>
5 * Copyright: (C) 2008 Mistral Solutions Pvt Ltd.,
6 *
7 * Based on sound/soc/codecs/wm8731.c by Richard Purdie
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 *
13 * Notes:
14 * The AIC23 is a driver for a low power stereo audio
15 * codec tlv320aic23
16 *
17 * The machine layer should disable unsupported inputs/outputs by
18 * snd_soc_dapm_disable_pin(codec, "LHPOUT"), etc.
19 */
20
21#include <linux/module.h>
22#include <linux/moduleparam.h>
23#include <linux/init.h>
24#include <linux/delay.h>
25#include <linux/pm.h>
26#include <linux/i2c.h>
27#include <linux/platform_device.h>
28#include <sound/core.h>
29#include <sound/pcm.h>
30#include <sound/pcm_params.h>
31#include <sound/soc.h>
32#include <sound/soc-dapm.h>
33#include <sound/tlv.h>
34#include <sound/initval.h>
35
36#include "tlv320aic23.h"
37
38#define AIC23_VERSION "0.1"
39
40struct tlv320aic23_srate_reg_info {
41 u32 sample_rate;
42 u8 control; /* SR3, SR2, SR1, SR0 and BOSR */
43 u8 divider; /* if 0 CLKIN = MCLK, if 1 CLKIN = MCLK/2 */
44};
45
46/*
47 * AIC23 register cache
48 */
49static const u16 tlv320aic23_reg[] = {
50 0x0097, 0x0097, 0x00F9, 0x00F9, /* 0 */
51 0x001A, 0x0004, 0x0007, 0x0001, /* 4 */
52 0x0020, 0x0000, 0x0000, 0x0000, /* 8 */
53 0x0000, 0x0000, 0x0000, 0x0000, /* 12 */
54};
55
56/*
57 * read tlv320aic23 register cache
58 */
59static inline unsigned int tlv320aic23_read_reg_cache(struct snd_soc_codec
60 *codec, unsigned int reg)
61{
62 u16 *cache = codec->reg_cache;
63 if (reg >= ARRAY_SIZE(tlv320aic23_reg))
64 return -1;
65 return cache[reg];
66}
67
68/*
69 * write tlv320aic23 register cache
70 */
71static inline void tlv320aic23_write_reg_cache(struct snd_soc_codec *codec,
72 u8 reg, u16 value)
73{
74 u16 *cache = codec->reg_cache;
75 if (reg >= ARRAY_SIZE(tlv320aic23_reg))
76 return;
77 cache[reg] = value;
78}
79
80/*
81 * write to the tlv320aic23 register space
82 */
83static int tlv320aic23_write(struct snd_soc_codec *codec, unsigned int reg,
84 unsigned int value)
85{
86
87 u8 data[2];
88
89 /* TLV320AIC23 has 7 bit address and 9 bits of data
90 * so we need to switch one data bit into reg and rest
91 * of data into val
92 */
93
94 if ((reg < 0 || reg > 9) && (reg != 15)) {
95 printk(KERN_WARNING "%s Invalid register R%d\n", __func__, reg);
96 return -1;
97 }
98
99 data[0] = (reg << 1) | (value >> 8 & 0x01);
100 data[1] = value & 0xff;
101
102 tlv320aic23_write_reg_cache(codec, reg, value);
103
104 if (codec->hw_write(codec->control_data, data, 2) == 2)
105 return 0;
106
107 printk(KERN_ERR "%s cannot write %03x to register R%d\n", __func__,
108 value, reg);
109
110 return -EIO;
111}
112
113static const char *rec_src_text[] = { "Line", "Mic" };
114static const char *deemph_text[] = {"None", "32Khz", "44.1Khz", "48Khz"};
115
116static const struct soc_enum rec_src_enum =
117 SOC_ENUM_SINGLE(TLV320AIC23_ANLG, 2, 2, rec_src_text);
118
119static const struct snd_kcontrol_new tlv320aic23_rec_src_mux_controls =
120SOC_DAPM_ENUM("Input Select", rec_src_enum);
121
122static const struct soc_enum tlv320aic23_rec_src =
123 SOC_ENUM_SINGLE(TLV320AIC23_ANLG, 2, 2, rec_src_text);
124static const struct soc_enum tlv320aic23_deemph =
125 SOC_ENUM_SINGLE(TLV320AIC23_DIGT, 1, 4, deemph_text);
126
127static const DECLARE_TLV_DB_SCALE(out_gain_tlv, -12100, 100, 0);
128static const DECLARE_TLV_DB_SCALE(input_gain_tlv, -1725, 75, 0);
129static const DECLARE_TLV_DB_SCALE(sidetone_vol_tlv, -1800, 300, 0);
130
131static int snd_soc_tlv320aic23_put_volsw(struct snd_kcontrol *kcontrol,
132 struct snd_ctl_elem_value *ucontrol)
133{
134 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
135 u16 val, reg;
136
137 val = (ucontrol->value.integer.value[0] & 0x07);
138
139 /* linear conversion to userspace
140 * 000 = -6db
141 * 001 = -9db
142 * 010 = -12db
143 * 011 = -18db (Min)
144 * 100 = 0db (Max)
145 */
146 val = (val >= 4) ? 4 : (3 - val);
147
148 reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_ANLG) & (~0x1C0);
149 tlv320aic23_write(codec, TLV320AIC23_ANLG, reg | (val << 6));
150
151 return 0;
152}
153
154static int snd_soc_tlv320aic23_get_volsw(struct snd_kcontrol *kcontrol,
155 struct snd_ctl_elem_value *ucontrol)
156{
157 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
158 u16 val;
159
160 val = tlv320aic23_read_reg_cache(codec, TLV320AIC23_ANLG) & (0x1C0);
161 val = val >> 6;
162 val = (val >= 4) ? 4 : (3 - val);
163 ucontrol->value.integer.value[0] = val;
164 return 0;
165
166}
167
168#define SOC_TLV320AIC23_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \
169{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
170 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
171 SNDRV_CTL_ELEM_ACCESS_READWRITE,\
172 .tlv.p = (tlv_array), \
173 .info = snd_soc_info_volsw, .get = snd_soc_tlv320aic23_get_volsw,\
174 .put = snd_soc_tlv320aic23_put_volsw, \
175 .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) }
176
177static const struct snd_kcontrol_new tlv320aic23_snd_controls[] = {
178 SOC_DOUBLE_R_TLV("Digital Playback Volume", TLV320AIC23_LCHNVOL,
179 TLV320AIC23_RCHNVOL, 0, 127, 0, out_gain_tlv),
180 SOC_SINGLE("Digital Playback Switch", TLV320AIC23_DIGT, 3, 1, 1),
181 SOC_DOUBLE_R("Line Input Switch", TLV320AIC23_LINVOL,
182 TLV320AIC23_RINVOL, 7, 1, 0),
183 SOC_DOUBLE_R_TLV("Line Input Volume", TLV320AIC23_LINVOL,
184 TLV320AIC23_RINVOL, 0, 31, 0, input_gain_tlv),
185 SOC_SINGLE("Mic Input Switch", TLV320AIC23_ANLG, 1, 1, 1),
186 SOC_SINGLE("Mic Booster Switch", TLV320AIC23_ANLG, 0, 1, 0),
187 SOC_TLV320AIC23_SINGLE_TLV("Sidetone Volume", TLV320AIC23_ANLG,
188 6, 4, 0, sidetone_vol_tlv),
189 SOC_ENUM("Playback De-emphasis", tlv320aic23_deemph),
190};
191
192/* add non dapm controls */
193static int tlv320aic23_add_controls(struct snd_soc_codec *codec)
194{
195
196 int err, i;
197
198 for (i = 0; i < ARRAY_SIZE(tlv320aic23_snd_controls); i++) {
199 err = snd_ctl_add(codec->card,
200 snd_soc_cnew(&tlv320aic23_snd_controls[i],
201 codec, NULL));
202 if (err < 0)
203 return err;
204 }
205
206 return 0;
207
208}
209
210/* PGA Mixer controls for Line and Mic switch */
211static const struct snd_kcontrol_new tlv320aic23_output_mixer_controls[] = {
212 SOC_DAPM_SINGLE("Line Bypass Switch", TLV320AIC23_ANLG, 3, 1, 0),
213 SOC_DAPM_SINGLE("Mic Sidetone Switch", TLV320AIC23_ANLG, 5, 1, 0),
214 SOC_DAPM_SINGLE("Playback Switch", TLV320AIC23_ANLG, 4, 1, 0),
215};
216
217static const struct snd_soc_dapm_widget tlv320aic23_dapm_widgets[] = {
218 SND_SOC_DAPM_DAC("DAC", "Playback", TLV320AIC23_PWR, 3, 1),
219 SND_SOC_DAPM_ADC("ADC", "Capture", TLV320AIC23_PWR, 2, 1),
220 SND_SOC_DAPM_MUX("Capture Source", SND_SOC_NOPM, 0, 0,
221 &tlv320aic23_rec_src_mux_controls),
222 SND_SOC_DAPM_MIXER("Output Mixer", TLV320AIC23_PWR, 4, 1,
223 &tlv320aic23_output_mixer_controls[0],
224 ARRAY_SIZE(tlv320aic23_output_mixer_controls)),
225 SND_SOC_DAPM_PGA("Line Input", TLV320AIC23_PWR, 0, 1, NULL, 0),
226 SND_SOC_DAPM_PGA("Mic Input", TLV320AIC23_PWR, 1, 1, NULL, 0),
227
228 SND_SOC_DAPM_OUTPUT("LHPOUT"),
229 SND_SOC_DAPM_OUTPUT("RHPOUT"),
230 SND_SOC_DAPM_OUTPUT("LOUT"),
231 SND_SOC_DAPM_OUTPUT("ROUT"),
232
233 SND_SOC_DAPM_INPUT("LLINEIN"),
234 SND_SOC_DAPM_INPUT("RLINEIN"),
235
236 SND_SOC_DAPM_INPUT("MICIN"),
237};
238
239static const struct snd_soc_dapm_route intercon[] = {
240 /* Output Mixer */
241 {"Output Mixer", "Line Bypass Switch", "Line Input"},
242 {"Output Mixer", "Playback Switch", "DAC"},
243 {"Output Mixer", "Mic Sidetone Switch", "Mic Input"},
244
245 /* Outputs */
246 {"RHPOUT", NULL, "Output Mixer"},
247 {"LHPOUT", NULL, "Output Mixer"},
248 {"LOUT", NULL, "Output Mixer"},
249 {"ROUT", NULL, "Output Mixer"},
250
251 /* Inputs */
252 {"Line Input", "NULL", "LLINEIN"},
253 {"Line Input", "NULL", "RLINEIN"},
254
255 {"Mic Input", "NULL", "MICIN"},
256
257 /* input mux */
258 {"Capture Source", "Line", "Line Input"},
259 {"Capture Source", "Mic", "Mic Input"},
260 {"ADC", NULL, "Capture Source"},
261
262};
263
264/* tlv320aic23 related */
265static const struct tlv320aic23_srate_reg_info srate_reg_info[] = {
266 {4000, 0x06, 1}, /* 4000 */
267 {8000, 0x06, 0}, /* 8000 */
268 {16000, 0x0C, 1}, /* 16000 */
269 {22050, 0x11, 1}, /* 22050 */
270 {24000, 0x00, 1}, /* 24000 */
271 {32000, 0x0C, 0}, /* 32000 */
272 {44100, 0x11, 0}, /* 44100 */
273 {48000, 0x00, 0}, /* 48000 */
274 {88200, 0x1F, 0}, /* 88200 */
275 {96000, 0x0E, 0}, /* 96000 */
276};
277
278static int tlv320aic23_add_widgets(struct snd_soc_codec *codec)
279{
280 snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets,
281 ARRAY_SIZE(tlv320aic23_dapm_widgets));
282
283 /* set up audio path interconnects */
284 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
285
286 snd_soc_dapm_new_widgets(codec);
287 return 0;
288}
289
290static int tlv320aic23_hw_params(struct snd_pcm_substream *substream,
291 struct snd_pcm_hw_params *params)
292{
293 struct snd_soc_pcm_runtime *rtd = substream->private_data;
294 struct snd_soc_device *socdev = rtd->socdev;
295 struct snd_soc_codec *codec = socdev->codec;
296 u16 iface_reg, data;
297 u8 count = 0;
298
299 iface_reg =
300 tlv320aic23_read_reg_cache(codec,
301 TLV320AIC23_DIGT_FMT) & ~(0x03 << 2);
302
303 /* Search for the right sample rate */
304 /* Verify what happens if the rate is not supported
305 * now it goes to 96Khz */
306 while ((srate_reg_info[count].sample_rate != params_rate(params)) &&
307 (count < ARRAY_SIZE(srate_reg_info))) {
308 count++;
309 }
310
311 data = (srate_reg_info[count].divider << TLV320AIC23_CLKIN_SHIFT) |
312 (srate_reg_info[count]. control << TLV320AIC23_BOSR_SHIFT) |
313 TLV320AIC23_USB_CLK_ON;
314
315 tlv320aic23_write(codec, TLV320AIC23_SRATE, data);
316
317 switch (params_format(params)) {
318 case SNDRV_PCM_FORMAT_S16_LE:
319 break;
320 case SNDRV_PCM_FORMAT_S20_3LE:
321 iface_reg |= (0x01 << 2);
322 break;
323 case SNDRV_PCM_FORMAT_S24_LE:
324 iface_reg |= (0x02 << 2);
325 break;
326 case SNDRV_PCM_FORMAT_S32_LE:
327 iface_reg |= (0x03 << 2);
328 break;
329 }
330 tlv320aic23_write(codec, TLV320AIC23_DIGT_FMT, iface_reg);
331
332 return 0;
333}
334
335static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream)
336{
337 struct snd_soc_pcm_runtime *rtd = substream->private_data;
338 struct snd_soc_device *socdev = rtd->socdev;
339 struct snd_soc_codec *codec = socdev->codec;
340
341 /* set active */
342 tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0001);
343
344 return 0;
345}
346
347static void tlv320aic23_shutdown(struct snd_pcm_substream *substream)
348{
349 struct snd_soc_pcm_runtime *rtd = substream->private_data;
350 struct snd_soc_device *socdev = rtd->socdev;
351 struct snd_soc_codec *codec = socdev->codec;
352
353 /* deactivate */
354 if (!codec->active) {
355 udelay(50);
356 tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0);
357 }
358}
359
360static int tlv320aic23_mute(struct snd_soc_dai *dai, int mute)
361{
362 struct snd_soc_codec *codec = dai->codec;
363 u16 reg;
364
365 reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_DIGT);
366 if (mute)
367 reg |= TLV320AIC23_DACM_MUTE;
368
369 else
370 reg &= ~TLV320AIC23_DACM_MUTE;
371
372 tlv320aic23_write(codec, TLV320AIC23_DIGT, reg);
373
374 return 0;
375}
376
377static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai,
378 unsigned int fmt)
379{
380 struct snd_soc_codec *codec = codec_dai->codec;
381 u16 iface_reg;
382
383 iface_reg =
384 tlv320aic23_read_reg_cache(codec, TLV320AIC23_DIGT_FMT) & (~0x03);
385
386 /* set master/slave audio interface */
387 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
388 case SND_SOC_DAIFMT_CBM_CFM:
389 iface_reg |= TLV320AIC23_MS_MASTER;
390 break;
391 case SND_SOC_DAIFMT_CBS_CFS:
392 break;
393 default:
394 return -EINVAL;
395
396 }
397
398 /* interface format */
399 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
400 case SND_SOC_DAIFMT_I2S:
401 iface_reg |= TLV320AIC23_FOR_I2S;
402 break;
403 case SND_SOC_DAIFMT_DSP_A:
404 iface_reg |= TLV320AIC23_FOR_DSP;
405 break;
406 case SND_SOC_DAIFMT_RIGHT_J:
407 break;
408 case SND_SOC_DAIFMT_LEFT_J:
409 iface_reg |= TLV320AIC23_FOR_LJUST;
410 break;
411 default:
412 return -EINVAL;
413
414 }
415
416 tlv320aic23_write(codec, TLV320AIC23_DIGT_FMT, iface_reg);
417
418 return 0;
419}
420
421static int tlv320aic23_set_dai_sysclk(struct snd_soc_dai *codec_dai,
422 int clk_id, unsigned int freq, int dir)
423{
424 struct snd_soc_codec *codec = codec_dai->codec;
425
426 switch (freq) {
427 case 12000000:
428 return 0;
429 }
430 return -EINVAL;
431}
432
433static int tlv320aic23_set_bias_level(struct snd_soc_codec *codec,
434 enum snd_soc_bias_level level)
435{
436 u16 reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_PWR) & 0xff7f;
437
438 switch (level) {
439 case SND_SOC_BIAS_ON:
440 /* vref/mid, osc on, dac unmute */
441 tlv320aic23_write(codec, TLV320AIC23_PWR, reg);
442 break;
443 case SND_SOC_BIAS_PREPARE:
444 break;
445 case SND_SOC_BIAS_STANDBY:
446 /* everything off except vref/vmid, */
447 tlv320aic23_write(codec, TLV320AIC23_PWR, reg | 0x0040);
448 break;
449 case SND_SOC_BIAS_OFF:
450 /* everything off, dac mute, inactive */
451 tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0);
452 tlv320aic23_write(codec, TLV320AIC23_PWR, 0xffff);
453 break;
454 }
455 codec->bias_level = level;
456 return 0;
457}
458
459#define AIC23_RATES SNDRV_PCM_RATE_8000_96000
460#define AIC23_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
461 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
462
463struct snd_soc_dai tlv320aic23_dai = {
464 .name = "tlv320aic23",
465 .playback = {
466 .stream_name = "Playback",
467 .channels_min = 2,
468 .channels_max = 2,
469 .rates = AIC23_RATES,
470 .formats = AIC23_FORMATS,},
471 .capture = {
472 .stream_name = "Capture",
473 .channels_min = 2,
474 .channels_max = 2,
475 .rates = AIC23_RATES,
476 .formats = AIC23_FORMATS,},
477 .ops = {
478 .prepare = tlv320aic23_pcm_prepare,
479 .hw_params = tlv320aic23_hw_params,
480 .shutdown = tlv320aic23_shutdown,
481 },
482 .dai_ops = {
483 .digital_mute = tlv320aic23_mute,
484 .set_fmt = tlv320aic23_set_dai_fmt,
485 .set_sysclk = tlv320aic23_set_dai_sysclk,
486 }
487};
488EXPORT_SYMBOL_GPL(tlv320aic23_dai);
489
490static int tlv320aic23_suspend(struct platform_device *pdev,
491 pm_message_t state)
492{
493 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
494 struct snd_soc_codec *codec = socdev->codec;
495
496 tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0);
497 tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF);
498
499 return 0;
500}
501
502static int tlv320aic23_resume(struct platform_device *pdev)
503{
504 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
505 struct snd_soc_codec *codec = socdev->codec;
506 int i;
507 u16 reg;
508
509 /* Sync reg_cache with the hardware */
510 for (reg = 0; reg < ARRAY_SIZE(tlv320aic23_reg); i++) {
511 u16 val = tlv320aic23_read_reg_cache(codec, reg);
512 tlv320aic23_write(codec, reg, val);
513 }
514
515 tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
516 tlv320aic23_set_bias_level(codec, codec->suspend_bias_level);
517
518 return 0;
519}
520
521/*
522 * initialise the AIC23 driver
523 * register the mixer and dsp interfaces with the kernel
524 */
525static int tlv320aic23_init(struct snd_soc_device *socdev)
526{
527 struct snd_soc_codec *codec = socdev->codec;
528 int ret = 0;
529 u16 reg;
530
531 codec->name = "tlv320aic23";
532 codec->owner = THIS_MODULE;
533 codec->read = tlv320aic23_read_reg_cache;
534 codec->write = tlv320aic23_write;
535 codec->set_bias_level = tlv320aic23_set_bias_level;
536 codec->dai = &tlv320aic23_dai;
537 codec->num_dai = 1;
538 codec->reg_cache_size = ARRAY_SIZE(tlv320aic23_reg);
539 codec->reg_cache =
540 kmemdup(tlv320aic23_reg, sizeof(tlv320aic23_reg), GFP_KERNEL);
541 if (codec->reg_cache == NULL)
542 return -ENOMEM;
543
544 /* Reset codec */
545 tlv320aic23_write(codec, TLV320AIC23_RESET, 0);
546
547 /* register pcms */
548 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
549 if (ret < 0) {
550 printk(KERN_ERR "tlv320aic23: failed to create pcms\n");
551 goto pcm_err;
552 }
553
554 /* power on device */
555 tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
556
557 tlv320aic23_write(codec, TLV320AIC23_DIGT, TLV320AIC23_DEEMP_44K);
558
559 /* Unmute input */
560 reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_LINVOL);
561 tlv320aic23_write(codec, TLV320AIC23_LINVOL,
562 (reg & (~TLV320AIC23_LIM_MUTED)) |
563 (TLV320AIC23_LRS_ENABLED));
564
565 reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_RINVOL);
566 tlv320aic23_write(codec, TLV320AIC23_RINVOL,
567 (reg & (~TLV320AIC23_LIM_MUTED)) |
568 TLV320AIC23_LRS_ENABLED);
569
570 reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_ANLG);
571 tlv320aic23_write(codec, TLV320AIC23_ANLG,
572 (reg) & (~TLV320AIC23_BYPASS_ON) &
573 (~TLV320AIC23_MICM_MUTED));
574
575 /* Default output volume */
576 tlv320aic23_write(codec, TLV320AIC23_LCHNVOL,
577 TLV320AIC23_DEFAULT_OUT_VOL &
578 TLV320AIC23_OUT_VOL_MASK);
579 tlv320aic23_write(codec, TLV320AIC23_RCHNVOL,
580 TLV320AIC23_DEFAULT_OUT_VOL &
581 TLV320AIC23_OUT_VOL_MASK);
582
583 tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x1);
584
585 tlv320aic23_add_controls(codec);
586 tlv320aic23_add_widgets(codec);
587 ret = snd_soc_register_card(socdev);
588 if (ret < 0) {
589 printk(KERN_ERR "tlv320aic23: failed to register card\n");
590 goto card_err;
591 }
592
593 return ret;
594
595card_err:
596 snd_soc_free_pcms(socdev);
597 snd_soc_dapm_free(socdev);
598pcm_err:
599 kfree(codec->reg_cache);
600 return ret;
601}
602static struct snd_soc_device *tlv320aic23_socdev;
603
604#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
605/*
606 * If the i2c layer weren't so broken, we could pass this kind of data
607 * around
608 */
609static int tlv320aic23_codec_probe(struct i2c_client *i2c,
610 const struct i2c_device_id *i2c_id)
611{
612 struct snd_soc_device *socdev = tlv320aic23_socdev;
613 struct snd_soc_codec *codec = socdev->codec;
614 int ret;
615
616 if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
617 return -EINVAL;
618
619 i2c_set_clientdata(i2c, codec);
620 codec->control_data = i2c;
621
622 ret = tlv320aic23_init(socdev);
623 if (ret < 0) {
624 printk(KERN_ERR "tlv320aic23: failed to initialise AIC23\n");
625 goto err;
626 }
627 return ret;
628
629err:
630 kfree(codec);
631 kfree(i2c);
632 return ret;
633}
634static int __exit tlv320aic23_i2c_remove(struct i2c_client *i2c)
635{
636 put_device(&i2c->dev);
637 return 0;
638}
639
640static const struct i2c_device_id tlv320aic23_id[] = {
641 {"tlv320aic23", 0},
642 {}
643};
644
645MODULE_DEVICE_TABLE(i2c, tlv320aic23_id);
646
647static struct i2c_driver tlv320aic23_i2c_driver = {
648 .driver = {
649 .name = "tlv320aic23",
650 },
651 .probe = tlv320aic23_codec_probe,
652 .remove = __exit_p(tlv320aic23_i2c_remove),
653 .id_table = tlv320aic23_id,
654};
655
656#endif
657
658static int tlv320aic23_probe(struct platform_device *pdev)
659{
660 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
661 struct snd_soc_codec *codec;
662 int ret = 0;
663
664 printk(KERN_INFO "AIC23 Audio Codec %s\n", AIC23_VERSION);
665
666 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
667 if (codec == NULL)
668 return -ENOMEM;
669
670 socdev->codec = codec;
671 mutex_init(&codec->mutex);
672 INIT_LIST_HEAD(&codec->dapm_widgets);
673 INIT_LIST_HEAD(&codec->dapm_paths);
674
675 tlv320aic23_socdev = socdev;
676#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
677 codec->hw_write = (hw_write_t) i2c_master_send;
678 codec->hw_read = NULL;
679 ret = i2c_add_driver(&tlv320aic23_i2c_driver);
680 if (ret != 0)
681 printk(KERN_ERR "can't add i2c driver");
682#endif
683 return ret;
684}
685
686static int tlv320aic23_remove(struct platform_device *pdev)
687{
688 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
689 struct snd_soc_codec *codec = socdev->codec;
690
691 if (codec->control_data)
692 tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF);
693
694 snd_soc_free_pcms(socdev);
695 snd_soc_dapm_free(socdev);
696#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
697 i2c_del_driver(&tlv320aic23_i2c_driver);
698#endif
699 kfree(codec->reg_cache);
700 kfree(codec);
701
702 return 0;
703}
704struct snd_soc_codec_device soc_codec_dev_tlv320aic23 = {
705 .probe = tlv320aic23_probe,
706 .remove = tlv320aic23_remove,
707 .suspend = tlv320aic23_suspend,
708 .resume = tlv320aic23_resume,
709};
710EXPORT_SYMBOL_GPL(soc_codec_dev_tlv320aic23);
711
712MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver");
713MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>");
714MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/tlv320aic23.h b/sound/soc/codecs/tlv320aic23.h
new file mode 100644
index 000000000000..79d1faf8e570
--- /dev/null
+++ b/sound/soc/codecs/tlv320aic23.h
@@ -0,0 +1,122 @@
1/*
2 * ALSA SoC TLV320AIC23 codec driver
3 *
4 * Author: Arun KS, <arunks@mistralsolutions.com>
5 * Copyright: (C) 2008 Mistral Solutions Pvt Ltd
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#ifndef _TLV320AIC23_H
13#define _TLV320AIC23_H
14
15/* Codec TLV320AIC23 */
16#define TLV320AIC23_LINVOL 0x00
17#define TLV320AIC23_RINVOL 0x01
18#define TLV320AIC23_LCHNVOL 0x02
19#define TLV320AIC23_RCHNVOL 0x03
20#define TLV320AIC23_ANLG 0x04
21#define TLV320AIC23_DIGT 0x05
22#define TLV320AIC23_PWR 0x06
23#define TLV320AIC23_DIGT_FMT 0x07
24#define TLV320AIC23_SRATE 0x08
25#define TLV320AIC23_ACTIVE 0x09
26#define TLV320AIC23_RESET 0x0F
27
28/* Left (right) line input volume control register */
29#define TLV320AIC23_LRS_ENABLED 0x0100
30#define TLV320AIC23_LIM_MUTED 0x0080
31#define TLV320AIC23_LIV_DEFAULT 0x0017
32#define TLV320AIC23_LIV_MAX 0x001f
33#define TLV320AIC23_LIV_MIN 0x0000
34
35/* Left (right) channel headphone volume control register */
36#define TLV320AIC23_LZC_ON 0x0080
37#define TLV320AIC23_LHV_DEFAULT 0x0079
38#define TLV320AIC23_LHV_MAX 0x007f
39#define TLV320AIC23_LHV_MIN 0x0000
40
41/* Analog audio path control register */
42#define TLV320AIC23_STA_REG(x) ((x)<<6)
43#define TLV320AIC23_STE_ENABLED 0x0020
44#define TLV320AIC23_DAC_SELECTED 0x0010
45#define TLV320AIC23_BYPASS_ON 0x0008
46#define TLV320AIC23_INSEL_MIC 0x0004
47#define TLV320AIC23_MICM_MUTED 0x0002
48#define TLV320AIC23_MICB_20DB 0x0001
49
50/* Digital audio path control register */
51#define TLV320AIC23_DACM_MUTE 0x0008
52#define TLV320AIC23_DEEMP_32K 0x0002
53#define TLV320AIC23_DEEMP_44K 0x0004
54#define TLV320AIC23_DEEMP_48K 0x0006
55#define TLV320AIC23_ADCHP_ON 0x0001
56
57/* Power control down register */
58#define TLV320AIC23_DEVICE_PWR_OFF 0x0080
59#define TLV320AIC23_CLK_OFF 0x0040
60#define TLV320AIC23_OSC_OFF 0x0020
61#define TLV320AIC23_OUT_OFF 0x0010
62#define TLV320AIC23_DAC_OFF 0x0008
63#define TLV320AIC23_ADC_OFF 0x0004
64#define TLV320AIC23_MIC_OFF 0x0002
65#define TLV320AIC23_LINE_OFF 0x0001
66
67/* Digital audio interface register */
68#define TLV320AIC23_MS_MASTER 0x0040
69#define TLV320AIC23_LRSWAP_ON 0x0020
70#define TLV320AIC23_LRP_ON 0x0010
71#define TLV320AIC23_IWL_16 0x0000
72#define TLV320AIC23_IWL_20 0x0004
73#define TLV320AIC23_IWL_24 0x0008
74#define TLV320AIC23_IWL_32 0x000C
75#define TLV320AIC23_FOR_I2S 0x0002
76#define TLV320AIC23_FOR_DSP 0x0003
77#define TLV320AIC23_FOR_LJUST 0x0001
78
79/* Sample rate control register */
80#define TLV320AIC23_CLKOUT_HALF 0x0080
81#define TLV320AIC23_CLKIN_HALF 0x0040
82#define TLV320AIC23_BOSR_384fs 0x0002 /* BOSR_272fs in USB mode */
83#define TLV320AIC23_USB_CLK_ON 0x0001
84#define TLV320AIC23_SR_MASK 0xf
85#define TLV320AIC23_CLKOUT_SHIFT 7
86#define TLV320AIC23_CLKIN_SHIFT 6
87#define TLV320AIC23_SR_SHIFT 2
88#define TLV320AIC23_BOSR_SHIFT 1
89
90/* Digital interface register */
91#define TLV320AIC23_ACT_ON 0x0001
92
93/*
94 * AUDIO related MACROS
95 */
96
97#define TLV320AIC23_DEFAULT_OUT_VOL 0x70
98#define TLV320AIC23_DEFAULT_IN_VOLUME 0x10
99
100#define TLV320AIC23_OUT_VOL_MIN TLV320AIC23_LHV_MIN
101#define TLV320AIC23_OUT_VOL_MAX TLV320AIC23_LHV_MAX
102#define TLV320AIC23_OUT_VO_RANGE (TLV320AIC23_OUT_VOL_MAX - \
103 TLV320AIC23_OUT_VOL_MIN)
104#define TLV320AIC23_OUT_VOL_MASK TLV320AIC23_OUT_VOL_MAX
105
106#define TLV320AIC23_IN_VOL_MIN TLV320AIC23_LIV_MIN
107#define TLV320AIC23_IN_VOL_MAX TLV320AIC23_LIV_MAX
108#define TLV320AIC23_IN_VOL_RANGE (TLV320AIC23_IN_VOL_MAX - \
109 TLV320AIC23_IN_VOL_MIN)
110#define TLV320AIC23_IN_VOL_MASK TLV320AIC23_IN_VOL_MAX
111
112#define TLV320AIC23_SIDETONE_MASK 0x1c0
113#define TLV320AIC23_SIDETONE_0 0x100
114#define TLV320AIC23_SIDETONE_6 0x000
115#define TLV320AIC23_SIDETONE_9 0x040
116#define TLV320AIC23_SIDETONE_12 0x080
117#define TLV320AIC23_SIDETONE_18 0x0c0
118
119extern struct snd_soc_dai tlv320aic23_dai;
120extern struct snd_soc_codec_device soc_codec_dev_tlv320aic23;
121
122#endif /* _TLV320AIC23_H */
diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c
new file mode 100644
index 000000000000..bed8a9e63ddc
--- /dev/null
+++ b/sound/soc/codecs/tlv320aic26.c
@@ -0,0 +1,520 @@
1/*
2 * Texas Instruments TLV320AIC26 low power audio CODEC
3 * ALSA SoC CODEC driver
4 *
5 * Copyright (C) 2008 Secret Lab Technologies Ltd.
6 */
7
8#include <linux/module.h>
9#include <linux/moduleparam.h>
10#include <linux/init.h>
11#include <linux/delay.h>
12#include <linux/pm.h>
13#include <linux/device.h>
14#include <linux/sysfs.h>
15#include <linux/spi/spi.h>
16#include <sound/core.h>
17#include <sound/pcm.h>
18#include <sound/pcm_params.h>
19#include <sound/soc.h>
20#include <sound/soc-dapm.h>
21#include <sound/soc-of-simple.h>
22#include <sound/initval.h>
23
24#include "tlv320aic26.h"
25
26MODULE_DESCRIPTION("ASoC TLV320AIC26 codec driver");
27MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
28MODULE_LICENSE("GPL");
29
30/* AIC26 driver private data */
31struct aic26 {
32 struct spi_device *spi;
33 struct snd_soc_codec codec;
34 u16 reg_cache[AIC26_NUM_REGS]; /* shadow registers */
35 int master;
36 int datfm;
37 int mclk;
38
39 /* Keyclick parameters */
40 int keyclick_amplitude;
41 int keyclick_freq;
42 int keyclick_len;
43};
44
45/* ---------------------------------------------------------------------
46 * Register access routines
47 */
48static unsigned int aic26_reg_read(struct snd_soc_codec *codec,
49 unsigned int reg)
50{
51 struct aic26 *aic26 = codec->private_data;
52 u16 *cache = codec->reg_cache;
53 u16 cmd, value;
54 u8 buffer[2];
55 int rc;
56
57 if (reg >= AIC26_NUM_REGS) {
58 WARN_ON_ONCE(1);
59 return 0;
60 }
61
62 /* Do SPI transfer; first 16bits are command; remaining is
63 * register contents */
64 cmd = AIC26_READ_COMMAND_WORD(reg);
65 buffer[0] = (cmd >> 8) & 0xff;
66 buffer[1] = cmd & 0xff;
67 rc = spi_write_then_read(aic26->spi, buffer, 2, buffer, 2);
68 if (rc) {
69 dev_err(&aic26->spi->dev, "AIC26 reg read error\n");
70 return -EIO;
71 }
72 value = (buffer[0] << 8) | buffer[1];
73
74 /* Update the cache before returning with the value */
75 cache[reg] = value;
76 return value;
77}
78
79static unsigned int aic26_reg_read_cache(struct snd_soc_codec *codec,
80 unsigned int reg)
81{
82 u16 *cache = codec->reg_cache;
83
84 if (reg >= AIC26_NUM_REGS) {
85 WARN_ON_ONCE(1);
86 return 0;
87 }
88
89 return cache[reg];
90}
91
92static int aic26_reg_write(struct snd_soc_codec *codec, unsigned int reg,
93 unsigned int value)
94{
95 struct aic26 *aic26 = codec->private_data;
96 u16 *cache = codec->reg_cache;
97 u16 cmd;
98 u8 buffer[4];
99 int rc;
100
101 if (reg >= AIC26_NUM_REGS) {
102 WARN_ON_ONCE(1);
103 return -EINVAL;
104 }
105
106 /* Do SPI transfer; first 16bits are command; remaining is data
107 * to write into register */
108 cmd = AIC26_WRITE_COMMAND_WORD(reg);
109 buffer[0] = (cmd >> 8) & 0xff;
110 buffer[1] = cmd & 0xff;
111 buffer[2] = value >> 8;
112 buffer[3] = value;
113 rc = spi_write(aic26->spi, buffer, 4);
114 if (rc) {
115 dev_err(&aic26->spi->dev, "AIC26 reg read error\n");
116 return -EIO;
117 }
118
119 /* update cache before returning */
120 cache[reg] = value;
121 return 0;
122}
123
124/* ---------------------------------------------------------------------
125 * Digital Audio Interface Operations
126 */
127static int aic26_hw_params(struct snd_pcm_substream *substream,
128 struct snd_pcm_hw_params *params)
129{
130 struct snd_soc_pcm_runtime *rtd = substream->private_data;
131 struct snd_soc_device *socdev = rtd->socdev;
132 struct snd_soc_codec *codec = socdev->codec;
133 struct aic26 *aic26 = codec->private_data;
134 int fsref, divisor, wlen, pval, jval, dval, qval;
135 u16 reg;
136
137 dev_dbg(&aic26->spi->dev, "aic26_hw_params(substream=%p, params=%p)\n",
138 substream, params);
139 dev_dbg(&aic26->spi->dev, "rate=%i format=%i\n", params_rate(params),
140 params_format(params));
141
142 switch (params_rate(params)) {
143 case 8000: fsref = 48000; divisor = AIC26_DIV_6; break;
144 case 11025: fsref = 44100; divisor = AIC26_DIV_4; break;
145 case 12000: fsref = 48000; divisor = AIC26_DIV_4; break;
146 case 16000: fsref = 48000; divisor = AIC26_DIV_3; break;
147 case 22050: fsref = 44100; divisor = AIC26_DIV_2; break;
148 case 24000: fsref = 48000; divisor = AIC26_DIV_2; break;
149 case 32000: fsref = 48000; divisor = AIC26_DIV_1_5; break;
150 case 44100: fsref = 44100; divisor = AIC26_DIV_1; break;
151 case 48000: fsref = 48000; divisor = AIC26_DIV_1; break;
152 default:
153 dev_dbg(&aic26->spi->dev, "bad rate\n"); return -EINVAL;
154 }
155
156 /* select data word length */
157 switch (params_format(params)) {
158 case SNDRV_PCM_FORMAT_S8: wlen = AIC26_WLEN_16; break;
159 case SNDRV_PCM_FORMAT_S16_BE: wlen = AIC26_WLEN_16; break;
160 case SNDRV_PCM_FORMAT_S24_BE: wlen = AIC26_WLEN_24; break;
161 case SNDRV_PCM_FORMAT_S32_BE: wlen = AIC26_WLEN_32; break;
162 default:
163 dev_dbg(&aic26->spi->dev, "bad format\n"); return -EINVAL;
164 }
165
166 /* Configure PLL */
167 pval = 1;
168 jval = (fsref == 44100) ? 7 : 8;
169 dval = (fsref == 44100) ? 5264 : 1920;
170 qval = 0;
171 reg = 0x8000 | qval << 11 | pval << 8 | jval << 2;
172 aic26_reg_write(codec, AIC26_REG_PLL_PROG1, reg);
173 reg = dval << 2;
174 aic26_reg_write(codec, AIC26_REG_PLL_PROG2, reg);
175
176 /* Audio Control 3 (master mode, fsref rate) */
177 reg = aic26_reg_read_cache(codec, AIC26_REG_AUDIO_CTRL3);
178 reg &= ~0xf800;
179 if (aic26->master)
180 reg |= 0x0800;
181 if (fsref == 48000)
182 reg |= 0x2000;
183 aic26_reg_write(codec, AIC26_REG_AUDIO_CTRL3, reg);
184
185 /* Audio Control 1 (FSref divisor) */
186 reg = aic26_reg_read_cache(codec, AIC26_REG_AUDIO_CTRL1);
187 reg &= ~0x0fff;
188 reg |= wlen | aic26->datfm | (divisor << 3) | divisor;
189 aic26_reg_write(codec, AIC26_REG_AUDIO_CTRL1, reg);
190
191 return 0;
192}
193
194/**
195 * aic26_mute - Mute control to reduce noise when changing audio format
196 */
197static int aic26_mute(struct snd_soc_dai *dai, int mute)
198{
199 struct snd_soc_codec *codec = dai->codec;
200 struct aic26 *aic26 = codec->private_data;
201 u16 reg = aic26_reg_read_cache(codec, AIC26_REG_DAC_GAIN);
202
203 dev_dbg(&aic26->spi->dev, "aic26_mute(dai=%p, mute=%i)\n",
204 dai, mute);
205
206 if (mute)
207 reg |= 0x8080;
208 else
209 reg &= ~0x8080;
210 aic26_reg_write(codec, AIC26_REG_DAC_GAIN, reg);
211
212 return 0;
213}
214
215static int aic26_set_sysclk(struct snd_soc_dai *codec_dai,
216 int clk_id, unsigned int freq, int dir)
217{
218 struct snd_soc_codec *codec = codec_dai->codec;
219 struct aic26 *aic26 = codec->private_data;
220
221 dev_dbg(&aic26->spi->dev, "aic26_set_sysclk(dai=%p, clk_id==%i,"
222 " freq=%i, dir=%i)\n",
223 codec_dai, clk_id, freq, dir);
224
225 /* MCLK needs to fall between 2MHz and 50 MHz */
226 if ((freq < 2000000) || (freq > 50000000))
227 return -EINVAL;
228
229 aic26->mclk = freq;
230 return 0;
231}
232
233static int aic26_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
234{
235 struct snd_soc_codec *codec = codec_dai->codec;
236 struct aic26 *aic26 = codec->private_data;
237
238 dev_dbg(&aic26->spi->dev, "aic26_set_fmt(dai=%p, fmt==%i)\n",
239 codec_dai, fmt);
240
241 /* set master/slave audio interface */
242 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
243 case SND_SOC_DAIFMT_CBM_CFM: aic26->master = 1; break;
244 case SND_SOC_DAIFMT_CBS_CFS: aic26->master = 0; break;
245 default:
246 dev_dbg(&aic26->spi->dev, "bad master\n"); return -EINVAL;
247 }
248
249 /* interface format */
250 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
251 case SND_SOC_DAIFMT_I2S: aic26->datfm = AIC26_DATFM_I2S; break;
252 case SND_SOC_DAIFMT_DSP_A: aic26->datfm = AIC26_DATFM_DSP; break;
253 case SND_SOC_DAIFMT_RIGHT_J: aic26->datfm = AIC26_DATFM_RIGHTJ; break;
254 case SND_SOC_DAIFMT_LEFT_J: aic26->datfm = AIC26_DATFM_LEFTJ; break;
255 default:
256 dev_dbg(&aic26->spi->dev, "bad format\n"); return -EINVAL;
257 }
258
259 return 0;
260}
261
262/* ---------------------------------------------------------------------
263 * Digital Audio Interface Definition
264 */
265#define AIC26_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
266 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
267 SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
268 SNDRV_PCM_RATE_48000)
269#define AIC26_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_BE |\
270 SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S32_BE)
271
272struct snd_soc_dai aic26_dai = {
273 .name = "tlv320aic26",
274 .playback = {
275 .stream_name = "Playback",
276 .channels_min = 2,
277 .channels_max = 2,
278 .rates = AIC26_RATES,
279 .formats = AIC26_FORMATS,
280 },
281 .capture = {
282 .stream_name = "Capture",
283 .channels_min = 2,
284 .channels_max = 2,
285 .rates = AIC26_RATES,
286 .formats = AIC26_FORMATS,
287 },
288 .ops = {
289 .hw_params = aic26_hw_params,
290 },
291 .dai_ops = {
292 .digital_mute = aic26_mute,
293 .set_sysclk = aic26_set_sysclk,
294 .set_fmt = aic26_set_fmt,
295 },
296};
297EXPORT_SYMBOL_GPL(aic26_dai);
298
299/* ---------------------------------------------------------------------
300 * ALSA controls
301 */
302static const char *aic26_capture_src_text[] = {"Mic", "Aux"};
303static const struct soc_enum aic26_capture_src_enum =
304 SOC_ENUM_SINGLE(AIC26_REG_AUDIO_CTRL1, 12, 2, aic26_capture_src_text);
305
306static const struct snd_kcontrol_new aic26_snd_controls[] = {
307 /* Output */
308 SOC_DOUBLE("PCM Playback Volume", AIC26_REG_DAC_GAIN, 8, 0, 0x7f, 1),
309 SOC_DOUBLE("PCM Playback Switch", AIC26_REG_DAC_GAIN, 15, 7, 1, 1),
310 SOC_SINGLE("PCM Capture Volume", AIC26_REG_ADC_GAIN, 8, 0x7f, 0),
311 SOC_SINGLE("PCM Capture Mute", AIC26_REG_ADC_GAIN, 15, 1, 1),
312 SOC_SINGLE("Keyclick activate", AIC26_REG_AUDIO_CTRL2, 15, 0x1, 0),
313 SOC_SINGLE("Keyclick amplitude", AIC26_REG_AUDIO_CTRL2, 12, 0x7, 0),
314 SOC_SINGLE("Keyclick frequency", AIC26_REG_AUDIO_CTRL2, 8, 0x7, 0),
315 SOC_SINGLE("Keyclick period", AIC26_REG_AUDIO_CTRL2, 4, 0xf, 0),
316 SOC_ENUM("Capture Source", aic26_capture_src_enum),
317};
318
319/* ---------------------------------------------------------------------
320 * SoC CODEC portion of driver: probe and release routines
321 */
322static int aic26_probe(struct platform_device *pdev)
323{
324 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
325 struct snd_soc_codec *codec;
326 struct snd_kcontrol *kcontrol;
327 struct aic26 *aic26;
328 int i, ret, err;
329
330 dev_info(&pdev->dev, "Probing AIC26 SoC CODEC driver\n");
331 dev_dbg(&pdev->dev, "socdev=%p\n", socdev);
332 dev_dbg(&pdev->dev, "codec_data=%p\n", socdev->codec_data);
333
334 /* Fetch the relevant aic26 private data here (it's already been
335 * stored in the .codec pointer) */
336 aic26 = socdev->codec_data;
337 if (aic26 == NULL) {
338 dev_err(&pdev->dev, "aic26: missing codec pointer\n");
339 return -ENODEV;
340 }
341 codec = &aic26->codec;
342 socdev->codec = codec;
343
344 dev_dbg(&pdev->dev, "Registering PCMs, dev=%p, socdev->dev=%p\n",
345 &pdev->dev, socdev->dev);
346 /* register pcms */
347 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
348 if (ret < 0) {
349 dev_err(&pdev->dev, "aic26: failed to create pcms\n");
350 return -ENODEV;
351 }
352
353 /* register controls */
354 dev_dbg(&pdev->dev, "Registering controls\n");
355 for (i = 0; i < ARRAY_SIZE(aic26_snd_controls); i++) {
356 kcontrol = snd_soc_cnew(&aic26_snd_controls[i], codec, NULL);
357 err = snd_ctl_add(codec->card, kcontrol);
358 WARN_ON(err < 0);
359 }
360
361 /* CODEC is setup, we can register the card now */
362 dev_dbg(&pdev->dev, "Registering card\n");
363 ret = snd_soc_register_card(socdev);
364 if (ret < 0) {
365 dev_err(&pdev->dev, "aic26: failed to register card\n");
366 goto card_err;
367 }
368 return 0;
369
370 card_err:
371 snd_soc_free_pcms(socdev);
372 return ret;
373}
374
375static int aic26_remove(struct platform_device *pdev)
376{
377 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
378 snd_soc_free_pcms(socdev);
379 return 0;
380}
381
382struct snd_soc_codec_device aic26_soc_codec_dev = {
383 .probe = aic26_probe,
384 .remove = aic26_remove,
385};
386EXPORT_SYMBOL_GPL(aic26_soc_codec_dev);
387
388/* ---------------------------------------------------------------------
389 * SPI device portion of driver: sysfs files for debugging
390 */
391
392static ssize_t aic26_keyclick_show(struct device *dev,
393 struct device_attribute *attr, char *buf)
394{
395 struct aic26 *aic26 = dev_get_drvdata(dev);
396 int val, amp, freq, len;
397
398 val = aic26_reg_read_cache(&aic26->codec, AIC26_REG_AUDIO_CTRL2);
399 amp = (val >> 12) & 0x7;
400 freq = (125 << ((val >> 8) & 0x7)) >> 1;
401 len = 2 * (1 + ((val >> 4) & 0xf));
402
403 return sprintf(buf, "amp=%x freq=%iHz len=%iclks\n", amp, freq, len);
404}
405
406/* Any write to the keyclick attribute will trigger the keyclick event */
407static ssize_t aic26_keyclick_set(struct device *dev,
408 struct device_attribute *attr,
409 const char *buf, size_t count)
410{
411 struct aic26 *aic26 = dev_get_drvdata(dev);
412 int val;
413
414 val = aic26_reg_read_cache(&aic26->codec, AIC26_REG_AUDIO_CTRL2);
415 val |= 0x8000;
416 aic26_reg_write(&aic26->codec, AIC26_REG_AUDIO_CTRL2, val);
417
418 return count;
419}
420
421static DEVICE_ATTR(keyclick, 0644, aic26_keyclick_show, aic26_keyclick_set);
422
423/* ---------------------------------------------------------------------
424 * SPI device portion of driver: probe and release routines and SPI
425 * driver registration.
426 */
427static int aic26_spi_probe(struct spi_device *spi)
428{
429 struct aic26 *aic26;
430 int rc, i, reg;
431
432 dev_dbg(&spi->dev, "probing tlv320aic26 spi device\n");
433
434 /* Allocate driver data */
435 aic26 = kzalloc(sizeof *aic26, GFP_KERNEL);
436 if (!aic26)
437 return -ENOMEM;
438
439 /* Initialize the driver data */
440 aic26->spi = spi;
441 dev_set_drvdata(&spi->dev, aic26);
442
443 /* Setup what we can in the codec structure so that the register
444 * access functions will work as expected. More will be filled
445 * out when it is probed by the SoC CODEC part of this driver */
446 aic26->codec.private_data = aic26;
447 aic26->codec.name = "aic26";
448 aic26->codec.owner = THIS_MODULE;
449 aic26->codec.dai = &aic26_dai;
450 aic26->codec.num_dai = 1;
451 aic26->codec.read = aic26_reg_read;
452 aic26->codec.write = aic26_reg_write;
453 aic26->master = 1;
454 mutex_init(&aic26->codec.mutex);
455 INIT_LIST_HEAD(&aic26->codec.dapm_widgets);
456 INIT_LIST_HEAD(&aic26->codec.dapm_paths);
457 aic26->codec.reg_cache_size = AIC26_NUM_REGS;
458 aic26->codec.reg_cache = aic26->reg_cache;
459
460 /* Reset the codec to power on defaults */
461 aic26_reg_write(&aic26->codec, AIC26_REG_RESET, 0xBB00);
462
463 /* Power up CODEC */
464 aic26_reg_write(&aic26->codec, AIC26_REG_POWER_CTRL, 0);
465
466 /* Audio Control 3 (master mode, fsref rate) */
467 reg = aic26_reg_read(&aic26->codec, AIC26_REG_AUDIO_CTRL3);
468 reg &= ~0xf800;
469 reg |= 0x0800; /* set master mode */
470 aic26_reg_write(&aic26->codec, AIC26_REG_AUDIO_CTRL3, reg);
471
472 /* Fill register cache */
473 for (i = 0; i < ARRAY_SIZE(aic26->reg_cache); i++)
474 aic26_reg_read(&aic26->codec, i);
475
476 /* Register the sysfs files for debugging */
477 /* Create SysFS files */
478 rc = device_create_file(&spi->dev, &dev_attr_keyclick);
479 if (rc)
480 dev_info(&spi->dev, "error creating sysfs files\n");
481
482#if defined(CONFIG_SND_SOC_OF_SIMPLE)
483 /* Tell the of_soc helper about this codec */
484 of_snd_soc_register_codec(&aic26_soc_codec_dev, aic26, &aic26_dai,
485 spi->dev.archdata.of_node);
486#endif
487
488 dev_dbg(&spi->dev, "SPI device initialized\n");
489 return 0;
490}
491
492static int aic26_spi_remove(struct spi_device *spi)
493{
494 struct aic26 *aic26 = dev_get_drvdata(&spi->dev);
495
496 kfree(aic26);
497
498 return 0;
499}
500
501static struct spi_driver aic26_spi = {
502 .driver = {
503 .name = "tlv320aic26",
504 .owner = THIS_MODULE,
505 },
506 .probe = aic26_spi_probe,
507 .remove = aic26_spi_remove,
508};
509
510static int __init aic26_init(void)
511{
512 return spi_register_driver(&aic26_spi);
513}
514module_init(aic26_init);
515
516static void __exit aic26_exit(void)
517{
518 spi_unregister_driver(&aic26_spi);
519}
520module_exit(aic26_exit);
diff --git a/sound/soc/codecs/tlv320aic26.h b/sound/soc/codecs/tlv320aic26.h
new file mode 100644
index 000000000000..786ba16c945f
--- /dev/null
+++ b/sound/soc/codecs/tlv320aic26.h
@@ -0,0 +1,96 @@
1/*
2 * Texas Instruments TLV320AIC26 low power audio CODEC
3 * register definitions
4 *
5 * Copyright (C) 2008 Secret Lab Technologies Ltd.
6 */
7
8#ifndef _TLV320AIC16_H_
9#define _TLV320AIC16_H_
10
11/* AIC26 Registers */
12#define AIC26_READ_COMMAND_WORD(addr) ((1 << 15) | (addr << 5))
13#define AIC26_WRITE_COMMAND_WORD(addr) ((0 << 15) | (addr << 5))
14#define AIC26_PAGE_ADDR(page, offset) ((page << 6) | offset)
15#define AIC26_NUM_REGS AIC26_PAGE_ADDR(3, 0)
16
17/* Page 0: Auxillary data registers */
18#define AIC26_REG_BAT1 AIC26_PAGE_ADDR(0, 0x05)
19#define AIC26_REG_BAT2 AIC26_PAGE_ADDR(0, 0x06)
20#define AIC26_REG_AUX AIC26_PAGE_ADDR(0, 0x07)
21#define AIC26_REG_TEMP1 AIC26_PAGE_ADDR(0, 0x09)
22#define AIC26_REG_TEMP2 AIC26_PAGE_ADDR(0, 0x0A)
23
24/* Page 1: Auxillary control registers */
25#define AIC26_REG_AUX_ADC AIC26_PAGE_ADDR(1, 0x00)
26#define AIC26_REG_STATUS AIC26_PAGE_ADDR(1, 0x01)
27#define AIC26_REG_REFERENCE AIC26_PAGE_ADDR(1, 0x03)
28#define AIC26_REG_RESET AIC26_PAGE_ADDR(1, 0x04)
29
30/* Page 2: Audio control registers */
31#define AIC26_REG_AUDIO_CTRL1 AIC26_PAGE_ADDR(2, 0x00)
32#define AIC26_REG_ADC_GAIN AIC26_PAGE_ADDR(2, 0x01)
33#define AIC26_REG_DAC_GAIN AIC26_PAGE_ADDR(2, 0x02)
34#define AIC26_REG_SIDETONE AIC26_PAGE_ADDR(2, 0x03)
35#define AIC26_REG_AUDIO_CTRL2 AIC26_PAGE_ADDR(2, 0x04)
36#define AIC26_REG_POWER_CTRL AIC26_PAGE_ADDR(2, 0x05)
37#define AIC26_REG_AUDIO_CTRL3 AIC26_PAGE_ADDR(2, 0x06)
38
39#define AIC26_REG_FILTER_COEFF_L_N0 AIC26_PAGE_ADDR(2, 0x07)
40#define AIC26_REG_FILTER_COEFF_L_N1 AIC26_PAGE_ADDR(2, 0x08)
41#define AIC26_REG_FILTER_COEFF_L_N2 AIC26_PAGE_ADDR(2, 0x09)
42#define AIC26_REG_FILTER_COEFF_L_N3 AIC26_PAGE_ADDR(2, 0x0A)
43#define AIC26_REG_FILTER_COEFF_L_N4 AIC26_PAGE_ADDR(2, 0x0B)
44#define AIC26_REG_FILTER_COEFF_L_N5 AIC26_PAGE_ADDR(2, 0x0C)
45#define AIC26_REG_FILTER_COEFF_L_D1 AIC26_PAGE_ADDR(2, 0x0D)
46#define AIC26_REG_FILTER_COEFF_L_D2 AIC26_PAGE_ADDR(2, 0x0E)
47#define AIC26_REG_FILTER_COEFF_L_D4 AIC26_PAGE_ADDR(2, 0x0F)
48#define AIC26_REG_FILTER_COEFF_L_D5 AIC26_PAGE_ADDR(2, 0x10)
49#define AIC26_REG_FILTER_COEFF_R_N0 AIC26_PAGE_ADDR(2, 0x11)
50#define AIC26_REG_FILTER_COEFF_R_N1 AIC26_PAGE_ADDR(2, 0x12)
51#define AIC26_REG_FILTER_COEFF_R_N2 AIC26_PAGE_ADDR(2, 0x13)
52#define AIC26_REG_FILTER_COEFF_R_N3 AIC26_PAGE_ADDR(2, 0x14)
53#define AIC26_REG_FILTER_COEFF_R_N4 AIC26_PAGE_ADDR(2, 0x15)
54#define AIC26_REG_FILTER_COEFF_R_N5 AIC26_PAGE_ADDR(2, 0x16)
55#define AIC26_REG_FILTER_COEFF_R_D1 AIC26_PAGE_ADDR(2, 0x17)
56#define AIC26_REG_FILTER_COEFF_R_D2 AIC26_PAGE_ADDR(2, 0x18)
57#define AIC26_REG_FILTER_COEFF_R_D4 AIC26_PAGE_ADDR(2, 0x19)
58#define AIC26_REG_FILTER_COEFF_R_D5 AIC26_PAGE_ADDR(2, 0x1A)
59
60#define AIC26_REG_PLL_PROG1 AIC26_PAGE_ADDR(2, 0x1B)
61#define AIC26_REG_PLL_PROG2 AIC26_PAGE_ADDR(2, 0x1C)
62#define AIC26_REG_AUDIO_CTRL4 AIC26_PAGE_ADDR(2, 0x1D)
63#define AIC26_REG_AUDIO_CTRL5 AIC26_PAGE_ADDR(2, 0x1E)
64
65/* fsref dividers; used in register 'Audio Control 1' */
66enum aic26_divisors {
67 AIC26_DIV_1 = 0,
68 AIC26_DIV_1_5 = 1,
69 AIC26_DIV_2 = 2,
70 AIC26_DIV_3 = 3,
71 AIC26_DIV_4 = 4,
72 AIC26_DIV_5 = 5,
73 AIC26_DIV_5_5 = 6,
74 AIC26_DIV_6 = 7,
75};
76
77/* Digital data format */
78enum aic26_datfm {
79 AIC26_DATFM_I2S = 0 << 8,
80 AIC26_DATFM_DSP = 1 << 8,
81 AIC26_DATFM_RIGHTJ = 2 << 8, /* right justified */
82 AIC26_DATFM_LEFTJ = 3 << 8, /* left justified */
83};
84
85/* Sample word length in bits; used in register 'Audio Control 1' */
86enum aic26_wlen {
87 AIC26_WLEN_16 = 0 << 10,
88 AIC26_WLEN_20 = 1 << 10,
89 AIC26_WLEN_24 = 2 << 10,
90 AIC26_WLEN_32 = 3 << 10,
91};
92
93extern struct snd_soc_dai aic26_dai;
94extern struct snd_soc_codec_device aic26_soc_codec_dev;
95
96#endif /* _TLV320AIC16_H_ */
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index 5f9abb199435..05336ed7e493 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * ALSA SoC TLV320AIC3X codec driver 2 * ALSA SoC TLV320AIC3X codec driver
3 * 3 *
4 * Author: Vladimir Barinov, <vbarinov@ru.mvista.com> 4 * Author: Vladimir Barinov, <vbarinov@embeddedalley.com>
5 * Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.com> 5 * Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.com>
6 * 6 *
7 * Based on sound/soc/codecs/wm8753.c by Liam Girdwood 7 * Based on sound/soc/codecs/wm8753.c by Liam Girdwood
@@ -48,7 +48,6 @@
48 48
49#include "tlv320aic3x.h" 49#include "tlv320aic3x.h"
50 50
51#define AUDIO_NAME "aic3x"
52#define AIC3X_VERSION "0.2" 51#define AIC3X_VERSION "0.2"
53 52
54/* codec private data */ 53/* codec private data */
@@ -991,7 +990,7 @@ EXPORT_SYMBOL_GPL(aic3x_headset_detected);
991 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) 990 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
992 991
993struct snd_soc_dai aic3x_dai = { 992struct snd_soc_dai aic3x_dai = {
994 .name = "aic3x", 993 .name = "tlv320aic3x",
995 .playback = { 994 .playback = {
996 .stream_name = "Playback", 995 .stream_name = "Playback",
997 .channels_min = 1, 996 .channels_min = 1,
@@ -1055,7 +1054,7 @@ static int aic3x_init(struct snd_soc_device *socdev)
1055 struct aic3x_setup_data *setup = socdev->codec_data; 1054 struct aic3x_setup_data *setup = socdev->codec_data;
1056 int reg, ret = 0; 1055 int reg, ret = 0;
1057 1056
1058 codec->name = "aic3x"; 1057 codec->name = "tlv320aic3x";
1059 codec->owner = THIS_MODULE; 1058 codec->owner = THIS_MODULE;
1060 codec->read = aic3x_read_reg_cache; 1059 codec->read = aic3x_read_reg_cache;
1061 codec->write = aic3x_write; 1060 codec->write = aic3x_write;
@@ -1172,71 +1171,39 @@ static struct snd_soc_device *aic3x_socdev;
1172 * AIC3X 2 wire address can be up to 4 devices with device addresses 1171 * AIC3X 2 wire address can be up to 4 devices with device addresses
1173 * 0x18, 0x19, 0x1A, 0x1B 1172 * 0x18, 0x19, 0x1A, 0x1B
1174 */ 1173 */
1175static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
1176
1177/* Magic definition of all other variables and things */
1178I2C_CLIENT_INSMOD;
1179
1180static struct i2c_driver aic3x_i2c_driver;
1181static struct i2c_client client_template;
1182 1174
1183/* 1175/*
1184 * If the i2c layer weren't so broken, we could pass this kind of data 1176 * If the i2c layer weren't so broken, we could pass this kind of data
1185 * around 1177 * around
1186 */ 1178 */
1187static int aic3x_codec_probe(struct i2c_adapter *adap, int addr, int kind) 1179static int aic3x_i2c_probe(struct i2c_client *i2c,
1180 const struct i2c_device_id *id)
1188{ 1181{
1189 struct snd_soc_device *socdev = aic3x_socdev; 1182 struct snd_soc_device *socdev = aic3x_socdev;
1190 struct aic3x_setup_data *setup = socdev->codec_data;
1191 struct snd_soc_codec *codec = socdev->codec; 1183 struct snd_soc_codec *codec = socdev->codec;
1192 struct i2c_client *i2c;
1193 int ret; 1184 int ret;
1194 1185
1195 if (addr != setup->i2c_address)
1196 return -ENODEV;
1197
1198 client_template.adapter = adap;
1199 client_template.addr = addr;
1200
1201 i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
1202 if (i2c == NULL)
1203 return -ENOMEM;
1204
1205 i2c_set_clientdata(i2c, codec); 1186 i2c_set_clientdata(i2c, codec);
1206 codec->control_data = i2c; 1187 codec->control_data = i2c;
1207 1188
1208 ret = i2c_attach_client(i2c);
1209 if (ret < 0) {
1210 printk(KERN_ERR "aic3x: failed to attach codec at addr %x\n",
1211 addr);
1212 goto err;
1213 }
1214
1215 ret = aic3x_init(socdev); 1189 ret = aic3x_init(socdev);
1216 if (ret < 0) { 1190 if (ret < 0)
1217 printk(KERN_ERR "aic3x: failed to initialise AIC3X\n"); 1191 printk(KERN_ERR "aic3x: failed to initialise AIC3X\n");
1218 goto err;
1219 }
1220 return ret;
1221
1222err:
1223 kfree(i2c);
1224 return ret; 1192 return ret;
1225} 1193}
1226 1194
1227static int aic3x_i2c_detach(struct i2c_client *client) 1195static int aic3x_i2c_remove(struct i2c_client *client)
1228{ 1196{
1229 struct snd_soc_codec *codec = i2c_get_clientdata(client); 1197 struct snd_soc_codec *codec = i2c_get_clientdata(client);
1230 i2c_detach_client(client);
1231 kfree(codec->reg_cache); 1198 kfree(codec->reg_cache);
1232 kfree(client);
1233 return 0; 1199 return 0;
1234} 1200}
1235 1201
1236static int aic3x_i2c_attach(struct i2c_adapter *adap) 1202static const struct i2c_device_id aic3x_i2c_id[] = {
1237{ 1203 { "tlv320aic3x", 0 },
1238 return i2c_probe(adap, &addr_data, aic3x_codec_probe); 1204 { }
1239} 1205};
1206MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id);
1240 1207
1241/* machine i2c codec control layer */ 1208/* machine i2c codec control layer */
1242static struct i2c_driver aic3x_i2c_driver = { 1209static struct i2c_driver aic3x_i2c_driver = {
@@ -1244,13 +1211,9 @@ static struct i2c_driver aic3x_i2c_driver = {
1244 .name = "aic3x I2C Codec", 1211 .name = "aic3x I2C Codec",
1245 .owner = THIS_MODULE, 1212 .owner = THIS_MODULE,
1246 }, 1213 },
1247 .attach_adapter = aic3x_i2c_attach, 1214 .probe = aic3x_i2c_probe,
1248 .detach_client = aic3x_i2c_detach, 1215 .remove = aic3x_i2c_remove,
1249}; 1216 .id_table = aic3x_i2c_id,
1250
1251static struct i2c_client client_template = {
1252 .name = "AIC3X",
1253 .driver = &aic3x_i2c_driver,
1254}; 1217};
1255 1218
1256static int aic3x_i2c_read(struct i2c_client *client, u8 *value, int len) 1219static int aic3x_i2c_read(struct i2c_client *client, u8 *value, int len)
@@ -1258,6 +1221,46 @@ static int aic3x_i2c_read(struct i2c_client *client, u8 *value, int len)
1258 value[0] = i2c_smbus_read_byte_data(client, value[0]); 1221 value[0] = i2c_smbus_read_byte_data(client, value[0]);
1259 return (len == 1); 1222 return (len == 1);
1260} 1223}
1224
1225static int aic3x_add_i2c_device(struct platform_device *pdev,
1226 const struct aic3x_setup_data *setup)
1227{
1228 struct i2c_board_info info;
1229 struct i2c_adapter *adapter;
1230 struct i2c_client *client;
1231 int ret;
1232
1233 ret = i2c_add_driver(&aic3x_i2c_driver);
1234 if (ret != 0) {
1235 dev_err(&pdev->dev, "can't add i2c driver\n");
1236 return ret;
1237 }
1238
1239 memset(&info, 0, sizeof(struct i2c_board_info));
1240 info.addr = setup->i2c_address;
1241 strlcpy(info.type, "tlv320aic3x", I2C_NAME_SIZE);
1242
1243 adapter = i2c_get_adapter(setup->i2c_bus);
1244 if (!adapter) {
1245 dev_err(&pdev->dev, "can't get i2c adapter %d\n",
1246 setup->i2c_bus);
1247 goto err_driver;
1248 }
1249
1250 client = i2c_new_device(adapter, &info);
1251 i2c_put_adapter(adapter);
1252 if (!client) {
1253 dev_err(&pdev->dev, "can't add i2c device at 0x%x\n",
1254 (unsigned int)info.addr);
1255 goto err_driver;
1256 }
1257
1258 return 0;
1259
1260err_driver:
1261 i2c_del_driver(&aic3x_i2c_driver);
1262 return -ENODEV;
1263}
1261#endif 1264#endif
1262 1265
1263static int aic3x_probe(struct platform_device *pdev) 1266static int aic3x_probe(struct platform_device *pdev)
@@ -1290,12 +1293,9 @@ static int aic3x_probe(struct platform_device *pdev)
1290 aic3x_socdev = socdev; 1293 aic3x_socdev = socdev;
1291#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 1294#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1292 if (setup->i2c_address) { 1295 if (setup->i2c_address) {
1293 normal_i2c[0] = setup->i2c_address;
1294 codec->hw_write = (hw_write_t) i2c_master_send; 1296 codec->hw_write = (hw_write_t) i2c_master_send;
1295 codec->hw_read = (hw_read_t) aic3x_i2c_read; 1297 codec->hw_read = (hw_read_t) aic3x_i2c_read;
1296 ret = i2c_add_driver(&aic3x_i2c_driver); 1298 ret = aic3x_add_i2c_device(pdev, setup);
1297 if (ret != 0)
1298 printk(KERN_ERR "can't add i2c driver");
1299 } 1299 }
1300#else 1300#else
1301 /* Add other interfaces here */ 1301 /* Add other interfaces here */
@@ -1320,6 +1320,7 @@ static int aic3x_remove(struct platform_device *pdev)
1320 snd_soc_free_pcms(socdev); 1320 snd_soc_free_pcms(socdev);
1321 snd_soc_dapm_free(socdev); 1321 snd_soc_dapm_free(socdev);
1322#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 1322#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1323 i2c_unregister_device(codec->control_data);
1323 i2c_del_driver(&aic3x_i2c_driver); 1324 i2c_del_driver(&aic3x_i2c_driver);
1324#endif 1325#endif
1325 kfree(codec->private_data); 1326 kfree(codec->private_data);
diff --git a/sound/soc/codecs/tlv320aic3x.h b/sound/soc/codecs/tlv320aic3x.h
index d76c079b86e7..00a195aa02e4 100644
--- a/sound/soc/codecs/tlv320aic3x.h
+++ b/sound/soc/codecs/tlv320aic3x.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * ALSA SoC TLV320AIC3X codec driver 2 * ALSA SoC TLV320AIC3X codec driver
3 * 3 *
4 * Author: Vladimir Barinov, <vbarinov@ru.mvista.com> 4 * Author: Vladimir Barinov, <vbarinov@embeddedalley.com>
5 * Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.com> 5 * Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.com>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
@@ -224,6 +224,7 @@ int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio);
224int aic3x_headset_detected(struct snd_soc_codec *codec); 224int aic3x_headset_detected(struct snd_soc_codec *codec);
225 225
226struct aic3x_setup_data { 226struct aic3x_setup_data {
227 int i2c_bus;
227 unsigned short i2c_address; 228 unsigned short i2c_address;
228 unsigned int gpio_func[2]; 229 unsigned int gpio_func[2];
229}; 230};
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c
index 807318fbdc8f..a69ee72a7af5 100644
--- a/sound/soc/codecs/uda1380.c
+++ b/sound/soc/codecs/uda1380.c
@@ -36,7 +36,6 @@
36#include "uda1380.h" 36#include "uda1380.h"
37 37
38#define UDA1380_VERSION "0.6" 38#define UDA1380_VERSION "0.6"
39#define AUDIO_NAME "uda1380"
40 39
41/* 40/*
42 * uda1380 register cache 41 * uda1380 register cache
@@ -701,87 +700,86 @@ static struct snd_soc_device *uda1380_socdev;
701 700
702#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 701#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
703 702
704#define I2C_DRIVERID_UDA1380 0xfefe /* liam - need a proper id */ 703static int uda1380_i2c_probe(struct i2c_client *i2c,
705 704 const struct i2c_device_id *id)
706static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
707
708/* Magic definition of all other variables and things */
709I2C_CLIENT_INSMOD;
710
711static struct i2c_driver uda1380_i2c_driver;
712static struct i2c_client client_template;
713
714/* If the i2c layer weren't so broken, we could pass this kind of data
715 around */
716
717static int uda1380_codec_probe(struct i2c_adapter *adap, int addr, int kind)
718{ 705{
719 struct snd_soc_device *socdev = uda1380_socdev; 706 struct snd_soc_device *socdev = uda1380_socdev;
720 struct uda1380_setup_data *setup = socdev->codec_data; 707 struct uda1380_setup_data *setup = socdev->codec_data;
721 struct snd_soc_codec *codec = socdev->codec; 708 struct snd_soc_codec *codec = socdev->codec;
722 struct i2c_client *i2c;
723 int ret; 709 int ret;
724 710
725 if (addr != setup->i2c_address)
726 return -ENODEV;
727
728 client_template.adapter = adap;
729 client_template.addr = addr;
730
731 i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
732 if (i2c == NULL)
733 return -ENOMEM;
734
735 i2c_set_clientdata(i2c, codec); 711 i2c_set_clientdata(i2c, codec);
736 codec->control_data = i2c; 712 codec->control_data = i2c;
737 713
738 ret = i2c_attach_client(i2c);
739 if (ret < 0) {
740 pr_err("uda1380: failed to attach codec at addr %x\n", addr);
741 goto err;
742 }
743
744 ret = uda1380_init(socdev, setup->dac_clk); 714 ret = uda1380_init(socdev, setup->dac_clk);
745 if (ret < 0) { 715 if (ret < 0)
746 pr_err("uda1380: failed to initialise UDA1380\n"); 716 pr_err("uda1380: failed to initialise UDA1380\n");
747 goto err;
748 }
749 return ret;
750 717
751err:
752 kfree(i2c);
753 return ret; 718 return ret;
754} 719}
755 720
756static int uda1380_i2c_detach(struct i2c_client *client) 721static int uda1380_i2c_remove(struct i2c_client *client)
757{ 722{
758 struct snd_soc_codec *codec = i2c_get_clientdata(client); 723 struct snd_soc_codec *codec = i2c_get_clientdata(client);
759 i2c_detach_client(client);
760 kfree(codec->reg_cache); 724 kfree(codec->reg_cache);
761 kfree(client);
762 return 0; 725 return 0;
763} 726}
764 727
765static int uda1380_i2c_attach(struct i2c_adapter *adap) 728static const struct i2c_device_id uda1380_i2c_id[] = {
766{ 729 { "uda1380", 0 },
767 return i2c_probe(adap, &addr_data, uda1380_codec_probe); 730 { }
768} 731};
732MODULE_DEVICE_TABLE(i2c, uda1380_i2c_id);
769 733
770static struct i2c_driver uda1380_i2c_driver = { 734static struct i2c_driver uda1380_i2c_driver = {
771 .driver = { 735 .driver = {
772 .name = "UDA1380 I2C Codec", 736 .name = "UDA1380 I2C Codec",
773 .owner = THIS_MODULE, 737 .owner = THIS_MODULE,
774 }, 738 },
775 .id = I2C_DRIVERID_UDA1380, 739 .probe = uda1380_i2c_probe,
776 .attach_adapter = uda1380_i2c_attach, 740 .remove = uda1380_i2c_remove,
777 .detach_client = uda1380_i2c_detach, 741 .id_table = uda1380_i2c_id,
778 .command = NULL,
779}; 742};
780 743
781static struct i2c_client client_template = { 744static int uda1380_add_i2c_device(struct platform_device *pdev,
782 .name = "UDA1380", 745 const struct uda1380_setup_data *setup)
783 .driver = &uda1380_i2c_driver, 746{
784}; 747 struct i2c_board_info info;
748 struct i2c_adapter *adapter;
749 struct i2c_client *client;
750 int ret;
751
752 ret = i2c_add_driver(&uda1380_i2c_driver);
753 if (ret != 0) {
754 dev_err(&pdev->dev, "can't add i2c driver\n");
755 return ret;
756 }
757
758 memset(&info, 0, sizeof(struct i2c_board_info));
759 info.addr = setup->i2c_address;
760 strlcpy(info.type, "uda1380", I2C_NAME_SIZE);
761
762 adapter = i2c_get_adapter(setup->i2c_bus);
763 if (!adapter) {
764 dev_err(&pdev->dev, "can't get i2c adapter %d\n",
765 setup->i2c_bus);
766 goto err_driver;
767 }
768
769 client = i2c_new_device(adapter, &info);
770 i2c_put_adapter(adapter);
771 if (!client) {
772 dev_err(&pdev->dev, "can't add i2c device at 0x%x\n",
773 (unsigned int)info.addr);
774 goto err_driver;
775 }
776
777 return 0;
778
779err_driver:
780 i2c_del_driver(&uda1380_i2c_driver);
781 return -ENODEV;
782}
785#endif 783#endif
786 784
787static int uda1380_probe(struct platform_device *pdev) 785static int uda1380_probe(struct platform_device *pdev)
@@ -789,7 +787,7 @@ static int uda1380_probe(struct platform_device *pdev)
789 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 787 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
790 struct uda1380_setup_data *setup; 788 struct uda1380_setup_data *setup;
791 struct snd_soc_codec *codec; 789 struct snd_soc_codec *codec;
792 int ret = 0; 790 int ret;
793 791
794 pr_info("UDA1380 Audio Codec %s", UDA1380_VERSION); 792 pr_info("UDA1380 Audio Codec %s", UDA1380_VERSION);
795 793
@@ -804,16 +802,13 @@ static int uda1380_probe(struct platform_device *pdev)
804 INIT_LIST_HEAD(&codec->dapm_paths); 802 INIT_LIST_HEAD(&codec->dapm_paths);
805 803
806 uda1380_socdev = socdev; 804 uda1380_socdev = socdev;
805 ret = -ENODEV;
806
807#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 807#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
808 if (setup->i2c_address) { 808 if (setup->i2c_address) {
809 normal_i2c[0] = setup->i2c_address;
810 codec->hw_write = (hw_write_t)i2c_master_send; 809 codec->hw_write = (hw_write_t)i2c_master_send;
811 ret = i2c_add_driver(&uda1380_i2c_driver); 810 ret = uda1380_add_i2c_device(pdev, setup);
812 if (ret != 0)
813 printk(KERN_ERR "can't add i2c driver");
814 } 811 }
815#else
816 /* Add other interfaces here */
817#endif 812#endif
818 813
819 if (ret != 0) 814 if (ret != 0)
@@ -833,6 +828,7 @@ static int uda1380_remove(struct platform_device *pdev)
833 snd_soc_free_pcms(socdev); 828 snd_soc_free_pcms(socdev);
834 snd_soc_dapm_free(socdev); 829 snd_soc_dapm_free(socdev);
835#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 830#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
831 i2c_unregister_device(codec->control_data);
836 i2c_del_driver(&uda1380_i2c_driver); 832 i2c_del_driver(&uda1380_i2c_driver);
837#endif 833#endif
838 kfree(codec); 834 kfree(codec);
diff --git a/sound/soc/codecs/uda1380.h b/sound/soc/codecs/uda1380.h
index 50c603e2c9f2..c55c17a52a12 100644
--- a/sound/soc/codecs/uda1380.h
+++ b/sound/soc/codecs/uda1380.h
@@ -73,6 +73,7 @@
73#define R23_AGC_EN 0x0001 73#define R23_AGC_EN 0x0001
74 74
75struct uda1380_setup_data { 75struct uda1380_setup_data {
76 int i2c_bus;
76 unsigned short i2c_address; 77 unsigned short i2c_address;
77 int dac_clk; 78 int dac_clk;
78#define UDA1380_DAC_CLK_SYSCLK 0 79#define UDA1380_DAC_CLK_SYSCLK 0
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c
index 3d998e6a997e..d8ca2da8d634 100644
--- a/sound/soc/codecs/wm8510.c
+++ b/sound/soc/codecs/wm8510.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * Copyright 2006 Wolfson Microelectronics PLC. 4 * Copyright 2006 Wolfson Microelectronics PLC.
5 * 5 *
6 * Author: Liam Girdwood <liam.girdwood@wolfsonmicro.com> 6 * Author: Liam Girdwood <lrg@slimlogic.co.uk>
7 * 7 *
8 * This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as 9 * it under the terms of the GNU General Public License version 2 as
@@ -18,6 +18,7 @@
18#include <linux/pm.h> 18#include <linux/pm.h>
19#include <linux/i2c.h> 19#include <linux/i2c.h>
20#include <linux/platform_device.h> 20#include <linux/platform_device.h>
21#include <linux/spi/spi.h>
21#include <sound/core.h> 22#include <sound/core.h>
22#include <sound/pcm.h> 23#include <sound/pcm.h>
23#include <sound/pcm_params.h> 24#include <sound/pcm_params.h>
@@ -27,7 +28,6 @@
27 28
28#include "wm8510.h" 29#include "wm8510.h"
29 30
30#define AUDIO_NAME "wm8510"
31#define WM8510_VERSION "0.6" 31#define WM8510_VERSION "0.6"
32 32
33struct snd_soc_codec_device soc_codec_dev_wm8510; 33struct snd_soc_codec_device soc_codec_dev_wm8510;
@@ -55,6 +55,9 @@ static const u16 wm8510_reg[WM8510_CACHEREGNUM] = {
55 0x0001, 55 0x0001,
56}; 56};
57 57
58#define WM8510_POWER1_BIASEN 0x08
59#define WM8510_POWER1_BUFIOEN 0x10
60
58/* 61/*
59 * read wm8510 register cache 62 * read wm8510 register cache
60 */ 63 */
@@ -199,7 +202,7 @@ SOC_DAPM_SINGLE("PCM Playback Switch", WM8510_MONOMIX, 0, 1, 0),
199}; 202};
200 203
201static const struct snd_kcontrol_new wm8510_boost_controls[] = { 204static const struct snd_kcontrol_new wm8510_boost_controls[] = {
202SOC_DAPM_SINGLE("Mic PGA Switch", WM8510_INPPGA, 6, 1, 0), 205SOC_DAPM_SINGLE("Mic PGA Switch", WM8510_INPPGA, 6, 1, 1),
203SOC_DAPM_SINGLE("Aux Volume", WM8510_ADCBOOST, 0, 7, 0), 206SOC_DAPM_SINGLE("Aux Volume", WM8510_ADCBOOST, 0, 7, 0),
204SOC_DAPM_SINGLE("Mic Volume", WM8510_ADCBOOST, 4, 7, 0), 207SOC_DAPM_SINGLE("Mic Volume", WM8510_ADCBOOST, 4, 7, 0),
205}; 208};
@@ -224,9 +227,9 @@ SND_SOC_DAPM_PGA("SpkN Out", WM8510_POWER3, 5, 0, NULL, 0),
224SND_SOC_DAPM_PGA("SpkP Out", WM8510_POWER3, 6, 0, NULL, 0), 227SND_SOC_DAPM_PGA("SpkP Out", WM8510_POWER3, 6, 0, NULL, 0),
225SND_SOC_DAPM_PGA("Mono Out", WM8510_POWER3, 7, 0, NULL, 0), 228SND_SOC_DAPM_PGA("Mono Out", WM8510_POWER3, 7, 0, NULL, 0),
226 229
227SND_SOC_DAPM_PGA("Mic PGA", WM8510_POWER2, 2, 0, 230SND_SOC_DAPM_MIXER("Mic PGA", WM8510_POWER2, 2, 0,
228 &wm8510_micpga_controls[0], 231 &wm8510_micpga_controls[0],
229 ARRAY_SIZE(wm8510_micpga_controls)), 232 ARRAY_SIZE(wm8510_micpga_controls)),
230SND_SOC_DAPM_MIXER("Boost Mixer", WM8510_POWER2, 4, 0, 233SND_SOC_DAPM_MIXER("Boost Mixer", WM8510_POWER2, 4, 0,
231 &wm8510_boost_controls[0], 234 &wm8510_boost_controls[0],
232 ARRAY_SIZE(wm8510_boost_controls)), 235 ARRAY_SIZE(wm8510_boost_controls)),
@@ -526,23 +529,35 @@ static int wm8510_mute(struct snd_soc_dai *dai, int mute)
526static int wm8510_set_bias_level(struct snd_soc_codec *codec, 529static int wm8510_set_bias_level(struct snd_soc_codec *codec,
527 enum snd_soc_bias_level level) 530 enum snd_soc_bias_level level)
528{ 531{
532 u16 power1 = wm8510_read_reg_cache(codec, WM8510_POWER1) & ~0x3;
529 533
530 switch (level) { 534 switch (level) {
531 case SND_SOC_BIAS_ON: 535 case SND_SOC_BIAS_ON:
532 wm8510_write(codec, WM8510_POWER1, 0x1ff);
533 wm8510_write(codec, WM8510_POWER2, 0x1ff);
534 wm8510_write(codec, WM8510_POWER3, 0x1ff);
535 break;
536 case SND_SOC_BIAS_PREPARE: 536 case SND_SOC_BIAS_PREPARE:
537 power1 |= 0x1; /* VMID 50k */
538 wm8510_write(codec, WM8510_POWER1, power1);
539 break;
540
537 case SND_SOC_BIAS_STANDBY: 541 case SND_SOC_BIAS_STANDBY:
542 power1 |= WM8510_POWER1_BIASEN | WM8510_POWER1_BUFIOEN;
543
544 if (codec->bias_level == SND_SOC_BIAS_OFF) {
545 /* Initial cap charge at VMID 5k */
546 wm8510_write(codec, WM8510_POWER1, power1 | 0x3);
547 mdelay(100);
548 }
549
550 power1 |= 0x2; /* VMID 500k */
551 wm8510_write(codec, WM8510_POWER1, power1);
538 break; 552 break;
553
539 case SND_SOC_BIAS_OFF: 554 case SND_SOC_BIAS_OFF:
540 /* everything off, dac mute, inactive */ 555 wm8510_write(codec, WM8510_POWER1, 0);
541 wm8510_write(codec, WM8510_POWER1, 0x0); 556 wm8510_write(codec, WM8510_POWER2, 0);
542 wm8510_write(codec, WM8510_POWER2, 0x0); 557 wm8510_write(codec, WM8510_POWER3, 0);
543 wm8510_write(codec, WM8510_POWER3, 0x0);
544 break; 558 break;
545 } 559 }
560
546 codec->bias_level = level; 561 codec->bias_level = level;
547 return 0; 562 return 0;
548} 563}
@@ -640,6 +655,7 @@ static int wm8510_init(struct snd_soc_device *socdev)
640 } 655 }
641 656
642 /* power on device */ 657 /* power on device */
658 codec->bias_level = SND_SOC_BIAS_OFF;
643 wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 659 wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
644 wm8510_add_controls(codec); 660 wm8510_add_controls(codec);
645 wm8510_add_widgets(codec); 661 wm8510_add_widgets(codec);
@@ -665,90 +681,144 @@ static struct snd_soc_device *wm8510_socdev;
665/* 681/*
666 * WM8510 2 wire address is 0x1a 682 * WM8510 2 wire address is 0x1a
667 */ 683 */
668#define I2C_DRIVERID_WM8510 0xfefe /* liam - need a proper id */
669
670static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
671 684
672/* Magic definition of all other variables and things */ 685static int wm8510_i2c_probe(struct i2c_client *i2c,
673I2C_CLIENT_INSMOD; 686 const struct i2c_device_id *id)
674
675static struct i2c_driver wm8510_i2c_driver;
676static struct i2c_client client_template;
677
678/* If the i2c layer weren't so broken, we could pass this kind of data
679 around */
680
681static int wm8510_codec_probe(struct i2c_adapter *adap, int addr, int kind)
682{ 687{
683 struct snd_soc_device *socdev = wm8510_socdev; 688 struct snd_soc_device *socdev = wm8510_socdev;
684 struct wm8510_setup_data *setup = socdev->codec_data;
685 struct snd_soc_codec *codec = socdev->codec; 689 struct snd_soc_codec *codec = socdev->codec;
686 struct i2c_client *i2c;
687 int ret; 690 int ret;
688 691
689 if (addr != setup->i2c_address)
690 return -ENODEV;
691
692 client_template.adapter = adap;
693 client_template.addr = addr;
694
695 i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
696 if (i2c == NULL)
697 return -ENOMEM;
698
699 i2c_set_clientdata(i2c, codec); 692 i2c_set_clientdata(i2c, codec);
700 codec->control_data = i2c; 693 codec->control_data = i2c;
701 694
702 ret = i2c_attach_client(i2c);
703 if (ret < 0) {
704 pr_err("failed to attach codec at addr %x\n", addr);
705 goto err;
706 }
707
708 ret = wm8510_init(socdev); 695 ret = wm8510_init(socdev);
709 if (ret < 0) { 696 if (ret < 0)
710 pr_err("failed to initialise WM8510\n"); 697 pr_err("failed to initialise WM8510\n");
711 goto err;
712 }
713 return ret;
714 698
715err:
716 kfree(i2c);
717 return ret; 699 return ret;
718} 700}
719 701
720static int wm8510_i2c_detach(struct i2c_client *client) 702static int wm8510_i2c_remove(struct i2c_client *client)
721{ 703{
722 struct snd_soc_codec *codec = i2c_get_clientdata(client); 704 struct snd_soc_codec *codec = i2c_get_clientdata(client);
723 i2c_detach_client(client);
724 kfree(codec->reg_cache); 705 kfree(codec->reg_cache);
725 kfree(client);
726 return 0; 706 return 0;
727} 707}
728 708
729static int wm8510_i2c_attach(struct i2c_adapter *adap) 709static const struct i2c_device_id wm8510_i2c_id[] = {
730{ 710 { "wm8510", 0 },
731 return i2c_probe(adap, &addr_data, wm8510_codec_probe); 711 { }
732} 712};
713MODULE_DEVICE_TABLE(i2c, wm8510_i2c_id);
733 714
734/* corgi i2c codec control layer */
735static struct i2c_driver wm8510_i2c_driver = { 715static struct i2c_driver wm8510_i2c_driver = {
736 .driver = { 716 .driver = {
737 .name = "WM8510 I2C Codec", 717 .name = "WM8510 I2C Codec",
738 .owner = THIS_MODULE, 718 .owner = THIS_MODULE,
739 }, 719 },
740 .id = I2C_DRIVERID_WM8510, 720 .probe = wm8510_i2c_probe,
741 .attach_adapter = wm8510_i2c_attach, 721 .remove = wm8510_i2c_remove,
742 .detach_client = wm8510_i2c_detach, 722 .id_table = wm8510_i2c_id,
743 .command = NULL,
744}; 723};
745 724
746static struct i2c_client client_template = { 725static int wm8510_add_i2c_device(struct platform_device *pdev,
747 .name = "WM8510", 726 const struct wm8510_setup_data *setup)
748 .driver = &wm8510_i2c_driver, 727{
749}; 728 struct i2c_board_info info;
729 struct i2c_adapter *adapter;
730 struct i2c_client *client;
731 int ret;
732
733 ret = i2c_add_driver(&wm8510_i2c_driver);
734 if (ret != 0) {
735 dev_err(&pdev->dev, "can't add i2c driver\n");
736 return ret;
737 }
738
739 memset(&info, 0, sizeof(struct i2c_board_info));
740 info.addr = setup->i2c_address;
741 strlcpy(info.type, "wm8510", I2C_NAME_SIZE);
742
743 adapter = i2c_get_adapter(setup->i2c_bus);
744 if (!adapter) {
745 dev_err(&pdev->dev, "can't get i2c adapter %d\n",
746 setup->i2c_bus);
747 goto err_driver;
748 }
749
750 client = i2c_new_device(adapter, &info);
751 i2c_put_adapter(adapter);
752 if (!client) {
753 dev_err(&pdev->dev, "can't add i2c device at 0x%x\n",
754 (unsigned int)info.addr);
755 goto err_driver;
756 }
757
758 return 0;
759
760err_driver:
761 i2c_del_driver(&wm8510_i2c_driver);
762 return -ENODEV;
763}
750#endif 764#endif
751 765
766#if defined(CONFIG_SPI_MASTER)
767static int __devinit wm8510_spi_probe(struct spi_device *spi)
768{
769 struct snd_soc_device *socdev = wm8510_socdev;
770 struct snd_soc_codec *codec = socdev->codec;
771 int ret;
772
773 codec->control_data = spi;
774
775 ret = wm8510_init(socdev);
776 if (ret < 0)
777 dev_err(&spi->dev, "failed to initialise WM8510\n");
778
779 return ret;
780}
781
782static int __devexit wm8510_spi_remove(struct spi_device *spi)
783{
784 return 0;
785}
786
787static struct spi_driver wm8510_spi_driver = {
788 .driver = {
789 .name = "wm8510",
790 .bus = &spi_bus_type,
791 .owner = THIS_MODULE,
792 },
793 .probe = wm8510_spi_probe,
794 .remove = __devexit_p(wm8510_spi_remove),
795};
796
797static int wm8510_spi_write(struct spi_device *spi, const char *data, int len)
798{
799 struct spi_transfer t;
800 struct spi_message m;
801 u8 msg[2];
802
803 if (len <= 0)
804 return 0;
805
806 msg[0] = data[0];
807 msg[1] = data[1];
808
809 spi_message_init(&m);
810 memset(&t, 0, (sizeof t));
811
812 t.tx_buf = &msg[0];
813 t.len = len;
814
815 spi_message_add_tail(&t, &m);
816 spi_sync(spi, &m);
817
818 return len;
819}
820#endif /* CONFIG_SPI_MASTER */
821
752static int wm8510_probe(struct platform_device *pdev) 822static int wm8510_probe(struct platform_device *pdev)
753{ 823{
754 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 824 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
@@ -771,14 +841,17 @@ static int wm8510_probe(struct platform_device *pdev)
771 wm8510_socdev = socdev; 841 wm8510_socdev = socdev;
772#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 842#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
773 if (setup->i2c_address) { 843 if (setup->i2c_address) {
774 normal_i2c[0] = setup->i2c_address;
775 codec->hw_write = (hw_write_t)i2c_master_send; 844 codec->hw_write = (hw_write_t)i2c_master_send;
776 ret = i2c_add_driver(&wm8510_i2c_driver); 845 ret = wm8510_add_i2c_device(pdev, setup);
846 }
847#endif
848#if defined(CONFIG_SPI_MASTER)
849 if (setup->spi) {
850 codec->hw_write = (hw_write_t)wm8510_spi_write;
851 ret = spi_register_driver(&wm8510_spi_driver);
777 if (ret != 0) 852 if (ret != 0)
778 printk(KERN_ERR "can't add i2c driver"); 853 printk(KERN_ERR "can't add spi driver");
779 } 854 }
780#else
781 /* Add other interfaces here */
782#endif 855#endif
783 856
784 if (ret != 0) 857 if (ret != 0)
@@ -798,8 +871,12 @@ static int wm8510_remove(struct platform_device *pdev)
798 snd_soc_free_pcms(socdev); 871 snd_soc_free_pcms(socdev);
799 snd_soc_dapm_free(socdev); 872 snd_soc_dapm_free(socdev);
800#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 873#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
874 i2c_unregister_device(codec->control_data);
801 i2c_del_driver(&wm8510_i2c_driver); 875 i2c_del_driver(&wm8510_i2c_driver);
802#endif 876#endif
877#if defined(CONFIG_SPI_MASTER)
878 spi_unregister_driver(&wm8510_spi_driver);
879#endif
803 kfree(codec); 880 kfree(codec);
804 881
805 return 0; 882 return 0;
diff --git a/sound/soc/codecs/wm8510.h b/sound/soc/codecs/wm8510.h
index f5d2e42eb3f4..bdefcf5c69ff 100644
--- a/sound/soc/codecs/wm8510.h
+++ b/sound/soc/codecs/wm8510.h
@@ -94,6 +94,8 @@
94#define WM8510_MCLKDIV_12 (7 << 5) 94#define WM8510_MCLKDIV_12 (7 << 5)
95 95
96struct wm8510_setup_data { 96struct wm8510_setup_data {
97 int spi;
98 int i2c_bus;
97 unsigned short i2c_address; 99 unsigned short i2c_address;
98}; 100};
99 101
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c
new file mode 100644
index 000000000000..627ebfb4209b
--- /dev/null
+++ b/sound/soc/codecs/wm8580.c
@@ -0,0 +1,1053 @@
1/*
2 * wm8580.c -- WM8580 ALSA Soc Audio driver
3 *
4 * Copyright 2008 Wolfson Microelectronics PLC.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 *
11 * Notes:
12 * The WM8580 is a multichannel codec with S/PDIF support, featuring six
13 * DAC channels and two ADC channels.
14 *
15 * Currently only the primary audio interface is supported - S/PDIF and
16 * the secondary audio interfaces are not.
17 */
18
19#include <linux/module.h>
20#include <linux/moduleparam.h>
21#include <linux/kernel.h>
22#include <linux/init.h>
23#include <linux/delay.h>
24#include <linux/pm.h>
25#include <linux/i2c.h>
26#include <linux/platform_device.h>
27#include <sound/core.h>
28#include <sound/pcm.h>
29#include <sound/pcm_params.h>
30#include <sound/soc.h>
31#include <sound/soc-dapm.h>
32#include <sound/tlv.h>
33#include <sound/initval.h>
34#include <asm/div64.h>
35
36#include "wm8580.h"
37
38#define WM8580_VERSION "0.1"
39
40struct pll_state {
41 unsigned int in;
42 unsigned int out;
43};
44
45/* codec private data */
46struct wm8580_priv {
47 struct pll_state a;
48 struct pll_state b;
49};
50
51/* WM8580 register space */
52#define WM8580_PLLA1 0x00
53#define WM8580_PLLA2 0x01
54#define WM8580_PLLA3 0x02
55#define WM8580_PLLA4 0x03
56#define WM8580_PLLB1 0x04
57#define WM8580_PLLB2 0x05
58#define WM8580_PLLB3 0x06
59#define WM8580_PLLB4 0x07
60#define WM8580_CLKSEL 0x08
61#define WM8580_PAIF1 0x09
62#define WM8580_PAIF2 0x0A
63#define WM8580_SAIF1 0x0B
64#define WM8580_PAIF3 0x0C
65#define WM8580_PAIF4 0x0D
66#define WM8580_SAIF2 0x0E
67#define WM8580_DAC_CONTROL1 0x0F
68#define WM8580_DAC_CONTROL2 0x10
69#define WM8580_DAC_CONTROL3 0x11
70#define WM8580_DAC_CONTROL4 0x12
71#define WM8580_DAC_CONTROL5 0x13
72#define WM8580_DIGITAL_ATTENUATION_DACL1 0x14
73#define WM8580_DIGITAL_ATTENUATION_DACR1 0x15
74#define WM8580_DIGITAL_ATTENUATION_DACL2 0x16
75#define WM8580_DIGITAL_ATTENUATION_DACR2 0x17
76#define WM8580_DIGITAL_ATTENUATION_DACL3 0x18
77#define WM8580_DIGITAL_ATTENUATION_DACR3 0x19
78#define WM8580_MASTER_DIGITAL_ATTENUATION 0x1C
79#define WM8580_ADC_CONTROL1 0x1D
80#define WM8580_SPDTXCHAN0 0x1E
81#define WM8580_SPDTXCHAN1 0x1F
82#define WM8580_SPDTXCHAN2 0x20
83#define WM8580_SPDTXCHAN3 0x21
84#define WM8580_SPDTXCHAN4 0x22
85#define WM8580_SPDTXCHAN5 0x23
86#define WM8580_SPDMODE 0x24
87#define WM8580_INTMASK 0x25
88#define WM8580_GPO1 0x26
89#define WM8580_GPO2 0x27
90#define WM8580_GPO3 0x28
91#define WM8580_GPO4 0x29
92#define WM8580_GPO5 0x2A
93#define WM8580_INTSTAT 0x2B
94#define WM8580_SPDRXCHAN1 0x2C
95#define WM8580_SPDRXCHAN2 0x2D
96#define WM8580_SPDRXCHAN3 0x2E
97#define WM8580_SPDRXCHAN4 0x2F
98#define WM8580_SPDRXCHAN5 0x30
99#define WM8580_SPDSTAT 0x31
100#define WM8580_PWRDN1 0x32
101#define WM8580_PWRDN2 0x33
102#define WM8580_READBACK 0x34
103#define WM8580_RESET 0x35
104
105/* PLLB4 (register 7h) */
106#define WM8580_PLLB4_MCLKOUTSRC_MASK 0x60
107#define WM8580_PLLB4_MCLKOUTSRC_PLLA 0x20
108#define WM8580_PLLB4_MCLKOUTSRC_PLLB 0x40
109#define WM8580_PLLB4_MCLKOUTSRC_OSC 0x60
110
111#define WM8580_PLLB4_CLKOUTSRC_MASK 0x180
112#define WM8580_PLLB4_CLKOUTSRC_PLLACLK 0x080
113#define WM8580_PLLB4_CLKOUTSRC_PLLBCLK 0x100
114#define WM8580_PLLB4_CLKOUTSRC_OSCCLK 0x180
115
116/* CLKSEL (register 8h) */
117#define WM8580_CLKSEL_DAC_CLKSEL_MASK 0x03
118#define WM8580_CLKSEL_DAC_CLKSEL_PLLA 0x01
119#define WM8580_CLKSEL_DAC_CLKSEL_PLLB 0x02
120
121/* AIF control 1 (registers 9h-bh) */
122#define WM8580_AIF_RATE_MASK 0x7
123#define WM8580_AIF_RATE_128 0x0
124#define WM8580_AIF_RATE_192 0x1
125#define WM8580_AIF_RATE_256 0x2
126#define WM8580_AIF_RATE_384 0x3
127#define WM8580_AIF_RATE_512 0x4
128#define WM8580_AIF_RATE_768 0x5
129#define WM8580_AIF_RATE_1152 0x6
130
131#define WM8580_AIF_BCLKSEL_MASK 0x18
132#define WM8580_AIF_BCLKSEL_64 0x00
133#define WM8580_AIF_BCLKSEL_128 0x08
134#define WM8580_AIF_BCLKSEL_256 0x10
135#define WM8580_AIF_BCLKSEL_SYSCLK 0x18
136
137#define WM8580_AIF_MS 0x20
138
139#define WM8580_AIF_CLKSRC_MASK 0xc0
140#define WM8580_AIF_CLKSRC_PLLA 0x40
141#define WM8580_AIF_CLKSRC_PLLB 0x40
142#define WM8580_AIF_CLKSRC_MCLK 0xc0
143
144/* AIF control 2 (registers ch-eh) */
145#define WM8580_AIF_FMT_MASK 0x03
146#define WM8580_AIF_FMT_RIGHTJ 0x00
147#define WM8580_AIF_FMT_LEFTJ 0x01
148#define WM8580_AIF_FMT_I2S 0x02
149#define WM8580_AIF_FMT_DSP 0x03
150
151#define WM8580_AIF_LENGTH_MASK 0x0c
152#define WM8580_AIF_LENGTH_16 0x00
153#define WM8580_AIF_LENGTH_20 0x04
154#define WM8580_AIF_LENGTH_24 0x08
155#define WM8580_AIF_LENGTH_32 0x0c
156
157#define WM8580_AIF_LRP 0x10
158#define WM8580_AIF_BCP 0x20
159
160/* Powerdown Register 1 (register 32h) */
161#define WM8580_PWRDN1_PWDN 0x001
162#define WM8580_PWRDN1_ALLDACPD 0x040
163
164/* Powerdown Register 2 (register 33h) */
165#define WM8580_PWRDN2_OSSCPD 0x001
166#define WM8580_PWRDN2_PLLAPD 0x002
167#define WM8580_PWRDN2_PLLBPD 0x004
168#define WM8580_PWRDN2_SPDIFPD 0x008
169#define WM8580_PWRDN2_SPDIFTXD 0x010
170#define WM8580_PWRDN2_SPDIFRXD 0x020
171
172#define WM8580_DAC_CONTROL5_MUTEALL 0x10
173
174/*
175 * wm8580 register cache
176 * We can't read the WM8580 register space when we
177 * are using 2 wire for device control, so we cache them instead.
178 */
179static const u16 wm8580_reg[] = {
180 0x0121, 0x017e, 0x007d, 0x0014, /*R3*/
181 0x0121, 0x017e, 0x007d, 0x0194, /*R7*/
182 0x001c, 0x0002, 0x0002, 0x00c2, /*R11*/
183 0x0182, 0x0082, 0x000a, 0x0024, /*R15*/
184 0x0009, 0x0000, 0x00ff, 0x0000, /*R19*/
185 0x00ff, 0x00ff, 0x00ff, 0x00ff, /*R23*/
186 0x00ff, 0x00ff, 0x00ff, 0x00ff, /*R27*/
187 0x01f0, 0x0040, 0x0000, 0x0000, /*R31(0x1F)*/
188 0x0000, 0x0000, 0x0031, 0x000b, /*R35*/
189 0x0039, 0x0000, 0x0010, 0x0032, /*R39*/
190 0x0054, 0x0076, 0x0098, 0x0000, /*R43(0x2B)*/
191 0x0000, 0x0000, 0x0000, 0x0000, /*R47*/
192 0x0000, 0x0000, 0x005e, 0x003e, /*R51(0x33)*/
193 0x0000, 0x0000 /*R53*/
194};
195
196/*
197 * read wm8580 register cache
198 */
199static inline unsigned int wm8580_read_reg_cache(struct snd_soc_codec *codec,
200 unsigned int reg)
201{
202 u16 *cache = codec->reg_cache;
203 BUG_ON(reg > ARRAY_SIZE(wm8580_reg));
204 return cache[reg];
205}
206
207/*
208 * write wm8580 register cache
209 */
210static inline void wm8580_write_reg_cache(struct snd_soc_codec *codec,
211 unsigned int reg, unsigned int value)
212{
213 u16 *cache = codec->reg_cache;
214
215 cache[reg] = value;
216}
217
218/*
219 * write to the WM8580 register space
220 */
221static int wm8580_write(struct snd_soc_codec *codec, unsigned int reg,
222 unsigned int value)
223{
224 u8 data[2];
225
226 BUG_ON(reg > ARRAY_SIZE(wm8580_reg));
227
228 /* Registers are 9 bits wide */
229 value &= 0x1ff;
230
231 switch (reg) {
232 case WM8580_RESET:
233 /* Uncached */
234 break;
235 default:
236 if (value == wm8580_read_reg_cache(codec, reg))
237 return 0;
238 }
239
240 /* data is
241 * D15..D9 WM8580 register offset
242 * D8...D0 register data
243 */
244 data[0] = (reg << 1) | ((value >> 8) & 0x0001);
245 data[1] = value & 0x00ff;
246
247 wm8580_write_reg_cache(codec, reg, value);
248 if (codec->hw_write(codec->control_data, data, 2) == 2)
249 return 0;
250 else
251 return -EIO;
252}
253
254static inline unsigned int wm8580_read(struct snd_soc_codec *codec,
255 unsigned int reg)
256{
257 switch (reg) {
258 default:
259 return wm8580_read_reg_cache(codec, reg);
260 }
261}
262
263static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1);
264
265static int wm8580_out_vu(struct snd_kcontrol *kcontrol,
266 struct snd_ctl_elem_value *ucontrol)
267{
268 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
269 int reg = kcontrol->private_value & 0xff;
270 int reg2 = (kcontrol->private_value >> 24) & 0xff;
271 int ret;
272 u16 val;
273
274 /* Clear the register cache so we write without VU set */
275 wm8580_write_reg_cache(codec, reg, 0);
276 wm8580_write_reg_cache(codec, reg2, 0);
277
278 ret = snd_soc_put_volsw_2r(kcontrol, ucontrol);
279 if (ret < 0)
280 return ret;
281
282 /* Now write again with the volume update bit set */
283 val = wm8580_read_reg_cache(codec, reg);
284 wm8580_write(codec, reg, val | 0x0100);
285
286 val = wm8580_read_reg_cache(codec, reg2);
287 wm8580_write(codec, reg2, val | 0x0100);
288
289 return 0;
290}
291
292#define SOC_WM8580_OUT_DOUBLE_R_TLV(xname, reg_left, reg_right, shift, max, invert, tlv_array) \
293{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
294 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
295 SNDRV_CTL_ELEM_ACCESS_READWRITE, \
296 .tlv.p = (tlv_array), \
297 .info = snd_soc_info_volsw_2r, \
298 .get = snd_soc_get_volsw_2r, .put = wm8580_out_vu, \
299 .private_value = (reg_left) | ((shift) << 8) | \
300 ((max) << 12) | ((invert) << 20) | ((reg_right) << 24) }
301
302static const struct snd_kcontrol_new wm8580_snd_controls[] = {
303SOC_WM8580_OUT_DOUBLE_R_TLV("DAC1 Playback Volume",
304 WM8580_DIGITAL_ATTENUATION_DACL1,
305 WM8580_DIGITAL_ATTENUATION_DACR1,
306 0, 0xff, 0, dac_tlv),
307SOC_WM8580_OUT_DOUBLE_R_TLV("DAC2 Playback Volume",
308 WM8580_DIGITAL_ATTENUATION_DACL2,
309 WM8580_DIGITAL_ATTENUATION_DACR2,
310 0, 0xff, 0, dac_tlv),
311SOC_WM8580_OUT_DOUBLE_R_TLV("DAC3 Playback Volume",
312 WM8580_DIGITAL_ATTENUATION_DACL3,
313 WM8580_DIGITAL_ATTENUATION_DACR3,
314 0, 0xff, 0, dac_tlv),
315
316SOC_SINGLE("DAC1 Deemphasis Switch", WM8580_DAC_CONTROL3, 0, 1, 0),
317SOC_SINGLE("DAC2 Deemphasis Switch", WM8580_DAC_CONTROL3, 1, 1, 0),
318SOC_SINGLE("DAC3 Deemphasis Switch", WM8580_DAC_CONTROL3, 2, 1, 0),
319
320SOC_DOUBLE("DAC1 Invert Switch", WM8580_DAC_CONTROL4, 0, 1, 1, 0),
321SOC_DOUBLE("DAC2 Invert Switch", WM8580_DAC_CONTROL4, 2, 3, 1, 0),
322SOC_DOUBLE("DAC3 Invert Switch", WM8580_DAC_CONTROL4, 4, 5, 1, 0),
323
324SOC_SINGLE("DAC ZC Switch", WM8580_DAC_CONTROL5, 5, 1, 0),
325SOC_SINGLE("DAC1 Switch", WM8580_DAC_CONTROL5, 0, 1, 0),
326SOC_SINGLE("DAC2 Switch", WM8580_DAC_CONTROL5, 1, 1, 0),
327SOC_SINGLE("DAC3 Switch", WM8580_DAC_CONTROL5, 2, 1, 0),
328
329SOC_DOUBLE("ADC Mute Switch", WM8580_ADC_CONTROL1, 0, 1, 1, 0),
330SOC_SINGLE("ADC High-Pass Filter Switch", WM8580_ADC_CONTROL1, 4, 1, 0),
331};
332
333/* Add non-DAPM controls */
334static int wm8580_add_controls(struct snd_soc_codec *codec)
335{
336 int err, i;
337
338 for (i = 0; i < ARRAY_SIZE(wm8580_snd_controls); i++) {
339 err = snd_ctl_add(codec->card,
340 snd_soc_cnew(&wm8580_snd_controls[i],
341 codec, NULL));
342 if (err < 0)
343 return err;
344 }
345 return 0;
346}
347static const struct snd_soc_dapm_widget wm8580_dapm_widgets[] = {
348SND_SOC_DAPM_DAC("DAC1", "Playback", WM8580_PWRDN1, 2, 1),
349SND_SOC_DAPM_DAC("DAC2", "Playback", WM8580_PWRDN1, 3, 1),
350SND_SOC_DAPM_DAC("DAC3", "Playback", WM8580_PWRDN1, 4, 1),
351
352SND_SOC_DAPM_OUTPUT("VOUT1L"),
353SND_SOC_DAPM_OUTPUT("VOUT1R"),
354SND_SOC_DAPM_OUTPUT("VOUT2L"),
355SND_SOC_DAPM_OUTPUT("VOUT2R"),
356SND_SOC_DAPM_OUTPUT("VOUT3L"),
357SND_SOC_DAPM_OUTPUT("VOUT3R"),
358
359SND_SOC_DAPM_ADC("ADC", "Capture", WM8580_PWRDN1, 1, 1),
360
361SND_SOC_DAPM_INPUT("AINL"),
362SND_SOC_DAPM_INPUT("AINR"),
363};
364
365static const struct snd_soc_dapm_route audio_map[] = {
366 { "VOUT1L", NULL, "DAC1" },
367 { "VOUT1R", NULL, "DAC1" },
368
369 { "VOUT2L", NULL, "DAC2" },
370 { "VOUT2R", NULL, "DAC2" },
371
372 { "VOUT3L", NULL, "DAC3" },
373 { "VOUT3R", NULL, "DAC3" },
374
375 { "ADC", NULL, "AINL" },
376 { "ADC", NULL, "AINR" },
377};
378
379static int wm8580_add_widgets(struct snd_soc_codec *codec)
380{
381 snd_soc_dapm_new_controls(codec, wm8580_dapm_widgets,
382 ARRAY_SIZE(wm8580_dapm_widgets));
383
384 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
385
386 snd_soc_dapm_new_widgets(codec);
387 return 0;
388}
389
390/* PLL divisors */
391struct _pll_div {
392 u32 prescale:1;
393 u32 postscale:1;
394 u32 freqmode:2;
395 u32 n:4;
396 u32 k:24;
397};
398
399/* The size in bits of the pll divide */
400#define FIXED_PLL_SIZE (1 << 22)
401
402/* PLL rate to output rate divisions */
403static struct {
404 unsigned int div;
405 unsigned int freqmode;
406 unsigned int postscale;
407} post_table[] = {
408 { 2, 0, 0 },
409 { 4, 0, 1 },
410 { 4, 1, 0 },
411 { 8, 1, 1 },
412 { 8, 2, 0 },
413 { 16, 2, 1 },
414 { 12, 3, 0 },
415 { 24, 3, 1 }
416};
417
418static int pll_factors(struct _pll_div *pll_div, unsigned int target,
419 unsigned int source)
420{
421 u64 Kpart;
422 unsigned int K, Ndiv, Nmod;
423 int i;
424
425 pr_debug("wm8580: PLL %dHz->%dHz\n", source, target);
426
427 /* Scale the output frequency up; the PLL should run in the
428 * region of 90-100MHz.
429 */
430 for (i = 0; i < ARRAY_SIZE(post_table); i++) {
431 if (target * post_table[i].div >= 90000000 &&
432 target * post_table[i].div <= 100000000) {
433 pll_div->freqmode = post_table[i].freqmode;
434 pll_div->postscale = post_table[i].postscale;
435 target *= post_table[i].div;
436 break;
437 }
438 }
439
440 if (i == ARRAY_SIZE(post_table)) {
441 printk(KERN_ERR "wm8580: Unable to scale output frequency "
442 "%u\n", target);
443 return -EINVAL;
444 }
445
446 Ndiv = target / source;
447
448 if (Ndiv < 5) {
449 source /= 2;
450 pll_div->prescale = 1;
451 Ndiv = target / source;
452 } else
453 pll_div->prescale = 0;
454
455 if ((Ndiv < 5) || (Ndiv > 13)) {
456 printk(KERN_ERR
457 "WM8580 N=%d outside supported range\n", Ndiv);
458 return -EINVAL;
459 }
460
461 pll_div->n = Ndiv;
462 Nmod = target % source;
463 Kpart = FIXED_PLL_SIZE * (long long)Nmod;
464
465 do_div(Kpart, source);
466
467 K = Kpart & 0xFFFFFFFF;
468
469 pll_div->k = K;
470
471 pr_debug("PLL %x.%x prescale %d freqmode %d postscale %d\n",
472 pll_div->n, pll_div->k, pll_div->prescale, pll_div->freqmode,
473 pll_div->postscale);
474
475 return 0;
476}
477
478static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai,
479 int pll_id, unsigned int freq_in, unsigned int freq_out)
480{
481 int offset;
482 struct snd_soc_codec *codec = codec_dai->codec;
483 struct wm8580_priv *wm8580 = codec->private_data;
484 struct pll_state *state;
485 struct _pll_div pll_div;
486 unsigned int reg;
487 unsigned int pwr_mask;
488 int ret;
489
490 /* GCC isn't able to work out the ifs below for initialising/using
491 * pll_div so suppress warnings.
492 */
493 memset(&pll_div, 0, sizeof(pll_div));
494
495 switch (pll_id) {
496 case WM8580_PLLA:
497 state = &wm8580->a;
498 offset = 0;
499 pwr_mask = WM8580_PWRDN2_PLLAPD;
500 break;
501 case WM8580_PLLB:
502 state = &wm8580->b;
503 offset = 4;
504 pwr_mask = WM8580_PWRDN2_PLLBPD;
505 break;
506 default:
507 return -ENODEV;
508 }
509
510 if (freq_in && freq_out) {
511 ret = pll_factors(&pll_div, freq_out, freq_in);
512 if (ret != 0)
513 return ret;
514 }
515
516 state->in = freq_in;
517 state->out = freq_out;
518
519 /* Always disable the PLL - it is not safe to leave it running
520 * while reprogramming it.
521 */
522 reg = wm8580_read(codec, WM8580_PWRDN2);
523 wm8580_write(codec, WM8580_PWRDN2, reg | pwr_mask);
524
525 if (!freq_in || !freq_out)
526 return 0;
527
528 wm8580_write(codec, WM8580_PLLA1 + offset, pll_div.k & 0x1ff);
529 wm8580_write(codec, WM8580_PLLA2 + offset, (pll_div.k >> 9) & 0xff);
530 wm8580_write(codec, WM8580_PLLA3 + offset,
531 (pll_div.k >> 18 & 0xf) | (pll_div.n << 4));
532
533 reg = wm8580_read(codec, WM8580_PLLA4 + offset);
534 reg &= ~0x3f;
535 reg |= pll_div.prescale | pll_div.postscale << 1 |
536 pll_div.freqmode << 4;
537
538 wm8580_write(codec, WM8580_PLLA4 + offset, reg);
539
540 /* All done, turn it on */
541 reg = wm8580_read(codec, WM8580_PWRDN2);
542 wm8580_write(codec, WM8580_PWRDN2, reg & ~pwr_mask);
543
544 return 0;
545}
546
547/*
548 * Set PCM DAI bit size and sample rate.
549 */
550static int wm8580_paif_hw_params(struct snd_pcm_substream *substream,
551 struct snd_pcm_hw_params *params)
552{
553 struct snd_soc_pcm_runtime *rtd = substream->private_data;
554 struct snd_soc_dai_link *dai = rtd->dai;
555 struct snd_soc_device *socdev = rtd->socdev;
556 struct snd_soc_codec *codec = socdev->codec;
557 u16 paifb = wm8580_read(codec, WM8580_PAIF3 + dai->codec_dai->id);
558
559 paifb &= ~WM8580_AIF_LENGTH_MASK;
560 /* bit size */
561 switch (params_format(params)) {
562 case SNDRV_PCM_FORMAT_S16_LE:
563 break;
564 case SNDRV_PCM_FORMAT_S20_3LE:
565 paifb |= WM8580_AIF_LENGTH_20;
566 break;
567 case SNDRV_PCM_FORMAT_S24_LE:
568 paifb |= WM8580_AIF_LENGTH_24;
569 break;
570 case SNDRV_PCM_FORMAT_S32_LE:
571 paifb |= WM8580_AIF_LENGTH_24;
572 break;
573 default:
574 return -EINVAL;
575 }
576
577 wm8580_write(codec, WM8580_PAIF3 + dai->codec_dai->id, paifb);
578 return 0;
579}
580
581static int wm8580_set_paif_dai_fmt(struct snd_soc_dai *codec_dai,
582 unsigned int fmt)
583{
584 struct snd_soc_codec *codec = codec_dai->codec;
585 unsigned int aifa;
586 unsigned int aifb;
587 int can_invert_lrclk;
588
589 aifa = wm8580_read(codec, WM8580_PAIF1 + codec_dai->id);
590 aifb = wm8580_read(codec, WM8580_PAIF3 + codec_dai->id);
591
592 aifb &= ~(WM8580_AIF_FMT_MASK | WM8580_AIF_LRP | WM8580_AIF_BCP);
593
594 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
595 case SND_SOC_DAIFMT_CBS_CFS:
596 aifa &= ~WM8580_AIF_MS;
597 break;
598 case SND_SOC_DAIFMT_CBM_CFM:
599 aifa |= WM8580_AIF_MS;
600 break;
601 default:
602 return -EINVAL;
603 }
604
605 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
606 case SND_SOC_DAIFMT_I2S:
607 can_invert_lrclk = 1;
608 aifb |= WM8580_AIF_FMT_I2S;
609 break;
610 case SND_SOC_DAIFMT_RIGHT_J:
611 can_invert_lrclk = 1;
612 aifb |= WM8580_AIF_FMT_RIGHTJ;
613 break;
614 case SND_SOC_DAIFMT_LEFT_J:
615 can_invert_lrclk = 1;
616 aifb |= WM8580_AIF_FMT_LEFTJ;
617 break;
618 case SND_SOC_DAIFMT_DSP_A:
619 can_invert_lrclk = 0;
620 aifb |= WM8580_AIF_FMT_DSP;
621 break;
622 case SND_SOC_DAIFMT_DSP_B:
623 can_invert_lrclk = 0;
624 aifb |= WM8580_AIF_FMT_DSP;
625 aifb |= WM8580_AIF_LRP;
626 break;
627 default:
628 return -EINVAL;
629 }
630
631 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
632 case SND_SOC_DAIFMT_NB_NF:
633 break;
634
635 case SND_SOC_DAIFMT_IB_IF:
636 if (!can_invert_lrclk)
637 return -EINVAL;
638 aifb |= WM8580_AIF_BCP;
639 aifb |= WM8580_AIF_LRP;
640 break;
641
642 case SND_SOC_DAIFMT_IB_NF:
643 aifb |= WM8580_AIF_BCP;
644 break;
645
646 case SND_SOC_DAIFMT_NB_IF:
647 if (!can_invert_lrclk)
648 return -EINVAL;
649 aifb |= WM8580_AIF_LRP;
650 break;
651
652 default:
653 return -EINVAL;
654 }
655
656 wm8580_write(codec, WM8580_PAIF1 + codec_dai->id, aifa);
657 wm8580_write(codec, WM8580_PAIF3 + codec_dai->id, aifb);
658
659 return 0;
660}
661
662static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
663 int div_id, int div)
664{
665 struct snd_soc_codec *codec = codec_dai->codec;
666 unsigned int reg;
667
668 switch (div_id) {
669 case WM8580_MCLK:
670 reg = wm8580_read(codec, WM8580_PLLB4);
671 reg &= ~WM8580_PLLB4_MCLKOUTSRC_MASK;
672
673 switch (div) {
674 case WM8580_CLKSRC_MCLK:
675 /* Input */
676 break;
677
678 case WM8580_CLKSRC_PLLA:
679 reg |= WM8580_PLLB4_MCLKOUTSRC_PLLA;
680 break;
681 case WM8580_CLKSRC_PLLB:
682 reg |= WM8580_PLLB4_MCLKOUTSRC_PLLB;
683 break;
684
685 case WM8580_CLKSRC_OSC:
686 reg |= WM8580_PLLB4_MCLKOUTSRC_OSC;
687 break;
688
689 default:
690 return -EINVAL;
691 }
692 wm8580_write(codec, WM8580_PLLB4, reg);
693 break;
694
695 case WM8580_DAC_CLKSEL:
696 reg = wm8580_read(codec, WM8580_CLKSEL);
697 reg &= ~WM8580_CLKSEL_DAC_CLKSEL_MASK;
698
699 switch (div) {
700 case WM8580_CLKSRC_MCLK:
701 break;
702
703 case WM8580_CLKSRC_PLLA:
704 reg |= WM8580_CLKSEL_DAC_CLKSEL_PLLA;
705 break;
706
707 case WM8580_CLKSRC_PLLB:
708 reg |= WM8580_CLKSEL_DAC_CLKSEL_PLLB;
709 break;
710
711 default:
712 return -EINVAL;
713 }
714 wm8580_write(codec, WM8580_CLKSEL, reg);
715 break;
716
717 case WM8580_CLKOUTSRC:
718 reg = wm8580_read(codec, WM8580_PLLB4);
719 reg &= ~WM8580_PLLB4_CLKOUTSRC_MASK;
720
721 switch (div) {
722 case WM8580_CLKSRC_NONE:
723 break;
724
725 case WM8580_CLKSRC_PLLA:
726 reg |= WM8580_PLLB4_CLKOUTSRC_PLLACLK;
727 break;
728
729 case WM8580_CLKSRC_PLLB:
730 reg |= WM8580_PLLB4_CLKOUTSRC_PLLBCLK;
731 break;
732
733 case WM8580_CLKSRC_OSC:
734 reg |= WM8580_PLLB4_CLKOUTSRC_OSCCLK;
735 break;
736
737 default:
738 return -EINVAL;
739 }
740 wm8580_write(codec, WM8580_PLLB4, reg);
741 break;
742
743 default:
744 return -EINVAL;
745 }
746
747 return 0;
748}
749
750static int wm8580_digital_mute(struct snd_soc_dai *codec_dai, int mute)
751{
752 struct snd_soc_codec *codec = codec_dai->codec;
753 unsigned int reg;
754
755 reg = wm8580_read(codec, WM8580_DAC_CONTROL5);
756
757 if (mute)
758 reg |= WM8580_DAC_CONTROL5_MUTEALL;
759 else
760 reg &= ~WM8580_DAC_CONTROL5_MUTEALL;
761
762 wm8580_write(codec, WM8580_DAC_CONTROL5, reg);
763
764 return 0;
765}
766
767static int wm8580_set_bias_level(struct snd_soc_codec *codec,
768 enum snd_soc_bias_level level)
769{
770 u16 reg;
771 switch (level) {
772 case SND_SOC_BIAS_ON:
773 case SND_SOC_BIAS_PREPARE:
774 case SND_SOC_BIAS_STANDBY:
775 break;
776 case SND_SOC_BIAS_OFF:
777 reg = wm8580_read(codec, WM8580_PWRDN1);
778 wm8580_write(codec, WM8580_PWRDN1, reg | WM8580_PWRDN1_PWDN);
779 break;
780 }
781 codec->bias_level = level;
782 return 0;
783}
784
785#define WM8580_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
786 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
787
788struct snd_soc_dai wm8580_dai[] = {
789 {
790 .name = "WM8580 PAIFRX",
791 .id = 0,
792 .playback = {
793 .stream_name = "Playback",
794 .channels_min = 1,
795 .channels_max = 6,
796 .rates = SNDRV_PCM_RATE_8000_192000,
797 .formats = WM8580_FORMATS,
798 },
799 .ops = {
800 .hw_params = wm8580_paif_hw_params,
801 },
802 .dai_ops = {
803 .set_fmt = wm8580_set_paif_dai_fmt,
804 .set_clkdiv = wm8580_set_dai_clkdiv,
805 .set_pll = wm8580_set_dai_pll,
806 .digital_mute = wm8580_digital_mute,
807 },
808 },
809 {
810 .name = "WM8580 PAIFTX",
811 .id = 1,
812 .capture = {
813 .stream_name = "Capture",
814 .channels_min = 2,
815 .channels_max = 2,
816 .rates = SNDRV_PCM_RATE_8000_192000,
817 .formats = WM8580_FORMATS,
818 },
819 .ops = {
820 .hw_params = wm8580_paif_hw_params,
821 },
822 .dai_ops = {
823 .set_fmt = wm8580_set_paif_dai_fmt,
824 .set_clkdiv = wm8580_set_dai_clkdiv,
825 .set_pll = wm8580_set_dai_pll,
826 },
827 },
828};
829EXPORT_SYMBOL_GPL(wm8580_dai);
830
831/*
832 * initialise the WM8580 driver
833 * register the mixer and dsp interfaces with the kernel
834 */
835static int wm8580_init(struct snd_soc_device *socdev)
836{
837 struct snd_soc_codec *codec = socdev->codec;
838 int ret = 0;
839
840 codec->name = "WM8580";
841 codec->owner = THIS_MODULE;
842 codec->read = wm8580_read_reg_cache;
843 codec->write = wm8580_write;
844 codec->set_bias_level = wm8580_set_bias_level;
845 codec->dai = wm8580_dai;
846 codec->num_dai = ARRAY_SIZE(wm8580_dai);
847 codec->reg_cache_size = ARRAY_SIZE(wm8580_reg);
848 codec->reg_cache = kmemdup(wm8580_reg, sizeof(wm8580_reg),
849 GFP_KERNEL);
850
851 if (codec->reg_cache == NULL)
852 return -ENOMEM;
853
854 /* Get the codec into a known state */
855 wm8580_write(codec, WM8580_RESET, 0);
856
857 /* Power up and get individual control of the DACs */
858 wm8580_write(codec, WM8580_PWRDN1, wm8580_read(codec, WM8580_PWRDN1) &
859 ~(WM8580_PWRDN1_PWDN | WM8580_PWRDN1_ALLDACPD));
860
861 /* Make VMID high impedence */
862 wm8580_write(codec, WM8580_ADC_CONTROL1,
863 wm8580_read(codec, WM8580_ADC_CONTROL1) & ~0x100);
864
865 /* register pcms */
866 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1,
867 SNDRV_DEFAULT_STR1);
868 if (ret < 0) {
869 printk(KERN_ERR "wm8580: failed to create pcms\n");
870 goto pcm_err;
871 }
872
873 wm8580_add_controls(codec);
874 wm8580_add_widgets(codec);
875
876 ret = snd_soc_register_card(socdev);
877 if (ret < 0) {
878 printk(KERN_ERR "wm8580: failed to register card\n");
879 goto card_err;
880 }
881 return ret;
882
883card_err:
884 snd_soc_free_pcms(socdev);
885 snd_soc_dapm_free(socdev);
886pcm_err:
887 kfree(codec->reg_cache);
888 return ret;
889}
890
891/* If the i2c layer weren't so broken, we could pass this kind of data
892 around */
893static struct snd_soc_device *wm8580_socdev;
894
895#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
896
897/*
898 * WM8580 2 wire address is determined by GPIO5
899 * state during powerup.
900 * low = 0x1a
901 * high = 0x1b
902 */
903static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
904
905/* Magic definition of all other variables and things */
906I2C_CLIENT_INSMOD;
907
908static struct i2c_driver wm8580_i2c_driver;
909static struct i2c_client client_template;
910
911static int wm8580_codec_probe(struct i2c_adapter *adap, int addr, int kind)
912{
913 struct snd_soc_device *socdev = wm8580_socdev;
914 struct wm8580_setup_data *setup = socdev->codec_data;
915 struct snd_soc_codec *codec = socdev->codec;
916 struct i2c_client *i2c;
917 int ret;
918
919 if (addr != setup->i2c_address)
920 return -ENODEV;
921
922 client_template.adapter = adap;
923 client_template.addr = addr;
924
925 i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
926 if (i2c == NULL) {
927 kfree(codec);
928 return -ENOMEM;
929 }
930 i2c_set_clientdata(i2c, codec);
931 codec->control_data = i2c;
932
933 ret = i2c_attach_client(i2c);
934 if (ret < 0) {
935 dev_err(&i2c->dev, "failed to attach codec at addr %x\n", addr);
936 goto err;
937 }
938
939 ret = wm8580_init(socdev);
940 if (ret < 0) {
941 dev_err(&i2c->dev, "failed to initialise WM8580\n");
942 goto err;
943 }
944
945 return ret;
946
947err:
948 kfree(codec);
949 kfree(i2c);
950 return ret;
951}
952
953static int wm8580_i2c_detach(struct i2c_client *client)
954{
955 struct snd_soc_codec *codec = i2c_get_clientdata(client);
956 i2c_detach_client(client);
957 kfree(codec->reg_cache);
958 kfree(client);
959 return 0;
960}
961
962static int wm8580_i2c_attach(struct i2c_adapter *adap)
963{
964 return i2c_probe(adap, &addr_data, wm8580_codec_probe);
965}
966
967/* corgi i2c codec control layer */
968static struct i2c_driver wm8580_i2c_driver = {
969 .driver = {
970 .name = "WM8580 I2C Codec",
971 .owner = THIS_MODULE,
972 },
973 .attach_adapter = wm8580_i2c_attach,
974 .detach_client = wm8580_i2c_detach,
975 .command = NULL,
976};
977
978static struct i2c_client client_template = {
979 .name = "WM8580",
980 .driver = &wm8580_i2c_driver,
981};
982#endif
983
984static int wm8580_probe(struct platform_device *pdev)
985{
986 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
987 struct wm8580_setup_data *setup;
988 struct snd_soc_codec *codec;
989 struct wm8580_priv *wm8580;
990 int ret = 0;
991
992 pr_info("WM8580 Audio Codec %s\n", WM8580_VERSION);
993
994 setup = socdev->codec_data;
995 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
996 if (codec == NULL)
997 return -ENOMEM;
998
999 wm8580 = kzalloc(sizeof(struct wm8580_priv), GFP_KERNEL);
1000 if (wm8580 == NULL) {
1001 kfree(codec);
1002 return -ENOMEM;
1003 }
1004
1005 codec->private_data = wm8580;
1006 socdev->codec = codec;
1007 mutex_init(&codec->mutex);
1008 INIT_LIST_HEAD(&codec->dapm_widgets);
1009 INIT_LIST_HEAD(&codec->dapm_paths);
1010 wm8580_socdev = socdev;
1011
1012#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1013 if (setup->i2c_address) {
1014 normal_i2c[0] = setup->i2c_address;
1015 codec->hw_write = (hw_write_t)i2c_master_send;
1016 ret = i2c_add_driver(&wm8580_i2c_driver);
1017 if (ret != 0)
1018 printk(KERN_ERR "can't add i2c driver");
1019 }
1020#else
1021 /* Add other interfaces here */
1022#endif
1023 return ret;
1024}
1025
1026/* power down chip */
1027static int wm8580_remove(struct platform_device *pdev)
1028{
1029 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1030 struct snd_soc_codec *codec = socdev->codec;
1031
1032 if (codec->control_data)
1033 wm8580_set_bias_level(codec, SND_SOC_BIAS_OFF);
1034 snd_soc_free_pcms(socdev);
1035 snd_soc_dapm_free(socdev);
1036#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1037 i2c_del_driver(&wm8580_i2c_driver);
1038#endif
1039 kfree(codec->private_data);
1040 kfree(codec);
1041
1042 return 0;
1043}
1044
1045struct snd_soc_codec_device soc_codec_dev_wm8580 = {
1046 .probe = wm8580_probe,
1047 .remove = wm8580_remove,
1048};
1049EXPORT_SYMBOL_GPL(soc_codec_dev_wm8580);
1050
1051MODULE_DESCRIPTION("ASoC WM8580 driver");
1052MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
1053MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8580.h b/sound/soc/codecs/wm8580.h
new file mode 100644
index 000000000000..589ddaba21d7
--- /dev/null
+++ b/sound/soc/codecs/wm8580.h
@@ -0,0 +1,42 @@
1/*
2 * wm8580.h -- audio driver for WM8580
3 *
4 * Copyright 2008 Samsung Electronics.
5 * Author: Ryu Euiyoul
6 * ryu.real@gmail.com
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 */
14
15#ifndef _WM8580_H
16#define _WM8580_H
17
18#define WM8580_PLLA 1
19#define WM8580_PLLB 2
20
21#define WM8580_MCLK 1
22#define WM8580_DAC_CLKSEL 2
23#define WM8580_CLKOUTSRC 3
24
25#define WM8580_CLKSRC_MCLK 1
26#define WM8580_CLKSRC_PLLA 2
27#define WM8580_CLKSRC_PLLB 3
28#define WM8580_CLKSRC_OSC 4
29#define WM8580_CLKSRC_NONE 5
30
31struct wm8580_setup_data {
32 unsigned short i2c_address;
33};
34
35#define WM8580_DAI_PAIFRX 0
36#define WM8580_DAI_PAIFTX 1
37
38extern struct snd_soc_dai wm8580_dai[];
39extern struct snd_soc_codec_device soc_codec_dev_wm8580;
40
41#endif
42
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index 9402fcaf04fa..7f8a7e36b33e 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -19,6 +19,7 @@
19#include <linux/pm.h> 19#include <linux/pm.h>
20#include <linux/i2c.h> 20#include <linux/i2c.h>
21#include <linux/platform_device.h> 21#include <linux/platform_device.h>
22#include <linux/spi/spi.h>
22#include <sound/core.h> 23#include <sound/core.h>
23#include <sound/pcm.h> 24#include <sound/pcm.h>
24#include <sound/pcm_params.h> 25#include <sound/pcm_params.h>
@@ -28,7 +29,6 @@
28 29
29#include "wm8731.h" 30#include "wm8731.h"
30 31
31#define AUDIO_NAME "wm8731"
32#define WM8731_VERSION "0.13" 32#define WM8731_VERSION "0.13"
33 33
34struct snd_soc_codec_device soc_codec_dev_wm8731; 34struct snd_soc_codec_device soc_codec_dev_wm8731;
@@ -570,88 +570,144 @@ static struct snd_soc_device *wm8731_socdev;
570 * low = 0x1a 570 * low = 0x1a
571 * high = 0x1b 571 * high = 0x1b
572 */ 572 */
573static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
574 573
575/* Magic definition of all other variables and things */ 574static int wm8731_i2c_probe(struct i2c_client *i2c,
576I2C_CLIENT_INSMOD; 575 const struct i2c_device_id *id)
577
578static struct i2c_driver wm8731_i2c_driver;
579static struct i2c_client client_template;
580
581/* If the i2c layer weren't so broken, we could pass this kind of data
582 around */
583
584static int wm8731_codec_probe(struct i2c_adapter *adap, int addr, int kind)
585{ 576{
586 struct snd_soc_device *socdev = wm8731_socdev; 577 struct snd_soc_device *socdev = wm8731_socdev;
587 struct wm8731_setup_data *setup = socdev->codec_data;
588 struct snd_soc_codec *codec = socdev->codec; 578 struct snd_soc_codec *codec = socdev->codec;
589 struct i2c_client *i2c;
590 int ret; 579 int ret;
591 580
592 if (addr != setup->i2c_address)
593 return -ENODEV;
594
595 client_template.adapter = adap;
596 client_template.addr = addr;
597
598 i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
599 if (i2c == NULL)
600 return -ENOMEM;
601
602 i2c_set_clientdata(i2c, codec); 581 i2c_set_clientdata(i2c, codec);
603 codec->control_data = i2c; 582 codec->control_data = i2c;
604 583
605 ret = i2c_attach_client(i2c);
606 if (ret < 0) {
607 pr_err("failed to attach codec at addr %x\n", addr);
608 goto err;
609 }
610
611 ret = wm8731_init(socdev); 584 ret = wm8731_init(socdev);
612 if (ret < 0) { 585 if (ret < 0)
613 pr_err("failed to initialise WM8731\n"); 586 pr_err("failed to initialise WM8731\n");
614 goto err;
615 }
616 return ret;
617 587
618err:
619 kfree(i2c);
620 return ret; 588 return ret;
621} 589}
622 590
623static int wm8731_i2c_detach(struct i2c_client *client) 591static int wm8731_i2c_remove(struct i2c_client *client)
624{ 592{
625 struct snd_soc_codec *codec = i2c_get_clientdata(client); 593 struct snd_soc_codec *codec = i2c_get_clientdata(client);
626 i2c_detach_client(client);
627 kfree(codec->reg_cache); 594 kfree(codec->reg_cache);
628 kfree(client);
629 return 0; 595 return 0;
630} 596}
631 597
632static int wm8731_i2c_attach(struct i2c_adapter *adap) 598static const struct i2c_device_id wm8731_i2c_id[] = {
633{ 599 { "wm8731", 0 },
634 return i2c_probe(adap, &addr_data, wm8731_codec_probe); 600 { }
635} 601};
602MODULE_DEVICE_TABLE(i2c, wm8731_i2c_id);
636 603
637/* corgi i2c codec control layer */
638static struct i2c_driver wm8731_i2c_driver = { 604static struct i2c_driver wm8731_i2c_driver = {
639 .driver = { 605 .driver = {
640 .name = "WM8731 I2C Codec", 606 .name = "WM8731 I2C Codec",
641 .owner = THIS_MODULE, 607 .owner = THIS_MODULE,
642 }, 608 },
643 .id = I2C_DRIVERID_WM8731, 609 .probe = wm8731_i2c_probe,
644 .attach_adapter = wm8731_i2c_attach, 610 .remove = wm8731_i2c_remove,
645 .detach_client = wm8731_i2c_detach, 611 .id_table = wm8731_i2c_id,
646 .command = NULL,
647}; 612};
648 613
649static struct i2c_client client_template = { 614static int wm8731_add_i2c_device(struct platform_device *pdev,
650 .name = "WM8731", 615 const struct wm8731_setup_data *setup)
651 .driver = &wm8731_i2c_driver, 616{
652}; 617 struct i2c_board_info info;
618 struct i2c_adapter *adapter;
619 struct i2c_client *client;
620 int ret;
621
622 ret = i2c_add_driver(&wm8731_i2c_driver);
623 if (ret != 0) {
624 dev_err(&pdev->dev, "can't add i2c driver\n");
625 return ret;
626 }
627
628 memset(&info, 0, sizeof(struct i2c_board_info));
629 info.addr = setup->i2c_address;
630 strlcpy(info.type, "wm8731", I2C_NAME_SIZE);
631
632 adapter = i2c_get_adapter(setup->i2c_bus);
633 if (!adapter) {
634 dev_err(&pdev->dev, "can't get i2c adapter %d\n",
635 setup->i2c_bus);
636 goto err_driver;
637 }
638
639 client = i2c_new_device(adapter, &info);
640 i2c_put_adapter(adapter);
641 if (!client) {
642 dev_err(&pdev->dev, "can't add i2c device at 0x%x\n",
643 (unsigned int)info.addr);
644 goto err_driver;
645 }
646
647 return 0;
648
649err_driver:
650 i2c_del_driver(&wm8731_i2c_driver);
651 return -ENODEV;
652}
653#endif 653#endif
654 654
655#if defined(CONFIG_SPI_MASTER)
656static int __devinit wm8731_spi_probe(struct spi_device *spi)
657{
658 struct snd_soc_device *socdev = wm8731_socdev;
659 struct snd_soc_codec *codec = socdev->codec;
660 int ret;
661
662 codec->control_data = spi;
663
664 ret = wm8731_init(socdev);
665 if (ret < 0)
666 dev_err(&spi->dev, "failed to initialise WM8731\n");
667
668 return ret;
669}
670
671static int __devexit wm8731_spi_remove(struct spi_device *spi)
672{
673 return 0;
674}
675
676static struct spi_driver wm8731_spi_driver = {
677 .driver = {
678 .name = "wm8731",
679 .bus = &spi_bus_type,
680 .owner = THIS_MODULE,
681 },
682 .probe = wm8731_spi_probe,
683 .remove = __devexit_p(wm8731_spi_remove),
684};
685
686static int wm8731_spi_write(struct spi_device *spi, const char *data, int len)
687{
688 struct spi_transfer t;
689 struct spi_message m;
690 u8 msg[2];
691
692 if (len <= 0)
693 return 0;
694
695 msg[0] = data[0];
696 msg[1] = data[1];
697
698 spi_message_init(&m);
699 memset(&t, 0, (sizeof t));
700
701 t.tx_buf = &msg[0];
702 t.len = len;
703
704 spi_message_add_tail(&t, &m);
705 spi_sync(spi, &m);
706
707 return len;
708}
709#endif /* CONFIG_SPI_MASTER */
710
655static int wm8731_probe(struct platform_device *pdev) 711static int wm8731_probe(struct platform_device *pdev)
656{ 712{
657 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 713 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
@@ -680,16 +736,21 @@ static int wm8731_probe(struct platform_device *pdev)
680 INIT_LIST_HEAD(&codec->dapm_paths); 736 INIT_LIST_HEAD(&codec->dapm_paths);
681 737
682 wm8731_socdev = socdev; 738 wm8731_socdev = socdev;
739 ret = -ENODEV;
740
683#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 741#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
684 if (setup->i2c_address) { 742 if (setup->i2c_address) {
685 normal_i2c[0] = setup->i2c_address;
686 codec->hw_write = (hw_write_t)i2c_master_send; 743 codec->hw_write = (hw_write_t)i2c_master_send;
687 ret = i2c_add_driver(&wm8731_i2c_driver); 744 ret = wm8731_add_i2c_device(pdev, setup);
745 }
746#endif
747#if defined(CONFIG_SPI_MASTER)
748 if (setup->spi) {
749 codec->hw_write = (hw_write_t)wm8731_spi_write;
750 ret = spi_register_driver(&wm8731_spi_driver);
688 if (ret != 0) 751 if (ret != 0)
689 printk(KERN_ERR "can't add i2c driver"); 752 printk(KERN_ERR "can't add spi driver");
690 } 753 }
691#else
692 /* Add other interfaces here */
693#endif 754#endif
694 755
695 if (ret != 0) { 756 if (ret != 0) {
@@ -711,8 +772,12 @@ static int wm8731_remove(struct platform_device *pdev)
711 snd_soc_free_pcms(socdev); 772 snd_soc_free_pcms(socdev);
712 snd_soc_dapm_free(socdev); 773 snd_soc_dapm_free(socdev);
713#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 774#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
775 i2c_unregister_device(codec->control_data);
714 i2c_del_driver(&wm8731_i2c_driver); 776 i2c_del_driver(&wm8731_i2c_driver);
715#endif 777#endif
778#if defined(CONFIG_SPI_MASTER)
779 spi_unregister_driver(&wm8731_spi_driver);
780#endif
716 kfree(codec->private_data); 781 kfree(codec->private_data);
717 kfree(codec); 782 kfree(codec);
718 783
diff --git a/sound/soc/codecs/wm8731.h b/sound/soc/codecs/wm8731.h
index 99f2e3c60e33..95190e9c0c14 100644
--- a/sound/soc/codecs/wm8731.h
+++ b/sound/soc/codecs/wm8731.h
@@ -35,6 +35,8 @@
35#define WM8731_DAI 0 35#define WM8731_DAI 0
36 36
37struct wm8731_setup_data { 37struct wm8731_setup_data {
38 int spi;
39 int i2c_bus;
38 unsigned short i2c_address; 40 unsigned short i2c_address;
39}; 41};
40 42
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
index dd1f55404b29..9b7296ee5b08 100644
--- a/sound/soc/codecs/wm8750.c
+++ b/sound/soc/codecs/wm8750.c
@@ -19,6 +19,7 @@
19#include <linux/pm.h> 19#include <linux/pm.h>
20#include <linux/i2c.h> 20#include <linux/i2c.h>
21#include <linux/platform_device.h> 21#include <linux/platform_device.h>
22#include <linux/spi/spi.h>
22#include <sound/core.h> 23#include <sound/core.h>
23#include <sound/pcm.h> 24#include <sound/pcm.h>
24#include <sound/pcm_params.h> 25#include <sound/pcm_params.h>
@@ -28,7 +29,6 @@
28 29
29#include "wm8750.h" 30#include "wm8750.h"
30 31
31#define AUDIO_NAME "WM8750"
32#define WM8750_VERSION "0.12" 32#define WM8750_VERSION "0.12"
33 33
34/* codec private data */ 34/* codec private data */
@@ -841,88 +841,147 @@ static struct snd_soc_device *wm8750_socdev;
841#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 841#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
842 842
843/* 843/*
844 * WM8731 2 wire address is determined by GPIO5 844 * WM8750 2 wire address is determined by GPIO5
845 * state during powerup. 845 * state during powerup.
846 * low = 0x1a 846 * low = 0x1a
847 * high = 0x1b 847 * high = 0x1b
848 */ 848 */
849static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
850 849
851/* Magic definition of all other variables and things */ 850static int wm8750_i2c_probe(struct i2c_client *i2c,
852I2C_CLIENT_INSMOD; 851 const struct i2c_device_id *id)
853
854static struct i2c_driver wm8750_i2c_driver;
855static struct i2c_client client_template;
856
857static int wm8750_codec_probe(struct i2c_adapter *adap, int addr, int kind)
858{ 852{
859 struct snd_soc_device *socdev = wm8750_socdev; 853 struct snd_soc_device *socdev = wm8750_socdev;
860 struct wm8750_setup_data *setup = socdev->codec_data;
861 struct snd_soc_codec *codec = socdev->codec; 854 struct snd_soc_codec *codec = socdev->codec;
862 struct i2c_client *i2c;
863 int ret; 855 int ret;
864 856
865 if (addr != setup->i2c_address)
866 return -ENODEV;
867
868 client_template.adapter = adap;
869 client_template.addr = addr;
870
871 i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
872 if (i2c == NULL)
873 return -ENOMEM;
874
875 i2c_set_clientdata(i2c, codec); 857 i2c_set_clientdata(i2c, codec);
876 codec->control_data = i2c; 858 codec->control_data = i2c;
877 859
878 ret = i2c_attach_client(i2c);
879 if (ret < 0) {
880 pr_err("failed to attach codec at addr %x\n", addr);
881 goto err;
882 }
883
884 ret = wm8750_init(socdev); 860 ret = wm8750_init(socdev);
885 if (ret < 0) { 861 if (ret < 0)
886 pr_err("failed to initialise WM8750\n"); 862 pr_err("failed to initialise WM8750\n");
887 goto err;
888 }
889 return ret;
890 863
891err:
892 kfree(i2c);
893 return ret; 864 return ret;
894} 865}
895 866
896static int wm8750_i2c_detach(struct i2c_client *client) 867static int wm8750_i2c_remove(struct i2c_client *client)
897{ 868{
898 struct snd_soc_codec *codec = i2c_get_clientdata(client); 869 struct snd_soc_codec *codec = i2c_get_clientdata(client);
899 i2c_detach_client(client);
900 kfree(codec->reg_cache); 870 kfree(codec->reg_cache);
901 kfree(client);
902 return 0; 871 return 0;
903} 872}
904 873
905static int wm8750_i2c_attach(struct i2c_adapter *adap) 874static const struct i2c_device_id wm8750_i2c_id[] = {
906{ 875 { "wm8750", 0 },
907 return i2c_probe(adap, &addr_data, wm8750_codec_probe); 876 { }
908} 877};
878MODULE_DEVICE_TABLE(i2c, wm8750_i2c_id);
909 879
910/* corgi i2c codec control layer */
911static struct i2c_driver wm8750_i2c_driver = { 880static struct i2c_driver wm8750_i2c_driver = {
912 .driver = { 881 .driver = {
913 .name = "WM8750 I2C Codec", 882 .name = "WM8750 I2C Codec",
914 .owner = THIS_MODULE, 883 .owner = THIS_MODULE,
915 }, 884 },
916 .id = I2C_DRIVERID_WM8750, 885 .probe = wm8750_i2c_probe,
917 .attach_adapter = wm8750_i2c_attach, 886 .remove = wm8750_i2c_remove,
918 .detach_client = wm8750_i2c_detach, 887 .id_table = wm8750_i2c_id,
919 .command = NULL,
920}; 888};
921 889
922static struct i2c_client client_template = { 890static int wm8750_add_i2c_device(struct platform_device *pdev,
923 .name = "WM8750", 891 const struct wm8750_setup_data *setup)
924 .driver = &wm8750_i2c_driver, 892{
893 struct i2c_board_info info;
894 struct i2c_adapter *adapter;
895 struct i2c_client *client;
896 int ret;
897
898 ret = i2c_add_driver(&wm8750_i2c_driver);
899 if (ret != 0) {
900 dev_err(&pdev->dev, "can't add i2c driver\n");
901 return ret;
902 }
903
904 memset(&info, 0, sizeof(struct i2c_board_info));
905 info.addr = setup->i2c_address;
906 strlcpy(info.type, "wm8750", I2C_NAME_SIZE);
907
908 adapter = i2c_get_adapter(setup->i2c_bus);
909 if (!adapter) {
910 dev_err(&pdev->dev, "can't get i2c adapter %d\n",
911 setup->i2c_bus);
912 goto err_driver;
913 }
914
915 client = i2c_new_device(adapter, &info);
916 i2c_put_adapter(adapter);
917 if (!client) {
918 dev_err(&pdev->dev, "can't add i2c device at 0x%x\n",
919 (unsigned int)info.addr);
920 goto err_driver;
921 }
922
923 return 0;
924
925err_driver:
926 i2c_del_driver(&wm8750_i2c_driver);
927 return -ENODEV;
928}
929#endif
930
931#if defined(CONFIG_SPI_MASTER)
932static int __devinit wm8750_spi_probe(struct spi_device *spi)
933{
934 struct snd_soc_device *socdev = wm8750_socdev;
935 struct snd_soc_codec *codec = socdev->codec;
936 int ret;
937
938 codec->control_data = spi;
939
940 ret = wm8750_init(socdev);
941 if (ret < 0)
942 dev_err(&spi->dev, "failed to initialise WM8750\n");
943
944 return ret;
945}
946
947static int __devexit wm8750_spi_remove(struct spi_device *spi)
948{
949 return 0;
950}
951
952static struct spi_driver wm8750_spi_driver = {
953 .driver = {
954 .name = "wm8750",
955 .bus = &spi_bus_type,
956 .owner = THIS_MODULE,
957 },
958 .probe = wm8750_spi_probe,
959 .remove = __devexit_p(wm8750_spi_remove),
925}; 960};
961
962static int wm8750_spi_write(struct spi_device *spi, const char *data, int len)
963{
964 struct spi_transfer t;
965 struct spi_message m;
966 u8 msg[2];
967
968 if (len <= 0)
969 return 0;
970
971 msg[0] = data[0];
972 msg[1] = data[1];
973
974 spi_message_init(&m);
975 memset(&t, 0, (sizeof t));
976
977 t.tx_buf = &msg[0];
978 t.len = len;
979
980 spi_message_add_tail(&t, &m);
981 spi_sync(spi, &m);
982
983 return len;
984}
926#endif 985#endif
927 986
928static int wm8750_probe(struct platform_device *pdev) 987static int wm8750_probe(struct platform_device *pdev)
@@ -931,7 +990,7 @@ static int wm8750_probe(struct platform_device *pdev)
931 struct wm8750_setup_data *setup = socdev->codec_data; 990 struct wm8750_setup_data *setup = socdev->codec_data;
932 struct snd_soc_codec *codec; 991 struct snd_soc_codec *codec;
933 struct wm8750_priv *wm8750; 992 struct wm8750_priv *wm8750;
934 int ret = 0; 993 int ret;
935 994
936 pr_info("WM8750 Audio Codec %s", WM8750_VERSION); 995 pr_info("WM8750 Audio Codec %s", WM8750_VERSION);
937 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); 996 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
@@ -952,16 +1011,21 @@ static int wm8750_probe(struct platform_device *pdev)
952 wm8750_socdev = socdev; 1011 wm8750_socdev = socdev;
953 INIT_DELAYED_WORK(&codec->delayed_work, wm8750_work); 1012 INIT_DELAYED_WORK(&codec->delayed_work, wm8750_work);
954 1013
1014 ret = -ENODEV;
1015
955#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 1016#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
956 if (setup->i2c_address) { 1017 if (setup->i2c_address) {
957 normal_i2c[0] = setup->i2c_address;
958 codec->hw_write = (hw_write_t)i2c_master_send; 1018 codec->hw_write = (hw_write_t)i2c_master_send;
959 ret = i2c_add_driver(&wm8750_i2c_driver); 1019 ret = wm8750_add_i2c_device(pdev, setup);
1020 }
1021#endif
1022#if defined(CONFIG_SPI_MASTER)
1023 if (setup->spi) {
1024 codec->hw_write = (hw_write_t)wm8750_spi_write;
1025 ret = spi_register_driver(&wm8750_spi_driver);
960 if (ret != 0) 1026 if (ret != 0)
961 printk(KERN_ERR "can't add i2c driver"); 1027 printk(KERN_ERR "can't add spi driver");
962 } 1028 }
963#else
964 /* Add other interfaces here */
965#endif 1029#endif
966 1030
967 if (ret != 0) { 1031 if (ret != 0) {
@@ -1002,8 +1066,12 @@ static int wm8750_remove(struct platform_device *pdev)
1002 snd_soc_free_pcms(socdev); 1066 snd_soc_free_pcms(socdev);
1003 snd_soc_dapm_free(socdev); 1067 snd_soc_dapm_free(socdev);
1004#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 1068#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1069 i2c_unregister_device(codec->control_data);
1005 i2c_del_driver(&wm8750_i2c_driver); 1070 i2c_del_driver(&wm8750_i2c_driver);
1006#endif 1071#endif
1072#if defined(CONFIG_SPI_MASTER)
1073 spi_unregister_driver(&wm8750_spi_driver);
1074#endif
1007 kfree(codec->private_data); 1075 kfree(codec->private_data);
1008 kfree(codec); 1076 kfree(codec);
1009 1077
diff --git a/sound/soc/codecs/wm8750.h b/sound/soc/codecs/wm8750.h
index 8ef30e628b21..1dc100e19cfe 100644
--- a/sound/soc/codecs/wm8750.h
+++ b/sound/soc/codecs/wm8750.h
@@ -58,6 +58,8 @@
58#define WM8750_SYSCLK 0 58#define WM8750_SYSCLK 0
59 59
60struct wm8750_setup_data { 60struct wm8750_setup_data {
61 int spi;
62 int i2c_bus;
61 unsigned short i2c_address; 63 unsigned short i2c_address;
62}; 64};
63 65
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index 5761164fe16d..d426eaa22185 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -2,8 +2,7 @@
2 * wm8753.c -- WM8753 ALSA Soc Audio driver 2 * wm8753.c -- WM8753 ALSA Soc Audio driver
3 * 3 *
4 * Copyright 2003 Wolfson Microelectronics PLC. 4 * Copyright 2003 Wolfson Microelectronics PLC.
5 * Author: Liam Girdwood 5 * Author: Liam Girdwood <lrg@slimlogic.co.uk>
6 * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
7 * 6 *
8 * This program is free software; you can redistribute it and/or modify it 7 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the 8 * under the terms of the GNU General Public License as published by the
@@ -40,6 +39,7 @@
40#include <linux/pm.h> 39#include <linux/pm.h>
41#include <linux/i2c.h> 40#include <linux/i2c.h>
42#include <linux/platform_device.h> 41#include <linux/platform_device.h>
42#include <linux/spi/spi.h>
43#include <sound/core.h> 43#include <sound/core.h>
44#include <sound/pcm.h> 44#include <sound/pcm.h>
45#include <sound/pcm_params.h> 45#include <sound/pcm_params.h>
@@ -51,7 +51,6 @@
51 51
52#include "wm8753.h" 52#include "wm8753.h"
53 53
54#define AUDIO_NAME "wm8753"
55#define WM8753_VERSION "0.16" 54#define WM8753_VERSION "0.16"
56 55
57static int caps_charge = 2000; 56static int caps_charge = 2000;
@@ -583,7 +582,7 @@ static const struct snd_soc_dapm_route audio_map[] = {
583 582
584 /* out 4 */ 583 /* out 4 */
585 {"Out4 Mux", "VREF", "VREF"}, 584 {"Out4 Mux", "VREF", "VREF"},
586 {"Out4 Mux", "Capture ST", "Capture ST Mixer"}, 585 {"Out4 Mux", "Capture ST", "Playback Mixer"},
587 {"Out4 Mux", "LOUT2", "LOUT2"}, 586 {"Out4 Mux", "LOUT2", "LOUT2"},
588 {"Out 4", NULL, "Out4 Mux"}, 587 {"Out 4", NULL, "Out4 Mux"},
589 {"OUT4", NULL, "Out 4"}, 588 {"OUT4", NULL, "Out 4"},
@@ -607,7 +606,7 @@ static const struct snd_soc_dapm_route audio_map[] = {
607 /* Capture Right Mux */ 606 /* Capture Right Mux */
608 {"Capture Right Mux", "PGA", "Right Capture Volume"}, 607 {"Capture Right Mux", "PGA", "Right Capture Volume"},
609 {"Capture Right Mux", "Line or RXP-RXN", "Line Right Mux"}, 608 {"Capture Right Mux", "Line or RXP-RXN", "Line Right Mux"},
610 {"Capture Right Mux", "Sidetone", "Capture ST Mixer"}, 609 {"Capture Right Mux", "Sidetone", "Playback Mixer"},
611 610
612 /* Mono Capture mixer-mux */ 611 /* Mono Capture mixer-mux */
613 {"Capture Right Mixer", "Stereo", "Capture Right Mux"}, 612 {"Capture Right Mixer", "Stereo", "Capture Right Mux"},
@@ -1637,86 +1636,145 @@ static struct snd_soc_device *wm8753_socdev;
1637 * low = 0x1a 1636 * low = 0x1a
1638 * high = 0x1b 1637 * high = 0x1b
1639 */ 1638 */
1640static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
1641 1639
1642/* Magic definition of all other variables and things */ 1640static int wm8753_i2c_probe(struct i2c_client *i2c,
1643I2C_CLIENT_INSMOD; 1641 const struct i2c_device_id *id)
1644
1645static struct i2c_driver wm8753_i2c_driver;
1646static struct i2c_client client_template;
1647
1648static int wm8753_codec_probe(struct i2c_adapter *adap, int addr, int kind)
1649{ 1642{
1650 struct snd_soc_device *socdev = wm8753_socdev; 1643 struct snd_soc_device *socdev = wm8753_socdev;
1651 struct wm8753_setup_data *setup = socdev->codec_data;
1652 struct snd_soc_codec *codec = socdev->codec; 1644 struct snd_soc_codec *codec = socdev->codec;
1653 struct i2c_client *i2c;
1654 int ret; 1645 int ret;
1655 1646
1656 if (addr != setup->i2c_address)
1657 return -ENODEV;
1658
1659 client_template.adapter = adap;
1660 client_template.addr = addr;
1661
1662 i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
1663 if (!i2c)
1664 return -ENOMEM;
1665
1666 i2c_set_clientdata(i2c, codec); 1647 i2c_set_clientdata(i2c, codec);
1667 codec->control_data = i2c; 1648 codec->control_data = i2c;
1668 1649
1669 ret = i2c_attach_client(i2c);
1670 if (ret < 0) {
1671 pr_err("failed to attach codec at addr %x\n", addr);
1672 goto err;
1673 }
1674
1675 ret = wm8753_init(socdev); 1650 ret = wm8753_init(socdev);
1676 if (ret < 0) { 1651 if (ret < 0)
1677 pr_err("failed to initialise WM8753\n"); 1652 pr_err("failed to initialise WM8753\n");
1678 goto err;
1679 }
1680
1681 return ret;
1682 1653
1683err:
1684 kfree(i2c);
1685 return ret; 1654 return ret;
1686} 1655}
1687 1656
1688static int wm8753_i2c_detach(struct i2c_client *client) 1657static int wm8753_i2c_remove(struct i2c_client *client)
1689{ 1658{
1690 struct snd_soc_codec *codec = i2c_get_clientdata(client); 1659 struct snd_soc_codec *codec = i2c_get_clientdata(client);
1691 i2c_detach_client(client);
1692 kfree(codec->reg_cache); 1660 kfree(codec->reg_cache);
1693 kfree(client);
1694 return 0; 1661 return 0;
1695} 1662}
1696 1663
1697static int wm8753_i2c_attach(struct i2c_adapter *adap) 1664static const struct i2c_device_id wm8753_i2c_id[] = {
1698{ 1665 { "wm8753", 0 },
1699 return i2c_probe(adap, &addr_data, wm8753_codec_probe); 1666 { }
1700} 1667};
1668MODULE_DEVICE_TABLE(i2c, wm8753_i2c_id);
1701 1669
1702/* corgi i2c codec control layer */
1703static struct i2c_driver wm8753_i2c_driver = { 1670static struct i2c_driver wm8753_i2c_driver = {
1704 .driver = { 1671 .driver = {
1705 .name = "WM8753 I2C Codec", 1672 .name = "WM8753 I2C Codec",
1706 .owner = THIS_MODULE, 1673 .owner = THIS_MODULE,
1707 }, 1674 },
1708 .id = I2C_DRIVERID_WM8753, 1675 .probe = wm8753_i2c_probe,
1709 .attach_adapter = wm8753_i2c_attach, 1676 .remove = wm8753_i2c_remove,
1710 .detach_client = wm8753_i2c_detach, 1677 .id_table = wm8753_i2c_id,
1711 .command = NULL,
1712}; 1678};
1713 1679
1714static struct i2c_client client_template = { 1680static int wm8753_add_i2c_device(struct platform_device *pdev,
1715 .name = "WM8753", 1681 const struct wm8753_setup_data *setup)
1716 .driver = &wm8753_i2c_driver, 1682{
1683 struct i2c_board_info info;
1684 struct i2c_adapter *adapter;
1685 struct i2c_client *client;
1686 int ret;
1687
1688 ret = i2c_add_driver(&wm8753_i2c_driver);
1689 if (ret != 0) {
1690 dev_err(&pdev->dev, "can't add i2c driver\n");
1691 return ret;
1692 }
1693
1694 memset(&info, 0, sizeof(struct i2c_board_info));
1695 info.addr = setup->i2c_address;
1696 strlcpy(info.type, "wm8753", I2C_NAME_SIZE);
1697
1698 adapter = i2c_get_adapter(setup->i2c_bus);
1699 if (!adapter) {
1700 dev_err(&pdev->dev, "can't get i2c adapter %d\n",
1701 setup->i2c_bus);
1702 goto err_driver;
1703 }
1704
1705 client = i2c_new_device(adapter, &info);
1706 i2c_put_adapter(adapter);
1707 if (!client) {
1708 dev_err(&pdev->dev, "can't add i2c device at 0x%x\n",
1709 (unsigned int)info.addr);
1710 goto err_driver;
1711 }
1712
1713 return 0;
1714
1715err_driver:
1716 i2c_del_driver(&wm8753_i2c_driver);
1717 return -ENODEV;
1718}
1719#endif
1720
1721#if defined(CONFIG_SPI_MASTER)
1722static int __devinit wm8753_spi_probe(struct spi_device *spi)
1723{
1724 struct snd_soc_device *socdev = wm8753_socdev;
1725 struct snd_soc_codec *codec = socdev->codec;
1726 int ret;
1727
1728 codec->control_data = spi;
1729
1730 ret = wm8753_init(socdev);
1731 if (ret < 0)
1732 dev_err(&spi->dev, "failed to initialise WM8753\n");
1733
1734 return ret;
1735}
1736
1737static int __devexit wm8753_spi_remove(struct spi_device *spi)
1738{
1739 return 0;
1740}
1741
1742static struct spi_driver wm8753_spi_driver = {
1743 .driver = {
1744 .name = "wm8753",
1745 .bus = &spi_bus_type,
1746 .owner = THIS_MODULE,
1747 },
1748 .probe = wm8753_spi_probe,
1749 .remove = __devexit_p(wm8753_spi_remove),
1717}; 1750};
1751
1752static int wm8753_spi_write(struct spi_device *spi, const char *data, int len)
1753{
1754 struct spi_transfer t;
1755 struct spi_message m;
1756 u8 msg[2];
1757
1758 if (len <= 0)
1759 return 0;
1760
1761 msg[0] = data[0];
1762 msg[1] = data[1];
1763
1764 spi_message_init(&m);
1765 memset(&t, 0, (sizeof t));
1766
1767 t.tx_buf = &msg[0];
1768 t.len = len;
1769
1770 spi_message_add_tail(&t, &m);
1771 spi_sync(spi, &m);
1772
1773 return len;
1774}
1718#endif 1775#endif
1719 1776
1777
1720static int wm8753_probe(struct platform_device *pdev) 1778static int wm8753_probe(struct platform_device *pdev)
1721{ 1779{
1722 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 1780 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
@@ -1748,14 +1806,17 @@ static int wm8753_probe(struct platform_device *pdev)
1748 1806
1749#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 1807#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1750 if (setup->i2c_address) { 1808 if (setup->i2c_address) {
1751 normal_i2c[0] = setup->i2c_address;
1752 codec->hw_write = (hw_write_t)i2c_master_send; 1809 codec->hw_write = (hw_write_t)i2c_master_send;
1753 ret = i2c_add_driver(&wm8753_i2c_driver); 1810 ret = wm8753_add_i2c_device(pdev, setup);
1811 }
1812#endif
1813#if defined(CONFIG_SPI_MASTER)
1814 if (setup->spi) {
1815 codec->hw_write = (hw_write_t)wm8753_spi_write;
1816 ret = spi_register_driver(&wm8753_spi_driver);
1754 if (ret != 0) 1817 if (ret != 0)
1755 printk(KERN_ERR "can't add i2c driver"); 1818 printk(KERN_ERR "can't add spi driver");
1756 } 1819 }
1757#else
1758 /* Add other interfaces here */
1759#endif 1820#endif
1760 1821
1761 if (ret != 0) { 1822 if (ret != 0) {
@@ -1796,8 +1857,12 @@ static int wm8753_remove(struct platform_device *pdev)
1796 snd_soc_free_pcms(socdev); 1857 snd_soc_free_pcms(socdev);
1797 snd_soc_dapm_free(socdev); 1858 snd_soc_dapm_free(socdev);
1798#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 1859#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1860 i2c_unregister_device(codec->control_data);
1799 i2c_del_driver(&wm8753_i2c_driver); 1861 i2c_del_driver(&wm8753_i2c_driver);
1800#endif 1862#endif
1863#if defined(CONFIG_SPI_MASTER)
1864 spi_unregister_driver(&wm8753_spi_driver);
1865#endif
1801 kfree(codec->private_data); 1866 kfree(codec->private_data);
1802 kfree(codec); 1867 kfree(codec);
1803 1868
diff --git a/sound/soc/codecs/wm8753.h b/sound/soc/codecs/wm8753.h
index 44f5f1ff0cc7..f55704ce931b 100644
--- a/sound/soc/codecs/wm8753.h
+++ b/sound/soc/codecs/wm8753.h
@@ -2,8 +2,7 @@
2 * wm8753.h -- audio driver for WM8753 2 * wm8753.h -- audio driver for WM8753
3 * 3 *
4 * Copyright 2003 Wolfson Microelectronics PLC. 4 * Copyright 2003 Wolfson Microelectronics PLC.
5 * Author: Liam Girdwood 5 * Author: Liam Girdwood <lrg@slimlogic.co.uk>
6 * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
7 * 6 *
8 * This program is free software; you can redistribute it and/or modify it 7 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the 8 * under the terms of the GNU General Public License as published by the
@@ -79,6 +78,8 @@
79#define WM8753_ADCTL2 0x3f 78#define WM8753_ADCTL2 0x3f
80 79
81struct wm8753_setup_data { 80struct wm8753_setup_data {
81 int spi;
82 int i2c_bus;
82 unsigned short i2c_address; 83 unsigned short i2c_address;
83}; 84};
84 85
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c
new file mode 100644
index 000000000000..3b326c9b5586
--- /dev/null
+++ b/sound/soc/codecs/wm8900.c
@@ -0,0 +1,1541 @@
1/*
2 * wm8900.c -- WM8900 ALSA Soc Audio driver
3 *
4 * Copyright 2007, 2008 Wolfson Microelectronics PLC.
5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * TODO:
13 * - Tristating.
14 * - TDM.
15 * - Jack detect.
16 * - FLL source configuration, currently only MCLK is supported.
17 */
18
19#include <linux/module.h>
20#include <linux/moduleparam.h>
21#include <linux/kernel.h>
22#include <linux/init.h>
23#include <linux/delay.h>
24#include <linux/pm.h>
25#include <linux/i2c.h>
26#include <linux/platform_device.h>
27#include <sound/core.h>
28#include <sound/pcm.h>
29#include <sound/pcm_params.h>
30#include <sound/soc.h>
31#include <sound/soc-dapm.h>
32#include <sound/initval.h>
33#include <sound/tlv.h>
34
35#include "wm8900.h"
36
37/* WM8900 register space */
38#define WM8900_REG_RESET 0x0
39#define WM8900_REG_ID 0x0
40#define WM8900_REG_POWER1 0x1
41#define WM8900_REG_POWER2 0x2
42#define WM8900_REG_POWER3 0x3
43#define WM8900_REG_AUDIO1 0x4
44#define WM8900_REG_AUDIO2 0x5
45#define WM8900_REG_CLOCKING1 0x6
46#define WM8900_REG_CLOCKING2 0x7
47#define WM8900_REG_AUDIO3 0x8
48#define WM8900_REG_AUDIO4 0x9
49#define WM8900_REG_DACCTRL 0xa
50#define WM8900_REG_LDAC_DV 0xb
51#define WM8900_REG_RDAC_DV 0xc
52#define WM8900_REG_SIDETONE 0xd
53#define WM8900_REG_ADCCTRL 0xe
54#define WM8900_REG_LADC_DV 0xf
55#define WM8900_REG_RADC_DV 0x10
56#define WM8900_REG_GPIO 0x12
57#define WM8900_REG_INCTL 0x15
58#define WM8900_REG_LINVOL 0x16
59#define WM8900_REG_RINVOL 0x17
60#define WM8900_REG_INBOOSTMIX1 0x18
61#define WM8900_REG_INBOOSTMIX2 0x19
62#define WM8900_REG_ADCPATH 0x1a
63#define WM8900_REG_AUXBOOST 0x1b
64#define WM8900_REG_ADDCTL 0x1e
65#define WM8900_REG_FLLCTL1 0x24
66#define WM8900_REG_FLLCTL2 0x25
67#define WM8900_REG_FLLCTL3 0x26
68#define WM8900_REG_FLLCTL4 0x27
69#define WM8900_REG_FLLCTL5 0x28
70#define WM8900_REG_FLLCTL6 0x29
71#define WM8900_REG_LOUTMIXCTL1 0x2c
72#define WM8900_REG_ROUTMIXCTL1 0x2d
73#define WM8900_REG_BYPASS1 0x2e
74#define WM8900_REG_BYPASS2 0x2f
75#define WM8900_REG_AUXOUT_CTL 0x30
76#define WM8900_REG_LOUT1CTL 0x33
77#define WM8900_REG_ROUT1CTL 0x34
78#define WM8900_REG_LOUT2CTL 0x35
79#define WM8900_REG_ROUT2CTL 0x36
80#define WM8900_REG_HPCTL1 0x3a
81#define WM8900_REG_OUTBIASCTL 0x73
82
83#define WM8900_MAXREG 0x80
84
85#define WM8900_REG_ADDCTL_OUT1_DIS 0x80
86#define WM8900_REG_ADDCTL_OUT2_DIS 0x40
87#define WM8900_REG_ADDCTL_VMID_DIS 0x20
88#define WM8900_REG_ADDCTL_BIAS_SRC 0x10
89#define WM8900_REG_ADDCTL_VMID_SOFTST 0x04
90#define WM8900_REG_ADDCTL_TEMP_SD 0x02
91
92#define WM8900_REG_GPIO_TEMP_ENA 0x2
93
94#define WM8900_REG_POWER1_STARTUP_BIAS_ENA 0x0100
95#define WM8900_REG_POWER1_BIAS_ENA 0x0008
96#define WM8900_REG_POWER1_VMID_BUF_ENA 0x0004
97#define WM8900_REG_POWER1_FLL_ENA 0x0040
98
99#define WM8900_REG_POWER2_SYSCLK_ENA 0x8000
100#define WM8900_REG_POWER2_ADCL_ENA 0x0002
101#define WM8900_REG_POWER2_ADCR_ENA 0x0001
102
103#define WM8900_REG_POWER3_DACL_ENA 0x0002
104#define WM8900_REG_POWER3_DACR_ENA 0x0001
105
106#define WM8900_REG_AUDIO1_AIF_FMT_MASK 0x0018
107#define WM8900_REG_AUDIO1_LRCLK_INV 0x0080
108#define WM8900_REG_AUDIO1_BCLK_INV 0x0100
109
110#define WM8900_REG_CLOCKING1_BCLK_DIR 0x1
111#define WM8900_REG_CLOCKING1_MCLK_SRC 0x100
112#define WM8900_REG_CLOCKING1_BCLK_MASK (~0x01e)
113#define WM8900_REG_CLOCKING1_OPCLK_MASK (~0x7000)
114
115#define WM8900_REG_CLOCKING2_ADC_CLKDIV 0xe0
116#define WM8900_REG_CLOCKING2_DAC_CLKDIV 0x1c
117
118#define WM8900_REG_DACCTRL_MUTE 0x004
119#define WM8900_REG_DACCTRL_AIF_LRCLKRATE 0x400
120
121#define WM8900_REG_AUDIO3_ADCLRC_DIR 0x0800
122
123#define WM8900_REG_AUDIO4_DACLRC_DIR 0x0800
124
125#define WM8900_REG_FLLCTL1_OSC_ENA 0x100
126
127#define WM8900_REG_FLLCTL6_FLL_SLOW_LOCK_REF 0x100
128
129#define WM8900_REG_HPCTL1_HP_IPSTAGE_ENA 0x80
130#define WM8900_REG_HPCTL1_HP_OPSTAGE_ENA 0x40
131#define WM8900_REG_HPCTL1_HP_CLAMP_IP 0x20
132#define WM8900_REG_HPCTL1_HP_CLAMP_OP 0x10
133#define WM8900_REG_HPCTL1_HP_SHORT 0x08
134#define WM8900_REG_HPCTL1_HP_SHORT2 0x04
135
136#define WM8900_LRC_MASK 0xfc00
137
138struct snd_soc_codec_device soc_codec_dev_wm8900;
139
140struct wm8900_priv {
141 u32 fll_in; /* FLL input frequency */
142 u32 fll_out; /* FLL output frequency */
143};
144
145/*
146 * wm8900 register cache. We can't read the entire register space and we
147 * have slow control buses so we cache the registers.
148 */
149static const u16 wm8900_reg_defaults[WM8900_MAXREG] = {
150 0x8900, 0x0000,
151 0xc000, 0x0000,
152 0x4050, 0x4000,
153 0x0008, 0x0000,
154 0x0040, 0x0040,
155 0x1004, 0x00c0,
156 0x00c0, 0x0000,
157 0x0100, 0x00c0,
158 0x00c0, 0x0000,
159 0xb001, 0x0000,
160 0x0000, 0x0044,
161 0x004c, 0x004c,
162 0x0044, 0x0044,
163 0x0000, 0x0044,
164 0x0000, 0x0000,
165 0x0002, 0x0000,
166 0x0000, 0x0000,
167 0x0000, 0x0000,
168 0x0008, 0x0000,
169 0x0000, 0x0008,
170 0x0097, 0x0100,
171 0x0000, 0x0000,
172 0x0050, 0x0050,
173 0x0055, 0x0055,
174 0x0055, 0x0000,
175 0x0000, 0x0079,
176 0x0079, 0x0079,
177 0x0079, 0x0000,
178 /* Remaining registers all zero */
179};
180
181/*
182 * read wm8900 register cache
183 */
184static inline unsigned int wm8900_read_reg_cache(struct snd_soc_codec *codec,
185 unsigned int reg)
186{
187 u16 *cache = codec->reg_cache;
188
189 BUG_ON(reg >= WM8900_MAXREG);
190
191 if (reg == WM8900_REG_ID)
192 return 0;
193
194 return cache[reg];
195}
196
197/*
198 * write wm8900 register cache
199 */
200static inline void wm8900_write_reg_cache(struct snd_soc_codec *codec,
201 u16 reg, unsigned int value)
202{
203 u16 *cache = codec->reg_cache;
204
205 BUG_ON(reg >= WM8900_MAXREG);
206
207 cache[reg] = value;
208}
209
210/*
211 * write to the WM8900 register space
212 */
213static int wm8900_write(struct snd_soc_codec *codec, unsigned int reg,
214 unsigned int value)
215{
216 u8 data[3];
217
218 if (value == wm8900_read_reg_cache(codec, reg))
219 return 0;
220
221 /* data is
222 * D15..D9 WM8900 register offset
223 * D8...D0 register data
224 */
225 data[0] = reg;
226 data[1] = value >> 8;
227 data[2] = value & 0x00ff;
228
229 wm8900_write_reg_cache(codec, reg, value);
230 if (codec->hw_write(codec->control_data, data, 3) == 3)
231 return 0;
232 else
233 return -EIO;
234}
235
236/*
237 * Read from the wm8900.
238 */
239static unsigned int wm8900_chip_read(struct snd_soc_codec *codec, u8 reg)
240{
241 struct i2c_msg xfer[2];
242 u16 data;
243 int ret;
244 struct i2c_client *client = codec->control_data;
245
246 BUG_ON(reg != WM8900_REG_ID && reg != WM8900_REG_POWER1);
247
248 /* Write register */
249 xfer[0].addr = client->addr;
250 xfer[0].flags = 0;
251 xfer[0].len = 1;
252 xfer[0].buf = &reg;
253
254 /* Read data */
255 xfer[1].addr = client->addr;
256 xfer[1].flags = I2C_M_RD;
257 xfer[1].len = 2;
258 xfer[1].buf = (u8 *)&data;
259
260 ret = i2c_transfer(client->adapter, xfer, 2);
261 if (ret != 2) {
262 printk(KERN_CRIT "i2c_transfer returned %d\n", ret);
263 return 0;
264 }
265
266 return (data >> 8) | ((data & 0xff) << 8);
267}
268
269/*
270 * Read from the WM8900 register space. Most registers can't be read
271 * and are therefore supplied from cache.
272 */
273static unsigned int wm8900_read(struct snd_soc_codec *codec, unsigned int reg)
274{
275 switch (reg) {
276 case WM8900_REG_ID:
277 return wm8900_chip_read(codec, reg);
278 default:
279 return wm8900_read_reg_cache(codec, reg);
280 }
281}
282
283static void wm8900_reset(struct snd_soc_codec *codec)
284{
285 wm8900_write(codec, WM8900_REG_RESET, 0);
286
287 memcpy(codec->reg_cache, wm8900_reg_defaults,
288 sizeof(codec->reg_cache));
289}
290
291static int wm8900_hp_event(struct snd_soc_dapm_widget *w,
292 struct snd_kcontrol *kcontrol, int event)
293{
294 struct snd_soc_codec *codec = w->codec;
295 u16 hpctl1 = wm8900_read(codec, WM8900_REG_HPCTL1);
296
297 switch (event) {
298 case SND_SOC_DAPM_PRE_PMU:
299 /* Clamp headphone outputs */
300 hpctl1 = WM8900_REG_HPCTL1_HP_CLAMP_IP |
301 WM8900_REG_HPCTL1_HP_CLAMP_OP;
302 wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1);
303 break;
304
305 case SND_SOC_DAPM_POST_PMU:
306 /* Enable the input stage */
307 hpctl1 &= ~WM8900_REG_HPCTL1_HP_CLAMP_IP;
308 hpctl1 |= WM8900_REG_HPCTL1_HP_SHORT |
309 WM8900_REG_HPCTL1_HP_SHORT2 |
310 WM8900_REG_HPCTL1_HP_IPSTAGE_ENA;
311 wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1);
312
313 msleep(400);
314
315 /* Enable the output stage */
316 hpctl1 &= ~WM8900_REG_HPCTL1_HP_CLAMP_OP;
317 hpctl1 |= WM8900_REG_HPCTL1_HP_OPSTAGE_ENA;
318 wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1);
319
320 /* Remove the shorts */
321 hpctl1 &= ~WM8900_REG_HPCTL1_HP_SHORT2;
322 wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1);
323 hpctl1 &= ~WM8900_REG_HPCTL1_HP_SHORT;
324 wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1);
325 break;
326
327 case SND_SOC_DAPM_PRE_PMD:
328 /* Short the output */
329 hpctl1 |= WM8900_REG_HPCTL1_HP_SHORT;
330 wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1);
331
332 /* Disable the output stage */
333 hpctl1 &= ~WM8900_REG_HPCTL1_HP_OPSTAGE_ENA;
334 wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1);
335
336 /* Clamp the outputs and power down input */
337 hpctl1 |= WM8900_REG_HPCTL1_HP_CLAMP_IP |
338 WM8900_REG_HPCTL1_HP_CLAMP_OP;
339 hpctl1 &= ~WM8900_REG_HPCTL1_HP_IPSTAGE_ENA;
340 wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1);
341 break;
342
343 case SND_SOC_DAPM_POST_PMD:
344 /* Disable everything */
345 wm8900_write(codec, WM8900_REG_HPCTL1, 0);
346 break;
347
348 default:
349 BUG();
350 }
351
352 return 0;
353}
354
355static const DECLARE_TLV_DB_SCALE(out_pga_tlv, -5700, 100, 0);
356
357static const DECLARE_TLV_DB_SCALE(out_mix_tlv, -1500, 300, 0);
358
359static const DECLARE_TLV_DB_SCALE(in_boost_tlv, -1200, 600, 0);
360
361static const DECLARE_TLV_DB_SCALE(in_pga_tlv, -1200, 100, 0);
362
363static const DECLARE_TLV_DB_SCALE(dac_boost_tlv, 0, 600, 0);
364
365static const DECLARE_TLV_DB_SCALE(dac_tlv, -7200, 75, 1);
366
367static const DECLARE_TLV_DB_SCALE(adc_svol_tlv, -3600, 300, 0);
368
369static const DECLARE_TLV_DB_SCALE(adc_tlv, -7200, 75, 1);
370
371static const char *mic_bias_level_txt[] = { "0.9*AVDD", "0.65*AVDD" };
372
373static const struct soc_enum mic_bias_level =
374SOC_ENUM_SINGLE(WM8900_REG_INCTL, 8, 2, mic_bias_level_txt);
375
376static const char *dac_mute_rate_txt[] = { "Fast", "Slow" };
377
378static const struct soc_enum dac_mute_rate =
379SOC_ENUM_SINGLE(WM8900_REG_DACCTRL, 7, 2, dac_mute_rate_txt);
380
381static const char *dac_deemphasis_txt[] = {
382 "Disabled", "32kHz", "44.1kHz", "48kHz"
383};
384
385static const struct soc_enum dac_deemphasis =
386SOC_ENUM_SINGLE(WM8900_REG_DACCTRL, 4, 4, dac_deemphasis_txt);
387
388static const char *adc_hpf_cut_txt[] = {
389 "Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"
390};
391
392static const struct soc_enum adc_hpf_cut =
393SOC_ENUM_SINGLE(WM8900_REG_ADCCTRL, 5, 4, adc_hpf_cut_txt);
394
395static const char *lr_txt[] = {
396 "Left", "Right"
397};
398
399static const struct soc_enum aifl_src =
400SOC_ENUM_SINGLE(WM8900_REG_AUDIO1, 15, 2, lr_txt);
401
402static const struct soc_enum aifr_src =
403SOC_ENUM_SINGLE(WM8900_REG_AUDIO1, 14, 2, lr_txt);
404
405static const struct soc_enum dacl_src =
406SOC_ENUM_SINGLE(WM8900_REG_AUDIO2, 15, 2, lr_txt);
407
408static const struct soc_enum dacr_src =
409SOC_ENUM_SINGLE(WM8900_REG_AUDIO2, 14, 2, lr_txt);
410
411static const char *sidetone_txt[] = {
412 "Disabled", "Left ADC", "Right ADC"
413};
414
415static const struct soc_enum dacl_sidetone =
416SOC_ENUM_SINGLE(WM8900_REG_SIDETONE, 2, 3, sidetone_txt);
417
418static const struct soc_enum dacr_sidetone =
419SOC_ENUM_SINGLE(WM8900_REG_SIDETONE, 0, 3, sidetone_txt);
420
421static const struct snd_kcontrol_new wm8900_snd_controls[] = {
422SOC_ENUM("Mic Bias Level", mic_bias_level),
423
424SOC_SINGLE_TLV("Left Input PGA Volume", WM8900_REG_LINVOL, 0, 31, 0,
425 in_pga_tlv),
426SOC_SINGLE("Left Input PGA Switch", WM8900_REG_LINVOL, 6, 1, 1),
427SOC_SINGLE("Left Input PGA ZC Switch", WM8900_REG_LINVOL, 7, 1, 0),
428
429SOC_SINGLE_TLV("Right Input PGA Volume", WM8900_REG_RINVOL, 0, 31, 0,
430 in_pga_tlv),
431SOC_SINGLE("Right Input PGA Switch", WM8900_REG_RINVOL, 6, 1, 1),
432SOC_SINGLE("Right Input PGA ZC Switch", WM8900_REG_RINVOL, 7, 1, 0),
433
434SOC_SINGLE("DAC Soft Mute Switch", WM8900_REG_DACCTRL, 6, 1, 1),
435SOC_ENUM("DAC Mute Rate", dac_mute_rate),
436SOC_SINGLE("DAC Mono Switch", WM8900_REG_DACCTRL, 9, 1, 0),
437SOC_ENUM("DAC Deemphasis", dac_deemphasis),
438SOC_SINGLE("DAC Sloping Stopband Filter Switch", WM8900_REG_DACCTRL, 8, 1, 0),
439SOC_SINGLE("DAC Sigma-Delta Modulator Clock Switch", WM8900_REG_DACCTRL,
440 12, 1, 0),
441
442SOC_SINGLE("ADC HPF Switch", WM8900_REG_ADCCTRL, 8, 1, 0),
443SOC_ENUM("ADC HPF Cut-Off", adc_hpf_cut),
444SOC_DOUBLE("ADC Invert Switch", WM8900_REG_ADCCTRL, 1, 0, 1, 0),
445SOC_SINGLE_TLV("Left ADC Sidetone Volume", WM8900_REG_SIDETONE, 9, 12, 0,
446 adc_svol_tlv),
447SOC_SINGLE_TLV("Right ADC Sidetone Volume", WM8900_REG_SIDETONE, 5, 12, 0,
448 adc_svol_tlv),
449SOC_ENUM("Left Digital Audio Source", aifl_src),
450SOC_ENUM("Right Digital Audio Source", aifr_src),
451
452SOC_SINGLE_TLV("DAC Input Boost Volume", WM8900_REG_AUDIO2, 10, 4, 0,
453 dac_boost_tlv),
454SOC_ENUM("Left DAC Source", dacl_src),
455SOC_ENUM("Right DAC Source", dacr_src),
456SOC_ENUM("Left DAC Sidetone", dacl_sidetone),
457SOC_ENUM("Right DAC Sidetone", dacr_sidetone),
458SOC_DOUBLE("DAC Invert Switch", WM8900_REG_DACCTRL, 1, 0, 1, 0),
459
460SOC_DOUBLE_R_TLV("Digital Playback Volume",
461 WM8900_REG_LDAC_DV, WM8900_REG_RDAC_DV,
462 1, 96, 0, dac_tlv),
463SOC_DOUBLE_R_TLV("Digital Capture Volume",
464 WM8900_REG_LADC_DV, WM8900_REG_RADC_DV, 1, 119, 0, adc_tlv),
465
466SOC_SINGLE_TLV("LINPUT3 Bypass Volume", WM8900_REG_LOUTMIXCTL1, 4, 7, 0,
467 out_mix_tlv),
468SOC_SINGLE_TLV("RINPUT3 Bypass Volume", WM8900_REG_ROUTMIXCTL1, 4, 7, 0,
469 out_mix_tlv),
470SOC_SINGLE_TLV("Left AUX Bypass Volume", WM8900_REG_AUXOUT_CTL, 4, 7, 0,
471 out_mix_tlv),
472SOC_SINGLE_TLV("Right AUX Bypass Volume", WM8900_REG_AUXOUT_CTL, 0, 7, 0,
473 out_mix_tlv),
474
475SOC_SINGLE_TLV("LeftIn to RightOut Mixer Volume", WM8900_REG_BYPASS1, 0, 7, 0,
476 out_mix_tlv),
477SOC_SINGLE_TLV("LeftIn to LeftOut Mixer Volume", WM8900_REG_BYPASS1, 4, 7, 0,
478 out_mix_tlv),
479SOC_SINGLE_TLV("RightIn to LeftOut Mixer Volume", WM8900_REG_BYPASS2, 0, 7, 0,
480 out_mix_tlv),
481SOC_SINGLE_TLV("RightIn to RightOut Mixer Volume", WM8900_REG_BYPASS2, 4, 7, 0,
482 out_mix_tlv),
483
484SOC_SINGLE_TLV("IN2L Boost Volume", WM8900_REG_INBOOSTMIX1, 0, 3, 0,
485 in_boost_tlv),
486SOC_SINGLE_TLV("IN3L Boost Volume", WM8900_REG_INBOOSTMIX1, 4, 3, 0,
487 in_boost_tlv),
488SOC_SINGLE_TLV("IN2R Boost Volume", WM8900_REG_INBOOSTMIX2, 0, 3, 0,
489 in_boost_tlv),
490SOC_SINGLE_TLV("IN3R Boost Volume", WM8900_REG_INBOOSTMIX2, 4, 3, 0,
491 in_boost_tlv),
492SOC_SINGLE_TLV("Left AUX Boost Volume", WM8900_REG_AUXBOOST, 4, 3, 0,
493 in_boost_tlv),
494SOC_SINGLE_TLV("Right AUX Boost Volume", WM8900_REG_AUXBOOST, 0, 3, 0,
495 in_boost_tlv),
496
497SOC_DOUBLE_R_TLV("LINEOUT1 Volume", WM8900_REG_LOUT1CTL, WM8900_REG_ROUT1CTL,
498 0, 63, 0, out_pga_tlv),
499SOC_DOUBLE_R("LINEOUT1 Switch", WM8900_REG_LOUT1CTL, WM8900_REG_ROUT1CTL,
500 6, 1, 1),
501SOC_DOUBLE_R("LINEOUT1 ZC Switch", WM8900_REG_LOUT1CTL, WM8900_REG_ROUT1CTL,
502 7, 1, 0),
503
504SOC_DOUBLE_R_TLV("LINEOUT2 Volume",
505 WM8900_REG_LOUT2CTL, WM8900_REG_ROUT2CTL,
506 0, 63, 0, out_pga_tlv),
507SOC_DOUBLE_R("LINEOUT2 Switch",
508 WM8900_REG_LOUT2CTL, WM8900_REG_ROUT2CTL, 6, 1, 1),
509SOC_DOUBLE_R("LINEOUT2 ZC Switch",
510 WM8900_REG_LOUT2CTL, WM8900_REG_ROUT2CTL, 7, 1, 0),
511SOC_SINGLE("LINEOUT2 LP -12dB", WM8900_REG_LOUTMIXCTL1,
512 0, 1, 1),
513
514};
515
516/* add non dapm controls */
517static int wm8900_add_controls(struct snd_soc_codec *codec)
518{
519 int err, i;
520
521 for (i = 0; i < ARRAY_SIZE(wm8900_snd_controls); i++) {
522 err = snd_ctl_add(codec->card,
523 snd_soc_cnew(&wm8900_snd_controls[i],
524 codec, NULL));
525 if (err < 0)
526 return err;
527 }
528
529 return 0;
530}
531
532static const struct snd_kcontrol_new wm8900_dapm_loutput2_control =
533SOC_DAPM_SINGLE("LINEOUT2L Switch", WM8900_REG_POWER3, 6, 1, 0);
534
535static const struct snd_kcontrol_new wm8900_dapm_routput2_control =
536SOC_DAPM_SINGLE("LINEOUT2R Switch", WM8900_REG_POWER3, 5, 1, 0);
537
538static const struct snd_kcontrol_new wm8900_loutmix_controls[] = {
539SOC_DAPM_SINGLE("LINPUT3 Bypass Switch", WM8900_REG_LOUTMIXCTL1, 7, 1, 0),
540SOC_DAPM_SINGLE("AUX Bypass Switch", WM8900_REG_AUXOUT_CTL, 7, 1, 0),
541SOC_DAPM_SINGLE("Left Input Mixer Switch", WM8900_REG_BYPASS1, 7, 1, 0),
542SOC_DAPM_SINGLE("Right Input Mixer Switch", WM8900_REG_BYPASS2, 3, 1, 0),
543SOC_DAPM_SINGLE("DACL Switch", WM8900_REG_LOUTMIXCTL1, 8, 1, 0),
544};
545
546static const struct snd_kcontrol_new wm8900_routmix_controls[] = {
547SOC_DAPM_SINGLE("RINPUT3 Bypass Switch", WM8900_REG_ROUTMIXCTL1, 7, 1, 0),
548SOC_DAPM_SINGLE("AUX Bypass Switch", WM8900_REG_AUXOUT_CTL, 3, 1, 0),
549SOC_DAPM_SINGLE("Left Input Mixer Switch", WM8900_REG_BYPASS1, 3, 1, 0),
550SOC_DAPM_SINGLE("Right Input Mixer Switch", WM8900_REG_BYPASS2, 7, 1, 0),
551SOC_DAPM_SINGLE("DACR Switch", WM8900_REG_ROUTMIXCTL1, 8, 1, 0),
552};
553
554static const struct snd_kcontrol_new wm8900_linmix_controls[] = {
555SOC_DAPM_SINGLE("LINPUT2 Switch", WM8900_REG_INBOOSTMIX1, 2, 1, 1),
556SOC_DAPM_SINGLE("LINPUT3 Switch", WM8900_REG_INBOOSTMIX1, 6, 1, 1),
557SOC_DAPM_SINGLE("AUX Switch", WM8900_REG_AUXBOOST, 6, 1, 1),
558SOC_DAPM_SINGLE("Input PGA Switch", WM8900_REG_ADCPATH, 6, 1, 0),
559};
560
561static const struct snd_kcontrol_new wm8900_rinmix_controls[] = {
562SOC_DAPM_SINGLE("RINPUT2 Switch", WM8900_REG_INBOOSTMIX2, 2, 1, 1),
563SOC_DAPM_SINGLE("RINPUT3 Switch", WM8900_REG_INBOOSTMIX2, 6, 1, 1),
564SOC_DAPM_SINGLE("AUX Switch", WM8900_REG_AUXBOOST, 2, 1, 1),
565SOC_DAPM_SINGLE("Input PGA Switch", WM8900_REG_ADCPATH, 2, 1, 0),
566};
567
568static const struct snd_kcontrol_new wm8900_linpga_controls[] = {
569SOC_DAPM_SINGLE("LINPUT1 Switch", WM8900_REG_INCTL, 6, 1, 0),
570SOC_DAPM_SINGLE("LINPUT2 Switch", WM8900_REG_INCTL, 5, 1, 0),
571SOC_DAPM_SINGLE("LINPUT3 Switch", WM8900_REG_INCTL, 4, 1, 0),
572};
573
574static const struct snd_kcontrol_new wm8900_rinpga_controls[] = {
575SOC_DAPM_SINGLE("RINPUT1 Switch", WM8900_REG_INCTL, 2, 1, 0),
576SOC_DAPM_SINGLE("RINPUT2 Switch", WM8900_REG_INCTL, 1, 1, 0),
577SOC_DAPM_SINGLE("RINPUT3 Switch", WM8900_REG_INCTL, 0, 1, 0),
578};
579
580static const char *wm9700_lp_mux[] = { "Disabled", "Enabled" };
581
582static const struct soc_enum wm8900_lineout2_lp_mux =
583SOC_ENUM_SINGLE(WM8900_REG_LOUTMIXCTL1, 1, 2, wm9700_lp_mux);
584
585static const struct snd_kcontrol_new wm8900_lineout2_lp =
586SOC_DAPM_ENUM("Route", wm8900_lineout2_lp_mux);
587
588static const struct snd_soc_dapm_widget wm8900_dapm_widgets[] = {
589
590/* Externally visible pins */
591SND_SOC_DAPM_OUTPUT("LINEOUT1L"),
592SND_SOC_DAPM_OUTPUT("LINEOUT1R"),
593SND_SOC_DAPM_OUTPUT("LINEOUT2L"),
594SND_SOC_DAPM_OUTPUT("LINEOUT2R"),
595SND_SOC_DAPM_OUTPUT("HP_L"),
596SND_SOC_DAPM_OUTPUT("HP_R"),
597
598SND_SOC_DAPM_INPUT("RINPUT1"),
599SND_SOC_DAPM_INPUT("LINPUT1"),
600SND_SOC_DAPM_INPUT("RINPUT2"),
601SND_SOC_DAPM_INPUT("LINPUT2"),
602SND_SOC_DAPM_INPUT("RINPUT3"),
603SND_SOC_DAPM_INPUT("LINPUT3"),
604SND_SOC_DAPM_INPUT("AUX"),
605
606SND_SOC_DAPM_VMID("VMID"),
607
608/* Input */
609SND_SOC_DAPM_MIXER("Left Input PGA", WM8900_REG_POWER2, 3, 0,
610 wm8900_linpga_controls,
611 ARRAY_SIZE(wm8900_linpga_controls)),
612SND_SOC_DAPM_MIXER("Right Input PGA", WM8900_REG_POWER2, 2, 0,
613 wm8900_rinpga_controls,
614 ARRAY_SIZE(wm8900_rinpga_controls)),
615
616SND_SOC_DAPM_MIXER("Left Input Mixer", WM8900_REG_POWER2, 5, 0,
617 wm8900_linmix_controls,
618 ARRAY_SIZE(wm8900_linmix_controls)),
619SND_SOC_DAPM_MIXER("Right Input Mixer", WM8900_REG_POWER2, 4, 0,
620 wm8900_rinmix_controls,
621 ARRAY_SIZE(wm8900_rinmix_controls)),
622
623SND_SOC_DAPM_MICBIAS("Mic Bias", WM8900_REG_POWER1, 4, 0),
624
625SND_SOC_DAPM_ADC("ADCL", "Left HiFi Capture", WM8900_REG_POWER2, 1, 0),
626SND_SOC_DAPM_ADC("ADCR", "Right HiFi Capture", WM8900_REG_POWER2, 0, 0),
627
628/* Output */
629SND_SOC_DAPM_DAC("DACL", "Left HiFi Playback", WM8900_REG_POWER3, 1, 0),
630SND_SOC_DAPM_DAC("DACR", "Right HiFi Playback", WM8900_REG_POWER3, 0, 0),
631
632SND_SOC_DAPM_PGA_E("Headphone Amplifier", WM8900_REG_POWER3, 7, 0, NULL, 0,
633 wm8900_hp_event,
634 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
635 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
636
637SND_SOC_DAPM_PGA("LINEOUT1L PGA", WM8900_REG_POWER2, 8, 0, NULL, 0),
638SND_SOC_DAPM_PGA("LINEOUT1R PGA", WM8900_REG_POWER2, 7, 0, NULL, 0),
639
640SND_SOC_DAPM_MUX("LINEOUT2 LP", SND_SOC_NOPM, 0, 0, &wm8900_lineout2_lp),
641SND_SOC_DAPM_PGA("LINEOUT2L PGA", WM8900_REG_POWER3, 6, 0, NULL, 0),
642SND_SOC_DAPM_PGA("LINEOUT2R PGA", WM8900_REG_POWER3, 5, 0, NULL, 0),
643
644SND_SOC_DAPM_MIXER("Left Output Mixer", WM8900_REG_POWER3, 3, 0,
645 wm8900_loutmix_controls,
646 ARRAY_SIZE(wm8900_loutmix_controls)),
647SND_SOC_DAPM_MIXER("Right Output Mixer", WM8900_REG_POWER3, 2, 0,
648 wm8900_routmix_controls,
649 ARRAY_SIZE(wm8900_routmix_controls)),
650};
651
652/* Target, Path, Source */
653static const struct snd_soc_dapm_route audio_map[] = {
654/* Inputs */
655{"Left Input PGA", "LINPUT1 Switch", "LINPUT1"},
656{"Left Input PGA", "LINPUT2 Switch", "LINPUT2"},
657{"Left Input PGA", "LINPUT3 Switch", "LINPUT3"},
658
659{"Right Input PGA", "RINPUT1 Switch", "RINPUT1"},
660{"Right Input PGA", "RINPUT2 Switch", "RINPUT2"},
661{"Right Input PGA", "RINPUT3 Switch", "RINPUT3"},
662
663{"Left Input Mixer", "LINPUT2 Switch", "LINPUT2"},
664{"Left Input Mixer", "LINPUT3 Switch", "LINPUT3"},
665{"Left Input Mixer", "AUX Switch", "AUX"},
666{"Left Input Mixer", "Input PGA Switch", "Left Input PGA"},
667
668{"Right Input Mixer", "RINPUT2 Switch", "RINPUT2"},
669{"Right Input Mixer", "RINPUT3 Switch", "RINPUT3"},
670{"Right Input Mixer", "AUX Switch", "AUX"},
671{"Right Input Mixer", "Input PGA Switch", "Right Input PGA"},
672
673{"ADCL", NULL, "Left Input Mixer"},
674{"ADCR", NULL, "Right Input Mixer"},
675
676/* Outputs */
677{"LINEOUT1L", NULL, "LINEOUT1L PGA"},
678{"LINEOUT1L PGA", NULL, "Left Output Mixer"},
679{"LINEOUT1R", NULL, "LINEOUT1R PGA"},
680{"LINEOUT1R PGA", NULL, "Right Output Mixer"},
681
682{"LINEOUT2L PGA", NULL, "Left Output Mixer"},
683{"LINEOUT2 LP", "Disabled", "LINEOUT2L PGA"},
684{"LINEOUT2 LP", "Enabled", "Left Output Mixer"},
685{"LINEOUT2L", NULL, "LINEOUT2 LP"},
686
687{"LINEOUT2R PGA", NULL, "Right Output Mixer"},
688{"LINEOUT2 LP", "Disabled", "LINEOUT2R PGA"},
689{"LINEOUT2 LP", "Enabled", "Right Output Mixer"},
690{"LINEOUT2R", NULL, "LINEOUT2 LP"},
691
692{"Left Output Mixer", "LINPUT3 Bypass Switch", "LINPUT3"},
693{"Left Output Mixer", "AUX Bypass Switch", "AUX"},
694{"Left Output Mixer", "Left Input Mixer Switch", "Left Input Mixer"},
695{"Left Output Mixer", "Right Input Mixer Switch", "Right Input Mixer"},
696{"Left Output Mixer", "DACL Switch", "DACL"},
697
698{"Right Output Mixer", "RINPUT3 Bypass Switch", "RINPUT3"},
699{"Right Output Mixer", "AUX Bypass Switch", "AUX"},
700{"Right Output Mixer", "Left Input Mixer Switch", "Left Input Mixer"},
701{"Right Output Mixer", "Right Input Mixer Switch", "Right Input Mixer"},
702{"Right Output Mixer", "DACR Switch", "DACR"},
703
704/* Note that the headphone output stage needs to be connected
705 * externally to LINEOUT2 via DC blocking capacitors. Other
706 * configurations are not supported.
707 *
708 * Note also that left and right headphone paths are treated as a
709 * mono path.
710 */
711{"Headphone Amplifier", NULL, "LINEOUT2 LP"},
712{"Headphone Amplifier", NULL, "LINEOUT2 LP"},
713{"HP_L", NULL, "Headphone Amplifier"},
714{"HP_R", NULL, "Headphone Amplifier"},
715};
716
717static int wm8900_add_widgets(struct snd_soc_codec *codec)
718{
719 snd_soc_dapm_new_controls(codec, wm8900_dapm_widgets,
720 ARRAY_SIZE(wm8900_dapm_widgets));
721
722 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
723
724 snd_soc_dapm_new_widgets(codec);
725
726 return 0;
727}
728
729static int wm8900_hw_params(struct snd_pcm_substream *substream,
730 struct snd_pcm_hw_params *params)
731{
732 struct snd_soc_pcm_runtime *rtd = substream->private_data;
733 struct snd_soc_device *socdev = rtd->socdev;
734 struct snd_soc_codec *codec = socdev->codec;
735 u16 reg;
736
737 reg = wm8900_read(codec, WM8900_REG_AUDIO1) & ~0x60;
738
739 switch (params_format(params)) {
740 case SNDRV_PCM_FORMAT_S16_LE:
741 break;
742 case SNDRV_PCM_FORMAT_S20_3LE:
743 reg |= 0x20;
744 break;
745 case SNDRV_PCM_FORMAT_S24_LE:
746 reg |= 0x40;
747 break;
748 case SNDRV_PCM_FORMAT_S32_LE:
749 reg |= 0x60;
750 break;
751 default:
752 return -EINVAL;
753 }
754
755 wm8900_write(codec, WM8900_REG_AUDIO1, reg);
756
757 return 0;
758}
759
760/* FLL divisors */
761struct _fll_div {
762 u16 fll_ratio;
763 u16 fllclk_div;
764 u16 fll_slow_lock_ref;
765 u16 n;
766 u16 k;
767};
768
769/* The size in bits of the FLL divide multiplied by 10
770 * to allow rounding later */
771#define FIXED_FLL_SIZE ((1 << 16) * 10)
772
773static int fll_factors(struct _fll_div *fll_div, unsigned int Fref,
774 unsigned int Fout)
775{
776 u64 Kpart;
777 unsigned int K, Ndiv, Nmod, target;
778 unsigned int div;
779
780 BUG_ON(!Fout);
781
782 /* The FLL must run at 90-100MHz which is then scaled down to
783 * the output value by FLLCLK_DIV. */
784 target = Fout;
785 div = 1;
786 while (target < 90000000) {
787 div *= 2;
788 target *= 2;
789 }
790
791 if (target > 100000000)
792 printk(KERN_WARNING "wm8900: FLL rate %d out of range, Fref=%d"
793 " Fout=%d\n", target, Fref, Fout);
794 if (div > 32) {
795 printk(KERN_ERR "wm8900: Invalid FLL division rate %u, "
796 "Fref=%d, Fout=%d, target=%d\n",
797 div, Fref, Fout, target);
798 return -EINVAL;
799 }
800
801 fll_div->fllclk_div = div >> 2;
802
803 if (Fref < 48000)
804 fll_div->fll_slow_lock_ref = 1;
805 else
806 fll_div->fll_slow_lock_ref = 0;
807
808 Ndiv = target / Fref;
809
810 if (Fref < 1000000)
811 fll_div->fll_ratio = 8;
812 else
813 fll_div->fll_ratio = 1;
814
815 fll_div->n = Ndiv / fll_div->fll_ratio;
816 Nmod = (target / fll_div->fll_ratio) % Fref;
817
818 /* Calculate fractional part - scale up so we can round. */
819 Kpart = FIXED_FLL_SIZE * (long long)Nmod;
820
821 do_div(Kpart, Fref);
822
823 K = Kpart & 0xFFFFFFFF;
824
825 if ((K % 10) >= 5)
826 K += 5;
827
828 /* Move down to proper range now rounding is done */
829 fll_div->k = K / 10;
830
831 BUG_ON(target != Fout * (fll_div->fllclk_div << 2));
832 BUG_ON(!K && target != Fref * fll_div->fll_ratio * fll_div->n);
833
834 return 0;
835}
836
837static int wm8900_set_fll(struct snd_soc_codec *codec,
838 int fll_id, unsigned int freq_in, unsigned int freq_out)
839{
840 struct wm8900_priv *wm8900 = codec->private_data;
841 struct _fll_div fll_div;
842 unsigned int reg;
843
844 if (wm8900->fll_in == freq_in && wm8900->fll_out == freq_out)
845 return 0;
846
847 /* The digital side should be disabled during any change. */
848 reg = wm8900_read(codec, WM8900_REG_POWER1);
849 wm8900_write(codec, WM8900_REG_POWER1,
850 reg & (~WM8900_REG_POWER1_FLL_ENA));
851
852 /* Disable the FLL? */
853 if (!freq_in || !freq_out) {
854 reg = wm8900_read(codec, WM8900_REG_CLOCKING1);
855 wm8900_write(codec, WM8900_REG_CLOCKING1,
856 reg & (~WM8900_REG_CLOCKING1_MCLK_SRC));
857
858 reg = wm8900_read(codec, WM8900_REG_FLLCTL1);
859 wm8900_write(codec, WM8900_REG_FLLCTL1,
860 reg & (~WM8900_REG_FLLCTL1_OSC_ENA));
861
862 wm8900->fll_in = freq_in;
863 wm8900->fll_out = freq_out;
864
865 return 0;
866 }
867
868 if (fll_factors(&fll_div, freq_in, freq_out) != 0)
869 goto reenable;
870
871 wm8900->fll_in = freq_in;
872 wm8900->fll_out = freq_out;
873
874 /* The osclilator *MUST* be enabled before we enable the
875 * digital circuit. */
876 wm8900_write(codec, WM8900_REG_FLLCTL1,
877 fll_div.fll_ratio | WM8900_REG_FLLCTL1_OSC_ENA);
878
879 wm8900_write(codec, WM8900_REG_FLLCTL4, fll_div.n >> 5);
880 wm8900_write(codec, WM8900_REG_FLLCTL5,
881 (fll_div.fllclk_div << 6) | (fll_div.n & 0x1f));
882
883 if (fll_div.k) {
884 wm8900_write(codec, WM8900_REG_FLLCTL2,
885 (fll_div.k >> 8) | 0x100);
886 wm8900_write(codec, WM8900_REG_FLLCTL3, fll_div.k & 0xff);
887 } else
888 wm8900_write(codec, WM8900_REG_FLLCTL2, 0);
889
890 if (fll_div.fll_slow_lock_ref)
891 wm8900_write(codec, WM8900_REG_FLLCTL6,
892 WM8900_REG_FLLCTL6_FLL_SLOW_LOCK_REF);
893 else
894 wm8900_write(codec, WM8900_REG_FLLCTL6, 0);
895
896 reg = wm8900_read(codec, WM8900_REG_POWER1);
897 wm8900_write(codec, WM8900_REG_POWER1,
898 reg | WM8900_REG_POWER1_FLL_ENA);
899
900reenable:
901 reg = wm8900_read(codec, WM8900_REG_CLOCKING1);
902 wm8900_write(codec, WM8900_REG_CLOCKING1,
903 reg | WM8900_REG_CLOCKING1_MCLK_SRC);
904
905 return 0;
906}
907
908static int wm8900_set_dai_pll(struct snd_soc_dai *codec_dai,
909 int pll_id, unsigned int freq_in, unsigned int freq_out)
910{
911 return wm8900_set_fll(codec_dai->codec, pll_id, freq_in, freq_out);
912}
913
914static int wm8900_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
915 int div_id, int div)
916{
917 struct snd_soc_codec *codec = codec_dai->codec;
918 unsigned int reg;
919
920 switch (div_id) {
921 case WM8900_BCLK_DIV:
922 reg = wm8900_read(codec, WM8900_REG_CLOCKING1);
923 wm8900_write(codec, WM8900_REG_CLOCKING1,
924 div | (reg & WM8900_REG_CLOCKING1_BCLK_MASK));
925 break;
926 case WM8900_OPCLK_DIV:
927 reg = wm8900_read(codec, WM8900_REG_CLOCKING1);
928 wm8900_write(codec, WM8900_REG_CLOCKING1,
929 div | (reg & WM8900_REG_CLOCKING1_OPCLK_MASK));
930 break;
931 case WM8900_DAC_LRCLK:
932 reg = wm8900_read(codec, WM8900_REG_AUDIO4);
933 wm8900_write(codec, WM8900_REG_AUDIO4,
934 div | (reg & WM8900_LRC_MASK));
935 break;
936 case WM8900_ADC_LRCLK:
937 reg = wm8900_read(codec, WM8900_REG_AUDIO3);
938 wm8900_write(codec, WM8900_REG_AUDIO3,
939 div | (reg & WM8900_LRC_MASK));
940 break;
941 case WM8900_DAC_CLKDIV:
942 reg = wm8900_read(codec, WM8900_REG_CLOCKING2);
943 wm8900_write(codec, WM8900_REG_CLOCKING2,
944 div | (reg & WM8900_REG_CLOCKING2_DAC_CLKDIV));
945 break;
946 case WM8900_ADC_CLKDIV:
947 reg = wm8900_read(codec, WM8900_REG_CLOCKING2);
948 wm8900_write(codec, WM8900_REG_CLOCKING2,
949 div | (reg & WM8900_REG_CLOCKING2_ADC_CLKDIV));
950 break;
951 case WM8900_LRCLK_MODE:
952 reg = wm8900_read(codec, WM8900_REG_DACCTRL);
953 wm8900_write(codec, WM8900_REG_DACCTRL,
954 div | (reg & WM8900_REG_DACCTRL_AIF_LRCLKRATE));
955 break;
956 default:
957 return -EINVAL;
958 }
959
960 return 0;
961}
962
963
964static int wm8900_set_dai_fmt(struct snd_soc_dai *codec_dai,
965 unsigned int fmt)
966{
967 struct snd_soc_codec *codec = codec_dai->codec;
968 unsigned int clocking1, aif1, aif3, aif4;
969
970 clocking1 = wm8900_read(codec, WM8900_REG_CLOCKING1);
971 aif1 = wm8900_read(codec, WM8900_REG_AUDIO1);
972 aif3 = wm8900_read(codec, WM8900_REG_AUDIO3);
973 aif4 = wm8900_read(codec, WM8900_REG_AUDIO4);
974
975 /* set master/slave audio interface */
976 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
977 case SND_SOC_DAIFMT_CBS_CFS:
978 clocking1 &= ~WM8900_REG_CLOCKING1_BCLK_DIR;
979 aif3 &= ~WM8900_REG_AUDIO3_ADCLRC_DIR;
980 aif4 &= ~WM8900_REG_AUDIO4_DACLRC_DIR;
981 break;
982 case SND_SOC_DAIFMT_CBS_CFM:
983 clocking1 &= ~WM8900_REG_CLOCKING1_BCLK_DIR;
984 aif3 |= WM8900_REG_AUDIO3_ADCLRC_DIR;
985 aif4 |= WM8900_REG_AUDIO4_DACLRC_DIR;
986 break;
987 case SND_SOC_DAIFMT_CBM_CFM:
988 clocking1 |= WM8900_REG_CLOCKING1_BCLK_DIR;
989 aif3 |= WM8900_REG_AUDIO3_ADCLRC_DIR;
990 aif4 |= WM8900_REG_AUDIO4_DACLRC_DIR;
991 break;
992 case SND_SOC_DAIFMT_CBM_CFS:
993 clocking1 |= WM8900_REG_CLOCKING1_BCLK_DIR;
994 aif3 &= ~WM8900_REG_AUDIO3_ADCLRC_DIR;
995 aif4 &= ~WM8900_REG_AUDIO4_DACLRC_DIR;
996 break;
997 default:
998 return -EINVAL;
999 }
1000
1001 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
1002 case SND_SOC_DAIFMT_DSP_A:
1003 aif1 |= WM8900_REG_AUDIO1_AIF_FMT_MASK;
1004 aif1 &= ~WM8900_REG_AUDIO1_LRCLK_INV;
1005 break;
1006 case SND_SOC_DAIFMT_DSP_B:
1007 aif1 |= WM8900_REG_AUDIO1_AIF_FMT_MASK;
1008 aif1 |= WM8900_REG_AUDIO1_LRCLK_INV;
1009 break;
1010 case SND_SOC_DAIFMT_I2S:
1011 aif1 &= ~WM8900_REG_AUDIO1_AIF_FMT_MASK;
1012 aif1 |= 0x10;
1013 break;
1014 case SND_SOC_DAIFMT_RIGHT_J:
1015 aif1 &= ~WM8900_REG_AUDIO1_AIF_FMT_MASK;
1016 break;
1017 case SND_SOC_DAIFMT_LEFT_J:
1018 aif1 &= ~WM8900_REG_AUDIO1_AIF_FMT_MASK;
1019 aif1 |= 0x8;
1020 break;
1021 default:
1022 return -EINVAL;
1023 }
1024
1025 /* Clock inversion */
1026 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
1027 case SND_SOC_DAIFMT_DSP_A:
1028 case SND_SOC_DAIFMT_DSP_B:
1029 /* frame inversion not valid for DSP modes */
1030 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
1031 case SND_SOC_DAIFMT_NB_NF:
1032 aif1 &= ~WM8900_REG_AUDIO1_BCLK_INV;
1033 break;
1034 case SND_SOC_DAIFMT_IB_NF:
1035 aif1 |= WM8900_REG_AUDIO1_BCLK_INV;
1036 break;
1037 default:
1038 return -EINVAL;
1039 }
1040 break;
1041 case SND_SOC_DAIFMT_I2S:
1042 case SND_SOC_DAIFMT_RIGHT_J:
1043 case SND_SOC_DAIFMT_LEFT_J:
1044 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
1045 case SND_SOC_DAIFMT_NB_NF:
1046 aif1 &= ~WM8900_REG_AUDIO1_BCLK_INV;
1047 aif1 &= ~WM8900_REG_AUDIO1_LRCLK_INV;
1048 break;
1049 case SND_SOC_DAIFMT_IB_IF:
1050 aif1 |= WM8900_REG_AUDIO1_BCLK_INV;
1051 aif1 |= WM8900_REG_AUDIO1_LRCLK_INV;
1052 break;
1053 case SND_SOC_DAIFMT_IB_NF:
1054 aif1 |= WM8900_REG_AUDIO1_BCLK_INV;
1055 aif1 &= ~WM8900_REG_AUDIO1_LRCLK_INV;
1056 break;
1057 case SND_SOC_DAIFMT_NB_IF:
1058 aif1 &= ~WM8900_REG_AUDIO1_BCLK_INV;
1059 aif1 |= WM8900_REG_AUDIO1_LRCLK_INV;
1060 break;
1061 default:
1062 return -EINVAL;
1063 }
1064 break;
1065 default:
1066 return -EINVAL;
1067 }
1068
1069 wm8900_write(codec, WM8900_REG_CLOCKING1, clocking1);
1070 wm8900_write(codec, WM8900_REG_AUDIO1, aif1);
1071 wm8900_write(codec, WM8900_REG_AUDIO3, aif3);
1072 wm8900_write(codec, WM8900_REG_AUDIO4, aif4);
1073
1074 return 0;
1075}
1076
1077static int wm8900_digital_mute(struct snd_soc_dai *codec_dai, int mute)
1078{
1079 struct snd_soc_codec *codec = codec_dai->codec;
1080 u16 reg;
1081
1082 reg = wm8900_read(codec, WM8900_REG_DACCTRL);
1083
1084 if (mute)
1085 reg |= WM8900_REG_DACCTRL_MUTE;
1086 else
1087 reg &= ~WM8900_REG_DACCTRL_MUTE;
1088
1089 wm8900_write(codec, WM8900_REG_DACCTRL, reg);
1090
1091 return 0;
1092}
1093
1094#define WM8900_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
1095 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
1096 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
1097
1098#define WM8900_PCM_FORMATS \
1099 (SNDRV_PCM_FORMAT_S16_LE | SNDRV_PCM_FORMAT_S20_3LE | \
1100 SNDRV_PCM_FORMAT_S24_LE)
1101
1102struct snd_soc_dai wm8900_dai = {
1103 .name = "WM8900 HiFi",
1104 .playback = {
1105 .stream_name = "HiFi Playback",
1106 .channels_min = 1,
1107 .channels_max = 2,
1108 .rates = WM8900_RATES,
1109 .formats = WM8900_PCM_FORMATS,
1110 },
1111 .capture = {
1112 .stream_name = "HiFi Capture",
1113 .channels_min = 1,
1114 .channels_max = 2,
1115 .rates = WM8900_RATES,
1116 .formats = WM8900_PCM_FORMATS,
1117 },
1118 .ops = {
1119 .hw_params = wm8900_hw_params,
1120 },
1121 .dai_ops = {
1122 .set_clkdiv = wm8900_set_dai_clkdiv,
1123 .set_pll = wm8900_set_dai_pll,
1124 .set_fmt = wm8900_set_dai_fmt,
1125 .digital_mute = wm8900_digital_mute,
1126 },
1127};
1128EXPORT_SYMBOL_GPL(wm8900_dai);
1129
1130static int wm8900_set_bias_level(struct snd_soc_codec *codec,
1131 enum snd_soc_bias_level level)
1132{
1133 u16 reg;
1134
1135 switch (level) {
1136 case SND_SOC_BIAS_ON:
1137 /* Enable thermal shutdown */
1138 reg = wm8900_read(codec, WM8900_REG_GPIO);
1139 wm8900_write(codec, WM8900_REG_GPIO,
1140 reg | WM8900_REG_GPIO_TEMP_ENA);
1141 reg = wm8900_read(codec, WM8900_REG_ADDCTL);
1142 wm8900_write(codec, WM8900_REG_ADDCTL,
1143 reg | WM8900_REG_ADDCTL_TEMP_SD);
1144 break;
1145
1146 case SND_SOC_BIAS_PREPARE:
1147 break;
1148
1149 case SND_SOC_BIAS_STANDBY:
1150 /* Charge capacitors if initial power up */
1151 if (codec->bias_level == SND_SOC_BIAS_OFF) {
1152 /* STARTUP_BIAS_ENA on */
1153 wm8900_write(codec, WM8900_REG_POWER1,
1154 WM8900_REG_POWER1_STARTUP_BIAS_ENA);
1155
1156 /* Startup bias mode */
1157 wm8900_write(codec, WM8900_REG_ADDCTL,
1158 WM8900_REG_ADDCTL_BIAS_SRC |
1159 WM8900_REG_ADDCTL_VMID_SOFTST);
1160
1161 /* VMID 2x50k */
1162 wm8900_write(codec, WM8900_REG_POWER1,
1163 WM8900_REG_POWER1_STARTUP_BIAS_ENA | 0x1);
1164
1165 /* Allow capacitors to charge */
1166 schedule_timeout_interruptible(msecs_to_jiffies(400));
1167
1168 /* Enable bias */
1169 wm8900_write(codec, WM8900_REG_POWER1,
1170 WM8900_REG_POWER1_STARTUP_BIAS_ENA |
1171 WM8900_REG_POWER1_BIAS_ENA | 0x1);
1172
1173 wm8900_write(codec, WM8900_REG_ADDCTL, 0);
1174
1175 wm8900_write(codec, WM8900_REG_POWER1,
1176 WM8900_REG_POWER1_BIAS_ENA | 0x1);
1177 }
1178
1179 reg = wm8900_read(codec, WM8900_REG_POWER1);
1180 wm8900_write(codec, WM8900_REG_POWER1,
1181 (reg & WM8900_REG_POWER1_FLL_ENA) |
1182 WM8900_REG_POWER1_BIAS_ENA | 0x1);
1183 wm8900_write(codec, WM8900_REG_POWER2,
1184 WM8900_REG_POWER2_SYSCLK_ENA);
1185 wm8900_write(codec, WM8900_REG_POWER3, 0);
1186 break;
1187
1188 case SND_SOC_BIAS_OFF:
1189 /* Startup bias enable */
1190 reg = wm8900_read(codec, WM8900_REG_POWER1);
1191 wm8900_write(codec, WM8900_REG_POWER1,
1192 reg & WM8900_REG_POWER1_STARTUP_BIAS_ENA);
1193 wm8900_write(codec, WM8900_REG_ADDCTL,
1194 WM8900_REG_ADDCTL_BIAS_SRC |
1195 WM8900_REG_ADDCTL_VMID_SOFTST);
1196
1197 /* Discharge caps */
1198 wm8900_write(codec, WM8900_REG_POWER1,
1199 WM8900_REG_POWER1_STARTUP_BIAS_ENA);
1200 schedule_timeout_interruptible(msecs_to_jiffies(500));
1201
1202 /* Remove clamp */
1203 wm8900_write(codec, WM8900_REG_HPCTL1, 0);
1204
1205 /* Power down */
1206 wm8900_write(codec, WM8900_REG_ADDCTL, 0);
1207 wm8900_write(codec, WM8900_REG_POWER1, 0);
1208 wm8900_write(codec, WM8900_REG_POWER2, 0);
1209 wm8900_write(codec, WM8900_REG_POWER3, 0);
1210
1211 /* Need to let things settle before stopping the clock
1212 * to ensure that restart works, see "Stopping the
1213 * master clock" in the datasheet. */
1214 schedule_timeout_interruptible(msecs_to_jiffies(1));
1215 wm8900_write(codec, WM8900_REG_POWER2,
1216 WM8900_REG_POWER2_SYSCLK_ENA);
1217 break;
1218 }
1219 codec->bias_level = level;
1220 return 0;
1221}
1222
1223static int wm8900_suspend(struct platform_device *pdev, pm_message_t state)
1224{
1225 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1226 struct snd_soc_codec *codec = socdev->codec;
1227 struct wm8900_priv *wm8900 = codec->private_data;
1228 int fll_out = wm8900->fll_out;
1229 int fll_in = wm8900->fll_in;
1230 int ret;
1231
1232 /* Stop the FLL in an orderly fashion */
1233 ret = wm8900_set_fll(codec, 0, 0, 0);
1234 if (ret != 0) {
1235 dev_err(&pdev->dev, "Failed to stop FLL\n");
1236 return ret;
1237 }
1238
1239 wm8900->fll_out = fll_out;
1240 wm8900->fll_in = fll_in;
1241
1242 wm8900_set_bias_level(codec, SND_SOC_BIAS_OFF);
1243
1244 return 0;
1245}
1246
1247static int wm8900_resume(struct platform_device *pdev)
1248{
1249 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1250 struct snd_soc_codec *codec = socdev->codec;
1251 struct wm8900_priv *wm8900 = codec->private_data;
1252 u16 *cache;
1253 int i, ret;
1254
1255 cache = kmemdup(codec->reg_cache, sizeof(wm8900_reg_defaults),
1256 GFP_KERNEL);
1257
1258 wm8900_reset(codec);
1259 wm8900_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1260
1261 /* Restart the FLL? */
1262 if (wm8900->fll_out) {
1263 int fll_out = wm8900->fll_out;
1264 int fll_in = wm8900->fll_in;
1265
1266 wm8900->fll_in = 0;
1267 wm8900->fll_out = 0;
1268
1269 ret = wm8900_set_fll(codec, 0, fll_in, fll_out);
1270 if (ret != 0) {
1271 dev_err(&pdev->dev, "Failed to restart FLL\n");
1272 return ret;
1273 }
1274 }
1275
1276 if (cache) {
1277 for (i = 0; i < WM8900_MAXREG; i++)
1278 wm8900_write(codec, i, cache[i]);
1279 kfree(cache);
1280 } else
1281 dev_err(&pdev->dev, "Unable to allocate register cache\n");
1282
1283 return 0;
1284}
1285
1286/*
1287 * initialise the WM8900 driver
1288 * register the mixer and dsp interfaces with the kernel
1289 */
1290static int wm8900_init(struct snd_soc_device *socdev)
1291{
1292 struct snd_soc_codec *codec = socdev->codec;
1293 int ret = 0;
1294 unsigned int reg;
1295 struct i2c_client *i2c_client = socdev->codec->control_data;
1296
1297 codec->name = "WM8900";
1298 codec->owner = THIS_MODULE;
1299 codec->read = wm8900_read;
1300 codec->write = wm8900_write;
1301 codec->dai = &wm8900_dai;
1302 codec->num_dai = 1;
1303 codec->reg_cache_size = WM8900_MAXREG;
1304 codec->reg_cache = kmemdup(wm8900_reg_defaults,
1305 sizeof(wm8900_reg_defaults), GFP_KERNEL);
1306
1307 if (codec->reg_cache == NULL)
1308 return -ENOMEM;
1309
1310 reg = wm8900_read(codec, WM8900_REG_ID);
1311 if (reg != 0x8900) {
1312 dev_err(&i2c_client->dev, "Device is not a WM8900 - ID %x\n",
1313 reg);
1314 return -ENODEV;
1315 }
1316
1317 codec->private_data = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL);
1318 if (codec->private_data == NULL) {
1319 ret = -ENOMEM;
1320 goto priv_err;
1321 }
1322
1323 /* Read back from the chip */
1324 reg = wm8900_chip_read(codec, WM8900_REG_POWER1);
1325 reg = (reg >> 12) & 0xf;
1326 dev_info(&i2c_client->dev, "WM8900 revision %d\n", reg);
1327
1328 wm8900_reset(codec);
1329
1330 /* Latch the volume update bits */
1331 wm8900_write(codec, WM8900_REG_LINVOL,
1332 wm8900_read(codec, WM8900_REG_LINVOL) | 0x100);
1333 wm8900_write(codec, WM8900_REG_RINVOL,
1334 wm8900_read(codec, WM8900_REG_RINVOL) | 0x100);
1335 wm8900_write(codec, WM8900_REG_LOUT1CTL,
1336 wm8900_read(codec, WM8900_REG_LOUT1CTL) | 0x100);
1337 wm8900_write(codec, WM8900_REG_ROUT1CTL,
1338 wm8900_read(codec, WM8900_REG_ROUT1CTL) | 0x100);
1339 wm8900_write(codec, WM8900_REG_LOUT2CTL,
1340 wm8900_read(codec, WM8900_REG_LOUT2CTL) | 0x100);
1341 wm8900_write(codec, WM8900_REG_ROUT2CTL,
1342 wm8900_read(codec, WM8900_REG_ROUT2CTL) | 0x100);
1343 wm8900_write(codec, WM8900_REG_LDAC_DV,
1344 wm8900_read(codec, WM8900_REG_LDAC_DV) | 0x100);
1345 wm8900_write(codec, WM8900_REG_RDAC_DV,
1346 wm8900_read(codec, WM8900_REG_RDAC_DV) | 0x100);
1347 wm8900_write(codec, WM8900_REG_LADC_DV,
1348 wm8900_read(codec, WM8900_REG_LADC_DV) | 0x100);
1349 wm8900_write(codec, WM8900_REG_RADC_DV,
1350 wm8900_read(codec, WM8900_REG_RADC_DV) | 0x100);
1351
1352 /* Set the DAC and mixer output bias */
1353 wm8900_write(codec, WM8900_REG_OUTBIASCTL, 0x81);
1354
1355 /* Register pcms */
1356 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1357 if (ret < 0) {
1358 dev_err(&i2c_client->dev, "Failed to register new PCMs\n");
1359 goto pcm_err;
1360 }
1361
1362 /* Turn the chip on */
1363 codec->bias_level = SND_SOC_BIAS_OFF;
1364 wm8900_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1365
1366 wm8900_add_controls(codec);
1367 wm8900_add_widgets(codec);
1368
1369 ret = snd_soc_register_card(socdev);
1370 if (ret < 0) {
1371 dev_err(&i2c_client->dev, "Failed to register card\n");
1372 goto card_err;
1373 }
1374 return ret;
1375
1376card_err:
1377 snd_soc_free_pcms(socdev);
1378 snd_soc_dapm_free(socdev);
1379pcm_err:
1380 kfree(codec->reg_cache);
1381priv_err:
1382 kfree(codec->private_data);
1383 return ret;
1384}
1385
1386static struct snd_soc_device *wm8900_socdev;
1387
1388#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1389
1390static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
1391
1392/* Magic definition of all other variables and things */
1393I2C_CLIENT_INSMOD;
1394
1395static struct i2c_driver wm8900_i2c_driver;
1396static struct i2c_client client_template;
1397
1398/* If the i2c layer weren't so broken, we could pass this kind of data
1399 around */
1400static int wm8900_codec_probe(struct i2c_adapter *adap, int addr, int kind)
1401{
1402 struct snd_soc_device *socdev = wm8900_socdev;
1403 struct wm8900_setup_data *setup = socdev->codec_data;
1404 struct snd_soc_codec *codec = socdev->codec;
1405 struct i2c_client *i2c;
1406 int ret;
1407
1408 if (addr != setup->i2c_address)
1409 return -ENODEV;
1410
1411 dev_err(&adap->dev, "Probe on %x\n", addr);
1412
1413 client_template.adapter = adap;
1414 client_template.addr = addr;
1415
1416 i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
1417 if (i2c == NULL) {
1418 kfree(codec);
1419 return -ENOMEM;
1420 }
1421 i2c_set_clientdata(i2c, codec);
1422 codec->control_data = i2c;
1423
1424 ret = i2c_attach_client(i2c);
1425 if (ret < 0) {
1426 dev_err(&adap->dev,
1427 "failed to attach codec at addr %x\n", addr);
1428 goto err;
1429 }
1430
1431 ret = wm8900_init(socdev);
1432 if (ret < 0) {
1433 dev_err(&adap->dev, "failed to initialise WM8900\n");
1434 goto err;
1435 }
1436 return ret;
1437
1438err:
1439 kfree(codec);
1440 kfree(i2c);
1441 return ret;
1442}
1443
1444static int wm8900_i2c_detach(struct i2c_client *client)
1445{
1446 struct snd_soc_codec *codec = i2c_get_clientdata(client);
1447 i2c_detach_client(client);
1448 kfree(codec->reg_cache);
1449 kfree(client);
1450 return 0;
1451}
1452
1453static int wm8900_i2c_attach(struct i2c_adapter *adap)
1454{
1455 return i2c_probe(adap, &addr_data, wm8900_codec_probe);
1456}
1457
1458/* corgi i2c codec control layer */
1459static struct i2c_driver wm8900_i2c_driver = {
1460 .driver = {
1461 .name = "WM8900 I2C codec",
1462 .owner = THIS_MODULE,
1463 },
1464 .attach_adapter = wm8900_i2c_attach,
1465 .detach_client = wm8900_i2c_detach,
1466 .command = NULL,
1467};
1468
1469static struct i2c_client client_template = {
1470 .name = "WM8900",
1471 .driver = &wm8900_i2c_driver,
1472};
1473#endif
1474
1475static int wm8900_probe(struct platform_device *pdev)
1476{
1477 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1478 struct wm8900_setup_data *setup;
1479 struct snd_soc_codec *codec;
1480 int ret = 0;
1481
1482 dev_info(&pdev->dev, "WM8900 Audio Codec\n");
1483
1484 setup = socdev->codec_data;
1485 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
1486 if (codec == NULL)
1487 return -ENOMEM;
1488
1489 mutex_init(&codec->mutex);
1490 INIT_LIST_HEAD(&codec->dapm_widgets);
1491 INIT_LIST_HEAD(&codec->dapm_paths);
1492
1493 socdev->codec = codec;
1494
1495 codec->set_bias_level = wm8900_set_bias_level;
1496
1497 wm8900_socdev = socdev;
1498#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1499 if (setup->i2c_address) {
1500 normal_i2c[0] = setup->i2c_address;
1501 codec->hw_write = (hw_write_t)i2c_master_send;
1502 ret = i2c_add_driver(&wm8900_i2c_driver);
1503 if (ret != 0)
1504 printk(KERN_ERR "can't add i2c driver");
1505 }
1506#else
1507#error Non-I2C interfaces not yet supported
1508#endif
1509 return ret;
1510}
1511
1512/* power down chip */
1513static int wm8900_remove(struct platform_device *pdev)
1514{
1515 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1516 struct snd_soc_codec *codec = socdev->codec;
1517
1518 if (codec->control_data)
1519 wm8900_set_bias_level(codec, SND_SOC_BIAS_OFF);
1520
1521 snd_soc_free_pcms(socdev);
1522 snd_soc_dapm_free(socdev);
1523#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1524 i2c_del_driver(&wm8900_i2c_driver);
1525#endif
1526 kfree(codec);
1527
1528 return 0;
1529}
1530
1531struct snd_soc_codec_device soc_codec_dev_wm8900 = {
1532 .probe = wm8900_probe,
1533 .remove = wm8900_remove,
1534 .suspend = wm8900_suspend,
1535 .resume = wm8900_resume,
1536};
1537EXPORT_SYMBOL_GPL(soc_codec_dev_wm8900);
1538
1539MODULE_DESCRIPTION("ASoC WM8900 driver");
1540MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfonmicro.com>");
1541MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8900.h b/sound/soc/codecs/wm8900.h
new file mode 100644
index 000000000000..ba450d99e902
--- /dev/null
+++ b/sound/soc/codecs/wm8900.h
@@ -0,0 +1,64 @@
1/*
2 * wm8900.h -- WM890 Soc Audio driver
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#ifndef _WM8900_H
10#define _WM8900_H
11
12#define WM8900_FLL 1
13
14#define WM8900_BCLK_DIV 1
15#define WM8900_ADC_CLKDIV 2
16#define WM8900_DAC_CLKDIV 3
17#define WM8900_ADC_LRCLK 4
18#define WM8900_DAC_LRCLK 5
19#define WM8900_OPCLK_DIV 6
20#define WM8900_LRCLK_MODE 7
21
22#define WM8900_BCLK_DIV_1 0x00
23#define WM8900_BCLK_DIV_1_5 0x02
24#define WM8900_BCLK_DIV_2 0x04
25#define WM8900_BCLK_DIV_3 0x06
26#define WM8900_BCLK_DIV_4 0x08
27#define WM8900_BCLK_DIV_5_5 0x0a
28#define WM8900_BCLK_DIV_6 0x0c
29#define WM8900_BCLK_DIV_8 0x0e
30#define WM8900_BCLK_DIV_11 0x10
31#define WM8900_BCLK_DIV_12 0x12
32#define WM8900_BCLK_DIV_16 0x14
33#define WM8900_BCLK_DIV_22 0x16
34#define WM8900_BCLK_DIV_24 0x18
35#define WM8900_BCLK_DIV_32 0x1a
36#define WM8900_BCLK_DIV_44 0x1c
37#define WM8900_BCLK_DIV_48 0x1e
38
39#define WM8900_ADC_CLKDIV_1 0x00
40#define WM8900_ADC_CLKDIV_1_5 0x20
41#define WM8900_ADC_CLKDIV_2 0x40
42#define WM8900_ADC_CLKDIV_3 0x60
43#define WM8900_ADC_CLKDIV_4 0x80
44#define WM8900_ADC_CLKDIV_5_5 0xa0
45#define WM8900_ADC_CLKDIV_6 0xc0
46
47#define WM8900_DAC_CLKDIV_1 0x00
48#define WM8900_DAC_CLKDIV_1_5 0x04
49#define WM8900_DAC_CLKDIV_2 0x08
50#define WM8900_DAC_CLKDIV_3 0x0c
51#define WM8900_DAC_CLKDIV_4 0x10
52#define WM8900_DAC_CLKDIV_5_5 0x14
53#define WM8900_DAC_CLKDIV_6 0x18
54
55#define WM8900_
56
57struct wm8900_setup_data {
58 unsigned short i2c_address;
59};
60
61extern struct snd_soc_dai wm8900_dai;
62extern struct snd_soc_codec_device soc_codec_dev_wm8900;
63
64#endif
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
new file mode 100644
index 000000000000..ce40d7877605
--- /dev/null
+++ b/sound/soc/codecs/wm8903.c
@@ -0,0 +1,1813 @@
1/*
2 * wm8903.c -- WM8903 ALSA SoC Audio driver
3 *
4 * Copyright 2008 Wolfson Microelectronics
5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * TODO:
13 * - TDM mode configuration.
14 * - Mic detect.
15 * - Digital microphone support.
16 * - Interrupt support (mic detect and sequencer).
17 */
18
19#include <linux/module.h>
20#include <linux/moduleparam.h>
21#include <linux/init.h>
22#include <linux/delay.h>
23#include <linux/pm.h>
24#include <linux/i2c.h>
25#include <linux/platform_device.h>
26#include <sound/core.h>
27#include <sound/pcm.h>
28#include <sound/pcm_params.h>
29#include <sound/tlv.h>
30#include <sound/soc.h>
31#include <sound/soc-dapm.h>
32#include <sound/initval.h>
33
34#include "wm8903.h"
35
36struct wm8903_priv {
37 int sysclk;
38
39 /* Reference counts */
40 int charge_pump_users;
41 int class_w_users;
42 int playback_active;
43 int capture_active;
44
45 struct snd_pcm_substream *master_substream;
46 struct snd_pcm_substream *slave_substream;
47};
48
49/* Register defaults at reset */
50static u16 wm8903_reg_defaults[] = {
51 0x8903, /* R0 - SW Reset and ID */
52 0x0000, /* R1 - Revision Number */
53 0x0000, /* R2 */
54 0x0000, /* R3 */
55 0x0018, /* R4 - Bias Control 0 */
56 0x0000, /* R5 - VMID Control 0 */
57 0x0000, /* R6 - Mic Bias Control 0 */
58 0x0000, /* R7 */
59 0x0001, /* R8 - Analogue DAC 0 */
60 0x0000, /* R9 */
61 0x0001, /* R10 - Analogue ADC 0 */
62 0x0000, /* R11 */
63 0x0000, /* R12 - Power Management 0 */
64 0x0000, /* R13 - Power Management 1 */
65 0x0000, /* R14 - Power Management 2 */
66 0x0000, /* R15 - Power Management 3 */
67 0x0000, /* R16 - Power Management 4 */
68 0x0000, /* R17 - Power Management 5 */
69 0x0000, /* R18 - Power Management 6 */
70 0x0000, /* R19 */
71 0x0400, /* R20 - Clock Rates 0 */
72 0x0D07, /* R21 - Clock Rates 1 */
73 0x0000, /* R22 - Clock Rates 2 */
74 0x0000, /* R23 */
75 0x0050, /* R24 - Audio Interface 0 */
76 0x0242, /* R25 - Audio Interface 1 */
77 0x0008, /* R26 - Audio Interface 2 */
78 0x0022, /* R27 - Audio Interface 3 */
79 0x0000, /* R28 */
80 0x0000, /* R29 */
81 0x00C0, /* R30 - DAC Digital Volume Left */
82 0x00C0, /* R31 - DAC Digital Volume Right */
83 0x0000, /* R32 - DAC Digital 0 */
84 0x0000, /* R33 - DAC Digital 1 */
85 0x0000, /* R34 */
86 0x0000, /* R35 */
87 0x00C0, /* R36 - ADC Digital Volume Left */
88 0x00C0, /* R37 - ADC Digital Volume Right */
89 0x0000, /* R38 - ADC Digital 0 */
90 0x0073, /* R39 - Digital Microphone 0 */
91 0x09BF, /* R40 - DRC 0 */
92 0x3241, /* R41 - DRC 1 */
93 0x0020, /* R42 - DRC 2 */
94 0x0000, /* R43 - DRC 3 */
95 0x0085, /* R44 - Analogue Left Input 0 */
96 0x0085, /* R45 - Analogue Right Input 0 */
97 0x0044, /* R46 - Analogue Left Input 1 */
98 0x0044, /* R47 - Analogue Right Input 1 */
99 0x0000, /* R48 */
100 0x0000, /* R49 */
101 0x0008, /* R50 - Analogue Left Mix 0 */
102 0x0004, /* R51 - Analogue Right Mix 0 */
103 0x0000, /* R52 - Analogue Spk Mix Left 0 */
104 0x0000, /* R53 - Analogue Spk Mix Left 1 */
105 0x0000, /* R54 - Analogue Spk Mix Right 0 */
106 0x0000, /* R55 - Analogue Spk Mix Right 1 */
107 0x0000, /* R56 */
108 0x002D, /* R57 - Analogue OUT1 Left */
109 0x002D, /* R58 - Analogue OUT1 Right */
110 0x0039, /* R59 - Analogue OUT2 Left */
111 0x0039, /* R60 - Analogue OUT2 Right */
112 0x0100, /* R61 */
113 0x0139, /* R62 - Analogue OUT3 Left */
114 0x0139, /* R63 - Analogue OUT3 Right */
115 0x0000, /* R64 */
116 0x0000, /* R65 - Analogue SPK Output Control 0 */
117 0x0000, /* R66 */
118 0x0010, /* R67 - DC Servo 0 */
119 0x0100, /* R68 */
120 0x00A4, /* R69 - DC Servo 2 */
121 0x0807, /* R70 */
122 0x0000, /* R71 */
123 0x0000, /* R72 */
124 0x0000, /* R73 */
125 0x0000, /* R74 */
126 0x0000, /* R75 */
127 0x0000, /* R76 */
128 0x0000, /* R77 */
129 0x0000, /* R78 */
130 0x000E, /* R79 */
131 0x0000, /* R80 */
132 0x0000, /* R81 */
133 0x0000, /* R82 */
134 0x0000, /* R83 */
135 0x0000, /* R84 */
136 0x0000, /* R85 */
137 0x0000, /* R86 */
138 0x0006, /* R87 */
139 0x0000, /* R88 */
140 0x0000, /* R89 */
141 0x0000, /* R90 - Analogue HP 0 */
142 0x0060, /* R91 */
143 0x0000, /* R92 */
144 0x0000, /* R93 */
145 0x0000, /* R94 - Analogue Lineout 0 */
146 0x0060, /* R95 */
147 0x0000, /* R96 */
148 0x0000, /* R97 */
149 0x0000, /* R98 - Charge Pump 0 */
150 0x1F25, /* R99 */
151 0x2B19, /* R100 */
152 0x01C0, /* R101 */
153 0x01EF, /* R102 */
154 0x2B00, /* R103 */
155 0x0000, /* R104 - Class W 0 */
156 0x01C0, /* R105 */
157 0x1C10, /* R106 */
158 0x0000, /* R107 */
159 0x0000, /* R108 - Write Sequencer 0 */
160 0x0000, /* R109 - Write Sequencer 1 */
161 0x0000, /* R110 - Write Sequencer 2 */
162 0x0000, /* R111 - Write Sequencer 3 */
163 0x0000, /* R112 - Write Sequencer 4 */
164 0x0000, /* R113 */
165 0x0000, /* R114 - Control Interface */
166 0x0000, /* R115 */
167 0x00A8, /* R116 - GPIO Control 1 */
168 0x00A8, /* R117 - GPIO Control 2 */
169 0x00A8, /* R118 - GPIO Control 3 */
170 0x0220, /* R119 - GPIO Control 4 */
171 0x01A0, /* R120 - GPIO Control 5 */
172 0x0000, /* R121 - Interrupt Status 1 */
173 0xFFFF, /* R122 - Interrupt Status 1 Mask */
174 0x0000, /* R123 - Interrupt Polarity 1 */
175 0x0000, /* R124 */
176 0x0003, /* R125 */
177 0x0000, /* R126 - Interrupt Control */
178 0x0000, /* R127 */
179 0x0005, /* R128 */
180 0x0000, /* R129 - Control Interface Test 1 */
181 0x0000, /* R130 */
182 0x0000, /* R131 */
183 0x0000, /* R132 */
184 0x0000, /* R133 */
185 0x0000, /* R134 */
186 0x03FF, /* R135 */
187 0x0007, /* R136 */
188 0x0040, /* R137 */
189 0x0000, /* R138 */
190 0x0000, /* R139 */
191 0x0000, /* R140 */
192 0x0000, /* R141 */
193 0x0000, /* R142 */
194 0x0000, /* R143 */
195 0x0000, /* R144 */
196 0x0000, /* R145 */
197 0x0000, /* R146 */
198 0x0000, /* R147 */
199 0x4000, /* R148 */
200 0x6810, /* R149 - Charge Pump Test 1 */
201 0x0004, /* R150 */
202 0x0000, /* R151 */
203 0x0000, /* R152 */
204 0x0000, /* R153 */
205 0x0000, /* R154 */
206 0x0000, /* R155 */
207 0x0000, /* R156 */
208 0x0000, /* R157 */
209 0x0000, /* R158 */
210 0x0000, /* R159 */
211 0x0000, /* R160 */
212 0x0000, /* R161 */
213 0x0000, /* R162 */
214 0x0000, /* R163 */
215 0x0028, /* R164 - Clock Rate Test 4 */
216 0x0004, /* R165 */
217 0x0000, /* R166 */
218 0x0060, /* R167 */
219 0x0000, /* R168 */
220 0x0000, /* R169 */
221 0x0000, /* R170 */
222 0x0000, /* R171 */
223 0x0000, /* R172 - Analogue Output Bias 0 */
224};
225
226static unsigned int wm8903_read_reg_cache(struct snd_soc_codec *codec,
227 unsigned int reg)
228{
229 u16 *cache = codec->reg_cache;
230
231 BUG_ON(reg >= ARRAY_SIZE(wm8903_reg_defaults));
232
233 return cache[reg];
234}
235
236static unsigned int wm8903_hw_read(struct snd_soc_codec *codec, u8 reg)
237{
238 struct i2c_msg xfer[2];
239 u16 data;
240 int ret;
241 struct i2c_client *client = codec->control_data;
242
243 /* Write register */
244 xfer[0].addr = client->addr;
245 xfer[0].flags = 0;
246 xfer[0].len = 1;
247 xfer[0].buf = &reg;
248
249 /* Read data */
250 xfer[1].addr = client->addr;
251 xfer[1].flags = I2C_M_RD;
252 xfer[1].len = 2;
253 xfer[1].buf = (u8 *)&data;
254
255 ret = i2c_transfer(client->adapter, xfer, 2);
256 if (ret != 2) {
257 pr_err("i2c_transfer returned %d\n", ret);
258 return 0;
259 }
260
261 return (data >> 8) | ((data & 0xff) << 8);
262}
263
264static unsigned int wm8903_read(struct snd_soc_codec *codec,
265 unsigned int reg)
266{
267 switch (reg) {
268 case WM8903_SW_RESET_AND_ID:
269 case WM8903_REVISION_NUMBER:
270 case WM8903_INTERRUPT_STATUS_1:
271 case WM8903_WRITE_SEQUENCER_4:
272 return wm8903_hw_read(codec, reg);
273
274 default:
275 return wm8903_read_reg_cache(codec, reg);
276 }
277}
278
279static void wm8903_write_reg_cache(struct snd_soc_codec *codec,
280 u16 reg, unsigned int value)
281{
282 u16 *cache = codec->reg_cache;
283
284 BUG_ON(reg >= ARRAY_SIZE(wm8903_reg_defaults));
285
286 switch (reg) {
287 case WM8903_SW_RESET_AND_ID:
288 case WM8903_REVISION_NUMBER:
289 break;
290
291 default:
292 cache[reg] = value;
293 break;
294 }
295}
296
297static int wm8903_write(struct snd_soc_codec *codec, unsigned int reg,
298 unsigned int value)
299{
300 u8 data[3];
301
302 wm8903_write_reg_cache(codec, reg, value);
303
304 /* Data format is 1 byte of address followed by 2 bytes of data */
305 data[0] = reg;
306 data[1] = (value >> 8) & 0xff;
307 data[2] = value & 0xff;
308
309 if (codec->hw_write(codec->control_data, data, 3) == 2)
310 return 0;
311 else
312 return -EIO;
313}
314
315static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start)
316{
317 u16 reg[5];
318 struct i2c_client *i2c = codec->control_data;
319
320 BUG_ON(start > 48);
321
322 /* Enable the sequencer */
323 reg[0] = wm8903_read(codec, WM8903_WRITE_SEQUENCER_0);
324 reg[0] |= WM8903_WSEQ_ENA;
325 wm8903_write(codec, WM8903_WRITE_SEQUENCER_0, reg[0]);
326
327 dev_dbg(&i2c->dev, "Starting sequence at %d\n", start);
328
329 wm8903_write(codec, WM8903_WRITE_SEQUENCER_3,
330 start | WM8903_WSEQ_START);
331
332 /* Wait for it to complete. If we have the interrupt wired up then
333 * we could block waiting for an interrupt, though polling may still
334 * be desirable for diagnostic purposes.
335 */
336 do {
337 msleep(10);
338
339 reg[4] = wm8903_read(codec, WM8903_WRITE_SEQUENCER_4);
340 } while (reg[4] & WM8903_WSEQ_BUSY);
341
342 dev_dbg(&i2c->dev, "Sequence complete\n");
343
344 /* Disable the sequencer again */
345 wm8903_write(codec, WM8903_WRITE_SEQUENCER_0,
346 reg[0] & ~WM8903_WSEQ_ENA);
347
348 return 0;
349}
350
351static void wm8903_sync_reg_cache(struct snd_soc_codec *codec, u16 *cache)
352{
353 int i;
354
355 /* There really ought to be something better we can do here :/ */
356 for (i = 0; i < ARRAY_SIZE(wm8903_reg_defaults); i++)
357 cache[i] = wm8903_hw_read(codec, i);
358}
359
360static void wm8903_reset(struct snd_soc_codec *codec)
361{
362 wm8903_write(codec, WM8903_SW_RESET_AND_ID, 0);
363}
364
365#define WM8903_OUTPUT_SHORT 0x8
366#define WM8903_OUTPUT_OUT 0x4
367#define WM8903_OUTPUT_INT 0x2
368#define WM8903_OUTPUT_IN 0x1
369
370/*
371 * Event for headphone and line out amplifier power changes. Special
372 * power up/down sequences are required in order to maximise pop/click
373 * performance.
374 */
375static int wm8903_output_event(struct snd_soc_dapm_widget *w,
376 struct snd_kcontrol *kcontrol, int event)
377{
378 struct snd_soc_codec *codec = w->codec;
379 struct wm8903_priv *wm8903 = codec->private_data;
380 struct i2c_client *i2c = codec->control_data;
381 u16 val;
382 u16 reg;
383 int shift;
384 u16 cp_reg = wm8903_read(codec, WM8903_CHARGE_PUMP_0);
385
386 switch (w->reg) {
387 case WM8903_POWER_MANAGEMENT_2:
388 reg = WM8903_ANALOGUE_HP_0;
389 break;
390 case WM8903_POWER_MANAGEMENT_3:
391 reg = WM8903_ANALOGUE_LINEOUT_0;
392 break;
393 default:
394 BUG();
395 }
396
397 switch (w->shift) {
398 case 0:
399 shift = 0;
400 break;
401 case 1:
402 shift = 4;
403 break;
404 default:
405 BUG();
406 }
407
408 if (event & SND_SOC_DAPM_PRE_PMU) {
409 val = wm8903_read(codec, reg);
410
411 /* Short the output */
412 val &= ~(WM8903_OUTPUT_SHORT << shift);
413 wm8903_write(codec, reg, val);
414
415 wm8903->charge_pump_users++;
416
417 dev_dbg(&i2c->dev, "Charge pump use count now %d\n",
418 wm8903->charge_pump_users);
419
420 if (wm8903->charge_pump_users == 1) {
421 dev_dbg(&i2c->dev, "Enabling charge pump\n");
422 wm8903_write(codec, WM8903_CHARGE_PUMP_0,
423 cp_reg | WM8903_CP_ENA);
424 mdelay(4);
425 }
426 }
427
428 if (event & SND_SOC_DAPM_POST_PMU) {
429 val = wm8903_read(codec, reg);
430
431 val |= (WM8903_OUTPUT_IN << shift);
432 wm8903_write(codec, reg, val);
433
434 val |= (WM8903_OUTPUT_INT << shift);
435 wm8903_write(codec, reg, val);
436
437 /* Turn on the output ENA_OUTP */
438 val |= (WM8903_OUTPUT_OUT << shift);
439 wm8903_write(codec, reg, val);
440
441 /* Remove the short */
442 val |= (WM8903_OUTPUT_SHORT << shift);
443 wm8903_write(codec, reg, val);
444 }
445
446 if (event & SND_SOC_DAPM_PRE_PMD) {
447 val = wm8903_read(codec, reg);
448
449 /* Short the output */
450 val &= ~(WM8903_OUTPUT_SHORT << shift);
451 wm8903_write(codec, reg, val);
452
453 /* Then disable the intermediate and output stages */
454 val &= ~((WM8903_OUTPUT_OUT | WM8903_OUTPUT_INT |
455 WM8903_OUTPUT_IN) << shift);
456 wm8903_write(codec, reg, val);
457 }
458
459 if (event & SND_SOC_DAPM_POST_PMD) {
460 wm8903->charge_pump_users--;
461
462 dev_dbg(&i2c->dev, "Charge pump use count now %d\n",
463 wm8903->charge_pump_users);
464
465 if (wm8903->charge_pump_users == 0) {
466 dev_dbg(&i2c->dev, "Disabling charge pump\n");
467 wm8903_write(codec, WM8903_CHARGE_PUMP_0,
468 cp_reg & ~WM8903_CP_ENA);
469 }
470 }
471
472 return 0;
473}
474
475/*
476 * When used with DAC outputs only the WM8903 charge pump supports
477 * operation in class W mode, providing very low power consumption
478 * when used with digital sources. Enable and disable this mode
479 * automatically depending on the mixer configuration.
480 *
481 * All the relevant controls are simple switches.
482 */
483static int wm8903_class_w_put(struct snd_kcontrol *kcontrol,
484 struct snd_ctl_elem_value *ucontrol)
485{
486 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
487 struct snd_soc_codec *codec = widget->codec;
488 struct wm8903_priv *wm8903 = codec->private_data;
489 struct i2c_client *i2c = codec->control_data;
490 u16 reg;
491 int ret;
492
493 reg = wm8903_read(codec, WM8903_CLASS_W_0);
494
495 /* Turn it off if we're about to enable bypass */
496 if (ucontrol->value.integer.value[0]) {
497 if (wm8903->class_w_users == 0) {
498 dev_dbg(&i2c->dev, "Disabling Class W\n");
499 wm8903_write(codec, WM8903_CLASS_W_0, reg &
500 ~(WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V));
501 }
502 wm8903->class_w_users++;
503 }
504
505 /* Implement the change */
506 ret = snd_soc_dapm_put_volsw(kcontrol, ucontrol);
507
508 /* If we've just disabled the last bypass path turn Class W on */
509 if (!ucontrol->value.integer.value[0]) {
510 if (wm8903->class_w_users == 1) {
511 dev_dbg(&i2c->dev, "Enabling Class W\n");
512 wm8903_write(codec, WM8903_CLASS_W_0, reg |
513 WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V);
514 }
515 wm8903->class_w_users--;
516 }
517
518 dev_dbg(&i2c->dev, "Bypass use count now %d\n",
519 wm8903->class_w_users);
520
521 return ret;
522}
523
524#define SOC_DAPM_SINGLE_W(xname, reg, shift, max, invert) \
525{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
526 .info = snd_soc_info_volsw, \
527 .get = snd_soc_dapm_get_volsw, .put = wm8903_class_w_put, \
528 .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) }
529
530
531/* ALSA can only do steps of .01dB */
532static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1);
533
534static const DECLARE_TLV_DB_SCALE(out_tlv, -5700, 100, 0);
535
536static const DECLARE_TLV_DB_SCALE(drc_tlv_thresh, 0, 75, 0);
537static const DECLARE_TLV_DB_SCALE(drc_tlv_amp, -2250, 75, 0);
538static const DECLARE_TLV_DB_SCALE(drc_tlv_min, 0, 600, 0);
539static const DECLARE_TLV_DB_SCALE(drc_tlv_max, 1200, 600, 0);
540static const DECLARE_TLV_DB_SCALE(drc_tlv_startup, -300, 50, 0);
541
542static const char *drc_slope_text[] = {
543 "1", "1/2", "1/4", "1/8", "1/16", "0"
544};
545
546static const struct soc_enum drc_slope_r0 =
547 SOC_ENUM_SINGLE(WM8903_DRC_2, 3, 6, drc_slope_text);
548
549static const struct soc_enum drc_slope_r1 =
550 SOC_ENUM_SINGLE(WM8903_DRC_2, 0, 6, drc_slope_text);
551
552static const char *drc_attack_text[] = {
553 "instantaneous",
554 "363us", "762us", "1.45ms", "2.9ms", "5.8ms", "11.6ms", "23.2ms",
555 "46.4ms", "92.8ms", "185.6ms"
556};
557
558static const struct soc_enum drc_attack =
559 SOC_ENUM_SINGLE(WM8903_DRC_1, 12, 11, drc_attack_text);
560
561static const char *drc_decay_text[] = {
562 "186ms", "372ms", "743ms", "1.49s", "2.97s", "5.94s", "11.89s",
563 "23.87s", "47.56s"
564};
565
566static const struct soc_enum drc_decay =
567 SOC_ENUM_SINGLE(WM8903_DRC_1, 8, 9, drc_decay_text);
568
569static const char *drc_ff_delay_text[] = {
570 "5 samples", "9 samples"
571};
572
573static const struct soc_enum drc_ff_delay =
574 SOC_ENUM_SINGLE(WM8903_DRC_0, 5, 2, drc_ff_delay_text);
575
576static const char *drc_qr_decay_text[] = {
577 "0.725ms", "1.45ms", "5.8ms"
578};
579
580static const struct soc_enum drc_qr_decay =
581 SOC_ENUM_SINGLE(WM8903_DRC_1, 4, 3, drc_qr_decay_text);
582
583static const char *drc_smoothing_text[] = {
584 "Low", "Medium", "High"
585};
586
587static const struct soc_enum drc_smoothing =
588 SOC_ENUM_SINGLE(WM8903_DRC_0, 11, 3, drc_smoothing_text);
589
590static const char *soft_mute_text[] = {
591 "Fast (fs/2)", "Slow (fs/32)"
592};
593
594static const struct soc_enum soft_mute =
595 SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_1, 10, 2, soft_mute_text);
596
597static const char *mute_mode_text[] = {
598 "Hard", "Soft"
599};
600
601static const struct soc_enum mute_mode =
602 SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_1, 9, 2, mute_mode_text);
603
604static const char *dac_deemphasis_text[] = {
605 "Disabled", "32kHz", "44.1kHz", "48kHz"
606};
607
608static const struct soc_enum dac_deemphasis =
609 SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_1, 1, 4, dac_deemphasis_text);
610
611static const char *companding_text[] = {
612 "ulaw", "alaw"
613};
614
615static const struct soc_enum dac_companding =
616 SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 0, 2, companding_text);
617
618static const struct soc_enum adc_companding =
619 SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 2, 2, companding_text);
620
621static const char *input_mode_text[] = {
622 "Single-Ended", "Differential Line", "Differential Mic"
623};
624
625static const struct soc_enum linput_mode_enum =
626 SOC_ENUM_SINGLE(WM8903_ANALOGUE_LEFT_INPUT_1, 0, 3, input_mode_text);
627
628static const struct soc_enum rinput_mode_enum =
629 SOC_ENUM_SINGLE(WM8903_ANALOGUE_RIGHT_INPUT_1, 0, 3, input_mode_text);
630
631static const char *linput_mux_text[] = {
632 "IN1L", "IN2L", "IN3L"
633};
634
635static const struct soc_enum linput_enum =
636 SOC_ENUM_SINGLE(WM8903_ANALOGUE_LEFT_INPUT_1, 2, 3, linput_mux_text);
637
638static const struct soc_enum linput_inv_enum =
639 SOC_ENUM_SINGLE(WM8903_ANALOGUE_LEFT_INPUT_1, 4, 3, linput_mux_text);
640
641static const char *rinput_mux_text[] = {
642 "IN1R", "IN2R", "IN3R"
643};
644
645static const struct soc_enum rinput_enum =
646 SOC_ENUM_SINGLE(WM8903_ANALOGUE_RIGHT_INPUT_1, 2, 3, rinput_mux_text);
647
648static const struct soc_enum rinput_inv_enum =
649 SOC_ENUM_SINGLE(WM8903_ANALOGUE_RIGHT_INPUT_1, 4, 3, rinput_mux_text);
650
651
652static const struct snd_kcontrol_new wm8903_snd_controls[] = {
653
654/* Input PGAs - No TLV since the scale depends on PGA mode */
655SOC_SINGLE("Left Input PGA Switch", WM8903_ANALOGUE_LEFT_INPUT_0,
656 7, 1, 1),
657SOC_SINGLE("Left Input PGA Volume", WM8903_ANALOGUE_LEFT_INPUT_0,
658 0, 31, 0),
659SOC_SINGLE("Left Input PGA Common Mode Switch", WM8903_ANALOGUE_LEFT_INPUT_1,
660 6, 1, 0),
661
662SOC_SINGLE("Right Input PGA Switch", WM8903_ANALOGUE_RIGHT_INPUT_0,
663 7, 1, 1),
664SOC_SINGLE("Right Input PGA Volume", WM8903_ANALOGUE_RIGHT_INPUT_0,
665 0, 31, 0),
666SOC_SINGLE("Right Input PGA Common Mode Switch", WM8903_ANALOGUE_RIGHT_INPUT_1,
667 6, 1, 0),
668
669/* ADCs */
670SOC_SINGLE("DRC Switch", WM8903_DRC_0, 15, 1, 0),
671SOC_ENUM("DRC Compressor Slope R0", drc_slope_r0),
672SOC_ENUM("DRC Compressor Slope R1", drc_slope_r1),
673SOC_SINGLE_TLV("DRC Compressor Threashold Volume", WM8903_DRC_3, 5, 124, 1,
674 drc_tlv_thresh),
675SOC_SINGLE_TLV("DRC Volume", WM8903_DRC_3, 0, 30, 1, drc_tlv_amp),
676SOC_SINGLE_TLV("DRC Minimum Gain Volume", WM8903_DRC_1, 2, 3, 1, drc_tlv_min),
677SOC_SINGLE_TLV("DRC Maximum Gain Volume", WM8903_DRC_1, 0, 3, 0, drc_tlv_max),
678SOC_ENUM("DRC Attack Rate", drc_attack),
679SOC_ENUM("DRC Decay Rate", drc_decay),
680SOC_ENUM("DRC FF Delay", drc_ff_delay),
681SOC_SINGLE("DRC Anticlip Switch", WM8903_DRC_0, 1, 1, 0),
682SOC_SINGLE("DRC QR Switch", WM8903_DRC_0, 2, 1, 0),
683SOC_SINGLE_TLV("DRC QR Threashold Volume", WM8903_DRC_0, 6, 3, 0, drc_tlv_max),
684SOC_ENUM("DRC QR Decay Rate", drc_qr_decay),
685SOC_SINGLE("DRC Smoothing Switch", WM8903_DRC_0, 3, 1, 0),
686SOC_SINGLE("DRC Smoothing Hysteresis Switch", WM8903_DRC_0, 0, 1, 0),
687SOC_ENUM("DRC Smoothing Threashold", drc_smoothing),
688SOC_SINGLE_TLV("DRC Startup Volume", WM8903_DRC_0, 6, 18, 0, drc_tlv_startup),
689
690SOC_DOUBLE_R_TLV("Digital Capture Volume", WM8903_ADC_DIGITAL_VOLUME_LEFT,
691 WM8903_ADC_DIGITAL_VOLUME_RIGHT, 1, 96, 0, digital_tlv),
692SOC_ENUM("ADC Companding Mode", adc_companding),
693SOC_SINGLE("ADC Companding Switch", WM8903_AUDIO_INTERFACE_0, 3, 1, 0),
694
695/* DAC */
696SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8903_DAC_DIGITAL_VOLUME_LEFT,
697 WM8903_DAC_DIGITAL_VOLUME_RIGHT, 1, 120, 0, digital_tlv),
698SOC_ENUM("DAC Soft Mute Rate", soft_mute),
699SOC_ENUM("DAC Mute Mode", mute_mode),
700SOC_SINGLE("DAC Mono Switch", WM8903_DAC_DIGITAL_1, 12, 1, 0),
701SOC_ENUM("DAC De-emphasis", dac_deemphasis),
702SOC_SINGLE("DAC Sloping Stopband Filter Switch",
703 WM8903_DAC_DIGITAL_1, 11, 1, 0),
704SOC_ENUM("DAC Companding Mode", dac_companding),
705SOC_SINGLE("DAC Companding Switch", WM8903_AUDIO_INTERFACE_0, 1, 1, 0),
706
707/* Headphones */
708SOC_DOUBLE_R("Headphone Switch",
709 WM8903_ANALOGUE_OUT1_LEFT, WM8903_ANALOGUE_OUT1_RIGHT,
710 8, 1, 1),
711SOC_DOUBLE_R("Headphone ZC Switch",
712 WM8903_ANALOGUE_OUT1_LEFT, WM8903_ANALOGUE_OUT1_RIGHT,
713 6, 1, 0),
714SOC_DOUBLE_R_TLV("Headphone Volume",
715 WM8903_ANALOGUE_OUT1_LEFT, WM8903_ANALOGUE_OUT1_RIGHT,
716 0, 63, 0, out_tlv),
717
718/* Line out */
719SOC_DOUBLE_R("Line Out Switch",
720 WM8903_ANALOGUE_OUT2_LEFT, WM8903_ANALOGUE_OUT2_RIGHT,
721 8, 1, 1),
722SOC_DOUBLE_R("Line Out ZC Switch",
723 WM8903_ANALOGUE_OUT2_LEFT, WM8903_ANALOGUE_OUT2_RIGHT,
724 6, 1, 0),
725SOC_DOUBLE_R_TLV("Line Out Volume",
726 WM8903_ANALOGUE_OUT2_LEFT, WM8903_ANALOGUE_OUT2_RIGHT,
727 0, 63, 0, out_tlv),
728
729/* Speaker */
730SOC_DOUBLE_R("Speaker Switch",
731 WM8903_ANALOGUE_OUT3_LEFT, WM8903_ANALOGUE_OUT3_RIGHT, 8, 1, 1),
732SOC_DOUBLE_R("Speaker ZC Switch",
733 WM8903_ANALOGUE_OUT3_LEFT, WM8903_ANALOGUE_OUT3_RIGHT, 6, 1, 0),
734SOC_DOUBLE_R_TLV("Speaker Volume",
735 WM8903_ANALOGUE_OUT3_LEFT, WM8903_ANALOGUE_OUT3_RIGHT,
736 0, 63, 0, out_tlv),
737};
738
739static int wm8903_add_controls(struct snd_soc_codec *codec)
740{
741 int err, i;
742
743 for (i = 0; i < ARRAY_SIZE(wm8903_snd_controls); i++) {
744 err = snd_ctl_add(codec->card,
745 snd_soc_cnew(&wm8903_snd_controls[i],
746 codec, NULL));
747 if (err < 0)
748 return err;
749 }
750
751 return 0;
752}
753
754static const struct snd_kcontrol_new linput_mode_mux =
755 SOC_DAPM_ENUM("Left Input Mode Mux", linput_mode_enum);
756
757static const struct snd_kcontrol_new rinput_mode_mux =
758 SOC_DAPM_ENUM("Right Input Mode Mux", rinput_mode_enum);
759
760static const struct snd_kcontrol_new linput_mux =
761 SOC_DAPM_ENUM("Left Input Mux", linput_enum);
762
763static const struct snd_kcontrol_new linput_inv_mux =
764 SOC_DAPM_ENUM("Left Inverting Input Mux", linput_inv_enum);
765
766static const struct snd_kcontrol_new rinput_mux =
767 SOC_DAPM_ENUM("Right Input Mux", rinput_enum);
768
769static const struct snd_kcontrol_new rinput_inv_mux =
770 SOC_DAPM_ENUM("Right Inverting Input Mux", rinput_inv_enum);
771
772static const struct snd_kcontrol_new left_output_mixer[] = {
773SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_LEFT_MIX_0, 3, 1, 0),
774SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_LEFT_MIX_0, 2, 1, 0),
775SOC_DAPM_SINGLE_W("Left Bypass Switch", WM8903_ANALOGUE_LEFT_MIX_0, 1, 1, 0),
776SOC_DAPM_SINGLE_W("Right Bypass Switch", WM8903_ANALOGUE_LEFT_MIX_0, 1, 1, 0),
777};
778
779static const struct snd_kcontrol_new right_output_mixer[] = {
780SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 3, 1, 0),
781SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 2, 1, 0),
782SOC_DAPM_SINGLE_W("Left Bypass Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 1, 1, 0),
783SOC_DAPM_SINGLE_W("Right Bypass Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 1, 1, 0),
784};
785
786static const struct snd_kcontrol_new left_speaker_mixer[] = {
787SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_SPK_MIX_LEFT_0, 3, 1, 0),
788SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_SPK_MIX_LEFT_0, 2, 1, 0),
789SOC_DAPM_SINGLE("Left Bypass Switch", WM8903_ANALOGUE_SPK_MIX_LEFT_0, 1, 1, 0),
790SOC_DAPM_SINGLE("Right Bypass Switch", WM8903_ANALOGUE_SPK_MIX_LEFT_0,
791 1, 1, 0),
792};
793
794static const struct snd_kcontrol_new right_speaker_mixer[] = {
795SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_SPK_MIX_RIGHT_0, 3, 1, 0),
796SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_SPK_MIX_RIGHT_0, 2, 1, 0),
797SOC_DAPM_SINGLE("Left Bypass Switch", WM8903_ANALOGUE_SPK_MIX_RIGHT_0,
798 1, 1, 0),
799SOC_DAPM_SINGLE("Right Bypass Switch", WM8903_ANALOGUE_SPK_MIX_RIGHT_0,
800 1, 1, 0),
801};
802
803static const struct snd_soc_dapm_widget wm8903_dapm_widgets[] = {
804SND_SOC_DAPM_INPUT("IN1L"),
805SND_SOC_DAPM_INPUT("IN1R"),
806SND_SOC_DAPM_INPUT("IN2L"),
807SND_SOC_DAPM_INPUT("IN2R"),
808SND_SOC_DAPM_INPUT("IN3L"),
809SND_SOC_DAPM_INPUT("IN3R"),
810
811SND_SOC_DAPM_OUTPUT("HPOUTL"),
812SND_SOC_DAPM_OUTPUT("HPOUTR"),
813SND_SOC_DAPM_OUTPUT("LINEOUTL"),
814SND_SOC_DAPM_OUTPUT("LINEOUTR"),
815SND_SOC_DAPM_OUTPUT("LOP"),
816SND_SOC_DAPM_OUTPUT("LON"),
817SND_SOC_DAPM_OUTPUT("ROP"),
818SND_SOC_DAPM_OUTPUT("RON"),
819
820SND_SOC_DAPM_MICBIAS("Mic Bias", WM8903_MIC_BIAS_CONTROL_0, 0, 0),
821
822SND_SOC_DAPM_MUX("Left Input Mux", SND_SOC_NOPM, 0, 0, &linput_mux),
823SND_SOC_DAPM_MUX("Left Input Inverting Mux", SND_SOC_NOPM, 0, 0,
824 &linput_inv_mux),
825SND_SOC_DAPM_MUX("Left Input Mode Mux", SND_SOC_NOPM, 0, 0, &linput_mode_mux),
826
827SND_SOC_DAPM_MUX("Right Input Mux", SND_SOC_NOPM, 0, 0, &rinput_mux),
828SND_SOC_DAPM_MUX("Right Input Inverting Mux", SND_SOC_NOPM, 0, 0,
829 &rinput_inv_mux),
830SND_SOC_DAPM_MUX("Right Input Mode Mux", SND_SOC_NOPM, 0, 0, &rinput_mode_mux),
831
832SND_SOC_DAPM_PGA("Left Input PGA", WM8903_POWER_MANAGEMENT_0, 1, 0, NULL, 0),
833SND_SOC_DAPM_PGA("Right Input PGA", WM8903_POWER_MANAGEMENT_0, 0, 0, NULL, 0),
834
835SND_SOC_DAPM_ADC("ADCL", "Left HiFi Capture", WM8903_POWER_MANAGEMENT_6, 1, 0),
836SND_SOC_DAPM_ADC("ADCR", "Right HiFi Capture", WM8903_POWER_MANAGEMENT_6, 0, 0),
837
838SND_SOC_DAPM_DAC("DACL", "Left Playback", WM8903_POWER_MANAGEMENT_6, 3, 0),
839SND_SOC_DAPM_DAC("DACR", "Right Playback", WM8903_POWER_MANAGEMENT_6, 2, 0),
840
841SND_SOC_DAPM_MIXER("Left Output Mixer", WM8903_POWER_MANAGEMENT_1, 1, 0,
842 left_output_mixer, ARRAY_SIZE(left_output_mixer)),
843SND_SOC_DAPM_MIXER("Right Output Mixer", WM8903_POWER_MANAGEMENT_1, 0, 0,
844 right_output_mixer, ARRAY_SIZE(right_output_mixer)),
845
846SND_SOC_DAPM_MIXER("Left Speaker Mixer", WM8903_POWER_MANAGEMENT_4, 1, 0,
847 left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer)),
848SND_SOC_DAPM_MIXER("Right Speaker Mixer", WM8903_POWER_MANAGEMENT_4, 0, 0,
849 right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer)),
850
851SND_SOC_DAPM_PGA_E("Left Headphone Output PGA", WM8903_POWER_MANAGEMENT_2,
852 1, 0, NULL, 0, wm8903_output_event,
853 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
854 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
855SND_SOC_DAPM_PGA_E("Right Headphone Output PGA", WM8903_POWER_MANAGEMENT_2,
856 0, 0, NULL, 0, wm8903_output_event,
857 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
858 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
859
860SND_SOC_DAPM_PGA_E("Left Line Output PGA", WM8903_POWER_MANAGEMENT_3, 1, 0,
861 NULL, 0, wm8903_output_event,
862 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
863 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
864SND_SOC_DAPM_PGA_E("Right Line Output PGA", WM8903_POWER_MANAGEMENT_3, 0, 0,
865 NULL, 0, wm8903_output_event,
866 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
867 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
868
869SND_SOC_DAPM_PGA("Left Speaker PGA", WM8903_POWER_MANAGEMENT_5, 1, 0,
870 NULL, 0),
871SND_SOC_DAPM_PGA("Right Speaker PGA", WM8903_POWER_MANAGEMENT_5, 0, 0,
872 NULL, 0),
873
874};
875
876static const struct snd_soc_dapm_route intercon[] = {
877
878 { "Left Input Mux", "IN1L", "IN1L" },
879 { "Left Input Mux", "IN2L", "IN2L" },
880 { "Left Input Mux", "IN3L", "IN3L" },
881
882 { "Left Input Inverting Mux", "IN1L", "IN1L" },
883 { "Left Input Inverting Mux", "IN2L", "IN2L" },
884 { "Left Input Inverting Mux", "IN3L", "IN3L" },
885
886 { "Right Input Mux", "IN1R", "IN1R" },
887 { "Right Input Mux", "IN2R", "IN2R" },
888 { "Right Input Mux", "IN3R", "IN3R" },
889
890 { "Right Input Inverting Mux", "IN1R", "IN1R" },
891 { "Right Input Inverting Mux", "IN2R", "IN2R" },
892 { "Right Input Inverting Mux", "IN3R", "IN3R" },
893
894 { "Left Input Mode Mux", "Single-Ended", "Left Input Inverting Mux" },
895 { "Left Input Mode Mux", "Differential Line",
896 "Left Input Mux" },
897 { "Left Input Mode Mux", "Differential Line",
898 "Left Input Inverting Mux" },
899 { "Left Input Mode Mux", "Differential Mic",
900 "Left Input Mux" },
901 { "Left Input Mode Mux", "Differential Mic",
902 "Left Input Inverting Mux" },
903
904 { "Right Input Mode Mux", "Single-Ended",
905 "Right Input Inverting Mux" },
906 { "Right Input Mode Mux", "Differential Line",
907 "Right Input Mux" },
908 { "Right Input Mode Mux", "Differential Line",
909 "Right Input Inverting Mux" },
910 { "Right Input Mode Mux", "Differential Mic",
911 "Right Input Mux" },
912 { "Right Input Mode Mux", "Differential Mic",
913 "Right Input Inverting Mux" },
914
915 { "Left Input PGA", NULL, "Left Input Mode Mux" },
916 { "Right Input PGA", NULL, "Right Input Mode Mux" },
917
918 { "ADCL", NULL, "Left Input PGA" },
919 { "ADCR", NULL, "Right Input PGA" },
920
921 { "Left Output Mixer", "Left Bypass Switch", "Left Input PGA" },
922 { "Left Output Mixer", "Right Bypass Switch", "Right Input PGA" },
923 { "Left Output Mixer", "DACL Switch", "DACL" },
924 { "Left Output Mixer", "DACR Switch", "DACR" },
925
926 { "Right Output Mixer", "Left Bypass Switch", "Left Input PGA" },
927 { "Right Output Mixer", "Right Bypass Switch", "Right Input PGA" },
928 { "Right Output Mixer", "DACL Switch", "DACL" },
929 { "Right Output Mixer", "DACR Switch", "DACR" },
930
931 { "Left Speaker Mixer", "Left Bypass Switch", "Left Input PGA" },
932 { "Left Speaker Mixer", "Right Bypass Switch", "Right Input PGA" },
933 { "Left Speaker Mixer", "DACL Switch", "DACL" },
934 { "Left Speaker Mixer", "DACR Switch", "DACR" },
935
936 { "Right Speaker Mixer", "Left Bypass Switch", "Left Input PGA" },
937 { "Right Speaker Mixer", "Right Bypass Switch", "Right Input PGA" },
938 { "Right Speaker Mixer", "DACL Switch", "DACL" },
939 { "Right Speaker Mixer", "DACR Switch", "DACR" },
940
941 { "Left Line Output PGA", NULL, "Left Output Mixer" },
942 { "Right Line Output PGA", NULL, "Right Output Mixer" },
943
944 { "Left Headphone Output PGA", NULL, "Left Output Mixer" },
945 { "Right Headphone Output PGA", NULL, "Right Output Mixer" },
946
947 { "Left Speaker PGA", NULL, "Left Speaker Mixer" },
948 { "Right Speaker PGA", NULL, "Right Speaker Mixer" },
949
950 { "HPOUTL", NULL, "Left Headphone Output PGA" },
951 { "HPOUTR", NULL, "Right Headphone Output PGA" },
952
953 { "LINEOUTL", NULL, "Left Line Output PGA" },
954 { "LINEOUTR", NULL, "Right Line Output PGA" },
955
956 { "LOP", NULL, "Left Speaker PGA" },
957 { "LON", NULL, "Left Speaker PGA" },
958
959 { "ROP", NULL, "Right Speaker PGA" },
960 { "RON", NULL, "Right Speaker PGA" },
961};
962
963static int wm8903_add_widgets(struct snd_soc_codec *codec)
964{
965 snd_soc_dapm_new_controls(codec, wm8903_dapm_widgets,
966 ARRAY_SIZE(wm8903_dapm_widgets));
967
968 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
969
970 snd_soc_dapm_new_widgets(codec);
971
972 return 0;
973}
974
975static int wm8903_set_bias_level(struct snd_soc_codec *codec,
976 enum snd_soc_bias_level level)
977{
978 struct i2c_client *i2c = codec->control_data;
979 u16 reg, reg2;
980
981 switch (level) {
982 case SND_SOC_BIAS_ON:
983 case SND_SOC_BIAS_PREPARE:
984 reg = wm8903_read(codec, WM8903_VMID_CONTROL_0);
985 reg &= ~(WM8903_VMID_RES_MASK);
986 reg |= WM8903_VMID_RES_50K;
987 wm8903_write(codec, WM8903_VMID_CONTROL_0, reg);
988 break;
989
990 case SND_SOC_BIAS_STANDBY:
991 if (codec->bias_level == SND_SOC_BIAS_OFF) {
992 wm8903_run_sequence(codec, 0);
993 wm8903_sync_reg_cache(codec, codec->reg_cache);
994
995 /* Enable low impedence charge pump output */
996 reg = wm8903_read(codec,
997 WM8903_CONTROL_INTERFACE_TEST_1);
998 wm8903_write(codec, WM8903_CONTROL_INTERFACE_TEST_1,
999 reg | WM8903_TEST_KEY);
1000 reg2 = wm8903_read(codec, WM8903_CHARGE_PUMP_TEST_1);
1001 wm8903_write(codec, WM8903_CHARGE_PUMP_TEST_1,
1002 reg2 | WM8903_CP_SW_KELVIN_MODE_MASK);
1003 wm8903_write(codec, WM8903_CONTROL_INTERFACE_TEST_1,
1004 reg);
1005
1006 /* By default no bypass paths are enabled so
1007 * enable Class W support.
1008 */
1009 dev_dbg(&i2c->dev, "Enabling Class W\n");
1010 wm8903_write(codec, WM8903_CLASS_W_0, reg |
1011 WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V);
1012 }
1013
1014 reg = wm8903_read(codec, WM8903_VMID_CONTROL_0);
1015 reg &= ~(WM8903_VMID_RES_MASK);
1016 reg |= WM8903_VMID_RES_250K;
1017 wm8903_write(codec, WM8903_VMID_CONTROL_0, reg);
1018 break;
1019
1020 case SND_SOC_BIAS_OFF:
1021 wm8903_run_sequence(codec, 32);
1022 break;
1023 }
1024
1025 codec->bias_level = level;
1026
1027 return 0;
1028}
1029
1030static int wm8903_set_dai_sysclk(struct snd_soc_dai *codec_dai,
1031 int clk_id, unsigned int freq, int dir)
1032{
1033 struct snd_soc_codec *codec = codec_dai->codec;
1034 struct wm8903_priv *wm8903 = codec->private_data;
1035
1036 wm8903->sysclk = freq;
1037
1038 return 0;
1039}
1040
1041static int wm8903_set_dai_fmt(struct snd_soc_dai *codec_dai,
1042 unsigned int fmt)
1043{
1044 struct snd_soc_codec *codec = codec_dai->codec;
1045 u16 aif1 = wm8903_read(codec, WM8903_AUDIO_INTERFACE_1);
1046
1047 aif1 &= ~(WM8903_LRCLK_DIR | WM8903_BCLK_DIR | WM8903_AIF_FMT_MASK |
1048 WM8903_AIF_LRCLK_INV | WM8903_AIF_BCLK_INV);
1049
1050 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
1051 case SND_SOC_DAIFMT_CBS_CFS:
1052 break;
1053 case SND_SOC_DAIFMT_CBS_CFM:
1054 aif1 |= WM8903_LRCLK_DIR;
1055 break;
1056 case SND_SOC_DAIFMT_CBM_CFM:
1057 aif1 |= WM8903_LRCLK_DIR | WM8903_BCLK_DIR;
1058 break;
1059 case SND_SOC_DAIFMT_CBM_CFS:
1060 aif1 |= WM8903_BCLK_DIR;
1061 break;
1062 default:
1063 return -EINVAL;
1064 }
1065
1066 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
1067 case SND_SOC_DAIFMT_DSP_A:
1068 aif1 |= 0x3;
1069 break;
1070 case SND_SOC_DAIFMT_DSP_B:
1071 aif1 |= 0x3 | WM8903_AIF_LRCLK_INV;
1072 break;
1073 case SND_SOC_DAIFMT_I2S:
1074 aif1 |= 0x2;
1075 break;
1076 case SND_SOC_DAIFMT_RIGHT_J:
1077 aif1 |= 0x1;
1078 break;
1079 case SND_SOC_DAIFMT_LEFT_J:
1080 break;
1081 default:
1082 return -EINVAL;
1083 }
1084
1085 /* Clock inversion */
1086 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
1087 case SND_SOC_DAIFMT_DSP_A:
1088 case SND_SOC_DAIFMT_DSP_B:
1089 /* frame inversion not valid for DSP modes */
1090 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
1091 case SND_SOC_DAIFMT_NB_NF:
1092 break;
1093 case SND_SOC_DAIFMT_IB_NF:
1094 aif1 |= WM8903_AIF_BCLK_INV;
1095 break;
1096 default:
1097 return -EINVAL;
1098 }
1099 break;
1100 case SND_SOC_DAIFMT_I2S:
1101 case SND_SOC_DAIFMT_RIGHT_J:
1102 case SND_SOC_DAIFMT_LEFT_J:
1103 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
1104 case SND_SOC_DAIFMT_NB_NF:
1105 break;
1106 case SND_SOC_DAIFMT_IB_IF:
1107 aif1 |= WM8903_AIF_BCLK_INV | WM8903_AIF_LRCLK_INV;
1108 break;
1109 case SND_SOC_DAIFMT_IB_NF:
1110 aif1 |= WM8903_AIF_BCLK_INV;
1111 break;
1112 case SND_SOC_DAIFMT_NB_IF:
1113 aif1 |= WM8903_AIF_LRCLK_INV;
1114 break;
1115 default:
1116 return -EINVAL;
1117 }
1118 break;
1119 default:
1120 return -EINVAL;
1121 }
1122
1123 wm8903_write(codec, WM8903_AUDIO_INTERFACE_1, aif1);
1124
1125 return 0;
1126}
1127
1128static int wm8903_digital_mute(struct snd_soc_dai *codec_dai, int mute)
1129{
1130 struct snd_soc_codec *codec = codec_dai->codec;
1131 u16 reg;
1132
1133 reg = wm8903_read(codec, WM8903_DAC_DIGITAL_1);
1134
1135 if (mute)
1136 reg |= WM8903_DAC_MUTE;
1137 else
1138 reg &= ~WM8903_DAC_MUTE;
1139
1140 wm8903_write(codec, WM8903_DAC_DIGITAL_1, reg);
1141
1142 return 0;
1143}
1144
1145/* Lookup table for CLK_SYS/fs ratio. 256fs or more is recommended
1146 * for optimal performance so we list the lower rates first and match
1147 * on the last match we find. */
1148static struct {
1149 int div;
1150 int rate;
1151 int mode;
1152 int mclk_div;
1153} clk_sys_ratios[] = {
1154 { 64, 0x0, 0x0, 1 },
1155 { 68, 0x0, 0x1, 1 },
1156 { 125, 0x0, 0x2, 1 },
1157 { 128, 0x1, 0x0, 1 },
1158 { 136, 0x1, 0x1, 1 },
1159 { 192, 0x2, 0x0, 1 },
1160 { 204, 0x2, 0x1, 1 },
1161
1162 { 64, 0x0, 0x0, 2 },
1163 { 68, 0x0, 0x1, 2 },
1164 { 125, 0x0, 0x2, 2 },
1165 { 128, 0x1, 0x0, 2 },
1166 { 136, 0x1, 0x1, 2 },
1167 { 192, 0x2, 0x0, 2 },
1168 { 204, 0x2, 0x1, 2 },
1169
1170 { 250, 0x2, 0x2, 1 },
1171 { 256, 0x3, 0x0, 1 },
1172 { 272, 0x3, 0x1, 1 },
1173 { 384, 0x4, 0x0, 1 },
1174 { 408, 0x4, 0x1, 1 },
1175 { 375, 0x4, 0x2, 1 },
1176 { 512, 0x5, 0x0, 1 },
1177 { 544, 0x5, 0x1, 1 },
1178 { 500, 0x5, 0x2, 1 },
1179 { 768, 0x6, 0x0, 1 },
1180 { 816, 0x6, 0x1, 1 },
1181 { 750, 0x6, 0x2, 1 },
1182 { 1024, 0x7, 0x0, 1 },
1183 { 1088, 0x7, 0x1, 1 },
1184 { 1000, 0x7, 0x2, 1 },
1185 { 1408, 0x8, 0x0, 1 },
1186 { 1496, 0x8, 0x1, 1 },
1187 { 1536, 0x9, 0x0, 1 },
1188 { 1632, 0x9, 0x1, 1 },
1189 { 1500, 0x9, 0x2, 1 },
1190
1191 { 250, 0x2, 0x2, 2 },
1192 { 256, 0x3, 0x0, 2 },
1193 { 272, 0x3, 0x1, 2 },
1194 { 384, 0x4, 0x0, 2 },
1195 { 408, 0x4, 0x1, 2 },
1196 { 375, 0x4, 0x2, 2 },
1197 { 512, 0x5, 0x0, 2 },
1198 { 544, 0x5, 0x1, 2 },
1199 { 500, 0x5, 0x2, 2 },
1200 { 768, 0x6, 0x0, 2 },
1201 { 816, 0x6, 0x1, 2 },
1202 { 750, 0x6, 0x2, 2 },
1203 { 1024, 0x7, 0x0, 2 },
1204 { 1088, 0x7, 0x1, 2 },
1205 { 1000, 0x7, 0x2, 2 },
1206 { 1408, 0x8, 0x0, 2 },
1207 { 1496, 0x8, 0x1, 2 },
1208 { 1536, 0x9, 0x0, 2 },
1209 { 1632, 0x9, 0x1, 2 },
1210 { 1500, 0x9, 0x2, 2 },
1211};
1212
1213/* CLK_SYS/BCLK ratios - multiplied by 10 due to .5s */
1214static struct {
1215 int ratio;
1216 int div;
1217} bclk_divs[] = {
1218 { 10, 0 },
1219 { 15, 1 },
1220 { 20, 2 },
1221 { 30, 3 },
1222 { 40, 4 },
1223 { 50, 5 },
1224 { 55, 6 },
1225 { 60, 7 },
1226 { 80, 8 },
1227 { 100, 9 },
1228 { 110, 10 },
1229 { 120, 11 },
1230 { 160, 12 },
1231 { 200, 13 },
1232 { 220, 14 },
1233 { 240, 15 },
1234 { 250, 16 },
1235 { 300, 17 },
1236 { 320, 18 },
1237 { 440, 19 },
1238 { 480, 20 },
1239};
1240
1241/* Sample rates for DSP */
1242static struct {
1243 int rate;
1244 int value;
1245} sample_rates[] = {
1246 { 8000, 0 },
1247 { 11025, 1 },
1248 { 12000, 2 },
1249 { 16000, 3 },
1250 { 22050, 4 },
1251 { 24000, 5 },
1252 { 32000, 6 },
1253 { 44100, 7 },
1254 { 48000, 8 },
1255 { 88200, 9 },
1256 { 96000, 10 },
1257 { 0, 0 },
1258};
1259
1260static int wm8903_startup(struct snd_pcm_substream *substream)
1261{
1262 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1263 struct snd_soc_device *socdev = rtd->socdev;
1264 struct snd_soc_codec *codec = socdev->codec;
1265 struct wm8903_priv *wm8903 = codec->private_data;
1266 struct i2c_client *i2c = codec->control_data;
1267 struct snd_pcm_runtime *master_runtime;
1268
1269 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
1270 wm8903->playback_active++;
1271 else
1272 wm8903->capture_active++;
1273
1274 /* The DAI has shared clocks so if we already have a playback or
1275 * capture going then constrain this substream to match it.
1276 */
1277 if (wm8903->master_substream) {
1278 master_runtime = wm8903->master_substream->runtime;
1279
1280 dev_dbg(&i2c->dev, "Constraining to %d bits at %dHz\n",
1281 master_runtime->sample_bits,
1282 master_runtime->rate);
1283
1284 snd_pcm_hw_constraint_minmax(substream->runtime,
1285 SNDRV_PCM_HW_PARAM_RATE,
1286 master_runtime->rate,
1287 master_runtime->rate);
1288
1289 snd_pcm_hw_constraint_minmax(substream->runtime,
1290 SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
1291 master_runtime->sample_bits,
1292 master_runtime->sample_bits);
1293
1294 wm8903->slave_substream = substream;
1295 } else
1296 wm8903->master_substream = substream;
1297
1298 return 0;
1299}
1300
1301static void wm8903_shutdown(struct snd_pcm_substream *substream)
1302{
1303 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1304 struct snd_soc_device *socdev = rtd->socdev;
1305 struct snd_soc_codec *codec = socdev->codec;
1306 struct wm8903_priv *wm8903 = codec->private_data;
1307
1308 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
1309 wm8903->playback_active--;
1310 else
1311 wm8903->capture_active--;
1312
1313 if (wm8903->master_substream == substream)
1314 wm8903->master_substream = wm8903->slave_substream;
1315
1316 wm8903->slave_substream = NULL;
1317}
1318
1319static int wm8903_hw_params(struct snd_pcm_substream *substream,
1320 struct snd_pcm_hw_params *params)
1321{
1322 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1323 struct snd_soc_device *socdev = rtd->socdev;
1324 struct snd_soc_codec *codec = socdev->codec;
1325 struct wm8903_priv *wm8903 = codec->private_data;
1326 struct i2c_client *i2c = codec->control_data;
1327 int fs = params_rate(params);
1328 int bclk;
1329 int bclk_div;
1330 int i;
1331 int dsp_config;
1332 int clk_config;
1333 int best_val;
1334 int cur_val;
1335 int clk_sys;
1336
1337 u16 aif1 = wm8903_read(codec, WM8903_AUDIO_INTERFACE_1);
1338 u16 aif2 = wm8903_read(codec, WM8903_AUDIO_INTERFACE_2);
1339 u16 aif3 = wm8903_read(codec, WM8903_AUDIO_INTERFACE_3);
1340 u16 clock0 = wm8903_read(codec, WM8903_CLOCK_RATES_0);
1341 u16 clock1 = wm8903_read(codec, WM8903_CLOCK_RATES_1);
1342
1343 if (substream == wm8903->slave_substream) {
1344 dev_dbg(&i2c->dev, "Ignoring hw_params for slave substream\n");
1345 return 0;
1346 }
1347
1348 /* Configure sample rate logic for DSP - choose nearest rate */
1349 dsp_config = 0;
1350 best_val = abs(sample_rates[dsp_config].rate - fs);
1351 for (i = 1; i < ARRAY_SIZE(sample_rates); i++) {
1352 cur_val = abs(sample_rates[i].rate - fs);
1353 if (cur_val <= best_val) {
1354 dsp_config = i;
1355 best_val = cur_val;
1356 }
1357 }
1358
1359 /* Constraints should stop us hitting this but let's make sure */
1360 if (wm8903->capture_active)
1361 switch (sample_rates[dsp_config].rate) {
1362 case 88200:
1363 case 96000:
1364 dev_err(&i2c->dev, "%dHz unsupported by ADC\n",
1365 fs);
1366 return -EINVAL;
1367
1368 default:
1369 break;
1370 }
1371
1372 dev_dbg(&i2c->dev, "DSP fs = %dHz\n", sample_rates[dsp_config].rate);
1373 clock1 &= ~WM8903_SAMPLE_RATE_MASK;
1374 clock1 |= sample_rates[dsp_config].value;
1375
1376 aif1 &= ~WM8903_AIF_WL_MASK;
1377 bclk = 2 * fs;
1378 switch (params_format(params)) {
1379 case SNDRV_PCM_FORMAT_S16_LE:
1380 bclk *= 16;
1381 break;
1382 case SNDRV_PCM_FORMAT_S20_3LE:
1383 bclk *= 20;
1384 aif1 |= 0x4;
1385 break;
1386 case SNDRV_PCM_FORMAT_S24_LE:
1387 bclk *= 24;
1388 aif1 |= 0x8;
1389 break;
1390 case SNDRV_PCM_FORMAT_S32_LE:
1391 bclk *= 32;
1392 aif1 |= 0xc;
1393 break;
1394 default:
1395 return -EINVAL;
1396 }
1397
1398 dev_dbg(&i2c->dev, "MCLK = %dHz, target sample rate = %dHz\n",
1399 wm8903->sysclk, fs);
1400
1401 /* We may not have an MCLK which allows us to generate exactly
1402 * the clock we want, particularly with USB derived inputs, so
1403 * approximate.
1404 */
1405 clk_config = 0;
1406 best_val = abs((wm8903->sysclk /
1407 (clk_sys_ratios[0].mclk_div *
1408 clk_sys_ratios[0].div)) - fs);
1409 for (i = 1; i < ARRAY_SIZE(clk_sys_ratios); i++) {
1410 cur_val = abs((wm8903->sysclk /
1411 (clk_sys_ratios[i].mclk_div *
1412 clk_sys_ratios[i].div)) - fs);
1413
1414 if (cur_val <= best_val) {
1415 clk_config = i;
1416 best_val = cur_val;
1417 }
1418 }
1419
1420 if (clk_sys_ratios[clk_config].mclk_div == 2) {
1421 clock0 |= WM8903_MCLKDIV2;
1422 clk_sys = wm8903->sysclk / 2;
1423 } else {
1424 clock0 &= ~WM8903_MCLKDIV2;
1425 clk_sys = wm8903->sysclk;
1426 }
1427
1428 clock1 &= ~(WM8903_CLK_SYS_RATE_MASK |
1429 WM8903_CLK_SYS_MODE_MASK);
1430 clock1 |= clk_sys_ratios[clk_config].rate << WM8903_CLK_SYS_RATE_SHIFT;
1431 clock1 |= clk_sys_ratios[clk_config].mode << WM8903_CLK_SYS_MODE_SHIFT;
1432
1433 dev_dbg(&i2c->dev, "CLK_SYS_RATE=%x, CLK_SYS_MODE=%x div=%d\n",
1434 clk_sys_ratios[clk_config].rate,
1435 clk_sys_ratios[clk_config].mode,
1436 clk_sys_ratios[clk_config].div);
1437
1438 dev_dbg(&i2c->dev, "Actual CLK_SYS = %dHz\n", clk_sys);
1439
1440 /* We may not get quite the right frequency if using
1441 * approximate clocks so look for the closest match that is
1442 * higher than the target (we need to ensure that there enough
1443 * BCLKs to clock out the samples).
1444 */
1445 bclk_div = 0;
1446 best_val = ((clk_sys * 10) / bclk_divs[0].ratio) - bclk;
1447 i = 1;
1448 while (i < ARRAY_SIZE(bclk_divs)) {
1449 cur_val = ((clk_sys * 10) / bclk_divs[i].ratio) - bclk;
1450 if (cur_val < 0) /* BCLK table is sorted */
1451 break;
1452 bclk_div = i;
1453 best_val = cur_val;
1454 i++;
1455 }
1456
1457 aif2 &= ~WM8903_BCLK_DIV_MASK;
1458 aif3 &= ~WM8903_LRCLK_RATE_MASK;
1459
1460 dev_dbg(&i2c->dev, "BCLK ratio %d for %dHz - actual BCLK = %dHz\n",
1461 bclk_divs[bclk_div].ratio / 10, bclk,
1462 (clk_sys * 10) / bclk_divs[bclk_div].ratio);
1463
1464 aif2 |= bclk_divs[bclk_div].div;
1465 aif3 |= bclk / fs;
1466
1467 wm8903_write(codec, WM8903_CLOCK_RATES_0, clock0);
1468 wm8903_write(codec, WM8903_CLOCK_RATES_1, clock1);
1469 wm8903_write(codec, WM8903_AUDIO_INTERFACE_1, aif1);
1470 wm8903_write(codec, WM8903_AUDIO_INTERFACE_2, aif2);
1471 wm8903_write(codec, WM8903_AUDIO_INTERFACE_3, aif3);
1472
1473 return 0;
1474}
1475
1476#define WM8903_PLAYBACK_RATES (SNDRV_PCM_RATE_8000 |\
1477 SNDRV_PCM_RATE_11025 | \
1478 SNDRV_PCM_RATE_16000 | \
1479 SNDRV_PCM_RATE_22050 | \
1480 SNDRV_PCM_RATE_32000 | \
1481 SNDRV_PCM_RATE_44100 | \
1482 SNDRV_PCM_RATE_48000 | \
1483 SNDRV_PCM_RATE_88200 | \
1484 SNDRV_PCM_RATE_96000)
1485
1486#define WM8903_CAPTURE_RATES (SNDRV_PCM_RATE_8000 |\
1487 SNDRV_PCM_RATE_11025 | \
1488 SNDRV_PCM_RATE_16000 | \
1489 SNDRV_PCM_RATE_22050 | \
1490 SNDRV_PCM_RATE_32000 | \
1491 SNDRV_PCM_RATE_44100 | \
1492 SNDRV_PCM_RATE_48000)
1493
1494#define WM8903_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
1495 SNDRV_PCM_FMTBIT_S20_3LE |\
1496 SNDRV_PCM_FMTBIT_S24_LE)
1497
1498struct snd_soc_dai wm8903_dai = {
1499 .name = "WM8903",
1500 .playback = {
1501 .stream_name = "Playback",
1502 .channels_min = 2,
1503 .channels_max = 2,
1504 .rates = WM8903_PLAYBACK_RATES,
1505 .formats = WM8903_FORMATS,
1506 },
1507 .capture = {
1508 .stream_name = "Capture",
1509 .channels_min = 2,
1510 .channels_max = 2,
1511 .rates = WM8903_CAPTURE_RATES,
1512 .formats = WM8903_FORMATS,
1513 },
1514 .ops = {
1515 .startup = wm8903_startup,
1516 .shutdown = wm8903_shutdown,
1517 .hw_params = wm8903_hw_params,
1518 },
1519 .dai_ops = {
1520 .digital_mute = wm8903_digital_mute,
1521 .set_fmt = wm8903_set_dai_fmt,
1522 .set_sysclk = wm8903_set_dai_sysclk
1523 }
1524};
1525EXPORT_SYMBOL_GPL(wm8903_dai);
1526
1527static int wm8903_suspend(struct platform_device *pdev, pm_message_t state)
1528{
1529 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1530 struct snd_soc_codec *codec = socdev->codec;
1531
1532 wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF);
1533
1534 return 0;
1535}
1536
1537static int wm8903_resume(struct platform_device *pdev)
1538{
1539 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1540 struct snd_soc_codec *codec = socdev->codec;
1541 struct i2c_client *i2c = codec->control_data;
1542 int i;
1543 u16 *reg_cache = codec->reg_cache;
1544 u16 *tmp_cache = kmemdup(codec->reg_cache, sizeof(wm8903_reg_defaults),
1545 GFP_KERNEL);
1546
1547 /* Bring the codec back up to standby first to minimise pop/clicks */
1548 wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1549 wm8903_set_bias_level(codec, codec->suspend_bias_level);
1550
1551 /* Sync back everything else */
1552 if (tmp_cache) {
1553 for (i = 2; i < ARRAY_SIZE(wm8903_reg_defaults); i++)
1554 if (tmp_cache[i] != reg_cache[i])
1555 wm8903_write(codec, i, tmp_cache[i]);
1556 } else {
1557 dev_err(&i2c->dev, "Failed to allocate temporary cache\n");
1558 }
1559
1560 return 0;
1561}
1562
1563/*
1564 * initialise the WM8903 driver
1565 * register the mixer and dsp interfaces with the kernel
1566 */
1567static int wm8903_init(struct snd_soc_device *socdev)
1568{
1569 struct snd_soc_codec *codec = socdev->codec;
1570 struct i2c_client *i2c = codec->control_data;
1571 int ret = 0;
1572 u16 val;
1573
1574 val = wm8903_hw_read(codec, WM8903_SW_RESET_AND_ID);
1575 if (val != wm8903_reg_defaults[WM8903_SW_RESET_AND_ID]) {
1576 dev_err(&i2c->dev,
1577 "Device with ID register %x is not a WM8903\n", val);
1578 return -ENODEV;
1579 }
1580
1581 codec->name = "WM8903";
1582 codec->owner = THIS_MODULE;
1583 codec->read = wm8903_read;
1584 codec->write = wm8903_write;
1585 codec->bias_level = SND_SOC_BIAS_OFF;
1586 codec->set_bias_level = wm8903_set_bias_level;
1587 codec->dai = &wm8903_dai;
1588 codec->num_dai = 1;
1589 codec->reg_cache_size = ARRAY_SIZE(wm8903_reg_defaults);
1590 codec->reg_cache = kmemdup(wm8903_reg_defaults,
1591 sizeof(wm8903_reg_defaults),
1592 GFP_KERNEL);
1593 if (codec->reg_cache == NULL) {
1594 dev_err(&i2c->dev, "Failed to allocate register cache\n");
1595 return -ENOMEM;
1596 }
1597
1598 val = wm8903_read(codec, WM8903_REVISION_NUMBER);
1599 dev_info(&i2c->dev, "WM8903 revision %d\n",
1600 val & WM8903_CHIP_REV_MASK);
1601
1602 wm8903_reset(codec);
1603
1604 /* register pcms */
1605 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1606 if (ret < 0) {
1607 dev_err(&i2c->dev, "failed to create pcms\n");
1608 goto pcm_err;
1609 }
1610
1611 /* SYSCLK is required for pretty much anything */
1612 wm8903_write(codec, WM8903_CLOCK_RATES_2, WM8903_CLK_SYS_ENA);
1613
1614 /* power on device */
1615 wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1616
1617 /* Latch volume update bits */
1618 val = wm8903_read(codec, WM8903_ADC_DIGITAL_VOLUME_LEFT);
1619 val |= WM8903_ADCVU;
1620 wm8903_write(codec, WM8903_ADC_DIGITAL_VOLUME_LEFT, val);
1621 wm8903_write(codec, WM8903_ADC_DIGITAL_VOLUME_RIGHT, val);
1622
1623 val = wm8903_read(codec, WM8903_DAC_DIGITAL_VOLUME_LEFT);
1624 val |= WM8903_DACVU;
1625 wm8903_write(codec, WM8903_DAC_DIGITAL_VOLUME_LEFT, val);
1626 wm8903_write(codec, WM8903_DAC_DIGITAL_VOLUME_RIGHT, val);
1627
1628 val = wm8903_read(codec, WM8903_ANALOGUE_OUT1_LEFT);
1629 val |= WM8903_HPOUTVU;
1630 wm8903_write(codec, WM8903_ANALOGUE_OUT1_LEFT, val);
1631 wm8903_write(codec, WM8903_ANALOGUE_OUT1_RIGHT, val);
1632
1633 val = wm8903_read(codec, WM8903_ANALOGUE_OUT2_LEFT);
1634 val |= WM8903_LINEOUTVU;
1635 wm8903_write(codec, WM8903_ANALOGUE_OUT2_LEFT, val);
1636 wm8903_write(codec, WM8903_ANALOGUE_OUT2_RIGHT, val);
1637
1638 val = wm8903_read(codec, WM8903_ANALOGUE_OUT3_LEFT);
1639 val |= WM8903_SPKVU;
1640 wm8903_write(codec, WM8903_ANALOGUE_OUT3_LEFT, val);
1641 wm8903_write(codec, WM8903_ANALOGUE_OUT3_RIGHT, val);
1642
1643 /* Enable DAC soft mute by default */
1644 val = wm8903_read(codec, WM8903_DAC_DIGITAL_1);
1645 val |= WM8903_DAC_MUTEMODE;
1646 wm8903_write(codec, WM8903_DAC_DIGITAL_1, val);
1647
1648 wm8903_add_controls(codec);
1649 wm8903_add_widgets(codec);
1650 ret = snd_soc_register_card(socdev);
1651 if (ret < 0) {
1652 dev_err(&i2c->dev, "wm8903: failed to register card\n");
1653 goto card_err;
1654 }
1655
1656 return ret;
1657
1658card_err:
1659 snd_soc_free_pcms(socdev);
1660 snd_soc_dapm_free(socdev);
1661pcm_err:
1662 kfree(codec->reg_cache);
1663 return ret;
1664}
1665
1666static struct snd_soc_device *wm8903_socdev;
1667
1668static int wm8903_i2c_probe(struct i2c_client *i2c,
1669 const struct i2c_device_id *id)
1670{
1671 struct snd_soc_device *socdev = wm8903_socdev;
1672 struct snd_soc_codec *codec = socdev->codec;
1673 int ret;
1674
1675 i2c_set_clientdata(i2c, codec);
1676 codec->control_data = i2c;
1677
1678 ret = wm8903_init(socdev);
1679 if (ret < 0)
1680 dev_err(&i2c->dev, "Device initialisation failed\n");
1681
1682 return ret;
1683}
1684
1685static int wm8903_i2c_remove(struct i2c_client *client)
1686{
1687 struct snd_soc_codec *codec = i2c_get_clientdata(client);
1688 kfree(codec->reg_cache);
1689 return 0;
1690}
1691
1692/* i2c codec control layer */
1693static const struct i2c_device_id wm8903_i2c_id[] = {
1694 { "wm8903", 0 },
1695 { }
1696};
1697MODULE_DEVICE_TABLE(i2c, wm8903_i2c_id);
1698
1699static struct i2c_driver wm8903_i2c_driver = {
1700 .driver = {
1701 .name = "WM8903",
1702 .owner = THIS_MODULE,
1703 },
1704 .probe = wm8903_i2c_probe,
1705 .remove = wm8903_i2c_remove,
1706 .id_table = wm8903_i2c_id,
1707};
1708
1709static int wm8903_probe(struct platform_device *pdev)
1710{
1711 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1712 struct wm8903_setup_data *setup;
1713 struct snd_soc_codec *codec;
1714 struct wm8903_priv *wm8903;
1715 struct i2c_board_info board_info;
1716 struct i2c_adapter *adapter;
1717 struct i2c_client *i2c_client;
1718 int ret = 0;
1719
1720 setup = socdev->codec_data;
1721
1722 if (!setup->i2c_address) {
1723 dev_err(&pdev->dev, "No codec address provided\n");
1724 return -ENODEV;
1725 }
1726
1727 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
1728 if (codec == NULL)
1729 return -ENOMEM;
1730
1731 wm8903 = kzalloc(sizeof(struct wm8903_priv), GFP_KERNEL);
1732 if (wm8903 == NULL) {
1733 ret = -ENOMEM;
1734 goto err_codec;
1735 }
1736
1737 codec->private_data = wm8903;
1738 socdev->codec = codec;
1739 mutex_init(&codec->mutex);
1740 INIT_LIST_HEAD(&codec->dapm_widgets);
1741 INIT_LIST_HEAD(&codec->dapm_paths);
1742
1743 wm8903_socdev = socdev;
1744
1745 codec->hw_write = (hw_write_t)i2c_master_send;
1746 ret = i2c_add_driver(&wm8903_i2c_driver);
1747 if (ret != 0) {
1748 dev_err(&pdev->dev, "can't add i2c driver\n");
1749 goto err_priv;
1750 } else {
1751 memset(&board_info, 0, sizeof(board_info));
1752 strlcpy(board_info.type, "wm8903", I2C_NAME_SIZE);
1753 board_info.addr = setup->i2c_address;
1754
1755 adapter = i2c_get_adapter(setup->i2c_bus);
1756 if (!adapter) {
1757 dev_err(&pdev->dev, "Can't get I2C bus %d\n",
1758 setup->i2c_bus);
1759 ret = -ENODEV;
1760 goto err_adapter;
1761 }
1762
1763 i2c_client = i2c_new_device(adapter, &board_info);
1764 i2c_put_adapter(adapter);
1765 if (i2c_client == NULL) {
1766 dev_err(&pdev->dev,
1767 "I2C driver registration failed\n");
1768 ret = -ENODEV;
1769 goto err_adapter;
1770 }
1771 }
1772
1773 return ret;
1774
1775err_adapter:
1776 i2c_del_driver(&wm8903_i2c_driver);
1777err_priv:
1778 kfree(codec->private_data);
1779err_codec:
1780 kfree(codec);
1781 return ret;
1782}
1783
1784/* power down chip */
1785static int wm8903_remove(struct platform_device *pdev)
1786{
1787 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1788 struct snd_soc_codec *codec = socdev->codec;
1789
1790 if (codec->control_data)
1791 wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF);
1792
1793 snd_soc_free_pcms(socdev);
1794 snd_soc_dapm_free(socdev);
1795 i2c_unregister_device(socdev->codec->control_data);
1796 i2c_del_driver(&wm8903_i2c_driver);
1797 kfree(codec->private_data);
1798 kfree(codec);
1799
1800 return 0;
1801}
1802
1803struct snd_soc_codec_device soc_codec_dev_wm8903 = {
1804 .probe = wm8903_probe,
1805 .remove = wm8903_remove,
1806 .suspend = wm8903_suspend,
1807 .resume = wm8903_resume,
1808};
1809EXPORT_SYMBOL_GPL(soc_codec_dev_wm8903);
1810
1811MODULE_DESCRIPTION("ASoC WM8903 driver");
1812MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.cm>");
1813MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8903.h b/sound/soc/codecs/wm8903.h
new file mode 100644
index 000000000000..cec622f2f660
--- /dev/null
+++ b/sound/soc/codecs/wm8903.h
@@ -0,0 +1,1463 @@
1/*
2 * wm8903.h - WM8903 audio codec interface
3 *
4 * Copyright 2008 Wolfson Microelectronics PLC.
5 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12
13#ifndef _WM8903_H
14#define _WM8903_H
15
16#include <linux/i2c.h>
17
18extern struct snd_soc_dai wm8903_dai;
19extern struct snd_soc_codec_device soc_codec_dev_wm8903;
20
21struct wm8903_setup_data {
22 int i2c_bus;
23 int i2c_address;
24};
25
26#define WM8903_MCLK_DIV_2 1
27#define WM8903_CLK_SYS 2
28#define WM8903_BCLK 3
29#define WM8903_LRCLK 4
30
31/*
32 * Register values.
33 */
34#define WM8903_SW_RESET_AND_ID 0x00
35#define WM8903_REVISION_NUMBER 0x01
36#define WM8903_BIAS_CONTROL_0 0x04
37#define WM8903_VMID_CONTROL_0 0x05
38#define WM8903_MIC_BIAS_CONTROL_0 0x06
39#define WM8903_ANALOGUE_DAC_0 0x08
40#define WM8903_ANALOGUE_ADC_0 0x0A
41#define WM8903_POWER_MANAGEMENT_0 0x0C
42#define WM8903_POWER_MANAGEMENT_1 0x0D
43#define WM8903_POWER_MANAGEMENT_2 0x0E
44#define WM8903_POWER_MANAGEMENT_3 0x0F
45#define WM8903_POWER_MANAGEMENT_4 0x10
46#define WM8903_POWER_MANAGEMENT_5 0x11
47#define WM8903_POWER_MANAGEMENT_6 0x12
48#define WM8903_CLOCK_RATES_0 0x14
49#define WM8903_CLOCK_RATES_1 0x15
50#define WM8903_CLOCK_RATES_2 0x16
51#define WM8903_AUDIO_INTERFACE_0 0x18
52#define WM8903_AUDIO_INTERFACE_1 0x19
53#define WM8903_AUDIO_INTERFACE_2 0x1A
54#define WM8903_AUDIO_INTERFACE_3 0x1B
55#define WM8903_DAC_DIGITAL_VOLUME_LEFT 0x1E
56#define WM8903_DAC_DIGITAL_VOLUME_RIGHT 0x1F
57#define WM8903_DAC_DIGITAL_0 0x20
58#define WM8903_DAC_DIGITAL_1 0x21
59#define WM8903_ADC_DIGITAL_VOLUME_LEFT 0x24
60#define WM8903_ADC_DIGITAL_VOLUME_RIGHT 0x25
61#define WM8903_ADC_DIGITAL_0 0x26
62#define WM8903_DIGITAL_MICROPHONE_0 0x27
63#define WM8903_DRC_0 0x28
64#define WM8903_DRC_1 0x29
65#define WM8903_DRC_2 0x2A
66#define WM8903_DRC_3 0x2B
67#define WM8903_ANALOGUE_LEFT_INPUT_0 0x2C
68#define WM8903_ANALOGUE_RIGHT_INPUT_0 0x2D
69#define WM8903_ANALOGUE_LEFT_INPUT_1 0x2E
70#define WM8903_ANALOGUE_RIGHT_INPUT_1 0x2F
71#define WM8903_ANALOGUE_LEFT_MIX_0 0x32
72#define WM8903_ANALOGUE_RIGHT_MIX_0 0x33
73#define WM8903_ANALOGUE_SPK_MIX_LEFT_0 0x34
74#define WM8903_ANALOGUE_SPK_MIX_LEFT_1 0x35
75#define WM8903_ANALOGUE_SPK_MIX_RIGHT_0 0x36
76#define WM8903_ANALOGUE_SPK_MIX_RIGHT_1 0x37
77#define WM8903_ANALOGUE_OUT1_LEFT 0x39
78#define WM8903_ANALOGUE_OUT1_RIGHT 0x3A
79#define WM8903_ANALOGUE_OUT2_LEFT 0x3B
80#define WM8903_ANALOGUE_OUT2_RIGHT 0x3C
81#define WM8903_ANALOGUE_OUT3_LEFT 0x3E
82#define WM8903_ANALOGUE_OUT3_RIGHT 0x3F
83#define WM8903_ANALOGUE_SPK_OUTPUT_CONTROL_0 0x41
84#define WM8903_DC_SERVO_0 0x43
85#define WM8903_DC_SERVO_2 0x45
86#define WM8903_ANALOGUE_HP_0 0x5A
87#define WM8903_ANALOGUE_LINEOUT_0 0x5E
88#define WM8903_CHARGE_PUMP_0 0x62
89#define WM8903_CLASS_W_0 0x68
90#define WM8903_WRITE_SEQUENCER_0 0x6C
91#define WM8903_WRITE_SEQUENCER_1 0x6D
92#define WM8903_WRITE_SEQUENCER_2 0x6E
93#define WM8903_WRITE_SEQUENCER_3 0x6F
94#define WM8903_WRITE_SEQUENCER_4 0x70
95#define WM8903_CONTROL_INTERFACE 0x72
96#define WM8903_GPIO_CONTROL_1 0x74
97#define WM8903_GPIO_CONTROL_2 0x75
98#define WM8903_GPIO_CONTROL_3 0x76
99#define WM8903_GPIO_CONTROL_4 0x77
100#define WM8903_GPIO_CONTROL_5 0x78
101#define WM8903_INTERRUPT_STATUS_1 0x79
102#define WM8903_INTERRUPT_STATUS_1_MASK 0x7A
103#define WM8903_INTERRUPT_POLARITY_1 0x7B
104#define WM8903_INTERRUPT_CONTROL 0x7E
105#define WM8903_CONTROL_INTERFACE_TEST_1 0x81
106#define WM8903_CHARGE_PUMP_TEST_1 0x95
107#define WM8903_CLOCK_RATE_TEST_4 0xA4
108#define WM8903_ANALOGUE_OUTPUT_BIAS_0 0xAC
109
110#define WM8903_REGISTER_COUNT 75
111#define WM8903_MAX_REGISTER 0xAC
112
113/*
114 * Field Definitions.
115 */
116
117/*
118 * R0 (0x00) - SW Reset and ID
119 */
120#define WM8903_SW_RESET_DEV_ID1_MASK 0xFFFF /* SW_RESET_DEV_ID1 - [15:0] */
121#define WM8903_SW_RESET_DEV_ID1_SHIFT 0 /* SW_RESET_DEV_ID1 - [15:0] */
122#define WM8903_SW_RESET_DEV_ID1_WIDTH 16 /* SW_RESET_DEV_ID1 - [15:0] */
123
124/*
125 * R1 (0x01) - Revision Number
126 */
127#define WM8903_CHIP_REV_MASK 0x000F /* CHIP_REV - [3:0] */
128#define WM8903_CHIP_REV_SHIFT 0 /* CHIP_REV - [3:0] */
129#define WM8903_CHIP_REV_WIDTH 4 /* CHIP_REV - [3:0] */
130
131/*
132 * R4 (0x04) - Bias Control 0
133 */
134#define WM8903_POBCTRL 0x0010 /* POBCTRL */
135#define WM8903_POBCTRL_MASK 0x0010 /* POBCTRL */
136#define WM8903_POBCTRL_SHIFT 4 /* POBCTRL */
137#define WM8903_POBCTRL_WIDTH 1 /* POBCTRL */
138#define WM8903_ISEL_MASK 0x000C /* ISEL - [3:2] */
139#define WM8903_ISEL_SHIFT 2 /* ISEL - [3:2] */
140#define WM8903_ISEL_WIDTH 2 /* ISEL - [3:2] */
141#define WM8903_STARTUP_BIAS_ENA 0x0002 /* STARTUP_BIAS_ENA */
142#define WM8903_STARTUP_BIAS_ENA_MASK 0x0002 /* STARTUP_BIAS_ENA */
143#define WM8903_STARTUP_BIAS_ENA_SHIFT 1 /* STARTUP_BIAS_ENA */
144#define WM8903_STARTUP_BIAS_ENA_WIDTH 1 /* STARTUP_BIAS_ENA */
145#define WM8903_BIAS_ENA 0x0001 /* BIAS_ENA */
146#define WM8903_BIAS_ENA_MASK 0x0001 /* BIAS_ENA */
147#define WM8903_BIAS_ENA_SHIFT 0 /* BIAS_ENA */
148#define WM8903_BIAS_ENA_WIDTH 1 /* BIAS_ENA */
149
150/*
151 * R5 (0x05) - VMID Control 0
152 */
153#define WM8903_VMID_TIE_ENA 0x0080 /* VMID_TIE_ENA */
154#define WM8903_VMID_TIE_ENA_MASK 0x0080 /* VMID_TIE_ENA */
155#define WM8903_VMID_TIE_ENA_SHIFT 7 /* VMID_TIE_ENA */
156#define WM8903_VMID_TIE_ENA_WIDTH 1 /* VMID_TIE_ENA */
157#define WM8903_BUFIO_ENA 0x0040 /* BUFIO_ENA */
158#define WM8903_BUFIO_ENA_MASK 0x0040 /* BUFIO_ENA */
159#define WM8903_BUFIO_ENA_SHIFT 6 /* BUFIO_ENA */
160#define WM8903_BUFIO_ENA_WIDTH 1 /* BUFIO_ENA */
161#define WM8903_VMID_IO_ENA 0x0020 /* VMID_IO_ENA */
162#define WM8903_VMID_IO_ENA_MASK 0x0020 /* VMID_IO_ENA */
163#define WM8903_VMID_IO_ENA_SHIFT 5 /* VMID_IO_ENA */
164#define WM8903_VMID_IO_ENA_WIDTH 1 /* VMID_IO_ENA */
165#define WM8903_VMID_SOFT_MASK 0x0018 /* VMID_SOFT - [4:3] */
166#define WM8903_VMID_SOFT_SHIFT 3 /* VMID_SOFT - [4:3] */
167#define WM8903_VMID_SOFT_WIDTH 2 /* VMID_SOFT - [4:3] */
168#define WM8903_VMID_RES_MASK 0x0006 /* VMID_RES - [2:1] */
169#define WM8903_VMID_RES_SHIFT 1 /* VMID_RES - [2:1] */
170#define WM8903_VMID_RES_WIDTH 2 /* VMID_RES - [2:1] */
171#define WM8903_VMID_BUF_ENA 0x0001 /* VMID_BUF_ENA */
172#define WM8903_VMID_BUF_ENA_MASK 0x0001 /* VMID_BUF_ENA */
173#define WM8903_VMID_BUF_ENA_SHIFT 0 /* VMID_BUF_ENA */
174#define WM8903_VMID_BUF_ENA_WIDTH 1 /* VMID_BUF_ENA */
175
176#define WM8903_VMID_RES_50K 2
177#define WM8903_VMID_RES_250K 3
178#define WM8903_VMID_RES_5K 4
179
180/*
181 * R6 (0x06) - Mic Bias Control 0
182 */
183#define WM8903_MICDET_HYST_ENA 0x0080 /* MICDET_HYST_ENA */
184#define WM8903_MICDET_HYST_ENA_MASK 0x0080 /* MICDET_HYST_ENA */
185#define WM8903_MICDET_HYST_ENA_SHIFT 7 /* MICDET_HYST_ENA */
186#define WM8903_MICDET_HYST_ENA_WIDTH 1 /* MICDET_HYST_ENA */
187#define WM8903_MICDET_THR_MASK 0x0070 /* MICDET_THR - [6:4] */
188#define WM8903_MICDET_THR_SHIFT 4 /* MICDET_THR - [6:4] */
189#define WM8903_MICDET_THR_WIDTH 3 /* MICDET_THR - [6:4] */
190#define WM8903_MICSHORT_THR_MASK 0x000C /* MICSHORT_THR - [3:2] */
191#define WM8903_MICSHORT_THR_SHIFT 2 /* MICSHORT_THR - [3:2] */
192#define WM8903_MICSHORT_THR_WIDTH 2 /* MICSHORT_THR - [3:2] */
193#define WM8903_MICDET_ENA 0x0002 /* MICDET_ENA */
194#define WM8903_MICDET_ENA_MASK 0x0002 /* MICDET_ENA */
195#define WM8903_MICDET_ENA_SHIFT 1 /* MICDET_ENA */
196#define WM8903_MICDET_ENA_WIDTH 1 /* MICDET_ENA */
197#define WM8903_MICBIAS_ENA 0x0001 /* MICBIAS_ENA */
198#define WM8903_MICBIAS_ENA_MASK 0x0001 /* MICBIAS_ENA */
199#define WM8903_MICBIAS_ENA_SHIFT 0 /* MICBIAS_ENA */
200#define WM8903_MICBIAS_ENA_WIDTH 1 /* MICBIAS_ENA */
201
202/*
203 * R8 (0x08) - Analogue DAC 0
204 */
205#define WM8903_DACBIAS_SEL_MASK 0x0018 /* DACBIAS_SEL - [4:3] */
206#define WM8903_DACBIAS_SEL_SHIFT 3 /* DACBIAS_SEL - [4:3] */
207#define WM8903_DACBIAS_SEL_WIDTH 2 /* DACBIAS_SEL - [4:3] */
208#define WM8903_DACVMID_BIAS_SEL_MASK 0x0006 /* DACVMID_BIAS_SEL - [2:1] */
209#define WM8903_DACVMID_BIAS_SEL_SHIFT 1 /* DACVMID_BIAS_SEL - [2:1] */
210#define WM8903_DACVMID_BIAS_SEL_WIDTH 2 /* DACVMID_BIAS_SEL - [2:1] */
211
212/*
213 * R10 (0x0A) - Analogue ADC 0
214 */
215#define WM8903_ADC_OSR128 0x0001 /* ADC_OSR128 */
216#define WM8903_ADC_OSR128_MASK 0x0001 /* ADC_OSR128 */
217#define WM8903_ADC_OSR128_SHIFT 0 /* ADC_OSR128 */
218#define WM8903_ADC_OSR128_WIDTH 1 /* ADC_OSR128 */
219
220/*
221 * R12 (0x0C) - Power Management 0
222 */
223#define WM8903_INL_ENA 0x0002 /* INL_ENA */
224#define WM8903_INL_ENA_MASK 0x0002 /* INL_ENA */
225#define WM8903_INL_ENA_SHIFT 1 /* INL_ENA */
226#define WM8903_INL_ENA_WIDTH 1 /* INL_ENA */
227#define WM8903_INR_ENA 0x0001 /* INR_ENA */
228#define WM8903_INR_ENA_MASK 0x0001 /* INR_ENA */
229#define WM8903_INR_ENA_SHIFT 0 /* INR_ENA */
230#define WM8903_INR_ENA_WIDTH 1 /* INR_ENA */
231
232/*
233 * R13 (0x0D) - Power Management 1
234 */
235#define WM8903_MIXOUTL_ENA 0x0002 /* MIXOUTL_ENA */
236#define WM8903_MIXOUTL_ENA_MASK 0x0002 /* MIXOUTL_ENA */
237#define WM8903_MIXOUTL_ENA_SHIFT 1 /* MIXOUTL_ENA */
238#define WM8903_MIXOUTL_ENA_WIDTH 1 /* MIXOUTL_ENA */
239#define WM8903_MIXOUTR_ENA 0x0001 /* MIXOUTR_ENA */
240#define WM8903_MIXOUTR_ENA_MASK 0x0001 /* MIXOUTR_ENA */
241#define WM8903_MIXOUTR_ENA_SHIFT 0 /* MIXOUTR_ENA */
242#define WM8903_MIXOUTR_ENA_WIDTH 1 /* MIXOUTR_ENA */
243
244/*
245 * R14 (0x0E) - Power Management 2
246 */
247#define WM8903_HPL_PGA_ENA 0x0002 /* HPL_PGA_ENA */
248#define WM8903_HPL_PGA_ENA_MASK 0x0002 /* HPL_PGA_ENA */
249#define WM8903_HPL_PGA_ENA_SHIFT 1 /* HPL_PGA_ENA */
250#define WM8903_HPL_PGA_ENA_WIDTH 1 /* HPL_PGA_ENA */
251#define WM8903_HPR_PGA_ENA 0x0001 /* HPR_PGA_ENA */
252#define WM8903_HPR_PGA_ENA_MASK 0x0001 /* HPR_PGA_ENA */
253#define WM8903_HPR_PGA_ENA_SHIFT 0 /* HPR_PGA_ENA */
254#define WM8903_HPR_PGA_ENA_WIDTH 1 /* HPR_PGA_ENA */
255
256/*
257 * R15 (0x0F) - Power Management 3
258 */
259#define WM8903_LINEOUTL_PGA_ENA 0x0002 /* LINEOUTL_PGA_ENA */
260#define WM8903_LINEOUTL_PGA_ENA_MASK 0x0002 /* LINEOUTL_PGA_ENA */
261#define WM8903_LINEOUTL_PGA_ENA_SHIFT 1 /* LINEOUTL_PGA_ENA */
262#define WM8903_LINEOUTL_PGA_ENA_WIDTH 1 /* LINEOUTL_PGA_ENA */
263#define WM8903_LINEOUTR_PGA_ENA 0x0001 /* LINEOUTR_PGA_ENA */
264#define WM8903_LINEOUTR_PGA_ENA_MASK 0x0001 /* LINEOUTR_PGA_ENA */
265#define WM8903_LINEOUTR_PGA_ENA_SHIFT 0 /* LINEOUTR_PGA_ENA */
266#define WM8903_LINEOUTR_PGA_ENA_WIDTH 1 /* LINEOUTR_PGA_ENA */
267
268/*
269 * R16 (0x10) - Power Management 4
270 */
271#define WM8903_MIXSPKL_ENA 0x0002 /* MIXSPKL_ENA */
272#define WM8903_MIXSPKL_ENA_MASK 0x0002 /* MIXSPKL_ENA */
273#define WM8903_MIXSPKL_ENA_SHIFT 1 /* MIXSPKL_ENA */
274#define WM8903_MIXSPKL_ENA_WIDTH 1 /* MIXSPKL_ENA */
275#define WM8903_MIXSPKR_ENA 0x0001 /* MIXSPKR_ENA */
276#define WM8903_MIXSPKR_ENA_MASK 0x0001 /* MIXSPKR_ENA */
277#define WM8903_MIXSPKR_ENA_SHIFT 0 /* MIXSPKR_ENA */
278#define WM8903_MIXSPKR_ENA_WIDTH 1 /* MIXSPKR_ENA */
279
280/*
281 * R17 (0x11) - Power Management 5
282 */
283#define WM8903_SPKL_ENA 0x0002 /* SPKL_ENA */
284#define WM8903_SPKL_ENA_MASK 0x0002 /* SPKL_ENA */
285#define WM8903_SPKL_ENA_SHIFT 1 /* SPKL_ENA */
286#define WM8903_SPKL_ENA_WIDTH 1 /* SPKL_ENA */
287#define WM8903_SPKR_ENA 0x0001 /* SPKR_ENA */
288#define WM8903_SPKR_ENA_MASK 0x0001 /* SPKR_ENA */
289#define WM8903_SPKR_ENA_SHIFT 0 /* SPKR_ENA */
290#define WM8903_SPKR_ENA_WIDTH 1 /* SPKR_ENA */
291
292/*
293 * R18 (0x12) - Power Management 6
294 */
295#define WM8903_DACL_ENA 0x0008 /* DACL_ENA */
296#define WM8903_DACL_ENA_MASK 0x0008 /* DACL_ENA */
297#define WM8903_DACL_ENA_SHIFT 3 /* DACL_ENA */
298#define WM8903_DACL_ENA_WIDTH 1 /* DACL_ENA */
299#define WM8903_DACR_ENA 0x0004 /* DACR_ENA */
300#define WM8903_DACR_ENA_MASK 0x0004 /* DACR_ENA */
301#define WM8903_DACR_ENA_SHIFT 2 /* DACR_ENA */
302#define WM8903_DACR_ENA_WIDTH 1 /* DACR_ENA */
303#define WM8903_ADCL_ENA 0x0002 /* ADCL_ENA */
304#define WM8903_ADCL_ENA_MASK 0x0002 /* ADCL_ENA */
305#define WM8903_ADCL_ENA_SHIFT 1 /* ADCL_ENA */
306#define WM8903_ADCL_ENA_WIDTH 1 /* ADCL_ENA */
307#define WM8903_ADCR_ENA 0x0001 /* ADCR_ENA */
308#define WM8903_ADCR_ENA_MASK 0x0001 /* ADCR_ENA */
309#define WM8903_ADCR_ENA_SHIFT 0 /* ADCR_ENA */
310#define WM8903_ADCR_ENA_WIDTH 1 /* ADCR_ENA */
311
312/*
313 * R20 (0x14) - Clock Rates 0
314 */
315#define WM8903_MCLKDIV2 0x0001 /* MCLKDIV2 */
316#define WM8903_MCLKDIV2_MASK 0x0001 /* MCLKDIV2 */
317#define WM8903_MCLKDIV2_SHIFT 0 /* MCLKDIV2 */
318#define WM8903_MCLKDIV2_WIDTH 1 /* MCLKDIV2 */
319
320/*
321 * R21 (0x15) - Clock Rates 1
322 */
323#define WM8903_CLK_SYS_RATE_MASK 0x3C00 /* CLK_SYS_RATE - [13:10] */
324#define WM8903_CLK_SYS_RATE_SHIFT 10 /* CLK_SYS_RATE - [13:10] */
325#define WM8903_CLK_SYS_RATE_WIDTH 4 /* CLK_SYS_RATE - [13:10] */
326#define WM8903_CLK_SYS_MODE_MASK 0x0300 /* CLK_SYS_MODE - [9:8] */
327#define WM8903_CLK_SYS_MODE_SHIFT 8 /* CLK_SYS_MODE - [9:8] */
328#define WM8903_CLK_SYS_MODE_WIDTH 2 /* CLK_SYS_MODE - [9:8] */
329#define WM8903_SAMPLE_RATE_MASK 0x000F /* SAMPLE_RATE - [3:0] */
330#define WM8903_SAMPLE_RATE_SHIFT 0 /* SAMPLE_RATE - [3:0] */
331#define WM8903_SAMPLE_RATE_WIDTH 4 /* SAMPLE_RATE - [3:0] */
332
333/*
334 * R22 (0x16) - Clock Rates 2
335 */
336#define WM8903_CLK_SYS_ENA 0x0004 /* CLK_SYS_ENA */
337#define WM8903_CLK_SYS_ENA_MASK 0x0004 /* CLK_SYS_ENA */
338#define WM8903_CLK_SYS_ENA_SHIFT 2 /* CLK_SYS_ENA */
339#define WM8903_CLK_SYS_ENA_WIDTH 1 /* CLK_SYS_ENA */
340#define WM8903_CLK_DSP_ENA 0x0002 /* CLK_DSP_ENA */
341#define WM8903_CLK_DSP_ENA_MASK 0x0002 /* CLK_DSP_ENA */
342#define WM8903_CLK_DSP_ENA_SHIFT 1 /* CLK_DSP_ENA */
343#define WM8903_CLK_DSP_ENA_WIDTH 1 /* CLK_DSP_ENA */
344#define WM8903_TO_ENA 0x0001 /* TO_ENA */
345#define WM8903_TO_ENA_MASK 0x0001 /* TO_ENA */
346#define WM8903_TO_ENA_SHIFT 0 /* TO_ENA */
347#define WM8903_TO_ENA_WIDTH 1 /* TO_ENA */
348
349/*
350 * R24 (0x18) - Audio Interface 0
351 */
352#define WM8903_DACL_DATINV 0x1000 /* DACL_DATINV */
353#define WM8903_DACL_DATINV_MASK 0x1000 /* DACL_DATINV */
354#define WM8903_DACL_DATINV_SHIFT 12 /* DACL_DATINV */
355#define WM8903_DACL_DATINV_WIDTH 1 /* DACL_DATINV */
356#define WM8903_DACR_DATINV 0x0800 /* DACR_DATINV */
357#define WM8903_DACR_DATINV_MASK 0x0800 /* DACR_DATINV */
358#define WM8903_DACR_DATINV_SHIFT 11 /* DACR_DATINV */
359#define WM8903_DACR_DATINV_WIDTH 1 /* DACR_DATINV */
360#define WM8903_DAC_BOOST_MASK 0x0600 /* DAC_BOOST - [10:9] */
361#define WM8903_DAC_BOOST_SHIFT 9 /* DAC_BOOST - [10:9] */
362#define WM8903_DAC_BOOST_WIDTH 2 /* DAC_BOOST - [10:9] */
363#define WM8903_LOOPBACK 0x0100 /* LOOPBACK */
364#define WM8903_LOOPBACK_MASK 0x0100 /* LOOPBACK */
365#define WM8903_LOOPBACK_SHIFT 8 /* LOOPBACK */
366#define WM8903_LOOPBACK_WIDTH 1 /* LOOPBACK */
367#define WM8903_AIFADCL_SRC 0x0080 /* AIFADCL_SRC */
368#define WM8903_AIFADCL_SRC_MASK 0x0080 /* AIFADCL_SRC */
369#define WM8903_AIFADCL_SRC_SHIFT 7 /* AIFADCL_SRC */
370#define WM8903_AIFADCL_SRC_WIDTH 1 /* AIFADCL_SRC */
371#define WM8903_AIFADCR_SRC 0x0040 /* AIFADCR_SRC */
372#define WM8903_AIFADCR_SRC_MASK 0x0040 /* AIFADCR_SRC */
373#define WM8903_AIFADCR_SRC_SHIFT 6 /* AIFADCR_SRC */
374#define WM8903_AIFADCR_SRC_WIDTH 1 /* AIFADCR_SRC */
375#define WM8903_AIFDACL_SRC 0x0020 /* AIFDACL_SRC */
376#define WM8903_AIFDACL_SRC_MASK 0x0020 /* AIFDACL_SRC */
377#define WM8903_AIFDACL_SRC_SHIFT 5 /* AIFDACL_SRC */
378#define WM8903_AIFDACL_SRC_WIDTH 1 /* AIFDACL_SRC */
379#define WM8903_AIFDACR_SRC 0x0010 /* AIFDACR_SRC */
380#define WM8903_AIFDACR_SRC_MASK 0x0010 /* AIFDACR_SRC */
381#define WM8903_AIFDACR_SRC_SHIFT 4 /* AIFDACR_SRC */
382#define WM8903_AIFDACR_SRC_WIDTH 1 /* AIFDACR_SRC */
383#define WM8903_ADC_COMP 0x0008 /* ADC_COMP */
384#define WM8903_ADC_COMP_MASK 0x0008 /* ADC_COMP */
385#define WM8903_ADC_COMP_SHIFT 3 /* ADC_COMP */
386#define WM8903_ADC_COMP_WIDTH 1 /* ADC_COMP */
387#define WM8903_ADC_COMPMODE 0x0004 /* ADC_COMPMODE */
388#define WM8903_ADC_COMPMODE_MASK 0x0004 /* ADC_COMPMODE */
389#define WM8903_ADC_COMPMODE_SHIFT 2 /* ADC_COMPMODE */
390#define WM8903_ADC_COMPMODE_WIDTH 1 /* ADC_COMPMODE */
391#define WM8903_DAC_COMP 0x0002 /* DAC_COMP */
392#define WM8903_DAC_COMP_MASK 0x0002 /* DAC_COMP */
393#define WM8903_DAC_COMP_SHIFT 1 /* DAC_COMP */
394#define WM8903_DAC_COMP_WIDTH 1 /* DAC_COMP */
395#define WM8903_DAC_COMPMODE 0x0001 /* DAC_COMPMODE */
396#define WM8903_DAC_COMPMODE_MASK 0x0001 /* DAC_COMPMODE */
397#define WM8903_DAC_COMPMODE_SHIFT 0 /* DAC_COMPMODE */
398#define WM8903_DAC_COMPMODE_WIDTH 1 /* DAC_COMPMODE */
399
400/*
401 * R25 (0x19) - Audio Interface 1
402 */
403#define WM8903_AIFDAC_TDM 0x2000 /* AIFDAC_TDM */
404#define WM8903_AIFDAC_TDM_MASK 0x2000 /* AIFDAC_TDM */
405#define WM8903_AIFDAC_TDM_SHIFT 13 /* AIFDAC_TDM */
406#define WM8903_AIFDAC_TDM_WIDTH 1 /* AIFDAC_TDM */
407#define WM8903_AIFDAC_TDM_CHAN 0x1000 /* AIFDAC_TDM_CHAN */
408#define WM8903_AIFDAC_TDM_CHAN_MASK 0x1000 /* AIFDAC_TDM_CHAN */
409#define WM8903_AIFDAC_TDM_CHAN_SHIFT 12 /* AIFDAC_TDM_CHAN */
410#define WM8903_AIFDAC_TDM_CHAN_WIDTH 1 /* AIFDAC_TDM_CHAN */
411#define WM8903_AIFADC_TDM 0x0800 /* AIFADC_TDM */
412#define WM8903_AIFADC_TDM_MASK 0x0800 /* AIFADC_TDM */
413#define WM8903_AIFADC_TDM_SHIFT 11 /* AIFADC_TDM */
414#define WM8903_AIFADC_TDM_WIDTH 1 /* AIFADC_TDM */
415#define WM8903_AIFADC_TDM_CHAN 0x0400 /* AIFADC_TDM_CHAN */
416#define WM8903_AIFADC_TDM_CHAN_MASK 0x0400 /* AIFADC_TDM_CHAN */
417#define WM8903_AIFADC_TDM_CHAN_SHIFT 10 /* AIFADC_TDM_CHAN */
418#define WM8903_AIFADC_TDM_CHAN_WIDTH 1 /* AIFADC_TDM_CHAN */
419#define WM8903_LRCLK_DIR 0x0200 /* LRCLK_DIR */
420#define WM8903_LRCLK_DIR_MASK 0x0200 /* LRCLK_DIR */
421#define WM8903_LRCLK_DIR_SHIFT 9 /* LRCLK_DIR */
422#define WM8903_LRCLK_DIR_WIDTH 1 /* LRCLK_DIR */
423#define WM8903_AIF_BCLK_INV 0x0080 /* AIF_BCLK_INV */
424#define WM8903_AIF_BCLK_INV_MASK 0x0080 /* AIF_BCLK_INV */
425#define WM8903_AIF_BCLK_INV_SHIFT 7 /* AIF_BCLK_INV */
426#define WM8903_AIF_BCLK_INV_WIDTH 1 /* AIF_BCLK_INV */
427#define WM8903_BCLK_DIR 0x0040 /* BCLK_DIR */
428#define WM8903_BCLK_DIR_MASK 0x0040 /* BCLK_DIR */
429#define WM8903_BCLK_DIR_SHIFT 6 /* BCLK_DIR */
430#define WM8903_BCLK_DIR_WIDTH 1 /* BCLK_DIR */
431#define WM8903_AIF_LRCLK_INV 0x0010 /* AIF_LRCLK_INV */
432#define WM8903_AIF_LRCLK_INV_MASK 0x0010 /* AIF_LRCLK_INV */
433#define WM8903_AIF_LRCLK_INV_SHIFT 4 /* AIF_LRCLK_INV */
434#define WM8903_AIF_LRCLK_INV_WIDTH 1 /* AIF_LRCLK_INV */
435#define WM8903_AIF_WL_MASK 0x000C /* AIF_WL - [3:2] */
436#define WM8903_AIF_WL_SHIFT 2 /* AIF_WL - [3:2] */
437#define WM8903_AIF_WL_WIDTH 2 /* AIF_WL - [3:2] */
438#define WM8903_AIF_FMT_MASK 0x0003 /* AIF_FMT - [1:0] */
439#define WM8903_AIF_FMT_SHIFT 0 /* AIF_FMT - [1:0] */
440#define WM8903_AIF_FMT_WIDTH 2 /* AIF_FMT - [1:0] */
441
442/*
443 * R26 (0x1A) - Audio Interface 2
444 */
445#define WM8903_BCLK_DIV_MASK 0x001F /* BCLK_DIV - [4:0] */
446#define WM8903_BCLK_DIV_SHIFT 0 /* BCLK_DIV - [4:0] */
447#define WM8903_BCLK_DIV_WIDTH 5 /* BCLK_DIV - [4:0] */
448
449/*
450 * R27 (0x1B) - Audio Interface 3
451 */
452#define WM8903_LRCLK_RATE_MASK 0x07FF /* LRCLK_RATE - [10:0] */
453#define WM8903_LRCLK_RATE_SHIFT 0 /* LRCLK_RATE - [10:0] */
454#define WM8903_LRCLK_RATE_WIDTH 11 /* LRCLK_RATE - [10:0] */
455
456/*
457 * R30 (0x1E) - DAC Digital Volume Left
458 */
459#define WM8903_DACVU 0x0100 /* DACVU */
460#define WM8903_DACVU_MASK 0x0100 /* DACVU */
461#define WM8903_DACVU_SHIFT 8 /* DACVU */
462#define WM8903_DACVU_WIDTH 1 /* DACVU */
463#define WM8903_DACL_VOL_MASK 0x00FF /* DACL_VOL - [7:0] */
464#define WM8903_DACL_VOL_SHIFT 0 /* DACL_VOL - [7:0] */
465#define WM8903_DACL_VOL_WIDTH 8 /* DACL_VOL - [7:0] */
466
467/*
468 * R31 (0x1F) - DAC Digital Volume Right
469 */
470#define WM8903_DACVU 0x0100 /* DACVU */
471#define WM8903_DACVU_MASK 0x0100 /* DACVU */
472#define WM8903_DACVU_SHIFT 8 /* DACVU */
473#define WM8903_DACVU_WIDTH 1 /* DACVU */
474#define WM8903_DACR_VOL_MASK 0x00FF /* DACR_VOL - [7:0] */
475#define WM8903_DACR_VOL_SHIFT 0 /* DACR_VOL - [7:0] */
476#define WM8903_DACR_VOL_WIDTH 8 /* DACR_VOL - [7:0] */
477
478/*
479 * R32 (0x20) - DAC Digital 0
480 */
481#define WM8903_ADCL_DAC_SVOL_MASK 0x0F00 /* ADCL_DAC_SVOL - [11:8] */
482#define WM8903_ADCL_DAC_SVOL_SHIFT 8 /* ADCL_DAC_SVOL - [11:8] */
483#define WM8903_ADCL_DAC_SVOL_WIDTH 4 /* ADCL_DAC_SVOL - [11:8] */
484#define WM8903_ADCR_DAC_SVOL_MASK 0x00F0 /* ADCR_DAC_SVOL - [7:4] */
485#define WM8903_ADCR_DAC_SVOL_SHIFT 4 /* ADCR_DAC_SVOL - [7:4] */
486#define WM8903_ADCR_DAC_SVOL_WIDTH 4 /* ADCR_DAC_SVOL - [7:4] */
487#define WM8903_ADC_TO_DACL_MASK 0x000C /* ADC_TO_DACL - [3:2] */
488#define WM8903_ADC_TO_DACL_SHIFT 2 /* ADC_TO_DACL - [3:2] */
489#define WM8903_ADC_TO_DACL_WIDTH 2 /* ADC_TO_DACL - [3:2] */
490#define WM8903_ADC_TO_DACR_MASK 0x0003 /* ADC_TO_DACR - [1:0] */
491#define WM8903_ADC_TO_DACR_SHIFT 0 /* ADC_TO_DACR - [1:0] */
492#define WM8903_ADC_TO_DACR_WIDTH 2 /* ADC_TO_DACR - [1:0] */
493
494/*
495 * R33 (0x21) - DAC Digital 1
496 */
497#define WM8903_DAC_MONO 0x1000 /* DAC_MONO */
498#define WM8903_DAC_MONO_MASK 0x1000 /* DAC_MONO */
499#define WM8903_DAC_MONO_SHIFT 12 /* DAC_MONO */
500#define WM8903_DAC_MONO_WIDTH 1 /* DAC_MONO */
501#define WM8903_DAC_SB_FILT 0x0800 /* DAC_SB_FILT */
502#define WM8903_DAC_SB_FILT_MASK 0x0800 /* DAC_SB_FILT */
503#define WM8903_DAC_SB_FILT_SHIFT 11 /* DAC_SB_FILT */
504#define WM8903_DAC_SB_FILT_WIDTH 1 /* DAC_SB_FILT */
505#define WM8903_DAC_MUTERATE 0x0400 /* DAC_MUTERATE */
506#define WM8903_DAC_MUTERATE_MASK 0x0400 /* DAC_MUTERATE */
507#define WM8903_DAC_MUTERATE_SHIFT 10 /* DAC_MUTERATE */
508#define WM8903_DAC_MUTERATE_WIDTH 1 /* DAC_MUTERATE */
509#define WM8903_DAC_MUTEMODE 0x0200 /* DAC_MUTEMODE */
510#define WM8903_DAC_MUTEMODE_MASK 0x0200 /* DAC_MUTEMODE */
511#define WM8903_DAC_MUTEMODE_SHIFT 9 /* DAC_MUTEMODE */
512#define WM8903_DAC_MUTEMODE_WIDTH 1 /* DAC_MUTEMODE */
513#define WM8903_DAC_MUTE 0x0008 /* DAC_MUTE */
514#define WM8903_DAC_MUTE_MASK 0x0008 /* DAC_MUTE */
515#define WM8903_DAC_MUTE_SHIFT 3 /* DAC_MUTE */
516#define WM8903_DAC_MUTE_WIDTH 1 /* DAC_MUTE */
517#define WM8903_DEEMPH_MASK 0x0006 /* DEEMPH - [2:1] */
518#define WM8903_DEEMPH_SHIFT 1 /* DEEMPH - [2:1] */
519#define WM8903_DEEMPH_WIDTH 2 /* DEEMPH - [2:1] */
520
521/*
522 * R36 (0x24) - ADC Digital Volume Left
523 */
524#define WM8903_ADCVU 0x0100 /* ADCVU */
525#define WM8903_ADCVU_MASK 0x0100 /* ADCVU */
526#define WM8903_ADCVU_SHIFT 8 /* ADCVU */
527#define WM8903_ADCVU_WIDTH 1 /* ADCVU */
528#define WM8903_ADCL_VOL_MASK 0x00FF /* ADCL_VOL - [7:0] */
529#define WM8903_ADCL_VOL_SHIFT 0 /* ADCL_VOL - [7:0] */
530#define WM8903_ADCL_VOL_WIDTH 8 /* ADCL_VOL - [7:0] */
531
532/*
533 * R37 (0x25) - ADC Digital Volume Right
534 */
535#define WM8903_ADCVU 0x0100 /* ADCVU */
536#define WM8903_ADCVU_MASK 0x0100 /* ADCVU */
537#define WM8903_ADCVU_SHIFT 8 /* ADCVU */
538#define WM8903_ADCVU_WIDTH 1 /* ADCVU */
539#define WM8903_ADCR_VOL_MASK 0x00FF /* ADCR_VOL - [7:0] */
540#define WM8903_ADCR_VOL_SHIFT 0 /* ADCR_VOL - [7:0] */
541#define WM8903_ADCR_VOL_WIDTH 8 /* ADCR_VOL - [7:0] */
542
543/*
544 * R38 (0x26) - ADC Digital 0
545 */
546#define WM8903_ADC_HPF_CUT_MASK 0x0060 /* ADC_HPF_CUT - [6:5] */
547#define WM8903_ADC_HPF_CUT_SHIFT 5 /* ADC_HPF_CUT - [6:5] */
548#define WM8903_ADC_HPF_CUT_WIDTH 2 /* ADC_HPF_CUT - [6:5] */
549#define WM8903_ADC_HPF_ENA 0x0010 /* ADC_HPF_ENA */
550#define WM8903_ADC_HPF_ENA_MASK 0x0010 /* ADC_HPF_ENA */
551#define WM8903_ADC_HPF_ENA_SHIFT 4 /* ADC_HPF_ENA */
552#define WM8903_ADC_HPF_ENA_WIDTH 1 /* ADC_HPF_ENA */
553#define WM8903_ADCL_DATINV 0x0002 /* ADCL_DATINV */
554#define WM8903_ADCL_DATINV_MASK 0x0002 /* ADCL_DATINV */
555#define WM8903_ADCL_DATINV_SHIFT 1 /* ADCL_DATINV */
556#define WM8903_ADCL_DATINV_WIDTH 1 /* ADCL_DATINV */
557#define WM8903_ADCR_DATINV 0x0001 /* ADCR_DATINV */
558#define WM8903_ADCR_DATINV_MASK 0x0001 /* ADCR_DATINV */
559#define WM8903_ADCR_DATINV_SHIFT 0 /* ADCR_DATINV */
560#define WM8903_ADCR_DATINV_WIDTH 1 /* ADCR_DATINV */
561
562/*
563 * R39 (0x27) - Digital Microphone 0
564 */
565#define WM8903_DIGMIC_MODE_SEL 0x0100 /* DIGMIC_MODE_SEL */
566#define WM8903_DIGMIC_MODE_SEL_MASK 0x0100 /* DIGMIC_MODE_SEL */
567#define WM8903_DIGMIC_MODE_SEL_SHIFT 8 /* DIGMIC_MODE_SEL */
568#define WM8903_DIGMIC_MODE_SEL_WIDTH 1 /* DIGMIC_MODE_SEL */
569#define WM8903_DIGMIC_CLK_SEL_L_MASK 0x00C0 /* DIGMIC_CLK_SEL_L - [7:6] */
570#define WM8903_DIGMIC_CLK_SEL_L_SHIFT 6 /* DIGMIC_CLK_SEL_L - [7:6] */
571#define WM8903_DIGMIC_CLK_SEL_L_WIDTH 2 /* DIGMIC_CLK_SEL_L - [7:6] */
572#define WM8903_DIGMIC_CLK_SEL_R_MASK 0x0030 /* DIGMIC_CLK_SEL_R - [5:4] */
573#define WM8903_DIGMIC_CLK_SEL_R_SHIFT 4 /* DIGMIC_CLK_SEL_R - [5:4] */
574#define WM8903_DIGMIC_CLK_SEL_R_WIDTH 2 /* DIGMIC_CLK_SEL_R - [5:4] */
575#define WM8903_DIGMIC_CLK_SEL_RT_MASK 0x000C /* DIGMIC_CLK_SEL_RT - [3:2] */
576#define WM8903_DIGMIC_CLK_SEL_RT_SHIFT 2 /* DIGMIC_CLK_SEL_RT - [3:2] */
577#define WM8903_DIGMIC_CLK_SEL_RT_WIDTH 2 /* DIGMIC_CLK_SEL_RT - [3:2] */
578#define WM8903_DIGMIC_CLK_SEL_MASK 0x0003 /* DIGMIC_CLK_SEL - [1:0] */
579#define WM8903_DIGMIC_CLK_SEL_SHIFT 0 /* DIGMIC_CLK_SEL - [1:0] */
580#define WM8903_DIGMIC_CLK_SEL_WIDTH 2 /* DIGMIC_CLK_SEL - [1:0] */
581
582/*
583 * R40 (0x28) - DRC 0
584 */
585#define WM8903_DRC_ENA 0x8000 /* DRC_ENA */
586#define WM8903_DRC_ENA_MASK 0x8000 /* DRC_ENA */
587#define WM8903_DRC_ENA_SHIFT 15 /* DRC_ENA */
588#define WM8903_DRC_ENA_WIDTH 1 /* DRC_ENA */
589#define WM8903_DRC_THRESH_HYST_MASK 0x1800 /* DRC_THRESH_HYST - [12:11] */
590#define WM8903_DRC_THRESH_HYST_SHIFT 11 /* DRC_THRESH_HYST - [12:11] */
591#define WM8903_DRC_THRESH_HYST_WIDTH 2 /* DRC_THRESH_HYST - [12:11] */
592#define WM8903_DRC_STARTUP_GAIN_MASK 0x07C0 /* DRC_STARTUP_GAIN - [10:6] */
593#define WM8903_DRC_STARTUP_GAIN_SHIFT 6 /* DRC_STARTUP_GAIN - [10:6] */
594#define WM8903_DRC_STARTUP_GAIN_WIDTH 5 /* DRC_STARTUP_GAIN - [10:6] */
595#define WM8903_DRC_FF_DELAY 0x0020 /* DRC_FF_DELAY */
596#define WM8903_DRC_FF_DELAY_MASK 0x0020 /* DRC_FF_DELAY */
597#define WM8903_DRC_FF_DELAY_SHIFT 5 /* DRC_FF_DELAY */
598#define WM8903_DRC_FF_DELAY_WIDTH 1 /* DRC_FF_DELAY */
599#define WM8903_DRC_SMOOTH_ENA 0x0008 /* DRC_SMOOTH_ENA */
600#define WM8903_DRC_SMOOTH_ENA_MASK 0x0008 /* DRC_SMOOTH_ENA */
601#define WM8903_DRC_SMOOTH_ENA_SHIFT 3 /* DRC_SMOOTH_ENA */
602#define WM8903_DRC_SMOOTH_ENA_WIDTH 1 /* DRC_SMOOTH_ENA */
603#define WM8903_DRC_QR_ENA 0x0004 /* DRC_QR_ENA */
604#define WM8903_DRC_QR_ENA_MASK 0x0004 /* DRC_QR_ENA */
605#define WM8903_DRC_QR_ENA_SHIFT 2 /* DRC_QR_ENA */
606#define WM8903_DRC_QR_ENA_WIDTH 1 /* DRC_QR_ENA */
607#define WM8903_DRC_ANTICLIP_ENA 0x0002 /* DRC_ANTICLIP_ENA */
608#define WM8903_DRC_ANTICLIP_ENA_MASK 0x0002 /* DRC_ANTICLIP_ENA */
609#define WM8903_DRC_ANTICLIP_ENA_SHIFT 1 /* DRC_ANTICLIP_ENA */
610#define WM8903_DRC_ANTICLIP_ENA_WIDTH 1 /* DRC_ANTICLIP_ENA */
611#define WM8903_DRC_HYST_ENA 0x0001 /* DRC_HYST_ENA */
612#define WM8903_DRC_HYST_ENA_MASK 0x0001 /* DRC_HYST_ENA */
613#define WM8903_DRC_HYST_ENA_SHIFT 0 /* DRC_HYST_ENA */
614#define WM8903_DRC_HYST_ENA_WIDTH 1 /* DRC_HYST_ENA */
615
616/*
617 * R41 (0x29) - DRC 1
618 */
619#define WM8903_DRC_ATTACK_RATE_MASK 0xF000 /* DRC_ATTACK_RATE - [15:12] */
620#define WM8903_DRC_ATTACK_RATE_SHIFT 12 /* DRC_ATTACK_RATE - [15:12] */
621#define WM8903_DRC_ATTACK_RATE_WIDTH 4 /* DRC_ATTACK_RATE - [15:12] */
622#define WM8903_DRC_DECAY_RATE_MASK 0x0F00 /* DRC_DECAY_RATE - [11:8] */
623#define WM8903_DRC_DECAY_RATE_SHIFT 8 /* DRC_DECAY_RATE - [11:8] */
624#define WM8903_DRC_DECAY_RATE_WIDTH 4 /* DRC_DECAY_RATE - [11:8] */
625#define WM8903_DRC_THRESH_QR_MASK 0x00C0 /* DRC_THRESH_QR - [7:6] */
626#define WM8903_DRC_THRESH_QR_SHIFT 6 /* DRC_THRESH_QR - [7:6] */
627#define WM8903_DRC_THRESH_QR_WIDTH 2 /* DRC_THRESH_QR - [7:6] */
628#define WM8903_DRC_RATE_QR_MASK 0x0030 /* DRC_RATE_QR - [5:4] */
629#define WM8903_DRC_RATE_QR_SHIFT 4 /* DRC_RATE_QR - [5:4] */
630#define WM8903_DRC_RATE_QR_WIDTH 2 /* DRC_RATE_QR - [5:4] */
631#define WM8903_DRC_MINGAIN_MASK 0x000C /* DRC_MINGAIN - [3:2] */
632#define WM8903_DRC_MINGAIN_SHIFT 2 /* DRC_MINGAIN - [3:2] */
633#define WM8903_DRC_MINGAIN_WIDTH 2 /* DRC_MINGAIN - [3:2] */
634#define WM8903_DRC_MAXGAIN_MASK 0x0003 /* DRC_MAXGAIN - [1:0] */
635#define WM8903_DRC_MAXGAIN_SHIFT 0 /* DRC_MAXGAIN - [1:0] */
636#define WM8903_DRC_MAXGAIN_WIDTH 2 /* DRC_MAXGAIN - [1:0] */
637
638/*
639 * R42 (0x2A) - DRC 2
640 */
641#define WM8903_DRC_R0_SLOPE_COMP_MASK 0x0038 /* DRC_R0_SLOPE_COMP - [5:3] */
642#define WM8903_DRC_R0_SLOPE_COMP_SHIFT 3 /* DRC_R0_SLOPE_COMP - [5:3] */
643#define WM8903_DRC_R0_SLOPE_COMP_WIDTH 3 /* DRC_R0_SLOPE_COMP - [5:3] */
644#define WM8903_DRC_R1_SLOPE_COMP_MASK 0x0007 /* DRC_R1_SLOPE_COMP - [2:0] */
645#define WM8903_DRC_R1_SLOPE_COMP_SHIFT 0 /* DRC_R1_SLOPE_COMP - [2:0] */
646#define WM8903_DRC_R1_SLOPE_COMP_WIDTH 3 /* DRC_R1_SLOPE_COMP - [2:0] */
647
648/*
649 * R43 (0x2B) - DRC 3
650 */
651#define WM8903_DRC_THRESH_COMP_MASK 0x07E0 /* DRC_THRESH_COMP - [10:5] */
652#define WM8903_DRC_THRESH_COMP_SHIFT 5 /* DRC_THRESH_COMP - [10:5] */
653#define WM8903_DRC_THRESH_COMP_WIDTH 6 /* DRC_THRESH_COMP - [10:5] */
654#define WM8903_DRC_AMP_COMP_MASK 0x001F /* DRC_AMP_COMP - [4:0] */
655#define WM8903_DRC_AMP_COMP_SHIFT 0 /* DRC_AMP_COMP - [4:0] */
656#define WM8903_DRC_AMP_COMP_WIDTH 5 /* DRC_AMP_COMP - [4:0] */
657
658/*
659 * R44 (0x2C) - Analogue Left Input 0
660 */
661#define WM8903_LINMUTE 0x0080 /* LINMUTE */
662#define WM8903_LINMUTE_MASK 0x0080 /* LINMUTE */
663#define WM8903_LINMUTE_SHIFT 7 /* LINMUTE */
664#define WM8903_LINMUTE_WIDTH 1 /* LINMUTE */
665#define WM8903_LIN_VOL_MASK 0x001F /* LIN_VOL - [4:0] */
666#define WM8903_LIN_VOL_SHIFT 0 /* LIN_VOL - [4:0] */
667#define WM8903_LIN_VOL_WIDTH 5 /* LIN_VOL - [4:0] */
668
669/*
670 * R45 (0x2D) - Analogue Right Input 0
671 */
672#define WM8903_RINMUTE 0x0080 /* RINMUTE */
673#define WM8903_RINMUTE_MASK 0x0080 /* RINMUTE */
674#define WM8903_RINMUTE_SHIFT 7 /* RINMUTE */
675#define WM8903_RINMUTE_WIDTH 1 /* RINMUTE */
676#define WM8903_RIN_VOL_MASK 0x001F /* RIN_VOL - [4:0] */
677#define WM8903_RIN_VOL_SHIFT 0 /* RIN_VOL - [4:0] */
678#define WM8903_RIN_VOL_WIDTH 5 /* RIN_VOL - [4:0] */
679
680/*
681 * R46 (0x2E) - Analogue Left Input 1
682 */
683#define WM8903_INL_CM_ENA 0x0040 /* INL_CM_ENA */
684#define WM8903_INL_CM_ENA_MASK 0x0040 /* INL_CM_ENA */
685#define WM8903_INL_CM_ENA_SHIFT 6 /* INL_CM_ENA */
686#define WM8903_INL_CM_ENA_WIDTH 1 /* INL_CM_ENA */
687#define WM8903_L_IP_SEL_N_MASK 0x0030 /* L_IP_SEL_N - [5:4] */
688#define WM8903_L_IP_SEL_N_SHIFT 4 /* L_IP_SEL_N - [5:4] */
689#define WM8903_L_IP_SEL_N_WIDTH 2 /* L_IP_SEL_N - [5:4] */
690#define WM8903_L_IP_SEL_P_MASK 0x000C /* L_IP_SEL_P - [3:2] */
691#define WM8903_L_IP_SEL_P_SHIFT 2 /* L_IP_SEL_P - [3:2] */
692#define WM8903_L_IP_SEL_P_WIDTH 2 /* L_IP_SEL_P - [3:2] */
693#define WM8903_L_MODE_MASK 0x0003 /* L_MODE - [1:0] */
694#define WM8903_L_MODE_SHIFT 0 /* L_MODE - [1:0] */
695#define WM8903_L_MODE_WIDTH 2 /* L_MODE - [1:0] */
696
697/*
698 * R47 (0x2F) - Analogue Right Input 1
699 */
700#define WM8903_INR_CM_ENA 0x0040 /* INR_CM_ENA */
701#define WM8903_INR_CM_ENA_MASK 0x0040 /* INR_CM_ENA */
702#define WM8903_INR_CM_ENA_SHIFT 6 /* INR_CM_ENA */
703#define WM8903_INR_CM_ENA_WIDTH 1 /* INR_CM_ENA */
704#define WM8903_R_IP_SEL_N_MASK 0x0030 /* R_IP_SEL_N - [5:4] */
705#define WM8903_R_IP_SEL_N_SHIFT 4 /* R_IP_SEL_N - [5:4] */
706#define WM8903_R_IP_SEL_N_WIDTH 2 /* R_IP_SEL_N - [5:4] */
707#define WM8903_R_IP_SEL_P_MASK 0x000C /* R_IP_SEL_P - [3:2] */
708#define WM8903_R_IP_SEL_P_SHIFT 2 /* R_IP_SEL_P - [3:2] */
709#define WM8903_R_IP_SEL_P_WIDTH 2 /* R_IP_SEL_P - [3:2] */
710#define WM8903_R_MODE_MASK 0x0003 /* R_MODE - [1:0] */
711#define WM8903_R_MODE_SHIFT 0 /* R_MODE - [1:0] */
712#define WM8903_R_MODE_WIDTH 2 /* R_MODE - [1:0] */
713
714/*
715 * R50 (0x32) - Analogue Left Mix 0
716 */
717#define WM8903_DACL_TO_MIXOUTL 0x0008 /* DACL_TO_MIXOUTL */
718#define WM8903_DACL_TO_MIXOUTL_MASK 0x0008 /* DACL_TO_MIXOUTL */
719#define WM8903_DACL_TO_MIXOUTL_SHIFT 3 /* DACL_TO_MIXOUTL */
720#define WM8903_DACL_TO_MIXOUTL_WIDTH 1 /* DACL_TO_MIXOUTL */
721#define WM8903_DACR_TO_MIXOUTL 0x0004 /* DACR_TO_MIXOUTL */
722#define WM8903_DACR_TO_MIXOUTL_MASK 0x0004 /* DACR_TO_MIXOUTL */
723#define WM8903_DACR_TO_MIXOUTL_SHIFT 2 /* DACR_TO_MIXOUTL */
724#define WM8903_DACR_TO_MIXOUTL_WIDTH 1 /* DACR_TO_MIXOUTL */
725#define WM8903_BYPASSL_TO_MIXOUTL 0x0002 /* BYPASSL_TO_MIXOUTL */
726#define WM8903_BYPASSL_TO_MIXOUTL_MASK 0x0002 /* BYPASSL_TO_MIXOUTL */
727#define WM8903_BYPASSL_TO_MIXOUTL_SHIFT 1 /* BYPASSL_TO_MIXOUTL */
728#define WM8903_BYPASSL_TO_MIXOUTL_WIDTH 1 /* BYPASSL_TO_MIXOUTL */
729#define WM8903_BYPASSR_TO_MIXOUTL 0x0001 /* BYPASSR_TO_MIXOUTL */
730#define WM8903_BYPASSR_TO_MIXOUTL_MASK 0x0001 /* BYPASSR_TO_MIXOUTL */
731#define WM8903_BYPASSR_TO_MIXOUTL_SHIFT 0 /* BYPASSR_TO_MIXOUTL */
732#define WM8903_BYPASSR_TO_MIXOUTL_WIDTH 1 /* BYPASSR_TO_MIXOUTL */
733
734/*
735 * R51 (0x33) - Analogue Right Mix 0
736 */
737#define WM8903_DACL_TO_MIXOUTR 0x0008 /* DACL_TO_MIXOUTR */
738#define WM8903_DACL_TO_MIXOUTR_MASK 0x0008 /* DACL_TO_MIXOUTR */
739#define WM8903_DACL_TO_MIXOUTR_SHIFT 3 /* DACL_TO_MIXOUTR */
740#define WM8903_DACL_TO_MIXOUTR_WIDTH 1 /* DACL_TO_MIXOUTR */
741#define WM8903_DACR_TO_MIXOUTR 0x0004 /* DACR_TO_MIXOUTR */
742#define WM8903_DACR_TO_MIXOUTR_MASK 0x0004 /* DACR_TO_MIXOUTR */
743#define WM8903_DACR_TO_MIXOUTR_SHIFT 2 /* DACR_TO_MIXOUTR */
744#define WM8903_DACR_TO_MIXOUTR_WIDTH 1 /* DACR_TO_MIXOUTR */
745#define WM8903_BYPASSL_TO_MIXOUTR 0x0002 /* BYPASSL_TO_MIXOUTR */
746#define WM8903_BYPASSL_TO_MIXOUTR_MASK 0x0002 /* BYPASSL_TO_MIXOUTR */
747#define WM8903_BYPASSL_TO_MIXOUTR_SHIFT 1 /* BYPASSL_TO_MIXOUTR */
748#define WM8903_BYPASSL_TO_MIXOUTR_WIDTH 1 /* BYPASSL_TO_MIXOUTR */
749#define WM8903_BYPASSR_TO_MIXOUTR 0x0001 /* BYPASSR_TO_MIXOUTR */
750#define WM8903_BYPASSR_TO_MIXOUTR_MASK 0x0001 /* BYPASSR_TO_MIXOUTR */
751#define WM8903_BYPASSR_TO_MIXOUTR_SHIFT 0 /* BYPASSR_TO_MIXOUTR */
752#define WM8903_BYPASSR_TO_MIXOUTR_WIDTH 1 /* BYPASSR_TO_MIXOUTR */
753
754/*
755 * R52 (0x34) - Analogue Spk Mix Left 0
756 */
757#define WM8903_DACL_TO_MIXSPKL 0x0008 /* DACL_TO_MIXSPKL */
758#define WM8903_DACL_TO_MIXSPKL_MASK 0x0008 /* DACL_TO_MIXSPKL */
759#define WM8903_DACL_TO_MIXSPKL_SHIFT 3 /* DACL_TO_MIXSPKL */
760#define WM8903_DACL_TO_MIXSPKL_WIDTH 1 /* DACL_TO_MIXSPKL */
761#define WM8903_DACR_TO_MIXSPKL 0x0004 /* DACR_TO_MIXSPKL */
762#define WM8903_DACR_TO_MIXSPKL_MASK 0x0004 /* DACR_TO_MIXSPKL */
763#define WM8903_DACR_TO_MIXSPKL_SHIFT 2 /* DACR_TO_MIXSPKL */
764#define WM8903_DACR_TO_MIXSPKL_WIDTH 1 /* DACR_TO_MIXSPKL */
765#define WM8903_BYPASSL_TO_MIXSPKL 0x0002 /* BYPASSL_TO_MIXSPKL */
766#define WM8903_BYPASSL_TO_MIXSPKL_MASK 0x0002 /* BYPASSL_TO_MIXSPKL */
767#define WM8903_BYPASSL_TO_MIXSPKL_SHIFT 1 /* BYPASSL_TO_MIXSPKL */
768#define WM8903_BYPASSL_TO_MIXSPKL_WIDTH 1 /* BYPASSL_TO_MIXSPKL */
769#define WM8903_BYPASSR_TO_MIXSPKL 0x0001 /* BYPASSR_TO_MIXSPKL */
770#define WM8903_BYPASSR_TO_MIXSPKL_MASK 0x0001 /* BYPASSR_TO_MIXSPKL */
771#define WM8903_BYPASSR_TO_MIXSPKL_SHIFT 0 /* BYPASSR_TO_MIXSPKL */
772#define WM8903_BYPASSR_TO_MIXSPKL_WIDTH 1 /* BYPASSR_TO_MIXSPKL */
773
774/*
775 * R53 (0x35) - Analogue Spk Mix Left 1
776 */
777#define WM8903_DACL_MIXSPKL_VOL 0x0008 /* DACL_MIXSPKL_VOL */
778#define WM8903_DACL_MIXSPKL_VOL_MASK 0x0008 /* DACL_MIXSPKL_VOL */
779#define WM8903_DACL_MIXSPKL_VOL_SHIFT 3 /* DACL_MIXSPKL_VOL */
780#define WM8903_DACL_MIXSPKL_VOL_WIDTH 1 /* DACL_MIXSPKL_VOL */
781#define WM8903_DACR_MIXSPKL_VOL 0x0004 /* DACR_MIXSPKL_VOL */
782#define WM8903_DACR_MIXSPKL_VOL_MASK 0x0004 /* DACR_MIXSPKL_VOL */
783#define WM8903_DACR_MIXSPKL_VOL_SHIFT 2 /* DACR_MIXSPKL_VOL */
784#define WM8903_DACR_MIXSPKL_VOL_WIDTH 1 /* DACR_MIXSPKL_VOL */
785#define WM8903_BYPASSL_MIXSPKL_VOL 0x0002 /* BYPASSL_MIXSPKL_VOL */
786#define WM8903_BYPASSL_MIXSPKL_VOL_MASK 0x0002 /* BYPASSL_MIXSPKL_VOL */
787#define WM8903_BYPASSL_MIXSPKL_VOL_SHIFT 1 /* BYPASSL_MIXSPKL_VOL */
788#define WM8903_BYPASSL_MIXSPKL_VOL_WIDTH 1 /* BYPASSL_MIXSPKL_VOL */
789#define WM8903_BYPASSR_MIXSPKL_VOL 0x0001 /* BYPASSR_MIXSPKL_VOL */
790#define WM8903_BYPASSR_MIXSPKL_VOL_MASK 0x0001 /* BYPASSR_MIXSPKL_VOL */
791#define WM8903_BYPASSR_MIXSPKL_VOL_SHIFT 0 /* BYPASSR_MIXSPKL_VOL */
792#define WM8903_BYPASSR_MIXSPKL_VOL_WIDTH 1 /* BYPASSR_MIXSPKL_VOL */
793
794/*
795 * R54 (0x36) - Analogue Spk Mix Right 0
796 */
797#define WM8903_DACL_TO_MIXSPKR 0x0008 /* DACL_TO_MIXSPKR */
798#define WM8903_DACL_TO_MIXSPKR_MASK 0x0008 /* DACL_TO_MIXSPKR */
799#define WM8903_DACL_TO_MIXSPKR_SHIFT 3 /* DACL_TO_MIXSPKR */
800#define WM8903_DACL_TO_MIXSPKR_WIDTH 1 /* DACL_TO_MIXSPKR */
801#define WM8903_DACR_TO_MIXSPKR 0x0004 /* DACR_TO_MIXSPKR */
802#define WM8903_DACR_TO_MIXSPKR_MASK 0x0004 /* DACR_TO_MIXSPKR */
803#define WM8903_DACR_TO_MIXSPKR_SHIFT 2 /* DACR_TO_MIXSPKR */
804#define WM8903_DACR_TO_MIXSPKR_WIDTH 1 /* DACR_TO_MIXSPKR */
805#define WM8903_BYPASSL_TO_MIXSPKR 0x0002 /* BYPASSL_TO_MIXSPKR */
806#define WM8903_BYPASSL_TO_MIXSPKR_MASK 0x0002 /* BYPASSL_TO_MIXSPKR */
807#define WM8903_BYPASSL_TO_MIXSPKR_SHIFT 1 /* BYPASSL_TO_MIXSPKR */
808#define WM8903_BYPASSL_TO_MIXSPKR_WIDTH 1 /* BYPASSL_TO_MIXSPKR */
809#define WM8903_BYPASSR_TO_MIXSPKR 0x0001 /* BYPASSR_TO_MIXSPKR */
810#define WM8903_BYPASSR_TO_MIXSPKR_MASK 0x0001 /* BYPASSR_TO_MIXSPKR */
811#define WM8903_BYPASSR_TO_MIXSPKR_SHIFT 0 /* BYPASSR_TO_MIXSPKR */
812#define WM8903_BYPASSR_TO_MIXSPKR_WIDTH 1 /* BYPASSR_TO_MIXSPKR */
813
814/*
815 * R55 (0x37) - Analogue Spk Mix Right 1
816 */
817#define WM8903_DACL_MIXSPKR_VOL 0x0008 /* DACL_MIXSPKR_VOL */
818#define WM8903_DACL_MIXSPKR_VOL_MASK 0x0008 /* DACL_MIXSPKR_VOL */
819#define WM8903_DACL_MIXSPKR_VOL_SHIFT 3 /* DACL_MIXSPKR_VOL */
820#define WM8903_DACL_MIXSPKR_VOL_WIDTH 1 /* DACL_MIXSPKR_VOL */
821#define WM8903_DACR_MIXSPKR_VOL 0x0004 /* DACR_MIXSPKR_VOL */
822#define WM8903_DACR_MIXSPKR_VOL_MASK 0x0004 /* DACR_MIXSPKR_VOL */
823#define WM8903_DACR_MIXSPKR_VOL_SHIFT 2 /* DACR_MIXSPKR_VOL */
824#define WM8903_DACR_MIXSPKR_VOL_WIDTH 1 /* DACR_MIXSPKR_VOL */
825#define WM8903_BYPASSL_MIXSPKR_VOL 0x0002 /* BYPASSL_MIXSPKR_VOL */
826#define WM8903_BYPASSL_MIXSPKR_VOL_MASK 0x0002 /* BYPASSL_MIXSPKR_VOL */
827#define WM8903_BYPASSL_MIXSPKR_VOL_SHIFT 1 /* BYPASSL_MIXSPKR_VOL */
828#define WM8903_BYPASSL_MIXSPKR_VOL_WIDTH 1 /* BYPASSL_MIXSPKR_VOL */
829#define WM8903_BYPASSR_MIXSPKR_VOL 0x0001 /* BYPASSR_MIXSPKR_VOL */
830#define WM8903_BYPASSR_MIXSPKR_VOL_MASK 0x0001 /* BYPASSR_MIXSPKR_VOL */
831#define WM8903_BYPASSR_MIXSPKR_VOL_SHIFT 0 /* BYPASSR_MIXSPKR_VOL */
832#define WM8903_BYPASSR_MIXSPKR_VOL_WIDTH 1 /* BYPASSR_MIXSPKR_VOL */
833
834/*
835 * R57 (0x39) - Analogue OUT1 Left
836 */
837#define WM8903_HPL_MUTE 0x0100 /* HPL_MUTE */
838#define WM8903_HPL_MUTE_MASK 0x0100 /* HPL_MUTE */
839#define WM8903_HPL_MUTE_SHIFT 8 /* HPL_MUTE */
840#define WM8903_HPL_MUTE_WIDTH 1 /* HPL_MUTE */
841#define WM8903_HPOUTVU 0x0080 /* HPOUTVU */
842#define WM8903_HPOUTVU_MASK 0x0080 /* HPOUTVU */
843#define WM8903_HPOUTVU_SHIFT 7 /* HPOUTVU */
844#define WM8903_HPOUTVU_WIDTH 1 /* HPOUTVU */
845#define WM8903_HPOUTLZC 0x0040 /* HPOUTLZC */
846#define WM8903_HPOUTLZC_MASK 0x0040 /* HPOUTLZC */
847#define WM8903_HPOUTLZC_SHIFT 6 /* HPOUTLZC */
848#define WM8903_HPOUTLZC_WIDTH 1 /* HPOUTLZC */
849#define WM8903_HPOUTL_VOL_MASK 0x003F /* HPOUTL_VOL - [5:0] */
850#define WM8903_HPOUTL_VOL_SHIFT 0 /* HPOUTL_VOL - [5:0] */
851#define WM8903_HPOUTL_VOL_WIDTH 6 /* HPOUTL_VOL - [5:0] */
852
853/*
854 * R58 (0x3A) - Analogue OUT1 Right
855 */
856#define WM8903_HPR_MUTE 0x0100 /* HPR_MUTE */
857#define WM8903_HPR_MUTE_MASK 0x0100 /* HPR_MUTE */
858#define WM8903_HPR_MUTE_SHIFT 8 /* HPR_MUTE */
859#define WM8903_HPR_MUTE_WIDTH 1 /* HPR_MUTE */
860#define WM8903_HPOUTVU 0x0080 /* HPOUTVU */
861#define WM8903_HPOUTVU_MASK 0x0080 /* HPOUTVU */
862#define WM8903_HPOUTVU_SHIFT 7 /* HPOUTVU */
863#define WM8903_HPOUTVU_WIDTH 1 /* HPOUTVU */
864#define WM8903_HPOUTRZC 0x0040 /* HPOUTRZC */
865#define WM8903_HPOUTRZC_MASK 0x0040 /* HPOUTRZC */
866#define WM8903_HPOUTRZC_SHIFT 6 /* HPOUTRZC */
867#define WM8903_HPOUTRZC_WIDTH 1 /* HPOUTRZC */
868#define WM8903_HPOUTR_VOL_MASK 0x003F /* HPOUTR_VOL - [5:0] */
869#define WM8903_HPOUTR_VOL_SHIFT 0 /* HPOUTR_VOL - [5:0] */
870#define WM8903_HPOUTR_VOL_WIDTH 6 /* HPOUTR_VOL - [5:0] */
871
872/*
873 * R59 (0x3B) - Analogue OUT2 Left
874 */
875#define WM8903_LINEOUTL_MUTE 0x0100 /* LINEOUTL_MUTE */
876#define WM8903_LINEOUTL_MUTE_MASK 0x0100 /* LINEOUTL_MUTE */
877#define WM8903_LINEOUTL_MUTE_SHIFT 8 /* LINEOUTL_MUTE */
878#define WM8903_LINEOUTL_MUTE_WIDTH 1 /* LINEOUTL_MUTE */
879#define WM8903_LINEOUTVU 0x0080 /* LINEOUTVU */
880#define WM8903_LINEOUTVU_MASK 0x0080 /* LINEOUTVU */
881#define WM8903_LINEOUTVU_SHIFT 7 /* LINEOUTVU */
882#define WM8903_LINEOUTVU_WIDTH 1 /* LINEOUTVU */
883#define WM8903_LINEOUTLZC 0x0040 /* LINEOUTLZC */
884#define WM8903_LINEOUTLZC_MASK 0x0040 /* LINEOUTLZC */
885#define WM8903_LINEOUTLZC_SHIFT 6 /* LINEOUTLZC */
886#define WM8903_LINEOUTLZC_WIDTH 1 /* LINEOUTLZC */
887#define WM8903_LINEOUTL_VOL_MASK 0x003F /* LINEOUTL_VOL - [5:0] */
888#define WM8903_LINEOUTL_VOL_SHIFT 0 /* LINEOUTL_VOL - [5:0] */
889#define WM8903_LINEOUTL_VOL_WIDTH 6 /* LINEOUTL_VOL - [5:0] */
890
891/*
892 * R60 (0x3C) - Analogue OUT2 Right
893 */
894#define WM8903_LINEOUTR_MUTE 0x0100 /* LINEOUTR_MUTE */
895#define WM8903_LINEOUTR_MUTE_MASK 0x0100 /* LINEOUTR_MUTE */
896#define WM8903_LINEOUTR_MUTE_SHIFT 8 /* LINEOUTR_MUTE */
897#define WM8903_LINEOUTR_MUTE_WIDTH 1 /* LINEOUTR_MUTE */
898#define WM8903_LINEOUTVU 0x0080 /* LINEOUTVU */
899#define WM8903_LINEOUTVU_MASK 0x0080 /* LINEOUTVU */
900#define WM8903_LINEOUTVU_SHIFT 7 /* LINEOUTVU */
901#define WM8903_LINEOUTVU_WIDTH 1 /* LINEOUTVU */
902#define WM8903_LINEOUTRZC 0x0040 /* LINEOUTRZC */
903#define WM8903_LINEOUTRZC_MASK 0x0040 /* LINEOUTRZC */
904#define WM8903_LINEOUTRZC_SHIFT 6 /* LINEOUTRZC */
905#define WM8903_LINEOUTRZC_WIDTH 1 /* LINEOUTRZC */
906#define WM8903_LINEOUTR_VOL_MASK 0x003F /* LINEOUTR_VOL - [5:0] */
907#define WM8903_LINEOUTR_VOL_SHIFT 0 /* LINEOUTR_VOL - [5:0] */
908#define WM8903_LINEOUTR_VOL_WIDTH 6 /* LINEOUTR_VOL - [5:0] */
909
910/*
911 * R62 (0x3E) - Analogue OUT3 Left
912 */
913#define WM8903_SPKL_MUTE 0x0100 /* SPKL_MUTE */
914#define WM8903_SPKL_MUTE_MASK 0x0100 /* SPKL_MUTE */
915#define WM8903_SPKL_MUTE_SHIFT 8 /* SPKL_MUTE */
916#define WM8903_SPKL_MUTE_WIDTH 1 /* SPKL_MUTE */
917#define WM8903_SPKVU 0x0080 /* SPKVU */
918#define WM8903_SPKVU_MASK 0x0080 /* SPKVU */
919#define WM8903_SPKVU_SHIFT 7 /* SPKVU */
920#define WM8903_SPKVU_WIDTH 1 /* SPKVU */
921#define WM8903_SPKLZC 0x0040 /* SPKLZC */
922#define WM8903_SPKLZC_MASK 0x0040 /* SPKLZC */
923#define WM8903_SPKLZC_SHIFT 6 /* SPKLZC */
924#define WM8903_SPKLZC_WIDTH 1 /* SPKLZC */
925#define WM8903_SPKL_VOL_MASK 0x003F /* SPKL_VOL - [5:0] */
926#define WM8903_SPKL_VOL_SHIFT 0 /* SPKL_VOL - [5:0] */
927#define WM8903_SPKL_VOL_WIDTH 6 /* SPKL_VOL - [5:0] */
928
929/*
930 * R63 (0x3F) - Analogue OUT3 Right
931 */
932#define WM8903_SPKR_MUTE 0x0100 /* SPKR_MUTE */
933#define WM8903_SPKR_MUTE_MASK 0x0100 /* SPKR_MUTE */
934#define WM8903_SPKR_MUTE_SHIFT 8 /* SPKR_MUTE */
935#define WM8903_SPKR_MUTE_WIDTH 1 /* SPKR_MUTE */
936#define WM8903_SPKVU 0x0080 /* SPKVU */
937#define WM8903_SPKVU_MASK 0x0080 /* SPKVU */
938#define WM8903_SPKVU_SHIFT 7 /* SPKVU */
939#define WM8903_SPKVU_WIDTH 1 /* SPKVU */
940#define WM8903_SPKRZC 0x0040 /* SPKRZC */
941#define WM8903_SPKRZC_MASK 0x0040 /* SPKRZC */
942#define WM8903_SPKRZC_SHIFT 6 /* SPKRZC */
943#define WM8903_SPKRZC_WIDTH 1 /* SPKRZC */
944#define WM8903_SPKR_VOL_MASK 0x003F /* SPKR_VOL - [5:0] */
945#define WM8903_SPKR_VOL_SHIFT 0 /* SPKR_VOL - [5:0] */
946#define WM8903_SPKR_VOL_WIDTH 6 /* SPKR_VOL - [5:0] */
947
948/*
949 * R65 (0x41) - Analogue SPK Output Control 0
950 */
951#define WM8903_SPK_DISCHARGE 0x0002 /* SPK_DISCHARGE */
952#define WM8903_SPK_DISCHARGE_MASK 0x0002 /* SPK_DISCHARGE */
953#define WM8903_SPK_DISCHARGE_SHIFT 1 /* SPK_DISCHARGE */
954#define WM8903_SPK_DISCHARGE_WIDTH 1 /* SPK_DISCHARGE */
955#define WM8903_VROI 0x0001 /* VROI */
956#define WM8903_VROI_MASK 0x0001 /* VROI */
957#define WM8903_VROI_SHIFT 0 /* VROI */
958#define WM8903_VROI_WIDTH 1 /* VROI */
959
960/*
961 * R67 (0x43) - DC Servo 0
962 */
963#define WM8903_DCS_MASTER_ENA 0x0010 /* DCS_MASTER_ENA */
964#define WM8903_DCS_MASTER_ENA_MASK 0x0010 /* DCS_MASTER_ENA */
965#define WM8903_DCS_MASTER_ENA_SHIFT 4 /* DCS_MASTER_ENA */
966#define WM8903_DCS_MASTER_ENA_WIDTH 1 /* DCS_MASTER_ENA */
967#define WM8903_DCS_ENA_MASK 0x000F /* DCS_ENA - [3:0] */
968#define WM8903_DCS_ENA_SHIFT 0 /* DCS_ENA - [3:0] */
969#define WM8903_DCS_ENA_WIDTH 4 /* DCS_ENA - [3:0] */
970
971/*
972 * R69 (0x45) - DC Servo 2
973 */
974#define WM8903_DCS_MODE_MASK 0x0003 /* DCS_MODE - [1:0] */
975#define WM8903_DCS_MODE_SHIFT 0 /* DCS_MODE - [1:0] */
976#define WM8903_DCS_MODE_WIDTH 2 /* DCS_MODE - [1:0] */
977
978/*
979 * R90 (0x5A) - Analogue HP 0
980 */
981#define WM8903_HPL_RMV_SHORT 0x0080 /* HPL_RMV_SHORT */
982#define WM8903_HPL_RMV_SHORT_MASK 0x0080 /* HPL_RMV_SHORT */
983#define WM8903_HPL_RMV_SHORT_SHIFT 7 /* HPL_RMV_SHORT */
984#define WM8903_HPL_RMV_SHORT_WIDTH 1 /* HPL_RMV_SHORT */
985#define WM8903_HPL_ENA_OUTP 0x0040 /* HPL_ENA_OUTP */
986#define WM8903_HPL_ENA_OUTP_MASK 0x0040 /* HPL_ENA_OUTP */
987#define WM8903_HPL_ENA_OUTP_SHIFT 6 /* HPL_ENA_OUTP */
988#define WM8903_HPL_ENA_OUTP_WIDTH 1 /* HPL_ENA_OUTP */
989#define WM8903_HPL_ENA_DLY 0x0020 /* HPL_ENA_DLY */
990#define WM8903_HPL_ENA_DLY_MASK 0x0020 /* HPL_ENA_DLY */
991#define WM8903_HPL_ENA_DLY_SHIFT 5 /* HPL_ENA_DLY */
992#define WM8903_HPL_ENA_DLY_WIDTH 1 /* HPL_ENA_DLY */
993#define WM8903_HPL_ENA 0x0010 /* HPL_ENA */
994#define WM8903_HPL_ENA_MASK 0x0010 /* HPL_ENA */
995#define WM8903_HPL_ENA_SHIFT 4 /* HPL_ENA */
996#define WM8903_HPL_ENA_WIDTH 1 /* HPL_ENA */
997#define WM8903_HPR_RMV_SHORT 0x0008 /* HPR_RMV_SHORT */
998#define WM8903_HPR_RMV_SHORT_MASK 0x0008 /* HPR_RMV_SHORT */
999#define WM8903_HPR_RMV_SHORT_SHIFT 3 /* HPR_RMV_SHORT */
1000#define WM8903_HPR_RMV_SHORT_WIDTH 1 /* HPR_RMV_SHORT */
1001#define WM8903_HPR_ENA_OUTP 0x0004 /* HPR_ENA_OUTP */
1002#define WM8903_HPR_ENA_OUTP_MASK 0x0004 /* HPR_ENA_OUTP */
1003#define WM8903_HPR_ENA_OUTP_SHIFT 2 /* HPR_ENA_OUTP */
1004#define WM8903_HPR_ENA_OUTP_WIDTH 1 /* HPR_ENA_OUTP */
1005#define WM8903_HPR_ENA_DLY 0x0002 /* HPR_ENA_DLY */
1006#define WM8903_HPR_ENA_DLY_MASK 0x0002 /* HPR_ENA_DLY */
1007#define WM8903_HPR_ENA_DLY_SHIFT 1 /* HPR_ENA_DLY */
1008#define WM8903_HPR_ENA_DLY_WIDTH 1 /* HPR_ENA_DLY */
1009#define WM8903_HPR_ENA 0x0001 /* HPR_ENA */
1010#define WM8903_HPR_ENA_MASK 0x0001 /* HPR_ENA */
1011#define WM8903_HPR_ENA_SHIFT 0 /* HPR_ENA */
1012#define WM8903_HPR_ENA_WIDTH 1 /* HPR_ENA */
1013
1014/*
1015 * R94 (0x5E) - Analogue Lineout 0
1016 */
1017#define WM8903_LINEOUTL_RMV_SHORT 0x0080 /* LINEOUTL_RMV_SHORT */
1018#define WM8903_LINEOUTL_RMV_SHORT_MASK 0x0080 /* LINEOUTL_RMV_SHORT */
1019#define WM8903_LINEOUTL_RMV_SHORT_SHIFT 7 /* LINEOUTL_RMV_SHORT */
1020#define WM8903_LINEOUTL_RMV_SHORT_WIDTH 1 /* LINEOUTL_RMV_SHORT */
1021#define WM8903_LINEOUTL_ENA_OUTP 0x0040 /* LINEOUTL_ENA_OUTP */
1022#define WM8903_LINEOUTL_ENA_OUTP_MASK 0x0040 /* LINEOUTL_ENA_OUTP */
1023#define WM8903_LINEOUTL_ENA_OUTP_SHIFT 6 /* LINEOUTL_ENA_OUTP */
1024#define WM8903_LINEOUTL_ENA_OUTP_WIDTH 1 /* LINEOUTL_ENA_OUTP */
1025#define WM8903_LINEOUTL_ENA_DLY 0x0020 /* LINEOUTL_ENA_DLY */
1026#define WM8903_LINEOUTL_ENA_DLY_MASK 0x0020 /* LINEOUTL_ENA_DLY */
1027#define WM8903_LINEOUTL_ENA_DLY_SHIFT 5 /* LINEOUTL_ENA_DLY */
1028#define WM8903_LINEOUTL_ENA_DLY_WIDTH 1 /* LINEOUTL_ENA_DLY */
1029#define WM8903_LINEOUTL_ENA 0x0010 /* LINEOUTL_ENA */
1030#define WM8903_LINEOUTL_ENA_MASK 0x0010 /* LINEOUTL_ENA */
1031#define WM8903_LINEOUTL_ENA_SHIFT 4 /* LINEOUTL_ENA */
1032#define WM8903_LINEOUTL_ENA_WIDTH 1 /* LINEOUTL_ENA */
1033#define WM8903_LINEOUTR_RMV_SHORT 0x0008 /* LINEOUTR_RMV_SHORT */
1034#define WM8903_LINEOUTR_RMV_SHORT_MASK 0x0008 /* LINEOUTR_RMV_SHORT */
1035#define WM8903_LINEOUTR_RMV_SHORT_SHIFT 3 /* LINEOUTR_RMV_SHORT */
1036#define WM8903_LINEOUTR_RMV_SHORT_WIDTH 1 /* LINEOUTR_RMV_SHORT */
1037#define WM8903_LINEOUTR_ENA_OUTP 0x0004 /* LINEOUTR_ENA_OUTP */
1038#define WM8903_LINEOUTR_ENA_OUTP_MASK 0x0004 /* LINEOUTR_ENA_OUTP */
1039#define WM8903_LINEOUTR_ENA_OUTP_SHIFT 2 /* LINEOUTR_ENA_OUTP */
1040#define WM8903_LINEOUTR_ENA_OUTP_WIDTH 1 /* LINEOUTR_ENA_OUTP */
1041#define WM8903_LINEOUTR_ENA_DLY 0x0002 /* LINEOUTR_ENA_DLY */
1042#define WM8903_LINEOUTR_ENA_DLY_MASK 0x0002 /* LINEOUTR_ENA_DLY */
1043#define WM8903_LINEOUTR_ENA_DLY_SHIFT 1 /* LINEOUTR_ENA_DLY */
1044#define WM8903_LINEOUTR_ENA_DLY_WIDTH 1 /* LINEOUTR_ENA_DLY */
1045#define WM8903_LINEOUTR_ENA 0x0001 /* LINEOUTR_ENA */
1046#define WM8903_LINEOUTR_ENA_MASK 0x0001 /* LINEOUTR_ENA */
1047#define WM8903_LINEOUTR_ENA_SHIFT 0 /* LINEOUTR_ENA */
1048#define WM8903_LINEOUTR_ENA_WIDTH 1 /* LINEOUTR_ENA */
1049
1050/*
1051 * R98 (0x62) - Charge Pump 0
1052 */
1053#define WM8903_CP_ENA 0x0001 /* CP_ENA */
1054#define WM8903_CP_ENA_MASK 0x0001 /* CP_ENA */
1055#define WM8903_CP_ENA_SHIFT 0 /* CP_ENA */
1056#define WM8903_CP_ENA_WIDTH 1 /* CP_ENA */
1057
1058/*
1059 * R104 (0x68) - Class W 0
1060 */
1061#define WM8903_CP_DYN_FREQ 0x0002 /* CP_DYN_FREQ */
1062#define WM8903_CP_DYN_FREQ_MASK 0x0002 /* CP_DYN_FREQ */
1063#define WM8903_CP_DYN_FREQ_SHIFT 1 /* CP_DYN_FREQ */
1064#define WM8903_CP_DYN_FREQ_WIDTH 1 /* CP_DYN_FREQ */
1065#define WM8903_CP_DYN_V 0x0001 /* CP_DYN_V */
1066#define WM8903_CP_DYN_V_MASK 0x0001 /* CP_DYN_V */
1067#define WM8903_CP_DYN_V_SHIFT 0 /* CP_DYN_V */
1068#define WM8903_CP_DYN_V_WIDTH 1 /* CP_DYN_V */
1069
1070/*
1071 * R108 (0x6C) - Write Sequencer 0
1072 */
1073#define WM8903_WSEQ_ENA 0x0100 /* WSEQ_ENA */
1074#define WM8903_WSEQ_ENA_MASK 0x0100 /* WSEQ_ENA */
1075#define WM8903_WSEQ_ENA_SHIFT 8 /* WSEQ_ENA */
1076#define WM8903_WSEQ_ENA_WIDTH 1 /* WSEQ_ENA */
1077#define WM8903_WSEQ_WRITE_INDEX_MASK 0x001F /* WSEQ_WRITE_INDEX - [4:0] */
1078#define WM8903_WSEQ_WRITE_INDEX_SHIFT 0 /* WSEQ_WRITE_INDEX - [4:0] */
1079#define WM8903_WSEQ_WRITE_INDEX_WIDTH 5 /* WSEQ_WRITE_INDEX - [4:0] */
1080
1081/*
1082 * R109 (0x6D) - Write Sequencer 1
1083 */
1084#define WM8903_WSEQ_DATA_WIDTH_MASK 0x7000 /* WSEQ_DATA_WIDTH - [14:12] */
1085#define WM8903_WSEQ_DATA_WIDTH_SHIFT 12 /* WSEQ_DATA_WIDTH - [14:12] */
1086#define WM8903_WSEQ_DATA_WIDTH_WIDTH 3 /* WSEQ_DATA_WIDTH - [14:12] */
1087#define WM8903_WSEQ_DATA_START_MASK 0x0F00 /* WSEQ_DATA_START - [11:8] */
1088#define WM8903_WSEQ_DATA_START_SHIFT 8 /* WSEQ_DATA_START - [11:8] */
1089#define WM8903_WSEQ_DATA_START_WIDTH 4 /* WSEQ_DATA_START - [11:8] */
1090#define WM8903_WSEQ_ADDR_MASK 0x00FF /* WSEQ_ADDR - [7:0] */
1091#define WM8903_WSEQ_ADDR_SHIFT 0 /* WSEQ_ADDR - [7:0] */
1092#define WM8903_WSEQ_ADDR_WIDTH 8 /* WSEQ_ADDR - [7:0] */
1093
1094/*
1095 * R110 (0x6E) - Write Sequencer 2
1096 */
1097#define WM8903_WSEQ_EOS 0x4000 /* WSEQ_EOS */
1098#define WM8903_WSEQ_EOS_MASK 0x4000 /* WSEQ_EOS */
1099#define WM8903_WSEQ_EOS_SHIFT 14 /* WSEQ_EOS */
1100#define WM8903_WSEQ_EOS_WIDTH 1 /* WSEQ_EOS */
1101#define WM8903_WSEQ_DELAY_MASK 0x0F00 /* WSEQ_DELAY - [11:8] */
1102#define WM8903_WSEQ_DELAY_SHIFT 8 /* WSEQ_DELAY - [11:8] */
1103#define WM8903_WSEQ_DELAY_WIDTH 4 /* WSEQ_DELAY - [11:8] */
1104#define WM8903_WSEQ_DATA_MASK 0x00FF /* WSEQ_DATA - [7:0] */
1105#define WM8903_WSEQ_DATA_SHIFT 0 /* WSEQ_DATA - [7:0] */
1106#define WM8903_WSEQ_DATA_WIDTH 8 /* WSEQ_DATA - [7:0] */
1107
1108/*
1109 * R111 (0x6F) - Write Sequencer 3
1110 */
1111#define WM8903_WSEQ_ABORT 0x0200 /* WSEQ_ABORT */
1112#define WM8903_WSEQ_ABORT_MASK 0x0200 /* WSEQ_ABORT */
1113#define WM8903_WSEQ_ABORT_SHIFT 9 /* WSEQ_ABORT */
1114#define WM8903_WSEQ_ABORT_WIDTH 1 /* WSEQ_ABORT */
1115#define WM8903_WSEQ_START 0x0100 /* WSEQ_START */
1116#define WM8903_WSEQ_START_MASK 0x0100 /* WSEQ_START */
1117#define WM8903_WSEQ_START_SHIFT 8 /* WSEQ_START */
1118#define WM8903_WSEQ_START_WIDTH 1 /* WSEQ_START */
1119#define WM8903_WSEQ_START_INDEX_MASK 0x003F /* WSEQ_START_INDEX - [5:0] */
1120#define WM8903_WSEQ_START_INDEX_SHIFT 0 /* WSEQ_START_INDEX - [5:0] */
1121#define WM8903_WSEQ_START_INDEX_WIDTH 6 /* WSEQ_START_INDEX - [5:0] */
1122
1123/*
1124 * R112 (0x70) - Write Sequencer 4
1125 */
1126#define WM8903_WSEQ_CURRENT_INDEX_MASK 0x03F0 /* WSEQ_CURRENT_INDEX - [9:4] */
1127#define WM8903_WSEQ_CURRENT_INDEX_SHIFT 4 /* WSEQ_CURRENT_INDEX - [9:4] */
1128#define WM8903_WSEQ_CURRENT_INDEX_WIDTH 6 /* WSEQ_CURRENT_INDEX - [9:4] */
1129#define WM8903_WSEQ_BUSY 0x0001 /* WSEQ_BUSY */
1130#define WM8903_WSEQ_BUSY_MASK 0x0001 /* WSEQ_BUSY */
1131#define WM8903_WSEQ_BUSY_SHIFT 0 /* WSEQ_BUSY */
1132#define WM8903_WSEQ_BUSY_WIDTH 1 /* WSEQ_BUSY */
1133
1134/*
1135 * R114 (0x72) - Control Interface
1136 */
1137#define WM8903_MASK_WRITE_ENA 0x0001 /* MASK_WRITE_ENA */
1138#define WM8903_MASK_WRITE_ENA_MASK 0x0001 /* MASK_WRITE_ENA */
1139#define WM8903_MASK_WRITE_ENA_SHIFT 0 /* MASK_WRITE_ENA */
1140#define WM8903_MASK_WRITE_ENA_WIDTH 1 /* MASK_WRITE_ENA */
1141
1142/*
1143 * R116 (0x74) - GPIO Control 1
1144 */
1145#define WM8903_GP1_FN_MASK 0x1F00 /* GP1_FN - [12:8] */
1146#define WM8903_GP1_FN_SHIFT 8 /* GP1_FN - [12:8] */
1147#define WM8903_GP1_FN_WIDTH 5 /* GP1_FN - [12:8] */
1148#define WM8903_GP1_DIR 0x0080 /* GP1_DIR */
1149#define WM8903_GP1_DIR_MASK 0x0080 /* GP1_DIR */
1150#define WM8903_GP1_DIR_SHIFT 7 /* GP1_DIR */
1151#define WM8903_GP1_DIR_WIDTH 1 /* GP1_DIR */
1152#define WM8903_GP1_OP_CFG 0x0040 /* GP1_OP_CFG */
1153#define WM8903_GP1_OP_CFG_MASK 0x0040 /* GP1_OP_CFG */
1154#define WM8903_GP1_OP_CFG_SHIFT 6 /* GP1_OP_CFG */
1155#define WM8903_GP1_OP_CFG_WIDTH 1 /* GP1_OP_CFG */
1156#define WM8903_GP1_IP_CFG 0x0020 /* GP1_IP_CFG */
1157#define WM8903_GP1_IP_CFG_MASK 0x0020 /* GP1_IP_CFG */
1158#define WM8903_GP1_IP_CFG_SHIFT 5 /* GP1_IP_CFG */
1159#define WM8903_GP1_IP_CFG_WIDTH 1 /* GP1_IP_CFG */
1160#define WM8903_GP1_LVL 0x0010 /* GP1_LVL */
1161#define WM8903_GP1_LVL_MASK 0x0010 /* GP1_LVL */
1162#define WM8903_GP1_LVL_SHIFT 4 /* GP1_LVL */
1163#define WM8903_GP1_LVL_WIDTH 1 /* GP1_LVL */
1164#define WM8903_GP1_PD 0x0008 /* GP1_PD */
1165#define WM8903_GP1_PD_MASK 0x0008 /* GP1_PD */
1166#define WM8903_GP1_PD_SHIFT 3 /* GP1_PD */
1167#define WM8903_GP1_PD_WIDTH 1 /* GP1_PD */
1168#define WM8903_GP1_PU 0x0004 /* GP1_PU */
1169#define WM8903_GP1_PU_MASK 0x0004 /* GP1_PU */
1170#define WM8903_GP1_PU_SHIFT 2 /* GP1_PU */
1171#define WM8903_GP1_PU_WIDTH 1 /* GP1_PU */
1172#define WM8903_GP1_INTMODE 0x0002 /* GP1_INTMODE */
1173#define WM8903_GP1_INTMODE_MASK 0x0002 /* GP1_INTMODE */
1174#define WM8903_GP1_INTMODE_SHIFT 1 /* GP1_INTMODE */
1175#define WM8903_GP1_INTMODE_WIDTH 1 /* GP1_INTMODE */
1176#define WM8903_GP1_DB 0x0001 /* GP1_DB */
1177#define WM8903_GP1_DB_MASK 0x0001 /* GP1_DB */
1178#define WM8903_GP1_DB_SHIFT 0 /* GP1_DB */
1179#define WM8903_GP1_DB_WIDTH 1 /* GP1_DB */
1180
1181/*
1182 * R117 (0x75) - GPIO Control 2
1183 */
1184#define WM8903_GP2_FN_MASK 0x1F00 /* GP2_FN - [12:8] */
1185#define WM8903_GP2_FN_SHIFT 8 /* GP2_FN - [12:8] */
1186#define WM8903_GP2_FN_WIDTH 5 /* GP2_FN - [12:8] */
1187#define WM8903_GP2_DIR 0x0080 /* GP2_DIR */
1188#define WM8903_GP2_DIR_MASK 0x0080 /* GP2_DIR */
1189#define WM8903_GP2_DIR_SHIFT 7 /* GP2_DIR */
1190#define WM8903_GP2_DIR_WIDTH 1 /* GP2_DIR */
1191#define WM8903_GP2_OP_CFG 0x0040 /* GP2_OP_CFG */
1192#define WM8903_GP2_OP_CFG_MASK 0x0040 /* GP2_OP_CFG */
1193#define WM8903_GP2_OP_CFG_SHIFT 6 /* GP2_OP_CFG */
1194#define WM8903_GP2_OP_CFG_WIDTH 1 /* GP2_OP_CFG */
1195#define WM8903_GP2_IP_CFG 0x0020 /* GP2_IP_CFG */
1196#define WM8903_GP2_IP_CFG_MASK 0x0020 /* GP2_IP_CFG */
1197#define WM8903_GP2_IP_CFG_SHIFT 5 /* GP2_IP_CFG */
1198#define WM8903_GP2_IP_CFG_WIDTH 1 /* GP2_IP_CFG */
1199#define WM8903_GP2_LVL 0x0010 /* GP2_LVL */
1200#define WM8903_GP2_LVL_MASK 0x0010 /* GP2_LVL */
1201#define WM8903_GP2_LVL_SHIFT 4 /* GP2_LVL */
1202#define WM8903_GP2_LVL_WIDTH 1 /* GP2_LVL */
1203#define WM8903_GP2_PD 0x0008 /* GP2_PD */
1204#define WM8903_GP2_PD_MASK 0x0008 /* GP2_PD */
1205#define WM8903_GP2_PD_SHIFT 3 /* GP2_PD */
1206#define WM8903_GP2_PD_WIDTH 1 /* GP2_PD */
1207#define WM8903_GP2_PU 0x0004 /* GP2_PU */
1208#define WM8903_GP2_PU_MASK 0x0004 /* GP2_PU */
1209#define WM8903_GP2_PU_SHIFT 2 /* GP2_PU */
1210#define WM8903_GP2_PU_WIDTH 1 /* GP2_PU */
1211#define WM8903_GP2_INTMODE 0x0002 /* GP2_INTMODE */
1212#define WM8903_GP2_INTMODE_MASK 0x0002 /* GP2_INTMODE */
1213#define WM8903_GP2_INTMODE_SHIFT 1 /* GP2_INTMODE */
1214#define WM8903_GP2_INTMODE_WIDTH 1 /* GP2_INTMODE */
1215#define WM8903_GP2_DB 0x0001 /* GP2_DB */
1216#define WM8903_GP2_DB_MASK 0x0001 /* GP2_DB */
1217#define WM8903_GP2_DB_SHIFT 0 /* GP2_DB */
1218#define WM8903_GP2_DB_WIDTH 1 /* GP2_DB */
1219
1220/*
1221 * R118 (0x76) - GPIO Control 3
1222 */
1223#define WM8903_GP3_FN_MASK 0x1F00 /* GP3_FN - [12:8] */
1224#define WM8903_GP3_FN_SHIFT 8 /* GP3_FN - [12:8] */
1225#define WM8903_GP3_FN_WIDTH 5 /* GP3_FN - [12:8] */
1226#define WM8903_GP3_DIR 0x0080 /* GP3_DIR */
1227#define WM8903_GP3_DIR_MASK 0x0080 /* GP3_DIR */
1228#define WM8903_GP3_DIR_SHIFT 7 /* GP3_DIR */
1229#define WM8903_GP3_DIR_WIDTH 1 /* GP3_DIR */
1230#define WM8903_GP3_OP_CFG 0x0040 /* GP3_OP_CFG */
1231#define WM8903_GP3_OP_CFG_MASK 0x0040 /* GP3_OP_CFG */
1232#define WM8903_GP3_OP_CFG_SHIFT 6 /* GP3_OP_CFG */
1233#define WM8903_GP3_OP_CFG_WIDTH 1 /* GP3_OP_CFG */
1234#define WM8903_GP3_IP_CFG 0x0020 /* GP3_IP_CFG */
1235#define WM8903_GP3_IP_CFG_MASK 0x0020 /* GP3_IP_CFG */
1236#define WM8903_GP3_IP_CFG_SHIFT 5 /* GP3_IP_CFG */
1237#define WM8903_GP3_IP_CFG_WIDTH 1 /* GP3_IP_CFG */
1238#define WM8903_GP3_LVL 0x0010 /* GP3_LVL */
1239#define WM8903_GP3_LVL_MASK 0x0010 /* GP3_LVL */
1240#define WM8903_GP3_LVL_SHIFT 4 /* GP3_LVL */
1241#define WM8903_GP3_LVL_WIDTH 1 /* GP3_LVL */
1242#define WM8903_GP3_PD 0x0008 /* GP3_PD */
1243#define WM8903_GP3_PD_MASK 0x0008 /* GP3_PD */
1244#define WM8903_GP3_PD_SHIFT 3 /* GP3_PD */
1245#define WM8903_GP3_PD_WIDTH 1 /* GP3_PD */
1246#define WM8903_GP3_PU 0x0004 /* GP3_PU */
1247#define WM8903_GP3_PU_MASK 0x0004 /* GP3_PU */
1248#define WM8903_GP3_PU_SHIFT 2 /* GP3_PU */
1249#define WM8903_GP3_PU_WIDTH 1 /* GP3_PU */
1250#define WM8903_GP3_INTMODE 0x0002 /* GP3_INTMODE */
1251#define WM8903_GP3_INTMODE_MASK 0x0002 /* GP3_INTMODE */
1252#define WM8903_GP3_INTMODE_SHIFT 1 /* GP3_INTMODE */
1253#define WM8903_GP3_INTMODE_WIDTH 1 /* GP3_INTMODE */
1254#define WM8903_GP3_DB 0x0001 /* GP3_DB */
1255#define WM8903_GP3_DB_MASK 0x0001 /* GP3_DB */
1256#define WM8903_GP3_DB_SHIFT 0 /* GP3_DB */
1257#define WM8903_GP3_DB_WIDTH 1 /* GP3_DB */
1258
1259/*
1260 * R119 (0x77) - GPIO Control 4
1261 */
1262#define WM8903_GP4_FN_MASK 0x1F00 /* GP4_FN - [12:8] */
1263#define WM8903_GP4_FN_SHIFT 8 /* GP4_FN - [12:8] */
1264#define WM8903_GP4_FN_WIDTH 5 /* GP4_FN - [12:8] */
1265#define WM8903_GP4_DIR 0x0080 /* GP4_DIR */
1266#define WM8903_GP4_DIR_MASK 0x0080 /* GP4_DIR */
1267#define WM8903_GP4_DIR_SHIFT 7 /* GP4_DIR */
1268#define WM8903_GP4_DIR_WIDTH 1 /* GP4_DIR */
1269#define WM8903_GP4_OP_CFG 0x0040 /* GP4_OP_CFG */
1270#define WM8903_GP4_OP_CFG_MASK 0x0040 /* GP4_OP_CFG */
1271#define WM8903_GP4_OP_CFG_SHIFT 6 /* GP4_OP_CFG */
1272#define WM8903_GP4_OP_CFG_WIDTH 1 /* GP4_OP_CFG */
1273#define WM8903_GP4_IP_CFG 0x0020 /* GP4_IP_CFG */
1274#define WM8903_GP4_IP_CFG_MASK 0x0020 /* GP4_IP_CFG */
1275#define WM8903_GP4_IP_CFG_SHIFT 5 /* GP4_IP_CFG */
1276#define WM8903_GP4_IP_CFG_WIDTH 1 /* GP4_IP_CFG */
1277#define WM8903_GP4_LVL 0x0010 /* GP4_LVL */
1278#define WM8903_GP4_LVL_MASK 0x0010 /* GP4_LVL */
1279#define WM8903_GP4_LVL_SHIFT 4 /* GP4_LVL */
1280#define WM8903_GP4_LVL_WIDTH 1 /* GP4_LVL */
1281#define WM8903_GP4_PD 0x0008 /* GP4_PD */
1282#define WM8903_GP4_PD_MASK 0x0008 /* GP4_PD */
1283#define WM8903_GP4_PD_SHIFT 3 /* GP4_PD */
1284#define WM8903_GP4_PD_WIDTH 1 /* GP4_PD */
1285#define WM8903_GP4_PU 0x0004 /* GP4_PU */
1286#define WM8903_GP4_PU_MASK 0x0004 /* GP4_PU */
1287#define WM8903_GP4_PU_SHIFT 2 /* GP4_PU */
1288#define WM8903_GP4_PU_WIDTH 1 /* GP4_PU */
1289#define WM8903_GP4_INTMODE 0x0002 /* GP4_INTMODE */
1290#define WM8903_GP4_INTMODE_MASK 0x0002 /* GP4_INTMODE */
1291#define WM8903_GP4_INTMODE_SHIFT 1 /* GP4_INTMODE */
1292#define WM8903_GP4_INTMODE_WIDTH 1 /* GP4_INTMODE */
1293#define WM8903_GP4_DB 0x0001 /* GP4_DB */
1294#define WM8903_GP4_DB_MASK 0x0001 /* GP4_DB */
1295#define WM8903_GP4_DB_SHIFT 0 /* GP4_DB */
1296#define WM8903_GP4_DB_WIDTH 1 /* GP4_DB */
1297
1298/*
1299 * R120 (0x78) - GPIO Control 5
1300 */
1301#define WM8903_GP5_FN_MASK 0x1F00 /* GP5_FN - [12:8] */
1302#define WM8903_GP5_FN_SHIFT 8 /* GP5_FN - [12:8] */
1303#define WM8903_GP5_FN_WIDTH 5 /* GP5_FN - [12:8] */
1304#define WM8903_GP5_DIR 0x0080 /* GP5_DIR */
1305#define WM8903_GP5_DIR_MASK 0x0080 /* GP5_DIR */
1306#define WM8903_GP5_DIR_SHIFT 7 /* GP5_DIR */
1307#define WM8903_GP5_DIR_WIDTH 1 /* GP5_DIR */
1308#define WM8903_GP5_OP_CFG 0x0040 /* GP5_OP_CFG */
1309#define WM8903_GP5_OP_CFG_MASK 0x0040 /* GP5_OP_CFG */
1310#define WM8903_GP5_OP_CFG_SHIFT 6 /* GP5_OP_CFG */
1311#define WM8903_GP5_OP_CFG_WIDTH 1 /* GP5_OP_CFG */
1312#define WM8903_GP5_IP_CFG 0x0020 /* GP5_IP_CFG */
1313#define WM8903_GP5_IP_CFG_MASK 0x0020 /* GP5_IP_CFG */
1314#define WM8903_GP5_IP_CFG_SHIFT 5 /* GP5_IP_CFG */
1315#define WM8903_GP5_IP_CFG_WIDTH 1 /* GP5_IP_CFG */
1316#define WM8903_GP5_LVL 0x0010 /* GP5_LVL */
1317#define WM8903_GP5_LVL_MASK 0x0010 /* GP5_LVL */
1318#define WM8903_GP5_LVL_SHIFT 4 /* GP5_LVL */
1319#define WM8903_GP5_LVL_WIDTH 1 /* GP5_LVL */
1320#define WM8903_GP5_PD 0x0008 /* GP5_PD */
1321#define WM8903_GP5_PD_MASK 0x0008 /* GP5_PD */
1322#define WM8903_GP5_PD_SHIFT 3 /* GP5_PD */
1323#define WM8903_GP5_PD_WIDTH 1 /* GP5_PD */
1324#define WM8903_GP5_PU 0x0004 /* GP5_PU */
1325#define WM8903_GP5_PU_MASK 0x0004 /* GP5_PU */
1326#define WM8903_GP5_PU_SHIFT 2 /* GP5_PU */
1327#define WM8903_GP5_PU_WIDTH 1 /* GP5_PU */
1328#define WM8903_GP5_INTMODE 0x0002 /* GP5_INTMODE */
1329#define WM8903_GP5_INTMODE_MASK 0x0002 /* GP5_INTMODE */
1330#define WM8903_GP5_INTMODE_SHIFT 1 /* GP5_INTMODE */
1331#define WM8903_GP5_INTMODE_WIDTH 1 /* GP5_INTMODE */
1332#define WM8903_GP5_DB 0x0001 /* GP5_DB */
1333#define WM8903_GP5_DB_MASK 0x0001 /* GP5_DB */
1334#define WM8903_GP5_DB_SHIFT 0 /* GP5_DB */
1335#define WM8903_GP5_DB_WIDTH 1 /* GP5_DB */
1336
1337/*
1338 * R121 (0x79) - Interrupt Status 1
1339 */
1340#define WM8903_MICSHRT_EINT 0x8000 /* MICSHRT_EINT */
1341#define WM8903_MICSHRT_EINT_MASK 0x8000 /* MICSHRT_EINT */
1342#define WM8903_MICSHRT_EINT_SHIFT 15 /* MICSHRT_EINT */
1343#define WM8903_MICSHRT_EINT_WIDTH 1 /* MICSHRT_EINT */
1344#define WM8903_MICDET_EINT 0x4000 /* MICDET_EINT */
1345#define WM8903_MICDET_EINT_MASK 0x4000 /* MICDET_EINT */
1346#define WM8903_MICDET_EINT_SHIFT 14 /* MICDET_EINT */
1347#define WM8903_MICDET_EINT_WIDTH 1 /* MICDET_EINT */
1348#define WM8903_WSEQ_BUSY_EINT 0x2000 /* WSEQ_BUSY_EINT */
1349#define WM8903_WSEQ_BUSY_EINT_MASK 0x2000 /* WSEQ_BUSY_EINT */
1350#define WM8903_WSEQ_BUSY_EINT_SHIFT 13 /* WSEQ_BUSY_EINT */
1351#define WM8903_WSEQ_BUSY_EINT_WIDTH 1 /* WSEQ_BUSY_EINT */
1352#define WM8903_GP5_EINT 0x0010 /* GP5_EINT */
1353#define WM8903_GP5_EINT_MASK 0x0010 /* GP5_EINT */
1354#define WM8903_GP5_EINT_SHIFT 4 /* GP5_EINT */
1355#define WM8903_GP5_EINT_WIDTH 1 /* GP5_EINT */
1356#define WM8903_GP4_EINT 0x0008 /* GP4_EINT */
1357#define WM8903_GP4_EINT_MASK 0x0008 /* GP4_EINT */
1358#define WM8903_GP4_EINT_SHIFT 3 /* GP4_EINT */
1359#define WM8903_GP4_EINT_WIDTH 1 /* GP4_EINT */
1360#define WM8903_GP3_EINT 0x0004 /* GP3_EINT */
1361#define WM8903_GP3_EINT_MASK 0x0004 /* GP3_EINT */
1362#define WM8903_GP3_EINT_SHIFT 2 /* GP3_EINT */
1363#define WM8903_GP3_EINT_WIDTH 1 /* GP3_EINT */
1364#define WM8903_GP2_EINT 0x0002 /* GP2_EINT */
1365#define WM8903_GP2_EINT_MASK 0x0002 /* GP2_EINT */
1366#define WM8903_GP2_EINT_SHIFT 1 /* GP2_EINT */
1367#define WM8903_GP2_EINT_WIDTH 1 /* GP2_EINT */
1368#define WM8903_GP1_EINT 0x0001 /* GP1_EINT */
1369#define WM8903_GP1_EINT_MASK 0x0001 /* GP1_EINT */
1370#define WM8903_GP1_EINT_SHIFT 0 /* GP1_EINT */
1371#define WM8903_GP1_EINT_WIDTH 1 /* GP1_EINT */
1372
1373/*
1374 * R122 (0x7A) - Interrupt Status 1 Mask
1375 */
1376#define WM8903_IM_MICSHRT_EINT 0x8000 /* IM_MICSHRT_EINT */
1377#define WM8903_IM_MICSHRT_EINT_MASK 0x8000 /* IM_MICSHRT_EINT */
1378#define WM8903_IM_MICSHRT_EINT_SHIFT 15 /* IM_MICSHRT_EINT */
1379#define WM8903_IM_MICSHRT_EINT_WIDTH 1 /* IM_MICSHRT_EINT */
1380#define WM8903_IM_MICDET_EINT 0x4000 /* IM_MICDET_EINT */
1381#define WM8903_IM_MICDET_EINT_MASK 0x4000 /* IM_MICDET_EINT */
1382#define WM8903_IM_MICDET_EINT_SHIFT 14 /* IM_MICDET_EINT */
1383#define WM8903_IM_MICDET_EINT_WIDTH 1 /* IM_MICDET_EINT */
1384#define WM8903_IM_WSEQ_BUSY_EINT 0x2000 /* IM_WSEQ_BUSY_EINT */
1385#define WM8903_IM_WSEQ_BUSY_EINT_MASK 0x2000 /* IM_WSEQ_BUSY_EINT */
1386#define WM8903_IM_WSEQ_BUSY_EINT_SHIFT 13 /* IM_WSEQ_BUSY_EINT */
1387#define WM8903_IM_WSEQ_BUSY_EINT_WIDTH 1 /* IM_WSEQ_BUSY_EINT */
1388#define WM8903_IM_GP5_EINT 0x0010 /* IM_GP5_EINT */
1389#define WM8903_IM_GP5_EINT_MASK 0x0010 /* IM_GP5_EINT */
1390#define WM8903_IM_GP5_EINT_SHIFT 4 /* IM_GP5_EINT */
1391#define WM8903_IM_GP5_EINT_WIDTH 1 /* IM_GP5_EINT */
1392#define WM8903_IM_GP4_EINT 0x0008 /* IM_GP4_EINT */
1393#define WM8903_IM_GP4_EINT_MASK 0x0008 /* IM_GP4_EINT */
1394#define WM8903_IM_GP4_EINT_SHIFT 3 /* IM_GP4_EINT */
1395#define WM8903_IM_GP4_EINT_WIDTH 1 /* IM_GP4_EINT */
1396#define WM8903_IM_GP3_EINT 0x0004 /* IM_GP3_EINT */
1397#define WM8903_IM_GP3_EINT_MASK 0x0004 /* IM_GP3_EINT */
1398#define WM8903_IM_GP3_EINT_SHIFT 2 /* IM_GP3_EINT */
1399#define WM8903_IM_GP3_EINT_WIDTH 1 /* IM_GP3_EINT */
1400#define WM8903_IM_GP2_EINT 0x0002 /* IM_GP2_EINT */
1401#define WM8903_IM_GP2_EINT_MASK 0x0002 /* IM_GP2_EINT */
1402#define WM8903_IM_GP2_EINT_SHIFT 1 /* IM_GP2_EINT */
1403#define WM8903_IM_GP2_EINT_WIDTH 1 /* IM_GP2_EINT */
1404#define WM8903_IM_GP1_EINT 0x0001 /* IM_GP1_EINT */
1405#define WM8903_IM_GP1_EINT_MASK 0x0001 /* IM_GP1_EINT */
1406#define WM8903_IM_GP1_EINT_SHIFT 0 /* IM_GP1_EINT */
1407#define WM8903_IM_GP1_EINT_WIDTH 1 /* IM_GP1_EINT */
1408
1409/*
1410 * R123 (0x7B) - Interrupt Polarity 1
1411 */
1412#define WM8903_MICSHRT_INV 0x8000 /* MICSHRT_INV */
1413#define WM8903_MICSHRT_INV_MASK 0x8000 /* MICSHRT_INV */
1414#define WM8903_MICSHRT_INV_SHIFT 15 /* MICSHRT_INV */
1415#define WM8903_MICSHRT_INV_WIDTH 1 /* MICSHRT_INV */
1416#define WM8903_MICDET_INV 0x4000 /* MICDET_INV */
1417#define WM8903_MICDET_INV_MASK 0x4000 /* MICDET_INV */
1418#define WM8903_MICDET_INV_SHIFT 14 /* MICDET_INV */
1419#define WM8903_MICDET_INV_WIDTH 1 /* MICDET_INV */
1420
1421/*
1422 * R126 (0x7E) - Interrupt Control
1423 */
1424#define WM8903_IRQ_POL 0x0001 /* IRQ_POL */
1425#define WM8903_IRQ_POL_MASK 0x0001 /* IRQ_POL */
1426#define WM8903_IRQ_POL_SHIFT 0 /* IRQ_POL */
1427#define WM8903_IRQ_POL_WIDTH 1 /* IRQ_POL */
1428
1429/*
1430 * R129 (0x81) - Control Interface Test 1
1431 */
1432#define WM8903_USER_KEY 0x0002 /* USER_KEY */
1433#define WM8903_USER_KEY_MASK 0x0002 /* USER_KEY */
1434#define WM8903_USER_KEY_SHIFT 1 /* USER_KEY */
1435#define WM8903_USER_KEY_WIDTH 1 /* USER_KEY */
1436#define WM8903_TEST_KEY 0x0001 /* TEST_KEY */
1437#define WM8903_TEST_KEY_MASK 0x0001 /* TEST_KEY */
1438#define WM8903_TEST_KEY_SHIFT 0 /* TEST_KEY */
1439#define WM8903_TEST_KEY_WIDTH 1 /* TEST_KEY */
1440
1441/*
1442 * R149 (0x95) - Charge Pump Test 1
1443 */
1444#define WM8903_CP_SW_KELVIN_MODE_MASK 0x0006 /* CP_SW_KELVIN_MODE - [2:1] */
1445#define WM8903_CP_SW_KELVIN_MODE_SHIFT 1 /* CP_SW_KELVIN_MODE - [2:1] */
1446#define WM8903_CP_SW_KELVIN_MODE_WIDTH 2 /* CP_SW_KELVIN_MODE - [2:1] */
1447
1448/*
1449 * R164 (0xA4) - Clock Rate Test 4
1450 */
1451#define WM8903_ADC_DIG_MIC 0x0200 /* ADC_DIG_MIC */
1452#define WM8903_ADC_DIG_MIC_MASK 0x0200 /* ADC_DIG_MIC */
1453#define WM8903_ADC_DIG_MIC_SHIFT 9 /* ADC_DIG_MIC */
1454#define WM8903_ADC_DIG_MIC_WIDTH 1 /* ADC_DIG_MIC */
1455
1456/*
1457 * R172 (0xAC) - Analogue Output Bias 0
1458 */
1459#define WM8903_PGA_BIAS_MASK 0x0070 /* PGA_BIAS - [6:4] */
1460#define WM8903_PGA_BIAS_SHIFT 4 /* PGA_BIAS - [6:4] */
1461#define WM8903_PGA_BIAS_WIDTH 3 /* PGA_BIAS - [6:4] */
1462
1463#endif
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c
new file mode 100644
index 000000000000..f41a578ddd4f
--- /dev/null
+++ b/sound/soc/codecs/wm8971.c
@@ -0,0 +1,941 @@
1/*
2 * wm8971.c -- WM8971 ALSA SoC Audio driver
3 *
4 * Copyright 2005 Lab126, Inc.
5 *
6 * Author: Kenneth Kiraly <kiraly@lab126.com>
7 *
8 * Based on wm8753.c by Liam Girdwood
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 */
15
16#include <linux/module.h>
17#include <linux/moduleparam.h>
18#include <linux/init.h>
19#include <linux/delay.h>
20#include <linux/pm.h>
21#include <linux/i2c.h>
22#include <linux/platform_device.h>
23#include <sound/core.h>
24#include <sound/pcm.h>
25#include <sound/pcm_params.h>
26#include <sound/soc.h>
27#include <sound/soc-dapm.h>
28#include <sound/initval.h>
29
30#include "wm8971.h"
31
32#define WM8971_VERSION "0.9"
33
34#define WM8971_REG_COUNT 43
35
36static struct workqueue_struct *wm8971_workq = NULL;
37
38/* codec private data */
39struct wm8971_priv {
40 unsigned int sysclk;
41};
42
43/*
44 * wm8971 register cache
45 * We can't read the WM8971 register space when we
46 * are using 2 wire for device control, so we cache them instead.
47 */
48static const u16 wm8971_reg[] = {
49 0x0097, 0x0097, 0x0079, 0x0079, /* 0 */
50 0x0000, 0x0008, 0x0000, 0x000a, /* 4 */
51 0x0000, 0x0000, 0x00ff, 0x00ff, /* 8 */
52 0x000f, 0x000f, 0x0000, 0x0000, /* 12 */
53 0x0000, 0x007b, 0x0000, 0x0032, /* 16 */
54 0x0000, 0x00c3, 0x00c3, 0x00c0, /* 20 */
55 0x0000, 0x0000, 0x0000, 0x0000, /* 24 */
56 0x0000, 0x0000, 0x0000, 0x0000, /* 28 */
57 0x0000, 0x0000, 0x0050, 0x0050, /* 32 */
58 0x0050, 0x0050, 0x0050, 0x0050, /* 36 */
59 0x0079, 0x0079, 0x0079, /* 40 */
60};
61
62static inline unsigned int wm8971_read_reg_cache(struct snd_soc_codec *codec,
63 unsigned int reg)
64{
65 u16 *cache = codec->reg_cache;
66 if (reg < WM8971_REG_COUNT)
67 return cache[reg];
68
69 return -1;
70}
71
72static inline void wm8971_write_reg_cache(struct snd_soc_codec *codec,
73 unsigned int reg, unsigned int value)
74{
75 u16 *cache = codec->reg_cache;
76 if (reg < WM8971_REG_COUNT)
77 cache[reg] = value;
78}
79
80static int wm8971_write(struct snd_soc_codec *codec, unsigned int reg,
81 unsigned int value)
82{
83 u8 data[2];
84
85 /* data is
86 * D15..D9 WM8753 register offset
87 * D8...D0 register data
88 */
89 data[0] = (reg << 1) | ((value >> 8) & 0x0001);
90 data[1] = value & 0x00ff;
91
92 wm8971_write_reg_cache (codec, reg, value);
93 if (codec->hw_write(codec->control_data, data, 2) == 2)
94 return 0;
95 else
96 return -EIO;
97}
98
99#define wm8971_reset(c) wm8971_write(c, WM8971_RESET, 0)
100
101/* WM8971 Controls */
102static const char *wm8971_bass[] = { "Linear Control", "Adaptive Boost" };
103static const char *wm8971_bass_filter[] = { "130Hz @ 48kHz",
104 "200Hz @ 48kHz" };
105static const char *wm8971_treble[] = { "8kHz", "4kHz" };
106static const char *wm8971_alc_func[] = { "Off", "Right", "Left", "Stereo" };
107static const char *wm8971_ng_type[] = { "Constant PGA Gain",
108 "Mute ADC Output" };
109static const char *wm8971_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" };
110static const char *wm8971_mono_mux[] = {"Stereo", "Mono (Left)",
111 "Mono (Right)", "Digital Mono"};
112static const char *wm8971_dac_phase[] = { "Non Inverted", "Inverted" };
113static const char *wm8971_lline_mux[] = {"Line", "NC", "NC", "PGA",
114 "Differential"};
115static const char *wm8971_rline_mux[] = {"Line", "Mic", "NC", "PGA",
116 "Differential"};
117static const char *wm8971_lpga_sel[] = {"Line", "NC", "NC", "Differential"};
118static const char *wm8971_rpga_sel[] = {"Line", "Mic", "NC", "Differential"};
119static const char *wm8971_adcpol[] = {"Normal", "L Invert", "R Invert",
120 "L + R Invert"};
121
122static const struct soc_enum wm8971_enum[] = {
123 SOC_ENUM_SINGLE(WM8971_BASS, 7, 2, wm8971_bass), /* 0 */
124 SOC_ENUM_SINGLE(WM8971_BASS, 6, 2, wm8971_bass_filter),
125 SOC_ENUM_SINGLE(WM8971_TREBLE, 6, 2, wm8971_treble),
126 SOC_ENUM_SINGLE(WM8971_ALC1, 7, 4, wm8971_alc_func),
127 SOC_ENUM_SINGLE(WM8971_NGATE, 1, 2, wm8971_ng_type), /* 4 */
128 SOC_ENUM_SINGLE(WM8971_ADCDAC, 1, 4, wm8971_deemp),
129 SOC_ENUM_SINGLE(WM8971_ADCTL1, 4, 4, wm8971_mono_mux),
130 SOC_ENUM_SINGLE(WM8971_ADCTL1, 1, 2, wm8971_dac_phase),
131 SOC_ENUM_SINGLE(WM8971_LOUTM1, 0, 5, wm8971_lline_mux), /* 8 */
132 SOC_ENUM_SINGLE(WM8971_ROUTM1, 0, 5, wm8971_rline_mux),
133 SOC_ENUM_SINGLE(WM8971_LADCIN, 6, 4, wm8971_lpga_sel),
134 SOC_ENUM_SINGLE(WM8971_RADCIN, 6, 4, wm8971_rpga_sel),
135 SOC_ENUM_SINGLE(WM8971_ADCDAC, 5, 4, wm8971_adcpol), /* 12 */
136 SOC_ENUM_SINGLE(WM8971_ADCIN, 6, 4, wm8971_mono_mux),
137};
138
139static const struct snd_kcontrol_new wm8971_snd_controls[] = {
140 SOC_DOUBLE_R("Capture Volume", WM8971_LINVOL, WM8971_RINVOL, 0, 63, 0),
141 SOC_DOUBLE_R("Capture ZC Switch", WM8971_LINVOL, WM8971_RINVOL,
142 6, 1, 0),
143 SOC_DOUBLE_R("Capture Switch", WM8971_LINVOL, WM8971_RINVOL, 7, 1, 1),
144
145 SOC_DOUBLE_R("Headphone Playback ZC Switch", WM8971_LOUT1V,
146 WM8971_ROUT1V, 7, 1, 0),
147 SOC_DOUBLE_R("Speaker Playback ZC Switch", WM8971_LOUT2V,
148 WM8971_ROUT2V, 7, 1, 0),
149 SOC_SINGLE("Mono Playback ZC Switch", WM8971_MOUTV, 7, 1, 0),
150
151 SOC_DOUBLE_R("PCM Volume", WM8971_LDAC, WM8971_RDAC, 0, 255, 0),
152
153 SOC_DOUBLE_R("Bypass Left Playback Volume", WM8971_LOUTM1,
154 WM8971_LOUTM2, 4, 7, 1),
155 SOC_DOUBLE_R("Bypass Right Playback Volume", WM8971_ROUTM1,
156 WM8971_ROUTM2, 4, 7, 1),
157 SOC_DOUBLE_R("Bypass Mono Playback Volume", WM8971_MOUTM1,
158 WM8971_MOUTM2, 4, 7, 1),
159
160 SOC_DOUBLE_R("Headphone Playback Volume", WM8971_LOUT1V,
161 WM8971_ROUT1V, 0, 127, 0),
162 SOC_DOUBLE_R("Speaker Playback Volume", WM8971_LOUT2V,
163 WM8971_ROUT2V, 0, 127, 0),
164
165 SOC_ENUM("Bass Boost", wm8971_enum[0]),
166 SOC_ENUM("Bass Filter", wm8971_enum[1]),
167 SOC_SINGLE("Bass Volume", WM8971_BASS, 0, 7, 1),
168
169 SOC_SINGLE("Treble Volume", WM8971_TREBLE, 0, 7, 0),
170 SOC_ENUM("Treble Cut-off", wm8971_enum[2]),
171
172 SOC_SINGLE("Capture Filter Switch", WM8971_ADCDAC, 0, 1, 1),
173
174 SOC_SINGLE("ALC Target Volume", WM8971_ALC1, 0, 7, 0),
175 SOC_SINGLE("ALC Max Volume", WM8971_ALC1, 4, 7, 0),
176
177 SOC_SINGLE("ALC Capture Target Volume", WM8971_ALC1, 0, 7, 0),
178 SOC_SINGLE("ALC Capture Max Volume", WM8971_ALC1, 4, 7, 0),
179 SOC_ENUM("ALC Capture Function", wm8971_enum[3]),
180 SOC_SINGLE("ALC Capture ZC Switch", WM8971_ALC2, 7, 1, 0),
181 SOC_SINGLE("ALC Capture Hold Time", WM8971_ALC2, 0, 15, 0),
182 SOC_SINGLE("ALC Capture Decay Time", WM8971_ALC3, 4, 15, 0),
183 SOC_SINGLE("ALC Capture Attack Time", WM8971_ALC3, 0, 15, 0),
184 SOC_SINGLE("ALC Capture NG Threshold", WM8971_NGATE, 3, 31, 0),
185 SOC_ENUM("ALC Capture NG Type", wm8971_enum[4]),
186 SOC_SINGLE("ALC Capture NG Switch", WM8971_NGATE, 0, 1, 0),
187
188 SOC_SINGLE("Capture 6dB Attenuate", WM8971_ADCDAC, 8, 1, 0),
189 SOC_SINGLE("Playback 6dB Attenuate", WM8971_ADCDAC, 7, 1, 0),
190
191 SOC_ENUM("Playback De-emphasis", wm8971_enum[5]),
192 SOC_ENUM("Playback Function", wm8971_enum[6]),
193 SOC_ENUM("Playback Phase", wm8971_enum[7]),
194
195 SOC_DOUBLE_R("Mic Boost", WM8971_LADCIN, WM8971_RADCIN, 4, 3, 0),
196};
197
198/* add non-DAPM controls */
199static int wm8971_add_controls(struct snd_soc_codec *codec)
200{
201 int err, i;
202
203 for (i = 0; i < ARRAY_SIZE(wm8971_snd_controls); i++) {
204 err = snd_ctl_add(codec->card,
205 snd_soc_cnew(&wm8971_snd_controls[i],
206 codec, NULL));
207 if (err < 0)
208 return err;
209 }
210 return 0;
211}
212
213/*
214 * DAPM Controls
215 */
216
217/* Left Mixer */
218static const struct snd_kcontrol_new wm8971_left_mixer_controls[] = {
219SOC_DAPM_SINGLE("Playback Switch", WM8971_LOUTM1, 8, 1, 0),
220SOC_DAPM_SINGLE("Left Bypass Switch", WM8971_LOUTM1, 7, 1, 0),
221SOC_DAPM_SINGLE("Right Playback Switch", WM8971_LOUTM2, 8, 1, 0),
222SOC_DAPM_SINGLE("Right Bypass Switch", WM8971_LOUTM2, 7, 1, 0),
223};
224
225/* Right Mixer */
226static const struct snd_kcontrol_new wm8971_right_mixer_controls[] = {
227SOC_DAPM_SINGLE("Left Playback Switch", WM8971_ROUTM1, 8, 1, 0),
228SOC_DAPM_SINGLE("Left Bypass Switch", WM8971_ROUTM1, 7, 1, 0),
229SOC_DAPM_SINGLE("Playback Switch", WM8971_ROUTM2, 8, 1, 0),
230SOC_DAPM_SINGLE("Right Bypass Switch", WM8971_ROUTM2, 7, 1, 0),
231};
232
233/* Mono Mixer */
234static const struct snd_kcontrol_new wm8971_mono_mixer_controls[] = {
235SOC_DAPM_SINGLE("Left Playback Switch", WM8971_MOUTM1, 8, 1, 0),
236SOC_DAPM_SINGLE("Left Bypass Switch", WM8971_MOUTM1, 7, 1, 0),
237SOC_DAPM_SINGLE("Right Playback Switch", WM8971_MOUTM2, 8, 1, 0),
238SOC_DAPM_SINGLE("Right Bypass Switch", WM8971_MOUTM2, 7, 1, 0),
239};
240
241/* Left Line Mux */
242static const struct snd_kcontrol_new wm8971_left_line_controls =
243SOC_DAPM_ENUM("Route", wm8971_enum[8]);
244
245/* Right Line Mux */
246static const struct snd_kcontrol_new wm8971_right_line_controls =
247SOC_DAPM_ENUM("Route", wm8971_enum[9]);
248
249/* Left PGA Mux */
250static const struct snd_kcontrol_new wm8971_left_pga_controls =
251SOC_DAPM_ENUM("Route", wm8971_enum[10]);
252
253/* Right PGA Mux */
254static const struct snd_kcontrol_new wm8971_right_pga_controls =
255SOC_DAPM_ENUM("Route", wm8971_enum[11]);
256
257/* Mono ADC Mux */
258static const struct snd_kcontrol_new wm8971_monomux_controls =
259SOC_DAPM_ENUM("Route", wm8971_enum[13]);
260
261static const struct snd_soc_dapm_widget wm8971_dapm_widgets[] = {
262 SND_SOC_DAPM_MIXER("Left Mixer", SND_SOC_NOPM, 0, 0,
263 &wm8971_left_mixer_controls[0],
264 ARRAY_SIZE(wm8971_left_mixer_controls)),
265 SND_SOC_DAPM_MIXER("Right Mixer", SND_SOC_NOPM, 0, 0,
266 &wm8971_right_mixer_controls[0],
267 ARRAY_SIZE(wm8971_right_mixer_controls)),
268 SND_SOC_DAPM_MIXER("Mono Mixer", WM8971_PWR2, 2, 0,
269 &wm8971_mono_mixer_controls[0],
270 ARRAY_SIZE(wm8971_mono_mixer_controls)),
271
272 SND_SOC_DAPM_PGA("Right Out 2", WM8971_PWR2, 3, 0, NULL, 0),
273 SND_SOC_DAPM_PGA("Left Out 2", WM8971_PWR2, 4, 0, NULL, 0),
274 SND_SOC_DAPM_PGA("Right Out 1", WM8971_PWR2, 5, 0, NULL, 0),
275 SND_SOC_DAPM_PGA("Left Out 1", WM8971_PWR2, 6, 0, NULL, 0),
276 SND_SOC_DAPM_DAC("Right DAC", "Right Playback", WM8971_PWR2, 7, 0),
277 SND_SOC_DAPM_DAC("Left DAC", "Left Playback", WM8971_PWR2, 8, 0),
278 SND_SOC_DAPM_PGA("Mono Out 1", WM8971_PWR2, 2, 0, NULL, 0),
279
280 SND_SOC_DAPM_MICBIAS("Mic Bias", WM8971_PWR1, 1, 0),
281 SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8971_PWR1, 2, 0),
282 SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8971_PWR1, 3, 0),
283
284 SND_SOC_DAPM_MUX("Left PGA Mux", WM8971_PWR1, 5, 0,
285 &wm8971_left_pga_controls),
286 SND_SOC_DAPM_MUX("Right PGA Mux", WM8971_PWR1, 4, 0,
287 &wm8971_right_pga_controls),
288 SND_SOC_DAPM_MUX("Left Line Mux", SND_SOC_NOPM, 0, 0,
289 &wm8971_left_line_controls),
290 SND_SOC_DAPM_MUX("Right Line Mux", SND_SOC_NOPM, 0, 0,
291 &wm8971_right_line_controls),
292
293 SND_SOC_DAPM_MUX("Left ADC Mux", SND_SOC_NOPM, 0, 0,
294 &wm8971_monomux_controls),
295 SND_SOC_DAPM_MUX("Right ADC Mux", SND_SOC_NOPM, 0, 0,
296 &wm8971_monomux_controls),
297
298 SND_SOC_DAPM_OUTPUT("LOUT1"),
299 SND_SOC_DAPM_OUTPUT("ROUT1"),
300 SND_SOC_DAPM_OUTPUT("LOUT2"),
301 SND_SOC_DAPM_OUTPUT("ROUT2"),
302 SND_SOC_DAPM_OUTPUT("MONO"),
303
304 SND_SOC_DAPM_INPUT("LINPUT1"),
305 SND_SOC_DAPM_INPUT("RINPUT1"),
306 SND_SOC_DAPM_INPUT("MIC"),
307};
308
309static const struct snd_soc_dapm_route audio_map[] = {
310 /* left mixer */
311 {"Left Mixer", "Playback Switch", "Left DAC"},
312 {"Left Mixer", "Left Bypass Switch", "Left Line Mux"},
313 {"Left Mixer", "Right Playback Switch", "Right DAC"},
314 {"Left Mixer", "Right Bypass Switch", "Right Line Mux"},
315
316 /* right mixer */
317 {"Right Mixer", "Left Playback Switch", "Left DAC"},
318 {"Right Mixer", "Left Bypass Switch", "Left Line Mux"},
319 {"Right Mixer", "Playback Switch", "Right DAC"},
320 {"Right Mixer", "Right Bypass Switch", "Right Line Mux"},
321
322 /* left out 1 */
323 {"Left Out 1", NULL, "Left Mixer"},
324 {"LOUT1", NULL, "Left Out 1"},
325
326 /* left out 2 */
327 {"Left Out 2", NULL, "Left Mixer"},
328 {"LOUT2", NULL, "Left Out 2"},
329
330 /* right out 1 */
331 {"Right Out 1", NULL, "Right Mixer"},
332 {"ROUT1", NULL, "Right Out 1"},
333
334 /* right out 2 */
335 {"Right Out 2", NULL, "Right Mixer"},
336 {"ROUT2", NULL, "Right Out 2"},
337
338 /* mono mixer */
339 {"Mono Mixer", "Left Playback Switch", "Left DAC"},
340 {"Mono Mixer", "Left Bypass Switch", "Left Line Mux"},
341 {"Mono Mixer", "Right Playback Switch", "Right DAC"},
342 {"Mono Mixer", "Right Bypass Switch", "Right Line Mux"},
343
344 /* mono out */
345 {"Mono Out", NULL, "Mono Mixer"},
346 {"MONO1", NULL, "Mono Out"},
347
348 /* Left Line Mux */
349 {"Left Line Mux", "Line", "LINPUT1"},
350 {"Left Line Mux", "PGA", "Left PGA Mux"},
351 {"Left Line Mux", "Differential", "Differential Mux"},
352
353 /* Right Line Mux */
354 {"Right Line Mux", "Line", "RINPUT1"},
355 {"Right Line Mux", "Mic", "MIC"},
356 {"Right Line Mux", "PGA", "Right PGA Mux"},
357 {"Right Line Mux", "Differential", "Differential Mux"},
358
359 /* Left PGA Mux */
360 {"Left PGA Mux", "Line", "LINPUT1"},
361 {"Left PGA Mux", "Differential", "Differential Mux"},
362
363 /* Right PGA Mux */
364 {"Right PGA Mux", "Line", "RINPUT1"},
365 {"Right PGA Mux", "Differential", "Differential Mux"},
366
367 /* Differential Mux */
368 {"Differential Mux", "Line", "LINPUT1"},
369 {"Differential Mux", "Line", "RINPUT1"},
370
371 /* Left ADC Mux */
372 {"Left ADC Mux", "Stereo", "Left PGA Mux"},
373 {"Left ADC Mux", "Mono (Left)", "Left PGA Mux"},
374 {"Left ADC Mux", "Digital Mono", "Left PGA Mux"},
375
376 /* Right ADC Mux */
377 {"Right ADC Mux", "Stereo", "Right PGA Mux"},
378 {"Right ADC Mux", "Mono (Right)", "Right PGA Mux"},
379 {"Right ADC Mux", "Digital Mono", "Right PGA Mux"},
380
381 /* ADC */
382 {"Left ADC", NULL, "Left ADC Mux"},
383 {"Right ADC", NULL, "Right ADC Mux"},
384};
385
386static int wm8971_add_widgets(struct snd_soc_codec *codec)
387{
388 snd_soc_dapm_new_controls(codec, wm8971_dapm_widgets,
389 ARRAY_SIZE(wm8971_dapm_widgets));
390
391 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
392
393 snd_soc_dapm_new_widgets(codec);
394
395 return 0;
396}
397
398struct _coeff_div {
399 u32 mclk;
400 u32 rate;
401 u16 fs;
402 u8 sr:5;
403 u8 usb:1;
404};
405
406/* codec hifi mclk clock divider coefficients */
407static const struct _coeff_div coeff_div[] = {
408 /* 8k */
409 {12288000, 8000, 1536, 0x6, 0x0},
410 {11289600, 8000, 1408, 0x16, 0x0},
411 {18432000, 8000, 2304, 0x7, 0x0},
412 {16934400, 8000, 2112, 0x17, 0x0},
413 {12000000, 8000, 1500, 0x6, 0x1},
414
415 /* 11.025k */
416 {11289600, 11025, 1024, 0x18, 0x0},
417 {16934400, 11025, 1536, 0x19, 0x0},
418 {12000000, 11025, 1088, 0x19, 0x1},
419
420 /* 16k */
421 {12288000, 16000, 768, 0xa, 0x0},
422 {18432000, 16000, 1152, 0xb, 0x0},
423 {12000000, 16000, 750, 0xa, 0x1},
424
425 /* 22.05k */
426 {11289600, 22050, 512, 0x1a, 0x0},
427 {16934400, 22050, 768, 0x1b, 0x0},
428 {12000000, 22050, 544, 0x1b, 0x1},
429
430 /* 32k */
431 {12288000, 32000, 384, 0xc, 0x0},
432 {18432000, 32000, 576, 0xd, 0x0},
433 {12000000, 32000, 375, 0xa, 0x1},
434
435 /* 44.1k */
436 {11289600, 44100, 256, 0x10, 0x0},
437 {16934400, 44100, 384, 0x11, 0x0},
438 {12000000, 44100, 272, 0x11, 0x1},
439
440 /* 48k */
441 {12288000, 48000, 256, 0x0, 0x0},
442 {18432000, 48000, 384, 0x1, 0x0},
443 {12000000, 48000, 250, 0x0, 0x1},
444
445 /* 88.2k */
446 {11289600, 88200, 128, 0x1e, 0x0},
447 {16934400, 88200, 192, 0x1f, 0x0},
448 {12000000, 88200, 136, 0x1f, 0x1},
449
450 /* 96k */
451 {12288000, 96000, 128, 0xe, 0x0},
452 {18432000, 96000, 192, 0xf, 0x0},
453 {12000000, 96000, 125, 0xe, 0x1},
454};
455
456static int get_coeff(int mclk, int rate)
457{
458 int i;
459
460 for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
461 if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk)
462 return i;
463 }
464 return -EINVAL;
465}
466
467static int wm8971_set_dai_sysclk(struct snd_soc_dai *codec_dai,
468 int clk_id, unsigned int freq, int dir)
469{
470 struct snd_soc_codec *codec = codec_dai->codec;
471 struct wm8971_priv *wm8971 = codec->private_data;
472
473 switch (freq) {
474 case 11289600:
475 case 12000000:
476 case 12288000:
477 case 16934400:
478 case 18432000:
479 wm8971->sysclk = freq;
480 return 0;
481 }
482 return -EINVAL;
483}
484
485static int wm8971_set_dai_fmt(struct snd_soc_dai *codec_dai,
486 unsigned int fmt)
487{
488 struct snd_soc_codec *codec = codec_dai->codec;
489 u16 iface = 0;
490
491 /* set master/slave audio interface */
492 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
493 case SND_SOC_DAIFMT_CBM_CFM:
494 iface = 0x0040;
495 break;
496 case SND_SOC_DAIFMT_CBS_CFS:
497 break;
498 default:
499 return -EINVAL;
500 }
501
502 /* interface format */
503 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
504 case SND_SOC_DAIFMT_I2S:
505 iface |= 0x0002;
506 break;
507 case SND_SOC_DAIFMT_RIGHT_J:
508 break;
509 case SND_SOC_DAIFMT_LEFT_J:
510 iface |= 0x0001;
511 break;
512 case SND_SOC_DAIFMT_DSP_A:
513 iface |= 0x0003;
514 break;
515 case SND_SOC_DAIFMT_DSP_B:
516 iface |= 0x0013;
517 break;
518 default:
519 return -EINVAL;
520 }
521
522 /* clock inversion */
523 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
524 case SND_SOC_DAIFMT_NB_NF:
525 break;
526 case SND_SOC_DAIFMT_IB_IF:
527 iface |= 0x0090;
528 break;
529 case SND_SOC_DAIFMT_IB_NF:
530 iface |= 0x0080;
531 break;
532 case SND_SOC_DAIFMT_NB_IF:
533 iface |= 0x0010;
534 break;
535 default:
536 return -EINVAL;
537 }
538
539 wm8971_write(codec, WM8971_IFACE, iface);
540 return 0;
541}
542
543static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream,
544 struct snd_pcm_hw_params *params)
545{
546 struct snd_soc_pcm_runtime *rtd = substream->private_data;
547 struct snd_soc_device *socdev = rtd->socdev;
548 struct snd_soc_codec *codec = socdev->codec;
549 struct wm8971_priv *wm8971 = codec->private_data;
550 u16 iface = wm8971_read_reg_cache(codec, WM8971_IFACE) & 0x1f3;
551 u16 srate = wm8971_read_reg_cache(codec, WM8971_SRATE) & 0x1c0;
552 int coeff = get_coeff(wm8971->sysclk, params_rate(params));
553
554 /* bit size */
555 switch (params_format(params)) {
556 case SNDRV_PCM_FORMAT_S16_LE:
557 break;
558 case SNDRV_PCM_FORMAT_S20_3LE:
559 iface |= 0x0004;
560 break;
561 case SNDRV_PCM_FORMAT_S24_LE:
562 iface |= 0x0008;
563 break;
564 case SNDRV_PCM_FORMAT_S32_LE:
565 iface |= 0x000c;
566 break;
567 }
568
569 /* set iface & srate */
570 wm8971_write(codec, WM8971_IFACE, iface);
571 if (coeff >= 0)
572 wm8971_write(codec, WM8971_SRATE, srate |
573 (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb);
574
575 return 0;
576}
577
578static int wm8971_mute(struct snd_soc_dai *dai, int mute)
579{
580 struct snd_soc_codec *codec = dai->codec;
581 u16 mute_reg = wm8971_read_reg_cache(codec, WM8971_ADCDAC) & 0xfff7;
582
583 if (mute)
584 wm8971_write(codec, WM8971_ADCDAC, mute_reg | 0x8);
585 else
586 wm8971_write(codec, WM8971_ADCDAC, mute_reg);
587 return 0;
588}
589
590static int wm8971_set_bias_level(struct snd_soc_codec *codec,
591 enum snd_soc_bias_level level)
592{
593 u16 pwr_reg = wm8971_read_reg_cache(codec, WM8971_PWR1) & 0xfe3e;
594
595 switch (level) {
596 case SND_SOC_BIAS_ON:
597 /* set vmid to 50k and unmute dac */
598 wm8971_write(codec, WM8971_PWR1, pwr_reg | 0x00c1);
599 break;
600 case SND_SOC_BIAS_PREPARE:
601 break;
602 case SND_SOC_BIAS_STANDBY:
603 /* mute dac and set vmid to 500k, enable VREF */
604 wm8971_write(codec, WM8971_PWR1, pwr_reg | 0x0140);
605 break;
606 case SND_SOC_BIAS_OFF:
607 wm8971_write(codec, WM8971_PWR1, 0x0001);
608 break;
609 }
610 codec->bias_level = level;
611 return 0;
612}
613
614#define WM8971_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
615 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
616 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
617
618#define WM8971_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
619 SNDRV_PCM_FMTBIT_S24_LE)
620
621struct snd_soc_dai wm8971_dai = {
622 .name = "WM8971",
623 .playback = {
624 .stream_name = "Playback",
625 .channels_min = 1,
626 .channels_max = 2,
627 .rates = WM8971_RATES,
628 .formats = WM8971_FORMATS,},
629 .capture = {
630 .stream_name = "Capture",
631 .channels_min = 1,
632 .channels_max = 2,
633 .rates = WM8971_RATES,
634 .formats = WM8971_FORMATS,},
635 .ops = {
636 .hw_params = wm8971_pcm_hw_params,
637 },
638 .dai_ops = {
639 .digital_mute = wm8971_mute,
640 .set_fmt = wm8971_set_dai_fmt,
641 .set_sysclk = wm8971_set_dai_sysclk,
642 },
643};
644EXPORT_SYMBOL_GPL(wm8971_dai);
645
646static void wm8971_work(struct work_struct *work)
647{
648 struct snd_soc_codec *codec =
649 container_of(work, struct snd_soc_codec, delayed_work.work);
650 wm8971_set_bias_level(codec, codec->bias_level);
651}
652
653static int wm8971_suspend(struct platform_device *pdev, pm_message_t state)
654{
655 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
656 struct snd_soc_codec *codec = socdev->codec;
657
658 wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF);
659 return 0;
660}
661
662static int wm8971_resume(struct platform_device *pdev)
663{
664 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
665 struct snd_soc_codec *codec = socdev->codec;
666 int i;
667 u8 data[2];
668 u16 *cache = codec->reg_cache;
669 u16 reg;
670
671 /* Sync reg_cache with the hardware */
672 for (i = 0; i < ARRAY_SIZE(wm8971_reg); i++) {
673 if (i + 1 == WM8971_RESET)
674 continue;
675 data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
676 data[1] = cache[i] & 0x00ff;
677 codec->hw_write(codec->control_data, data, 2);
678 }
679
680 wm8971_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
681
682 /* charge wm8971 caps */
683 if (codec->suspend_bias_level == SND_SOC_BIAS_ON) {
684 reg = wm8971_read_reg_cache(codec, WM8971_PWR1) & 0xfe3e;
685 wm8971_write(codec, WM8971_PWR1, reg | 0x01c0);
686 codec->bias_level = SND_SOC_BIAS_ON;
687 queue_delayed_work(wm8971_workq, &codec->delayed_work,
688 msecs_to_jiffies(1000));
689 }
690
691 return 0;
692}
693
694static int wm8971_init(struct snd_soc_device *socdev)
695{
696 struct snd_soc_codec *codec = socdev->codec;
697 int reg, ret = 0;
698
699 codec->name = "WM8971";
700 codec->owner = THIS_MODULE;
701 codec->read = wm8971_read_reg_cache;
702 codec->write = wm8971_write;
703 codec->set_bias_level = wm8971_set_bias_level;
704 codec->dai = &wm8971_dai;
705 codec->reg_cache_size = ARRAY_SIZE(wm8971_reg);
706 codec->num_dai = 1;
707 codec->reg_cache = kmemdup(wm8971_reg, sizeof(wm8971_reg), GFP_KERNEL);
708
709 if (codec->reg_cache == NULL)
710 return -ENOMEM;
711
712 wm8971_reset(codec);
713
714 /* register pcms */
715 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
716 if (ret < 0) {
717 printk(KERN_ERR "wm8971: failed to create pcms\n");
718 goto pcm_err;
719 }
720
721 /* charge output caps - set vmid to 5k for quick power up */
722 reg = wm8971_read_reg_cache(codec, WM8971_PWR1) & 0xfe3e;
723 wm8971_write(codec, WM8971_PWR1, reg | 0x01c0);
724 codec->bias_level = SND_SOC_BIAS_STANDBY;
725 queue_delayed_work(wm8971_workq, &codec->delayed_work,
726 msecs_to_jiffies(1000));
727
728 /* set the update bits */
729 reg = wm8971_read_reg_cache(codec, WM8971_LDAC);
730 wm8971_write(codec, WM8971_LDAC, reg | 0x0100);
731 reg = wm8971_read_reg_cache(codec, WM8971_RDAC);
732 wm8971_write(codec, WM8971_RDAC, reg | 0x0100);
733
734 reg = wm8971_read_reg_cache(codec, WM8971_LOUT1V);
735 wm8971_write(codec, WM8971_LOUT1V, reg | 0x0100);
736 reg = wm8971_read_reg_cache(codec, WM8971_ROUT1V);
737 wm8971_write(codec, WM8971_ROUT1V, reg | 0x0100);
738
739 reg = wm8971_read_reg_cache(codec, WM8971_LOUT2V);
740 wm8971_write(codec, WM8971_LOUT2V, reg | 0x0100);
741 reg = wm8971_read_reg_cache(codec, WM8971_ROUT2V);
742 wm8971_write(codec, WM8971_ROUT2V, reg | 0x0100);
743
744 reg = wm8971_read_reg_cache(codec, WM8971_LINVOL);
745 wm8971_write(codec, WM8971_LINVOL, reg | 0x0100);
746 reg = wm8971_read_reg_cache(codec, WM8971_RINVOL);
747 wm8971_write(codec, WM8971_RINVOL, reg | 0x0100);
748
749 wm8971_add_controls(codec);
750 wm8971_add_widgets(codec);
751 ret = snd_soc_register_card(socdev);
752 if (ret < 0) {
753 printk(KERN_ERR "wm8971: failed to register card\n");
754 goto card_err;
755 }
756 return ret;
757
758card_err:
759 snd_soc_free_pcms(socdev);
760 snd_soc_dapm_free(socdev);
761pcm_err:
762 kfree(codec->reg_cache);
763 return ret;
764}
765
766/* If the i2c layer weren't so broken, we could pass this kind of data
767 around */
768static struct snd_soc_device *wm8971_socdev;
769
770#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
771
772static int wm8971_i2c_probe(struct i2c_client *i2c,
773 const struct i2c_device_id *id)
774{
775 struct snd_soc_device *socdev = wm8971_socdev;
776 struct snd_soc_codec *codec = socdev->codec;
777 int ret;
778
779 i2c_set_clientdata(i2c, codec);
780
781 codec->control_data = i2c;
782
783 ret = wm8971_init(socdev);
784 if (ret < 0)
785 pr_err("failed to initialise WM8971\n");
786
787 return ret;
788}
789
790static int wm8971_i2c_remove(struct i2c_client *client)
791{
792 struct snd_soc_codec *codec = i2c_get_clientdata(client);
793 kfree(codec->reg_cache);
794 return 0;
795}
796
797static const struct i2c_device_id wm8971_i2c_id[] = {
798 { "wm8971", 0 },
799 { }
800};
801MODULE_DEVICE_TABLE(i2c, wm8971_i2c_id);
802
803static struct i2c_driver wm8971_i2c_driver = {
804 .driver = {
805 .name = "WM8971 I2C Codec",
806 .owner = THIS_MODULE,
807 },
808 .probe = wm8971_i2c_probe,
809 .remove = wm8971_i2c_remove,
810 .id_table = wm8971_i2c_id,
811};
812
813static int wm8971_add_i2c_device(struct platform_device *pdev,
814 const struct wm8971_setup_data *setup)
815{
816 struct i2c_board_info info;
817 struct i2c_adapter *adapter;
818 struct i2c_client *client;
819 int ret;
820
821 ret = i2c_add_driver(&wm8971_i2c_driver);
822 if (ret != 0) {
823 dev_err(&pdev->dev, "can't add i2c driver\n");
824 return ret;
825 }
826
827 memset(&info, 0, sizeof(struct i2c_board_info));
828 info.addr = setup->i2c_address;
829 strlcpy(info.type, "wm8971", I2C_NAME_SIZE);
830
831 adapter = i2c_get_adapter(setup->i2c_bus);
832 if (!adapter) {
833 dev_err(&pdev->dev, "can't get i2c adapter %d\n",
834 setup->i2c_bus);
835 goto err_driver;
836 }
837
838 client = i2c_new_device(adapter, &info);
839 i2c_put_adapter(adapter);
840 if (!client) {
841 dev_err(&pdev->dev, "can't add i2c device at 0x%x\n",
842 (unsigned int)info.addr);
843 goto err_driver;
844 }
845
846 return 0;
847
848err_driver:
849 i2c_del_driver(&wm8971_i2c_driver);
850 return -ENODEV;
851}
852
853#endif
854
855static int wm8971_probe(struct platform_device *pdev)
856{
857 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
858 struct wm8971_setup_data *setup;
859 struct snd_soc_codec *codec;
860 struct wm8971_priv *wm8971;
861 int ret = 0;
862
863 pr_info("WM8971 Audio Codec %s", WM8971_VERSION);
864
865 setup = socdev->codec_data;
866 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
867 if (codec == NULL)
868 return -ENOMEM;
869
870 wm8971 = kzalloc(sizeof(struct wm8971_priv), GFP_KERNEL);
871 if (wm8971 == NULL) {
872 kfree(codec);
873 return -ENOMEM;
874 }
875
876 codec->private_data = wm8971;
877 socdev->codec = codec;
878 mutex_init(&codec->mutex);
879 INIT_LIST_HEAD(&codec->dapm_widgets);
880 INIT_LIST_HEAD(&codec->dapm_paths);
881 wm8971_socdev = socdev;
882
883 INIT_DELAYED_WORK(&codec->delayed_work, wm8971_work);
884 wm8971_workq = create_workqueue("wm8971");
885 if (wm8971_workq == NULL) {
886 kfree(codec->private_data);
887 kfree(codec);
888 return -ENOMEM;
889 }
890
891#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
892 if (setup->i2c_address) {
893 codec->hw_write = (hw_write_t)i2c_master_send;
894 ret = wm8971_add_i2c_device(pdev, setup);
895 }
896#endif
897 /* Add other interfaces here */
898
899 if (ret != 0) {
900 destroy_workqueue(wm8971_workq);
901 kfree(codec->private_data);
902 kfree(codec);
903 }
904
905 return ret;
906}
907
908/* power down chip */
909static int wm8971_remove(struct platform_device *pdev)
910{
911 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
912 struct snd_soc_codec *codec = socdev->codec;
913
914 if (codec->control_data)
915 wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF);
916 if (wm8971_workq)
917 destroy_workqueue(wm8971_workq);
918 snd_soc_free_pcms(socdev);
919 snd_soc_dapm_free(socdev);
920#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
921 i2c_unregister_device(codec->control_data);
922 i2c_del_driver(&wm8971_i2c_driver);
923#endif
924 kfree(codec->private_data);
925 kfree(codec);
926
927 return 0;
928}
929
930struct snd_soc_codec_device soc_codec_dev_wm8971 = {
931 .probe = wm8971_probe,
932 .remove = wm8971_remove,
933 .suspend = wm8971_suspend,
934 .resume = wm8971_resume,
935};
936
937EXPORT_SYMBOL_GPL(soc_codec_dev_wm8971);
938
939MODULE_DESCRIPTION("ASoC WM8971 driver");
940MODULE_AUTHOR("Lab126");
941MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8971.h b/sound/soc/codecs/wm8971.h
new file mode 100644
index 000000000000..ef4f08f9f344
--- /dev/null
+++ b/sound/soc/codecs/wm8971.h
@@ -0,0 +1,64 @@
1/*
2 * wm8971.h -- audio driver for WM8971
3 *
4 * Copyright 2005 Lab126, Inc.
5 *
6 * Author: Kenneth Kiraly <kiraly@lab126.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 */
14
15#ifndef _WM8971_H
16#define _WM8971_H
17
18#define WM8971_LINVOL 0x00
19#define WM8971_RINVOL 0x01
20#define WM8971_LOUT1V 0x02
21#define WM8971_ROUT1V 0x03
22#define WM8971_ADCDAC 0x05
23#define WM8971_IFACE 0x07
24#define WM8971_SRATE 0x08
25#define WM8971_LDAC 0x0a
26#define WM8971_RDAC 0x0b
27#define WM8971_BASS 0x0c
28#define WM8971_TREBLE 0x0d
29#define WM8971_RESET 0x0f
30#define WM8971_ALC1 0x11
31#define WM8971_ALC2 0x12
32#define WM8971_ALC3 0x13
33#define WM8971_NGATE 0x14
34#define WM8971_LADC 0x15
35#define WM8971_RADC 0x16
36#define WM8971_ADCTL1 0x17
37#define WM8971_ADCTL2 0x18
38#define WM8971_PWR1 0x19
39#define WM8971_PWR2 0x1a
40#define WM8971_ADCTL3 0x1b
41#define WM8971_ADCIN 0x1f
42#define WM8971_LADCIN 0x20
43#define WM8971_RADCIN 0x21
44#define WM8971_LOUTM1 0x22
45#define WM8971_LOUTM2 0x23
46#define WM8971_ROUTM1 0x24
47#define WM8971_ROUTM2 0x25
48#define WM8971_MOUTM1 0x26
49#define WM8971_MOUTM2 0x27
50#define WM8971_LOUT2V 0x28
51#define WM8971_ROUT2V 0x29
52#define WM8971_MOUTV 0x2A
53
54#define WM8971_SYSCLK 0
55
56struct wm8971_setup_data {
57 int i2c_bus;
58 unsigned short i2c_address;
59};
60
61extern struct snd_soc_dai wm8971_dai;
62extern struct snd_soc_codec_device soc_codec_dev_wm8971;
63
64#endif
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c
index dd995ef448b4..572d22b0880b 100644
--- a/sound/soc/codecs/wm8990.c
+++ b/sound/soc/codecs/wm8990.c
@@ -30,7 +30,6 @@
30 30
31#include "wm8990.h" 31#include "wm8990.h"
32 32
33#define AUDIO_NAME "wm8990"
34#define WM8990_VERSION "0.2" 33#define WM8990_VERSION "0.2"
35 34
36/* codec private data */ 35/* codec private data */
@@ -1477,81 +1476,86 @@ static struct snd_soc_device *wm8990_socdev;
1477 * low = 0x34 1476 * low = 0x34
1478 * high = 0x36 1477 * high = 0x36
1479 */ 1478 */
1480static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
1481 1479
1482/* Magic definition of all other variables and things */ 1480static int wm8990_i2c_probe(struct i2c_client *i2c,
1483I2C_CLIENT_INSMOD; 1481 const struct i2c_device_id *id)
1484
1485static struct i2c_driver wm8990_i2c_driver;
1486static struct i2c_client client_template;
1487
1488static int wm8990_codec_probe(struct i2c_adapter *adap, int addr, int kind)
1489{ 1482{
1490 struct snd_soc_device *socdev = wm8990_socdev; 1483 struct snd_soc_device *socdev = wm8990_socdev;
1491 struct wm8990_setup_data *setup = socdev->codec_data;
1492 struct snd_soc_codec *codec = socdev->codec; 1484 struct snd_soc_codec *codec = socdev->codec;
1493 struct i2c_client *i2c;
1494 int ret; 1485 int ret;
1495 1486
1496 if (addr != setup->i2c_address)
1497 return -ENODEV;
1498
1499 client_template.adapter = adap;
1500 client_template.addr = addr;
1501
1502 i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
1503 if (i2c == NULL)
1504 return -ENOMEM;
1505
1506 i2c_set_clientdata(i2c, codec); 1487 i2c_set_clientdata(i2c, codec);
1507 codec->control_data = i2c; 1488 codec->control_data = i2c;
1508 1489
1509 ret = i2c_attach_client(i2c);
1510 if (ret < 0) {
1511 pr_err("failed to attach codec at addr %x\n", addr);
1512 goto err;
1513 }
1514
1515 ret = wm8990_init(socdev); 1490 ret = wm8990_init(socdev);
1516 if (ret < 0) { 1491 if (ret < 0)
1517 pr_err("failed to initialise WM8990\n"); 1492 pr_err("failed to initialise WM8990\n");
1518 goto err;
1519 }
1520 return ret;
1521 1493
1522err:
1523 kfree(i2c);
1524 return ret; 1494 return ret;
1525} 1495}
1526 1496
1527static int wm8990_i2c_detach(struct i2c_client *client) 1497static int wm8990_i2c_remove(struct i2c_client *client)
1528{ 1498{
1529 struct snd_soc_codec *codec = i2c_get_clientdata(client); 1499 struct snd_soc_codec *codec = i2c_get_clientdata(client);
1530 i2c_detach_client(client);
1531 kfree(codec->reg_cache); 1500 kfree(codec->reg_cache);
1532 kfree(client);
1533 return 0; 1501 return 0;
1534} 1502}
1535 1503
1536static int wm8990_i2c_attach(struct i2c_adapter *adap) 1504static const struct i2c_device_id wm8990_i2c_id[] = {
1537{ 1505 { "wm8990", 0 },
1538 return i2c_probe(adap, &addr_data, wm8990_codec_probe); 1506 { }
1539} 1507};
1508MODULE_DEVICE_TABLE(i2c, wm8990_i2c_id);
1540 1509
1541static struct i2c_driver wm8990_i2c_driver = { 1510static struct i2c_driver wm8990_i2c_driver = {
1542 .driver = { 1511 .driver = {
1543 .name = "WM8990 I2C Codec", 1512 .name = "WM8990 I2C Codec",
1544 .owner = THIS_MODULE, 1513 .owner = THIS_MODULE,
1545 }, 1514 },
1546 .attach_adapter = wm8990_i2c_attach, 1515 .probe = wm8990_i2c_probe,
1547 .detach_client = wm8990_i2c_detach, 1516 .remove = wm8990_i2c_remove,
1548 .command = NULL, 1517 .id_table = wm8990_i2c_id,
1549}; 1518};
1550 1519
1551static struct i2c_client client_template = { 1520static int wm8990_add_i2c_device(struct platform_device *pdev,
1552 .name = "WM8990", 1521 const struct wm8990_setup_data *setup)
1553 .driver = &wm8990_i2c_driver, 1522{
1554}; 1523 struct i2c_board_info info;
1524 struct i2c_adapter *adapter;
1525 struct i2c_client *client;
1526 int ret;
1527
1528 ret = i2c_add_driver(&wm8990_i2c_driver);
1529 if (ret != 0) {
1530 dev_err(&pdev->dev, "can't add i2c driver\n");
1531 return ret;
1532 }
1533
1534 memset(&info, 0, sizeof(struct i2c_board_info));
1535 info.addr = setup->i2c_address;
1536 strlcpy(info.type, "wm8990", I2C_NAME_SIZE);
1537
1538 adapter = i2c_get_adapter(setup->i2c_bus);
1539 if (!adapter) {
1540 dev_err(&pdev->dev, "can't get i2c adapter %d\n",
1541 setup->i2c_bus);
1542 goto err_driver;
1543 }
1544
1545 client = i2c_new_device(adapter, &info);
1546 i2c_put_adapter(adapter);
1547 if (!client) {
1548 dev_err(&pdev->dev, "can't add i2c device at 0x%x\n",
1549 (unsigned int)info.addr);
1550 goto err_driver;
1551 }
1552
1553 return 0;
1554
1555err_driver:
1556 i2c_del_driver(&wm8990_i2c_driver);
1557 return -ENODEV;
1558}
1555#endif 1559#endif
1556 1560
1557static int wm8990_probe(struct platform_device *pdev) 1561static int wm8990_probe(struct platform_device *pdev)
@@ -1560,7 +1564,7 @@ static int wm8990_probe(struct platform_device *pdev)
1560 struct wm8990_setup_data *setup; 1564 struct wm8990_setup_data *setup;
1561 struct snd_soc_codec *codec; 1565 struct snd_soc_codec *codec;
1562 struct wm8990_priv *wm8990; 1566 struct wm8990_priv *wm8990;
1563 int ret = 0; 1567 int ret;
1564 1568
1565 pr_info("WM8990 Audio Codec %s\n", WM8990_VERSION); 1569 pr_info("WM8990 Audio Codec %s\n", WM8990_VERSION);
1566 1570
@@ -1582,16 +1586,13 @@ static int wm8990_probe(struct platform_device *pdev)
1582 INIT_LIST_HEAD(&codec->dapm_paths); 1586 INIT_LIST_HEAD(&codec->dapm_paths);
1583 wm8990_socdev = socdev; 1587 wm8990_socdev = socdev;
1584 1588
1589 ret = -ENODEV;
1590
1585#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 1591#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1586 if (setup->i2c_address) { 1592 if (setup->i2c_address) {
1587 normal_i2c[0] = setup->i2c_address;
1588 codec->hw_write = (hw_write_t)i2c_master_send; 1593 codec->hw_write = (hw_write_t)i2c_master_send;
1589 ret = i2c_add_driver(&wm8990_i2c_driver); 1594 ret = wm8990_add_i2c_device(pdev, setup);
1590 if (ret != 0)
1591 printk(KERN_ERR "can't add i2c driver");
1592 } 1595 }
1593#else
1594 /* Add other interfaces here */
1595#endif 1596#endif
1596 1597
1597 if (ret != 0) { 1598 if (ret != 0) {
@@ -1612,6 +1613,7 @@ static int wm8990_remove(struct platform_device *pdev)
1612 snd_soc_free_pcms(socdev); 1613 snd_soc_free_pcms(socdev);
1613 snd_soc_dapm_free(socdev); 1614 snd_soc_dapm_free(socdev);
1614#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 1615#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1616 i2c_unregister_device(codec->control_data);
1615 i2c_del_driver(&wm8990_i2c_driver); 1617 i2c_del_driver(&wm8990_i2c_driver);
1616#endif 1618#endif
1617 kfree(codec->private_data); 1619 kfree(codec->private_data);
diff --git a/sound/soc/codecs/wm8990.h b/sound/soc/codecs/wm8990.h
index 0a08325d5443..0e192f3b0788 100644
--- a/sound/soc/codecs/wm8990.h
+++ b/sound/soc/codecs/wm8990.h
@@ -827,6 +827,7 @@
827#define WM8990_AINRMUX_PWR_BIT 3 827#define WM8990_AINRMUX_PWR_BIT 3
828 828
829struct wm8990_setup_data { 829struct wm8990_setup_data {
830 unsigned i2c_bus;
830 unsigned short i2c_address; 831 unsigned short i2c_address;
831}; 832};
832 833
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c
index 2f1c91b1d556..ffb471e420e2 100644
--- a/sound/soc/codecs/wm9712.c
+++ b/sound/soc/codecs/wm9712.c
@@ -2,8 +2,7 @@
2 * wm9712.c -- ALSA Soc WM9712 codec support 2 * wm9712.c -- ALSA Soc WM9712 codec support
3 * 3 *
4 * Copyright 2006 Wolfson Microelectronics PLC. 4 * Copyright 2006 Wolfson Microelectronics PLC.
5 * Author: Liam Girdwood 5 * Author: Liam Girdwood <lrg@slimlogic.co.uk>
6 * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
7 * 6 *
8 * This program is free software; you can redistribute it and/or modify it 7 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the 8 * under the terms of the GNU General Public License as published by the
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
index 38d1fe0971fc..aba402b3c999 100644
--- a/sound/soc/codecs/wm9713.c
+++ b/sound/soc/codecs/wm9713.c
@@ -2,8 +2,7 @@
2 * wm9713.c -- ALSA Soc WM9713 codec support 2 * wm9713.c -- ALSA Soc WM9713 codec support
3 * 3 *
4 * Copyright 2006 Wolfson Microelectronics PLC. 4 * Copyright 2006 Wolfson Microelectronics PLC.
5 * Author: Liam Girdwood 5 * Author: Liam Girdwood <lrg@slimlogic.co.uk>
6 * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
7 * 6 *
8 * This program is free software; you can redistribute it and/or modify it 7 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the 8 * under the terms of the GNU General Public License as published by the
@@ -419,8 +418,12 @@ SND_SOC_DAPM_MIXER("Line Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
419SND_SOC_DAPM_MIXER("Capture Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), 418SND_SOC_DAPM_MIXER("Capture Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
420SND_SOC_DAPM_DAC("Voice DAC", "Voice Playback", AC97_EXTENDED_MID, 12, 1), 419SND_SOC_DAPM_DAC("Voice DAC", "Voice Playback", AC97_EXTENDED_MID, 12, 1),
421SND_SOC_DAPM_DAC("Aux DAC", "Aux Playback", AC97_EXTENDED_MID, 11, 1), 420SND_SOC_DAPM_DAC("Aux DAC", "Aux Playback", AC97_EXTENDED_MID, 11, 1),
422SND_SOC_DAPM_ADC("Left ADC", "Left HiFi Capture", AC97_EXTENDED_MID, 5, 1), 421SND_SOC_DAPM_PGA("Left ADC", AC97_EXTENDED_MID, 5, 1, NULL, 0),
423SND_SOC_DAPM_ADC("Right ADC", "Right HiFi Capture", AC97_EXTENDED_MID, 4, 1), 422SND_SOC_DAPM_PGA("Right ADC", AC97_EXTENDED_MID, 4, 1, NULL, 0),
423SND_SOC_DAPM_ADC("Left HiFi ADC", "Left HiFi Capture", SND_SOC_NOPM, 0, 0),
424SND_SOC_DAPM_ADC("Right HiFi ADC", "Right HiFi Capture", SND_SOC_NOPM, 0, 0),
425SND_SOC_DAPM_ADC("Left Voice ADC", "Left Voice Capture", SND_SOC_NOPM, 0, 0),
426SND_SOC_DAPM_ADC("Right Voice ADC", "Right Voice Capture", SND_SOC_NOPM, 0, 0),
424SND_SOC_DAPM_PGA("Left Headphone", AC97_EXTENDED_MSTATUS, 10, 1, NULL, 0), 427SND_SOC_DAPM_PGA("Left Headphone", AC97_EXTENDED_MSTATUS, 10, 1, NULL, 0),
425SND_SOC_DAPM_PGA("Right Headphone", AC97_EXTENDED_MSTATUS, 9, 1, NULL, 0), 428SND_SOC_DAPM_PGA("Right Headphone", AC97_EXTENDED_MSTATUS, 9, 1, NULL, 0),
426SND_SOC_DAPM_PGA("Left Speaker", AC97_EXTENDED_MSTATUS, 8, 1, NULL, 0), 429SND_SOC_DAPM_PGA("Left Speaker", AC97_EXTENDED_MSTATUS, 8, 1, NULL, 0),
@@ -583,9 +586,13 @@ static const struct snd_soc_dapm_route audio_map[] = {
583 586
584 /* left ADC */ 587 /* left ADC */
585 {"Left ADC", NULL, "Left Capture Source"}, 588 {"Left ADC", NULL, "Left Capture Source"},
589 {"Left Voice ADC", NULL, "Left ADC"},
590 {"Left HiFi ADC", NULL, "Left ADC"},
586 591
587 /* right ADC */ 592 /* right ADC */
588 {"Right ADC", NULL, "Right Capture Source"}, 593 {"Right ADC", NULL, "Right Capture Source"},
594 {"Right Voice ADC", NULL, "Right ADC"},
595 {"Right HiFi ADC", NULL, "Right ADC"},
589 596
590 /* mic */ 597 /* mic */
591 {"Mic A Pre Amp", NULL, "Mic A Source"}, 598 {"Mic A Pre Amp", NULL, "Mic A Source"},
@@ -949,17 +956,17 @@ static int wm9713_pcm_hw_params(struct snd_pcm_substream *substream,
949 956
950static void wm9713_voiceshutdown(struct snd_pcm_substream *substream) 957static void wm9713_voiceshutdown(struct snd_pcm_substream *substream)
951{ 958{
952 struct snd_soc_pcm_runtime *rtd = substream->private_data; 959 struct snd_soc_pcm_runtime *rtd = substream->private_data;
953 struct snd_soc_device *socdev = rtd->socdev; 960 struct snd_soc_device *socdev = rtd->socdev;
954 struct snd_soc_codec *codec = socdev->codec; 961 struct snd_soc_codec *codec = socdev->codec;
955 u16 status; 962 u16 status;
956 963
957 /* Gracefully shut down the voice interface. */ 964 /* Gracefully shut down the voice interface. */
958 status = ac97_read(codec, AC97_EXTENDED_STATUS) | 0x1000; 965 status = ac97_read(codec, AC97_EXTENDED_STATUS) | 0x1000;
959 ac97_write(codec, AC97_HANDSET_RATE, 0x0280); 966 ac97_write(codec, AC97_HANDSET_RATE, 0x0280);
960 schedule_timeout_interruptible(msecs_to_jiffies(1)); 967 schedule_timeout_interruptible(msecs_to_jiffies(1));
961 ac97_write(codec, AC97_HANDSET_RATE, 0x0F80); 968 ac97_write(codec, AC97_HANDSET_RATE, 0x0F80);
962 ac97_write(codec, AC97_EXTENDED_MID, status); 969 ac97_write(codec, AC97_EXTENDED_MID, status);
963} 970}
964 971
965static int ac97_hifi_prepare(struct snd_pcm_substream *substream) 972static int ac97_hifi_prepare(struct snd_pcm_substream *substream)
diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c
index 65fdbd81a379..9e6062cd6b59 100644
--- a/sound/soc/davinci/davinci-evm.c
+++ b/sound/soc/davinci/davinci-evm.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * ASoC driver for TI DAVINCI EVM platform 2 * ASoC driver for TI DAVINCI EVM platform
3 * 3 *
4 * Author: Vladimir Barinov, <vbarinov@ru.mvista.com> 4 * Author: Vladimir Barinov, <vbarinov@embeddedalley.com>
5 * Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.com> 5 * Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.com>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
@@ -136,6 +136,7 @@ static struct snd_soc_machine snd_soc_machine_evm = {
136 136
137/* evm audio private data */ 137/* evm audio private data */
138static struct aic3x_setup_data evm_aic3x_setup = { 138static struct aic3x_setup_data evm_aic3x_setup = {
139 .i2c_bus = 0,
139 .i2c_address = 0x1b, 140 .i2c_address = 0x1b,
140}; 141};
141 142
diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c
index 5ebf1ff71c4c..abb5fedb0b1e 100644
--- a/sound/soc/davinci/davinci-i2s.c
+++ b/sound/soc/davinci/davinci-i2s.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * ALSA SoC I2S (McBSP) Audio Layer for TI DAVINCI processor 2 * ALSA SoC I2S (McBSP) Audio Layer for TI DAVINCI processor
3 * 3 *
4 * Author: Vladimir Barinov, <vbarinov@ru.mvista.com> 4 * Author: Vladimir Barinov, <vbarinov@embeddedalley.com>
5 * Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.com> 5 * Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.com>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
@@ -256,7 +256,7 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
256 mcbsp_word_length = DAVINCI_MCBSP_WORD_32; 256 mcbsp_word_length = DAVINCI_MCBSP_WORD_32;
257 break; 257 break;
258 default: 258 default:
259 printk(KERN_WARNING "davinci-i2s: unsupported PCM format"); 259 printk(KERN_WARNING "davinci-i2s: unsupported PCM format\n");
260 return -EINVAL; 260 return -EINVAL;
261 } 261 }
262 262
diff --git a/sound/soc/davinci/davinci-i2s.h b/sound/soc/davinci/davinci-i2s.h
index c5b091807eec..241648ce8873 100644
--- a/sound/soc/davinci/davinci-i2s.h
+++ b/sound/soc/davinci/davinci-i2s.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * ALSA SoC I2S (McBSP) Audio Layer for TI DAVINCI processor 2 * ALSA SoC I2S (McBSP) Audio Layer for TI DAVINCI processor
3 * 3 *
4 * Author: Vladimir Barinov, <vbarinov@ru.mvista.com> 4 * Author: Vladimir Barinov, <vbarinov@embeddedalley.com>
5 * Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.com> 5 * Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.com>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c
index 6a5e56a782bb..76feaa657375 100644
--- a/sound/soc/davinci/davinci-pcm.c
+++ b/sound/soc/davinci/davinci-pcm.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * ALSA PCM interface for the TI DAVINCI processor 2 * ALSA PCM interface for the TI DAVINCI processor
3 * 3 *
4 * Author: Vladimir Barinov, <vbarinov@ru.mvista.com> 4 * Author: Vladimir Barinov, <vbarinov@embeddedalley.com>
5 * Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.com> 5 * Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.com>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
diff --git a/sound/soc/davinci/davinci-pcm.h b/sound/soc/davinci/davinci-pcm.h
index 8d6a45e75a6e..62cb4eb07e34 100644
--- a/sound/soc/davinci/davinci-pcm.h
+++ b/sound/soc/davinci/davinci-pcm.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * ALSA PCM interface for the TI DAVINCI processor 2 * ALSA PCM interface for the TI DAVINCI processor
3 * 3 *
4 * Author: Vladimir Barinov, <vbarinov@ru.mvista.com> 4 * Author: Vladimir Barinov, <vbarinov@embeddedalley.com>
5 * Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.com> 5 * Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.com>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 3368ace60977..bba9546ba5f5 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -1,3 +1,6 @@
1config SND_SOC_OF_SIMPLE
2 tristate
3
1config SND_SOC_MPC8610 4config SND_SOC_MPC8610
2 bool "ALSA SoC support for the MPC8610 SOC" 5 bool "ALSA SoC support for the MPC8610 SOC"
3 depends on MPC8610_HPCD 6 depends on MPC8610_HPCD
@@ -14,3 +17,10 @@ config SND_SOC_MPC8610_HPCD
14 default y if MPC8610_HPCD 17 default y if MPC8610_HPCD
15 help 18 help
16 Say Y if you want to enable audio on the Freescale MPC8610 HPCD. 19 Say Y if you want to enable audio on the Freescale MPC8610 HPCD.
20
21config SND_SOC_MPC5200_I2S
22 tristate "Freescale MPC5200 PSC in I2S mode driver"
23 select SND_SOC_OF_SIMPLE
24 depends on SND_SOC && PPC_MPC52xx
25 help
26 Say Y here to support the MPC5200 PSCs in I2S mode.
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index 62f680a4a776..035da4afec34 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -1,6 +1,11 @@
1# Simple machine driver that extracts configuration from the OF device tree
2obj-$(CONFIG_SND_SOC_OF_SIMPLE) += soc-of-simple.o
3
1# MPC8610 HPCD Machine Support 4# MPC8610 HPCD Machine Support
2obj-$(CONFIG_SND_SOC_MPC8610_HPCD) += mpc8610_hpcd.o 5obj-$(CONFIG_SND_SOC_MPC8610_HPCD) += mpc8610_hpcd.o
3 6
4# MPC8610 Platform Support 7# MPC8610 Platform Support
5obj-$(CONFIG_SND_SOC_MPC8610) += fsl_ssi.o fsl_dma.o 8obj-$(CONFIG_SND_SOC_MPC8610) += fsl_ssi.o fsl_dma.o
6 9
10obj-$(CONFIG_SND_SOC_MPC5200_I2S) += mpc5200_psc_i2s.o
11
diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c
new file mode 100644
index 000000000000..86923299bc10
--- /dev/null
+++ b/sound/soc/fsl/mpc5200_psc_i2s.c
@@ -0,0 +1,884 @@
1/*
2 * Freescale MPC5200 PSC in I2S mode
3 * ALSA SoC Digital Audio Interface (DAI) driver
4 *
5 * Copyright (C) 2008 Secret Lab Technologies Ltd.
6 */
7
8#include <linux/init.h>
9#include <linux/module.h>
10#include <linux/interrupt.h>
11#include <linux/device.h>
12#include <linux/delay.h>
13#include <linux/of_device.h>
14#include <linux/of_platform.h>
15#include <linux/dma-mapping.h>
16
17#include <sound/core.h>
18#include <sound/pcm.h>
19#include <sound/pcm_params.h>
20#include <sound/initval.h>
21#include <sound/soc.h>
22#include <sound/soc-of-simple.h>
23
24#include <sysdev/bestcomm/bestcomm.h>
25#include <sysdev/bestcomm/gen_bd.h>
26#include <asm/mpc52xx_psc.h>
27
28MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
29MODULE_DESCRIPTION("Freescale MPC5200 PSC in I2S mode ASoC Driver");
30MODULE_LICENSE("GPL");
31
32/**
33 * PSC_I2S_RATES: sample rates supported by the I2S
34 *
35 * This driver currently only supports the PSC running in I2S slave mode,
36 * which means the codec determines the sample rate. Therefore, we tell
37 * ALSA that we support all rates and let the codec driver decide what rates
38 * are really supported.
39 */
40#define PSC_I2S_RATES (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_192000 | \
41 SNDRV_PCM_RATE_CONTINUOUS)
42
43/**
44 * PSC_I2S_FORMATS: audio formats supported by the PSC I2S mode
45 */
46#define PSC_I2S_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_BE | \
47 SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S24_BE | \
48 SNDRV_PCM_FMTBIT_S32_BE)
49
50/**
51 * psc_i2s_stream - Data specific to a single stream (playback or capture)
52 * @active: flag indicating if the stream is active
53 * @psc_i2s: pointer back to parent psc_i2s data structure
54 * @bcom_task: bestcomm task structure
55 * @irq: irq number for bestcomm task
56 * @period_start: physical address of start of DMA region
57 * @period_end: physical address of end of DMA region
58 * @period_next_pt: physical address of next DMA buffer to enqueue
59 * @period_bytes: size of DMA period in bytes
60 */
61struct psc_i2s_stream {
62 int active;
63 struct psc_i2s *psc_i2s;
64 struct bcom_task *bcom_task;
65 int irq;
66 struct snd_pcm_substream *stream;
67 dma_addr_t period_start;
68 dma_addr_t period_end;
69 dma_addr_t period_next_pt;
70 dma_addr_t period_current_pt;
71 int period_bytes;
72};
73
74/**
75 * psc_i2s - Private driver data
76 * @name: short name for this device ("PSC0", "PSC1", etc)
77 * @psc_regs: pointer to the PSC's registers
78 * @fifo_regs: pointer to the PSC's FIFO registers
79 * @irq: IRQ of this PSC
80 * @dev: struct device pointer
81 * @dai: the CPU DAI for this device
82 * @sicr: Base value used in serial interface control register; mode is ORed
83 * with this value.
84 * @playback: Playback stream context data
85 * @capture: Capture stream context data
86 */
87struct psc_i2s {
88 char name[32];
89 struct mpc52xx_psc __iomem *psc_regs;
90 struct mpc52xx_psc_fifo __iomem *fifo_regs;
91 unsigned int irq;
92 struct device *dev;
93 struct snd_soc_dai dai;
94 spinlock_t lock;
95 u32 sicr;
96
97 /* per-stream data */
98 struct psc_i2s_stream playback;
99 struct psc_i2s_stream capture;
100
101 /* Statistics */
102 struct {
103 int overrun_count;
104 int underrun_count;
105 } stats;
106};
107
108/*
109 * Interrupt handlers
110 */
111static irqreturn_t psc_i2s_status_irq(int irq, void *_psc_i2s)
112{
113 struct psc_i2s *psc_i2s = _psc_i2s;
114 struct mpc52xx_psc __iomem *regs = psc_i2s->psc_regs;
115 u16 isr;
116
117 isr = in_be16(&regs->mpc52xx_psc_isr);
118
119 /* Playback underrun error */
120 if (psc_i2s->playback.active && (isr & MPC52xx_PSC_IMR_TXEMP))
121 psc_i2s->stats.underrun_count++;
122
123 /* Capture overrun error */
124 if (psc_i2s->capture.active && (isr & MPC52xx_PSC_IMR_ORERR))
125 psc_i2s->stats.overrun_count++;
126
127 out_8(&regs->command, 4 << 4); /* reset the error status */
128
129 return IRQ_HANDLED;
130}
131
132/**
133 * psc_i2s_bcom_enqueue_next_buffer - Enqueue another audio buffer
134 * @s: pointer to stream private data structure
135 *
136 * Enqueues another audio period buffer into the bestcomm queue.
137 *
138 * Note: The routine must only be called when there is space available in
139 * the queue. Otherwise the enqueue will fail and the audio ring buffer
140 * will get out of sync
141 */
142static void psc_i2s_bcom_enqueue_next_buffer(struct psc_i2s_stream *s)
143{
144 struct bcom_bd *bd;
145
146 /* Prepare and enqueue the next buffer descriptor */
147 bd = bcom_prepare_next_buffer(s->bcom_task);
148 bd->status = s->period_bytes;
149 bd->data[0] = s->period_next_pt;
150 bcom_submit_next_buffer(s->bcom_task, NULL);
151
152 /* Update for next period */
153 s->period_next_pt += s->period_bytes;
154 if (s->period_next_pt >= s->period_end)
155 s->period_next_pt = s->period_start;
156}
157
158/* Bestcomm DMA irq handler */
159static irqreturn_t psc_i2s_bcom_irq(int irq, void *_psc_i2s_stream)
160{
161 struct psc_i2s_stream *s = _psc_i2s_stream;
162
163 /* For each finished period, dequeue the completed period buffer
164 * and enqueue a new one in it's place. */
165 while (bcom_buffer_done(s->bcom_task)) {
166 bcom_retrieve_buffer(s->bcom_task, NULL, NULL);
167 s->period_current_pt += s->period_bytes;
168 if (s->period_current_pt >= s->period_end)
169 s->period_current_pt = s->period_start;
170 psc_i2s_bcom_enqueue_next_buffer(s);
171 bcom_enable(s->bcom_task);
172 }
173
174 /* If the stream is active, then also inform the PCM middle layer
175 * of the period finished event. */
176 if (s->active)
177 snd_pcm_period_elapsed(s->stream);
178
179 return IRQ_HANDLED;
180}
181
182/**
183 * psc_i2s_startup: create a new substream
184 *
185 * This is the first function called when a stream is opened.
186 *
187 * If this is the first stream open, then grab the IRQ and program most of
188 * the PSC registers.
189 */
190static int psc_i2s_startup(struct snd_pcm_substream *substream)
191{
192 struct snd_soc_pcm_runtime *rtd = substream->private_data;
193 struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;
194 int rc;
195
196 dev_dbg(psc_i2s->dev, "psc_i2s_startup(substream=%p)\n", substream);
197
198 if (!psc_i2s->playback.active &&
199 !psc_i2s->capture.active) {
200 /* Setup the IRQs */
201 rc = request_irq(psc_i2s->irq, &psc_i2s_status_irq, IRQF_SHARED,
202 "psc-i2s-status", psc_i2s);
203 rc |= request_irq(psc_i2s->capture.irq,
204 &psc_i2s_bcom_irq, IRQF_SHARED,
205 "psc-i2s-capture", &psc_i2s->capture);
206 rc |= request_irq(psc_i2s->playback.irq,
207 &psc_i2s_bcom_irq, IRQF_SHARED,
208 "psc-i2s-playback", &psc_i2s->playback);
209 if (rc) {
210 free_irq(psc_i2s->irq, psc_i2s);
211 free_irq(psc_i2s->capture.irq,
212 &psc_i2s->capture);
213 free_irq(psc_i2s->playback.irq,
214 &psc_i2s->playback);
215 return -ENODEV;
216 }
217 }
218
219 return 0;
220}
221
222static int psc_i2s_hw_params(struct snd_pcm_substream *substream,
223 struct snd_pcm_hw_params *params)
224{
225 struct snd_soc_pcm_runtime *rtd = substream->private_data;
226 struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;
227 u32 mode;
228
229 dev_dbg(psc_i2s->dev, "%s(substream=%p) p_size=%i p_bytes=%i"
230 " periods=%i buffer_size=%i buffer_bytes=%i\n",
231 __func__, substream, params_period_size(params),
232 params_period_bytes(params), params_periods(params),
233 params_buffer_size(params), params_buffer_bytes(params));
234
235 switch (params_format(params)) {
236 case SNDRV_PCM_FORMAT_S8:
237 mode = MPC52xx_PSC_SICR_SIM_CODEC_8;
238 break;
239 case SNDRV_PCM_FORMAT_S16_BE:
240 mode = MPC52xx_PSC_SICR_SIM_CODEC_16;
241 break;
242 case SNDRV_PCM_FORMAT_S24_BE:
243 mode = MPC52xx_PSC_SICR_SIM_CODEC_24;
244 break;
245 case SNDRV_PCM_FORMAT_S32_BE:
246 mode = MPC52xx_PSC_SICR_SIM_CODEC_32;
247 break;
248 default:
249 dev_dbg(psc_i2s->dev, "invalid format\n");
250 return -EINVAL;
251 }
252 out_be32(&psc_i2s->psc_regs->sicr, psc_i2s->sicr | mode);
253
254 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
255
256 return 0;
257}
258
259static int psc_i2s_hw_free(struct snd_pcm_substream *substream)
260{
261 snd_pcm_set_runtime_buffer(substream, NULL);
262 return 0;
263}
264
265/**
266 * psc_i2s_trigger: start and stop the DMA transfer.
267 *
268 * This function is called by ALSA to start, stop, pause, and resume the DMA
269 * transfer of data.
270 */
271static int psc_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
272{
273 struct snd_soc_pcm_runtime *rtd = substream->private_data;
274 struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;
275 struct snd_pcm_runtime *runtime = substream->runtime;
276 struct psc_i2s_stream *s;
277 struct mpc52xx_psc __iomem *regs = psc_i2s->psc_regs;
278 u16 imr;
279 u8 psc_cmd;
280 long flags;
281
282 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
283 s = &psc_i2s->capture;
284 else
285 s = &psc_i2s->playback;
286
287 dev_dbg(psc_i2s->dev, "psc_i2s_trigger(substream=%p, cmd=%i)"
288 " stream_id=%i\n",
289 substream, cmd, substream->pstr->stream);
290
291 switch (cmd) {
292 case SNDRV_PCM_TRIGGER_START:
293 s->period_bytes = frames_to_bytes(runtime,
294 runtime->period_size);
295 s->period_start = virt_to_phys(runtime->dma_area);
296 s->period_end = s->period_start +
297 (s->period_bytes * runtime->periods);
298 s->period_next_pt = s->period_start;
299 s->period_current_pt = s->period_start;
300 s->active = 1;
301
302 /* First; reset everything */
303 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) {
304 out_8(&regs->command, MPC52xx_PSC_RST_RX);
305 out_8(&regs->command, MPC52xx_PSC_RST_ERR_STAT);
306 } else {
307 out_8(&regs->command, MPC52xx_PSC_RST_TX);
308 out_8(&regs->command, MPC52xx_PSC_RST_ERR_STAT);
309 }
310
311 /* Next, fill up the bestcomm bd queue and enable DMA.
312 * This will begin filling the PSC's fifo. */
313 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
314 bcom_gen_bd_rx_reset(s->bcom_task);
315 else
316 bcom_gen_bd_tx_reset(s->bcom_task);
317 while (!bcom_queue_full(s->bcom_task))
318 psc_i2s_bcom_enqueue_next_buffer(s);
319 bcom_enable(s->bcom_task);
320
321 /* Due to errata in the i2s mode; need to line up enabling
322 * the transmitter with a transition on the frame sync
323 * line */
324
325 spin_lock_irqsave(&psc_i2s->lock, flags);
326 /* first make sure it is low */
327 while ((in_8(&regs->ipcr_acr.ipcr) & 0x80) != 0)
328 ;
329 /* then wait for the transition to high */
330 while ((in_8(&regs->ipcr_acr.ipcr) & 0x80) == 0)
331 ;
332 /* Finally, enable the PSC.
333 * Receiver must always be enabled; even when we only want
334 * transmit. (see 15.3.2.3 of MPC5200B User's Guide) */
335 psc_cmd = MPC52xx_PSC_RX_ENABLE;
336 if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK)
337 psc_cmd |= MPC52xx_PSC_TX_ENABLE;
338 out_8(&regs->command, psc_cmd);
339 spin_unlock_irqrestore(&psc_i2s->lock, flags);
340
341 break;
342
343 case SNDRV_PCM_TRIGGER_STOP:
344 /* Turn off the PSC */
345 s->active = 0;
346 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) {
347 if (!psc_i2s->playback.active) {
348 out_8(&regs->command, 2 << 4); /* reset rx */
349 out_8(&regs->command, 3 << 4); /* reset tx */
350 out_8(&regs->command, 4 << 4); /* reset err */
351 }
352 } else {
353 out_8(&regs->command, 3 << 4); /* reset tx */
354 out_8(&regs->command, 4 << 4); /* reset err */
355 if (!psc_i2s->capture.active)
356 out_8(&regs->command, 2 << 4); /* reset rx */
357 }
358
359 bcom_disable(s->bcom_task);
360 while (!bcom_queue_empty(s->bcom_task))
361 bcom_retrieve_buffer(s->bcom_task, NULL, NULL);
362
363 break;
364
365 default:
366 dev_dbg(psc_i2s->dev, "invalid command\n");
367 return -EINVAL;
368 }
369
370 /* Update interrupt enable settings */
371 imr = 0;
372 if (psc_i2s->playback.active)
373 imr |= MPC52xx_PSC_IMR_TXEMP;
374 if (psc_i2s->capture.active)
375 imr |= MPC52xx_PSC_IMR_ORERR;
376 out_be16(&regs->isr_imr.imr, imr);
377
378 return 0;
379}
380
381/**
382 * psc_i2s_shutdown: shutdown the data transfer on a stream
383 *
384 * Shutdown the PSC if there are no other substreams open.
385 */
386static void psc_i2s_shutdown(struct snd_pcm_substream *substream)
387{
388 struct snd_soc_pcm_runtime *rtd = substream->private_data;
389 struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;
390
391 dev_dbg(psc_i2s->dev, "psc_i2s_shutdown(substream=%p)\n", substream);
392
393 /*
394 * If this is the last active substream, disable the PSC and release
395 * the IRQ.
396 */
397 if (!psc_i2s->playback.active &&
398 !psc_i2s->capture.active) {
399
400 /* Disable all interrupts and reset the PSC */
401 out_be16(&psc_i2s->psc_regs->isr_imr.imr, 0);
402 out_8(&psc_i2s->psc_regs->command, 3 << 4); /* reset tx */
403 out_8(&psc_i2s->psc_regs->command, 2 << 4); /* reset rx */
404 out_8(&psc_i2s->psc_regs->command, 1 << 4); /* reset mode */
405 out_8(&psc_i2s->psc_regs->command, 4 << 4); /* reset error */
406
407 /* Release irqs */
408 free_irq(psc_i2s->irq, psc_i2s);
409 free_irq(psc_i2s->capture.irq, &psc_i2s->capture);
410 free_irq(psc_i2s->playback.irq, &psc_i2s->playback);
411 }
412}
413
414/**
415 * psc_i2s_set_sysclk: set the clock frequency and direction
416 *
417 * This function is called by the machine driver to tell us what the clock
418 * frequency and direction are.
419 *
420 * Currently, we only support operating as a clock slave (SND_SOC_CLOCK_IN),
421 * and we don't care about the frequency. Return an error if the direction
422 * is not SND_SOC_CLOCK_IN.
423 *
424 * @clk_id: reserved, should be zero
425 * @freq: the frequency of the given clock ID, currently ignored
426 * @dir: SND_SOC_CLOCK_IN (clock slave) or SND_SOC_CLOCK_OUT (clock master)
427 */
428static int psc_i2s_set_sysclk(struct snd_soc_dai *cpu_dai,
429 int clk_id, unsigned int freq, int dir)
430{
431 struct psc_i2s *psc_i2s = cpu_dai->private_data;
432 dev_dbg(psc_i2s->dev, "psc_i2s_set_sysclk(cpu_dai=%p, dir=%i)\n",
433 cpu_dai, dir);
434 return (dir == SND_SOC_CLOCK_IN) ? 0 : -EINVAL;
435}
436
437/**
438 * psc_i2s_set_fmt: set the serial format.
439 *
440 * This function is called by the machine driver to tell us what serial
441 * format to use.
442 *
443 * This driver only supports I2S mode. Return an error if the format is
444 * not SND_SOC_DAIFMT_I2S.
445 *
446 * @format: one of SND_SOC_DAIFMT_xxx
447 */
448static int psc_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int format)
449{
450 struct psc_i2s *psc_i2s = cpu_dai->private_data;
451 dev_dbg(psc_i2s->dev, "psc_i2s_set_fmt(cpu_dai=%p, format=%i)\n",
452 cpu_dai, format);
453 return (format == SND_SOC_DAIFMT_I2S) ? 0 : -EINVAL;
454}
455
456/* ---------------------------------------------------------------------
457 * ALSA SoC Bindings
458 *
459 * - Digital Audio Interface (DAI) template
460 * - create/destroy dai hooks
461 */
462
463/**
464 * psc_i2s_dai_template: template CPU Digital Audio Interface
465 */
466static struct snd_soc_dai psc_i2s_dai_template = {
467 .type = SND_SOC_DAI_I2S,
468 .playback = {
469 .channels_min = 2,
470 .channels_max = 2,
471 .rates = PSC_I2S_RATES,
472 .formats = PSC_I2S_FORMATS,
473 },
474 .capture = {
475 .channels_min = 2,
476 .channels_max = 2,
477 .rates = PSC_I2S_RATES,
478 .formats = PSC_I2S_FORMATS,
479 },
480 .ops = {
481 .startup = psc_i2s_startup,
482 .hw_params = psc_i2s_hw_params,
483 .hw_free = psc_i2s_hw_free,
484 .shutdown = psc_i2s_shutdown,
485 .trigger = psc_i2s_trigger,
486 },
487 .dai_ops = {
488 .set_sysclk = psc_i2s_set_sysclk,
489 .set_fmt = psc_i2s_set_fmt,
490 },
491};
492
493/* ---------------------------------------------------------------------
494 * The PSC I2S 'ASoC platform' driver
495 *
496 * Can be referenced by an 'ASoC machine' driver
497 * This driver only deals with the audio bus; it doesn't have any
498 * interaction with the attached codec
499 */
500
501static const struct snd_pcm_hardware psc_i2s_pcm_hardware = {
502 .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
503 SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER,
504 .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_BE |
505 SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S32_BE,
506 .rate_min = 8000,
507 .rate_max = 48000,
508 .channels_min = 2,
509 .channels_max = 2,
510 .period_bytes_max = 1024 * 1024,
511 .period_bytes_min = 32,
512 .periods_min = 2,
513 .periods_max = 256,
514 .buffer_bytes_max = 2 * 1024 * 1024,
515 .fifo_size = 0,
516};
517
518static int psc_i2s_pcm_open(struct snd_pcm_substream *substream)
519{
520 struct snd_soc_pcm_runtime *rtd = substream->private_data;
521 struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;
522 struct psc_i2s_stream *s;
523
524 dev_dbg(psc_i2s->dev, "psc_i2s_pcm_open(substream=%p)\n", substream);
525
526 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
527 s = &psc_i2s->capture;
528 else
529 s = &psc_i2s->playback;
530
531 snd_soc_set_runtime_hwparams(substream, &psc_i2s_pcm_hardware);
532
533 s->stream = substream;
534 return 0;
535}
536
537static int psc_i2s_pcm_close(struct snd_pcm_substream *substream)
538{
539 struct snd_soc_pcm_runtime *rtd = substream->private_data;
540 struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;
541 struct psc_i2s_stream *s;
542
543 dev_dbg(psc_i2s->dev, "psc_i2s_pcm_close(substream=%p)\n", substream);
544
545 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
546 s = &psc_i2s->capture;
547 else
548 s = &psc_i2s->playback;
549
550 s->stream = NULL;
551 return 0;
552}
553
554static snd_pcm_uframes_t
555psc_i2s_pcm_pointer(struct snd_pcm_substream *substream)
556{
557 struct snd_soc_pcm_runtime *rtd = substream->private_data;
558 struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;
559 struct psc_i2s_stream *s;
560 dma_addr_t count;
561
562 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
563 s = &psc_i2s->capture;
564 else
565 s = &psc_i2s->playback;
566
567 count = s->period_current_pt - s->period_start;
568
569 return bytes_to_frames(substream->runtime, count);
570}
571
572static struct snd_pcm_ops psc_i2s_pcm_ops = {
573 .open = psc_i2s_pcm_open,
574 .close = psc_i2s_pcm_close,
575 .ioctl = snd_pcm_lib_ioctl,
576 .pointer = psc_i2s_pcm_pointer,
577};
578
579static u64 psc_i2s_pcm_dmamask = 0xffffffff;
580static int psc_i2s_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
581 struct snd_pcm *pcm)
582{
583 struct snd_soc_pcm_runtime *rtd = pcm->private_data;
584 size_t size = psc_i2s_pcm_hardware.buffer_bytes_max;
585 int rc = 0;
586
587 dev_dbg(rtd->socdev->dev, "psc_i2s_pcm_new(card=%p, dai=%p, pcm=%p)\n",
588 card, dai, pcm);
589
590 if (!card->dev->dma_mask)
591 card->dev->dma_mask = &psc_i2s_pcm_dmamask;
592 if (!card->dev->coherent_dma_mask)
593 card->dev->coherent_dma_mask = 0xffffffff;
594
595 if (pcm->streams[0].substream) {
596 rc = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->dev, size,
597 &pcm->streams[0].substream->dma_buffer);
598 if (rc)
599 goto playback_alloc_err;
600 }
601
602 if (pcm->streams[1].substream) {
603 rc = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->dev, size,
604 &pcm->streams[1].substream->dma_buffer);
605 if (rc)
606 goto capture_alloc_err;
607 }
608
609 return 0;
610
611 capture_alloc_err:
612 if (pcm->streams[0].substream)
613 snd_dma_free_pages(&pcm->streams[0].substream->dma_buffer);
614 playback_alloc_err:
615 dev_err(card->dev, "Cannot allocate buffer(s)\n");
616 return -ENOMEM;
617}
618
619static void psc_i2s_pcm_free(struct snd_pcm *pcm)
620{
621 struct snd_soc_pcm_runtime *rtd = pcm->private_data;
622 struct snd_pcm_substream *substream;
623 int stream;
624
625 dev_dbg(rtd->socdev->dev, "psc_i2s_pcm_free(pcm=%p)\n", pcm);
626
627 for (stream = 0; stream < 2; stream++) {
628 substream = pcm->streams[stream].substream;
629 if (substream) {
630 snd_dma_free_pages(&substream->dma_buffer);
631 substream->dma_buffer.area = NULL;
632 substream->dma_buffer.addr = 0;
633 }
634 }
635}
636
637struct snd_soc_platform psc_i2s_pcm_soc_platform = {
638 .name = "mpc5200-psc-audio",
639 .pcm_ops = &psc_i2s_pcm_ops,
640 .pcm_new = &psc_i2s_pcm_new,
641 .pcm_free = &psc_i2s_pcm_free,
642};
643
644/* ---------------------------------------------------------------------
645 * Sysfs attributes for debugging
646 */
647
648static ssize_t psc_i2s_status_show(struct device *dev,
649 struct device_attribute *attr, char *buf)
650{
651 struct psc_i2s *psc_i2s = dev_get_drvdata(dev);
652
653 return sprintf(buf, "status=%.4x sicr=%.8x rfnum=%i rfstat=0x%.4x "
654 "tfnum=%i tfstat=0x%.4x\n",
655 in_be16(&psc_i2s->psc_regs->sr_csr.status),
656 in_be32(&psc_i2s->psc_regs->sicr),
657 in_be16(&psc_i2s->fifo_regs->rfnum) & 0x1ff,
658 in_be16(&psc_i2s->fifo_regs->rfstat),
659 in_be16(&psc_i2s->fifo_regs->tfnum) & 0x1ff,
660 in_be16(&psc_i2s->fifo_regs->tfstat));
661}
662
663static int *psc_i2s_get_stat_attr(struct psc_i2s *psc_i2s, const char *name)
664{
665 if (strcmp(name, "playback_underrun") == 0)
666 return &psc_i2s->stats.underrun_count;
667 if (strcmp(name, "capture_overrun") == 0)
668 return &psc_i2s->stats.overrun_count;
669
670 return NULL;
671}
672
673static ssize_t psc_i2s_stat_show(struct device *dev,
674 struct device_attribute *attr, char *buf)
675{
676 struct psc_i2s *psc_i2s = dev_get_drvdata(dev);
677 int *attrib;
678
679 attrib = psc_i2s_get_stat_attr(psc_i2s, attr->attr.name);
680 if (!attrib)
681 return 0;
682
683 return sprintf(buf, "%i\n", *attrib);
684}
685
686static ssize_t psc_i2s_stat_store(struct device *dev,
687 struct device_attribute *attr,
688 const char *buf,
689 size_t count)
690{
691 struct psc_i2s *psc_i2s = dev_get_drvdata(dev);
692 int *attrib;
693
694 attrib = psc_i2s_get_stat_attr(psc_i2s, attr->attr.name);
695 if (!attrib)
696 return 0;
697
698 *attrib = simple_strtoul(buf, NULL, 0);
699 return count;
700}
701
702DEVICE_ATTR(status, 0644, psc_i2s_status_show, NULL);
703DEVICE_ATTR(playback_underrun, 0644, psc_i2s_stat_show, psc_i2s_stat_store);
704DEVICE_ATTR(capture_overrun, 0644, psc_i2s_stat_show, psc_i2s_stat_store);
705
706/* ---------------------------------------------------------------------
707 * OF platform bus binding code:
708 * - Probe/remove operations
709 * - OF device match table
710 */
711static int __devinit psc_i2s_of_probe(struct of_device *op,
712 const struct of_device_id *match)
713{
714 phys_addr_t fifo;
715 struct psc_i2s *psc_i2s;
716 struct resource res;
717 int size, psc_id, irq, rc;
718 const __be32 *prop;
719 void __iomem *regs;
720
721 dev_dbg(&op->dev, "probing psc i2s device\n");
722
723 /* Get the PSC ID */
724 prop = of_get_property(op->node, "cell-index", &size);
725 if (!prop || size < sizeof *prop)
726 return -ENODEV;
727 psc_id = be32_to_cpu(*prop);
728
729 /* Fetch the registers and IRQ of the PSC */
730 irq = irq_of_parse_and_map(op->node, 0);
731 if (of_address_to_resource(op->node, 0, &res)) {
732 dev_err(&op->dev, "Missing reg property\n");
733 return -ENODEV;
734 }
735 regs = ioremap(res.start, 1 + res.end - res.start);
736 if (!regs) {
737 dev_err(&op->dev, "Could not map registers\n");
738 return -ENODEV;
739 }
740
741 /* Allocate and initialize the driver private data */
742 psc_i2s = kzalloc(sizeof *psc_i2s, GFP_KERNEL);
743 if (!psc_i2s) {
744 iounmap(regs);
745 return -ENOMEM;
746 }
747 spin_lock_init(&psc_i2s->lock);
748 psc_i2s->irq = irq;
749 psc_i2s->psc_regs = regs;
750 psc_i2s->fifo_regs = regs + sizeof *psc_i2s->psc_regs;
751 psc_i2s->dev = &op->dev;
752 psc_i2s->playback.psc_i2s = psc_i2s;
753 psc_i2s->capture.psc_i2s = psc_i2s;
754 snprintf(psc_i2s->name, sizeof psc_i2s->name, "PSC%u", psc_id+1);
755
756 /* Fill out the CPU DAI structure */
757 memcpy(&psc_i2s->dai, &psc_i2s_dai_template, sizeof psc_i2s->dai);
758 psc_i2s->dai.private_data = psc_i2s;
759 psc_i2s->dai.name = psc_i2s->name;
760 psc_i2s->dai.id = psc_id;
761
762 /* Find the address of the fifo data registers and setup the
763 * DMA tasks */
764 fifo = res.start + offsetof(struct mpc52xx_psc, buffer.buffer_32);
765 psc_i2s->capture.bcom_task =
766 bcom_psc_gen_bd_rx_init(psc_id, 10, fifo, 512);
767 psc_i2s->playback.bcom_task =
768 bcom_psc_gen_bd_tx_init(psc_id, 10, fifo);
769 if (!psc_i2s->capture.bcom_task ||
770 !psc_i2s->playback.bcom_task) {
771 dev_err(&op->dev, "Could not allocate bestcomm tasks\n");
772 iounmap(regs);
773 kfree(psc_i2s);
774 return -ENODEV;
775 }
776
777 /* Disable all interrupts and reset the PSC */
778 out_be16(&psc_i2s->psc_regs->isr_imr.imr, 0);
779 out_8(&psc_i2s->psc_regs->command, 3 << 4); /* reset transmitter */
780 out_8(&psc_i2s->psc_regs->command, 2 << 4); /* reset receiver */
781 out_8(&psc_i2s->psc_regs->command, 1 << 4); /* reset mode */
782 out_8(&psc_i2s->psc_regs->command, 4 << 4); /* reset error */
783
784 /* Configure the serial interface mode; defaulting to CODEC8 mode */
785 psc_i2s->sicr = MPC52xx_PSC_SICR_DTS1 | MPC52xx_PSC_SICR_I2S |
786 MPC52xx_PSC_SICR_CLKPOL;
787 if (of_get_property(op->node, "fsl,cellslave", NULL))
788 psc_i2s->sicr |= MPC52xx_PSC_SICR_CELLSLAVE |
789 MPC52xx_PSC_SICR_GENCLK;
790 out_be32(&psc_i2s->psc_regs->sicr,
791 psc_i2s->sicr | MPC52xx_PSC_SICR_SIM_CODEC_8);
792
793 /* Check for the codec handle. If it is not present then we
794 * are done */
795 if (!of_get_property(op->node, "codec-handle", NULL))
796 return 0;
797
798 /* Set up mode register;
799 * First write: RxRdy (FIFO Alarm) generates rx FIFO irq
800 * Second write: register Normal mode for non loopback
801 */
802 out_8(&psc_i2s->psc_regs->mode, 0);
803 out_8(&psc_i2s->psc_regs->mode, 0);
804
805 /* Set the TX and RX fifo alarm thresholds */
806 out_be16(&psc_i2s->fifo_regs->rfalarm, 0x100);
807 out_8(&psc_i2s->fifo_regs->rfcntl, 0x4);
808 out_be16(&psc_i2s->fifo_regs->tfalarm, 0x100);
809 out_8(&psc_i2s->fifo_regs->tfcntl, 0x7);
810
811 /* Lookup the IRQ numbers */
812 psc_i2s->playback.irq =
813 bcom_get_task_irq(psc_i2s->playback.bcom_task);
814 psc_i2s->capture.irq =
815 bcom_get_task_irq(psc_i2s->capture.bcom_task);
816
817 /* Save what we've done so it can be found again later */
818 dev_set_drvdata(&op->dev, psc_i2s);
819
820 /* Register the SYSFS files */
821 rc = device_create_file(psc_i2s->dev, &dev_attr_status);
822 rc = device_create_file(psc_i2s->dev, &dev_attr_capture_overrun);
823 rc = device_create_file(psc_i2s->dev, &dev_attr_playback_underrun);
824 if (rc)
825 dev_info(psc_i2s->dev, "error creating sysfs files\n");
826
827 /* Tell the ASoC OF helpers about it */
828 of_snd_soc_register_platform(&psc_i2s_pcm_soc_platform, op->node,
829 &psc_i2s->dai);
830
831 return 0;
832}
833
834static int __devexit psc_i2s_of_remove(struct of_device *op)
835{
836 struct psc_i2s *psc_i2s = dev_get_drvdata(&op->dev);
837
838 dev_dbg(&op->dev, "psc_i2s_remove()\n");
839
840 bcom_gen_bd_rx_release(psc_i2s->capture.bcom_task);
841 bcom_gen_bd_tx_release(psc_i2s->playback.bcom_task);
842
843 iounmap(psc_i2s->psc_regs);
844 iounmap(psc_i2s->fifo_regs);
845 kfree(psc_i2s);
846 dev_set_drvdata(&op->dev, NULL);
847
848 return 0;
849}
850
851/* Match table for of_platform binding */
852static struct of_device_id psc_i2s_match[] __devinitdata = {
853 { .compatible = "fsl,mpc5200-psc-i2s", },
854 {}
855};
856MODULE_DEVICE_TABLE(of, psc_i2s_match);
857
858static struct of_platform_driver psc_i2s_driver = {
859 .match_table = psc_i2s_match,
860 .probe = psc_i2s_of_probe,
861 .remove = __devexit_p(psc_i2s_of_remove),
862 .driver = {
863 .name = "mpc5200-psc-i2s",
864 .owner = THIS_MODULE,
865 },
866};
867
868/* ---------------------------------------------------------------------
869 * Module setup and teardown; simply register the of_platform driver
870 * for the PSC in I2S mode.
871 */
872static int __init psc_i2s_init(void)
873{
874 return of_register_platform_driver(&psc_i2s_driver);
875}
876module_init(psc_i2s_init);
877
878static void __exit psc_i2s_exit(void)
879{
880 of_unregister_platform_driver(&psc_i2s_driver);
881}
882module_exit(psc_i2s_exit);
883
884
diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c
index 4bdc9d8fc90e..94f89debde1f 100644
--- a/sound/soc/fsl/mpc8610_hpcd.c
+++ b/sound/soc/fsl/mpc8610_hpcd.c
@@ -68,10 +68,6 @@ static int mpc8610_hpcd_machine_probe(struct platform_device *sound_device)
68 guts_set_pmuxcr_dma(machine_data->guts, machine_data->dma_id, 68 guts_set_pmuxcr_dma(machine_data->guts, machine_data->dma_id,
69 machine_data->dma_channel_id[1], 0); 69 machine_data->dma_channel_id[1], 0);
70 70
71 guts_set_pmuxcr_dma(machine_data->guts, 1, 0, 0);
72 guts_set_pmuxcr_dma(machine_data->guts, 1, 3, 0);
73 guts_set_pmuxcr_dma(machine_data->guts, 0, 3, 0);
74
75 switch (machine_data->ssi_id) { 71 switch (machine_data->ssi_id) {
76 case 0: 72 case 0:
77 clrsetbits_be32(&machine_data->guts->pmuxcr, 73 clrsetbits_be32(&machine_data->guts->pmuxcr,
@@ -230,6 +226,8 @@ static int mpc8610_hpcd_probe(struct of_device *ofdev,
230 struct fsl_ssi_info ssi_info; 226 struct fsl_ssi_info ssi_info;
231 struct fsl_dma_info dma_info; 227 struct fsl_dma_info dma_info;
232 int ret = -ENODEV; 228 int ret = -ENODEV;
229 unsigned int playback_dma_channel;
230 unsigned int capture_dma_channel;
233 231
234 machine_data = kzalloc(sizeof(struct mpc8610_hpcd_data), GFP_KERNEL); 232 machine_data = kzalloc(sizeof(struct mpc8610_hpcd_data), GFP_KERNEL);
235 if (!machine_data) 233 if (!machine_data)
@@ -381,8 +379,9 @@ static int mpc8610_hpcd_probe(struct of_device *ofdev,
381 goto error; 379 goto error;
382 } 380 }
383 381
384 /* Find the DMA channels to use. For now, we always use the first DMA 382 /* Find the DMA channels to use. Both SSIs need to use the same DMA
385 controller. */ 383 * controller, so let's use DMA#1.
384 */
386 for_each_compatible_node(dma_np, NULL, "fsl,mpc8610-dma") { 385 for_each_compatible_node(dma_np, NULL, "fsl,mpc8610-dma") {
387 iprop = of_get_property(dma_np, "cell-index", NULL); 386 iprop = of_get_property(dma_np, "cell-index", NULL);
388 if (iprop && (*iprop == 0)) { 387 if (iprop && (*iprop == 0)) {
@@ -397,14 +396,19 @@ static int mpc8610_hpcd_probe(struct of_device *ofdev,
397 } 396 }
398 machine_data->dma_id = *iprop; 397 machine_data->dma_id = *iprop;
399 398
399 /* SSI1 needs to use DMA Channels 0 and 1, and SSI2 needs to use DMA
400 * channels 2 and 3. This is just how the MPC8610 is wired
401 * internally.
402 */
403 playback_dma_channel = (machine_data->ssi_id == 0) ? 0 : 2;
404 capture_dma_channel = (machine_data->ssi_id == 0) ? 1 : 3;
405
400 /* 406 /*
401 * Find the DMA channels to use. For now, we always use DMA channel 0 407 * Find the DMA channels to use.
402 * for playback, and DMA channel 1 for capture.
403 */ 408 */
404 while ((dma_channel_np = of_get_next_child(dma_np, dma_channel_np))) { 409 while ((dma_channel_np = of_get_next_child(dma_np, dma_channel_np))) {
405 iprop = of_get_property(dma_channel_np, "cell-index", NULL); 410 iprop = of_get_property(dma_channel_np, "cell-index", NULL);
406 /* Is it DMA channel 0? */ 411 if (iprop && (*iprop == playback_dma_channel)) {
407 if (iprop && (*iprop == 0)) {
408 /* dma_channel[0] and dma_irq[0] are for playback */ 412 /* dma_channel[0] and dma_irq[0] are for playback */
409 dma_info.dma_channel[0] = of_iomap(dma_channel_np, 0); 413 dma_info.dma_channel[0] = of_iomap(dma_channel_np, 0);
410 dma_info.dma_irq[0] = 414 dma_info.dma_irq[0] =
@@ -412,7 +416,7 @@ static int mpc8610_hpcd_probe(struct of_device *ofdev,
412 machine_data->dma_channel_id[0] = *iprop; 416 machine_data->dma_channel_id[0] = *iprop;
413 continue; 417 continue;
414 } 418 }
415 if (iprop && (*iprop == 1)) { 419 if (iprop && (*iprop == capture_dma_channel)) {
416 /* dma_channel[1] and dma_irq[1] are for capture */ 420 /* dma_channel[1] and dma_irq[1] are for capture */
417 dma_info.dma_channel[1] = of_iomap(dma_channel_np, 0); 421 dma_info.dma_channel[1] = of_iomap(dma_channel_np, 0);
418 dma_info.dma_irq[1] = 422 dma_info.dma_irq[1] =
diff --git a/sound/soc/fsl/soc-of-simple.c b/sound/soc/fsl/soc-of-simple.c
new file mode 100644
index 000000000000..0382fdac51cd
--- /dev/null
+++ b/sound/soc/fsl/soc-of-simple.c
@@ -0,0 +1,171 @@
1/*
2 * OF helpers for ALSA SoC Layer
3 *
4 * Copyright (C) 2008, Secret Lab Technologies Ltd.
5 */
6
7#include <linux/module.h>
8#include <linux/moduleparam.h>
9#include <linux/init.h>
10#include <linux/delay.h>
11#include <linux/pm.h>
12#include <linux/bitops.h>
13#include <linux/platform_device.h>
14#include <linux/of.h>
15#include <sound/core.h>
16#include <sound/pcm.h>
17#include <sound/pcm_params.h>
18#include <sound/soc.h>
19#include <sound/soc-of-simple.h>
20#include <sound/initval.h>
21
22MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
23MODULE_LICENSE("GPL");
24MODULE_DESCRIPTION("ALSA SoC OpenFirmware bindings");
25
26static DEFINE_MUTEX(of_snd_soc_mutex);
27static LIST_HEAD(of_snd_soc_device_list);
28static int of_snd_soc_next_index;
29
30struct of_snd_soc_device {
31 int id;
32 struct list_head list;
33 struct snd_soc_device device;
34 struct snd_soc_machine machine;
35 struct snd_soc_dai_link dai_link;
36 struct platform_device *pdev;
37 struct device_node *platform_node;
38 struct device_node *codec_node;
39};
40
41static struct snd_soc_ops of_snd_soc_ops = {
42};
43
44static struct of_snd_soc_device *
45of_snd_soc_get_device(struct device_node *codec_node)
46{
47 struct of_snd_soc_device *of_soc;
48
49 list_for_each_entry(of_soc, &of_snd_soc_device_list, list) {
50 if (of_soc->codec_node == codec_node)
51 return of_soc;
52 }
53
54 of_soc = kzalloc(sizeof(struct of_snd_soc_device), GFP_KERNEL);
55 if (!of_soc)
56 return NULL;
57
58 /* Initialize the structure and add it to the global list */
59 of_soc->codec_node = codec_node;
60 of_soc->id = of_snd_soc_next_index++;
61 of_soc->machine.dai_link = &of_soc->dai_link;
62 of_soc->machine.num_links = 1;
63 of_soc->device.machine = &of_soc->machine;
64 of_soc->dai_link.ops = &of_snd_soc_ops;
65 list_add(&of_soc->list, &of_snd_soc_device_list);
66
67 return of_soc;
68}
69
70static void of_snd_soc_register_device(struct of_snd_soc_device *of_soc)
71{
72 struct platform_device *pdev;
73 int rc;
74
75 /* Only register the device if both the codec and platform have
76 * been registered */
77 if ((!of_soc->device.codec_data) || (!of_soc->platform_node))
78 return;
79
80 pr_info("platform<-->codec match achieved; registering machine\n");
81
82 pdev = platform_device_alloc("soc-audio", of_soc->id);
83 if (!pdev) {
84 pr_err("of_soc: platform_device_alloc() failed\n");
85 return;
86 }
87
88 pdev->dev.platform_data = of_soc;
89 platform_set_drvdata(pdev, &of_soc->device);
90 of_soc->device.dev = &pdev->dev;
91
92 /* The ASoC device is complete; register it */
93 rc = platform_device_add(pdev);
94 if (rc) {
95 pr_err("of_soc: platform_device_add() failed\n");
96 return;
97 }
98
99}
100
101int of_snd_soc_register_codec(struct snd_soc_codec_device *codec_dev,
102 void *codec_data, struct snd_soc_dai *dai,
103 struct device_node *node)
104{
105 struct of_snd_soc_device *of_soc;
106 int rc = 0;
107
108 pr_info("registering ASoC codec driver: %s\n", node->full_name);
109
110 mutex_lock(&of_snd_soc_mutex);
111 of_soc = of_snd_soc_get_device(node);
112 if (!of_soc) {
113 rc = -ENOMEM;
114 goto out;
115 }
116
117 /* Store the codec data */
118 of_soc->device.codec_data = codec_data;
119 of_soc->device.codec_dev = codec_dev;
120 of_soc->dai_link.name = (char *)node->name;
121 of_soc->dai_link.stream_name = (char *)node->name;
122 of_soc->dai_link.codec_dai = dai;
123
124 /* Now try to register the SoC device */
125 of_snd_soc_register_device(of_soc);
126
127 out:
128 mutex_unlock(&of_snd_soc_mutex);
129 return rc;
130}
131EXPORT_SYMBOL_GPL(of_snd_soc_register_codec);
132
133int of_snd_soc_register_platform(struct snd_soc_platform *platform,
134 struct device_node *node,
135 struct snd_soc_dai *cpu_dai)
136{
137 struct of_snd_soc_device *of_soc;
138 struct device_node *codec_node;
139 const phandle *handle;
140 int len, rc = 0;
141
142 pr_info("registering ASoC platform driver: %s\n", node->full_name);
143
144 handle = of_get_property(node, "codec-handle", &len);
145 if (!handle || len < sizeof(handle))
146 return -ENODEV;
147 codec_node = of_find_node_by_phandle(*handle);
148 if (!codec_node)
149 return -ENODEV;
150 pr_info("looking for codec: %s\n", codec_node->full_name);
151
152 mutex_lock(&of_snd_soc_mutex);
153 of_soc = of_snd_soc_get_device(codec_node);
154 if (!of_soc) {
155 rc = -ENOMEM;
156 goto out;
157 }
158
159 of_soc->platform_node = node;
160 of_soc->dai_link.cpu_dai = cpu_dai;
161 of_soc->device.platform = platform;
162 of_soc->machine.name = of_soc->dai_link.cpu_dai->name;
163
164 /* Now try to register the SoC device */
165 of_snd_soc_register_device(of_soc);
166
167 out:
168 mutex_unlock(&of_snd_soc_mutex);
169 return rc;
170}
171EXPORT_SYMBOL_GPL(of_snd_soc_register_platform);
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
index aea27e70043c..8b7766b998d7 100644
--- a/sound/soc/omap/Kconfig
+++ b/sound/soc/omap/Kconfig
@@ -13,3 +13,11 @@ config SND_OMAP_SOC_N810
13 select SND_SOC_TLV320AIC3X 13 select SND_SOC_TLV320AIC3X
14 help 14 help
15 Say Y if you want to add support for SoC audio on Nokia N810. 15 Say Y if you want to add support for SoC audio on Nokia N810.
16
17config SND_OMAP_SOC_OSK5912
18 tristate "SoC Audio support for omap osk5912"
19 depends on SND_OMAP_SOC && MACH_OMAP_OSK
20 select SND_OMAP_SOC_MCBSP
21 select SND_SOC_TLV320AIC23
22 help
23 Say Y if you want to add support for SoC audio on osk5912.
diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile
index d8d8d58075e3..e09d1f297f64 100644
--- a/sound/soc/omap/Makefile
+++ b/sound/soc/omap/Makefile
@@ -7,5 +7,7 @@ obj-$(CONFIG_SND_OMAP_SOC_MCBSP) += snd-soc-omap-mcbsp.o
7 7
8# OMAP Machine Support 8# OMAP Machine Support
9snd-soc-n810-objs := n810.o 9snd-soc-n810-objs := n810.o
10snd-soc-osk5912-objs := osk5912.o
10 11
11obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o 12obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o
13obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o
diff --git a/sound/soc/omap/n810.c b/sound/soc/omap/n810.c
index 87d0ed01f65a..fae3ad36e0bf 100644
--- a/sound/soc/omap/n810.c
+++ b/sound/soc/omap/n810.c
@@ -247,9 +247,9 @@ static int n810_aic33_init(struct snd_soc_codec *codec)
247 int i, err; 247 int i, err;
248 248
249 /* Not connected */ 249 /* Not connected */
250 snd_soc_dapm_disable_pin(codec, "MONO_LOUT"); 250 snd_soc_dapm_nc_pin(codec, "MONO_LOUT");
251 snd_soc_dapm_disable_pin(codec, "HPLCOM"); 251 snd_soc_dapm_nc_pin(codec, "HPLCOM");
252 snd_soc_dapm_disable_pin(codec, "HPRCOM"); 252 snd_soc_dapm_nc_pin(codec, "HPRCOM");
253 253
254 /* Add N810 specific controls */ 254 /* Add N810 specific controls */
255 for (i = 0; i < ARRAY_SIZE(aic33_n810_controls); i++) { 255 for (i = 0; i < ARRAY_SIZE(aic33_n810_controls); i++) {
@@ -290,6 +290,7 @@ static struct snd_soc_machine snd_soc_machine_n810 = {
290 290
291/* Audio private data */ 291/* Audio private data */
292static struct aic3x_setup_data n810_aic33_setup = { 292static struct aic3x_setup_data n810_aic33_setup = {
293 .i2c_bus = 2,
293 .i2c_address = 0x18, 294 .i2c_address = 0x18,
294 .gpio_func[0] = AIC3X_GPIO1_FUNC_DISABLED, 295 .gpio_func[0] = AIC3X_GPIO1_FUNC_DISABLED,
295 .gpio_func[1] = AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT, 296 .gpio_func[1] = AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT,
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index 35310e16d7f3..0a063a98a661 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -59,12 +59,7 @@ static struct omap_mcbsp_data mcbsp_data[NUM_LINKS];
59 * Stream DMA parameters. DMA request line and port address are set runtime 59 * Stream DMA parameters. DMA request line and port address are set runtime
60 * since they are different between OMAP1 and later OMAPs 60 * since they are different between OMAP1 and later OMAPs
61 */ 61 */
62static struct omap_pcm_dma_data omap_mcbsp_dai_dma_params[NUM_LINKS][2] = { 62static struct omap_pcm_dma_data omap_mcbsp_dai_dma_params[NUM_LINKS][2];
63{
64 { .name = "I2S PCM Stereo out", },
65 { .name = "I2S PCM Stereo in", },
66},
67};
68 63
69#if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX) 64#if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX)
70static const int omap1_dma_reqs[][2] = { 65static const int omap1_dma_reqs[][2] = {
@@ -84,11 +79,22 @@ static const unsigned long omap1_mcbsp_port[][2] = {
84static const int omap1_dma_reqs[][2] = {}; 79static const int omap1_dma_reqs[][2] = {};
85static const unsigned long omap1_mcbsp_port[][2] = {}; 80static const unsigned long omap1_mcbsp_port[][2] = {};
86#endif 81#endif
87#if defined(CONFIG_ARCH_OMAP2420) 82
88static const int omap2420_dma_reqs[][2] = { 83#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
84static const int omap24xx_dma_reqs[][2] = {
89 { OMAP24XX_DMA_MCBSP1_TX, OMAP24XX_DMA_MCBSP1_RX }, 85 { OMAP24XX_DMA_MCBSP1_TX, OMAP24XX_DMA_MCBSP1_RX },
90 { OMAP24XX_DMA_MCBSP2_TX, OMAP24XX_DMA_MCBSP2_RX }, 86 { OMAP24XX_DMA_MCBSP2_TX, OMAP24XX_DMA_MCBSP2_RX },
87#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP34XX)
88 { OMAP24XX_DMA_MCBSP3_TX, OMAP24XX_DMA_MCBSP3_RX },
89 { OMAP24XX_DMA_MCBSP4_TX, OMAP24XX_DMA_MCBSP4_RX },
90 { OMAP24XX_DMA_MCBSP5_TX, OMAP24XX_DMA_MCBSP5_RX },
91#endif
91}; 92};
93#else
94static const int omap24xx_dma_reqs[][2] = {};
95#endif
96
97#if defined(CONFIG_ARCH_OMAP2420)
92static const unsigned long omap2420_mcbsp_port[][2] = { 98static const unsigned long omap2420_mcbsp_port[][2] = {
93 { OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR1, 99 { OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR1,
94 OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DRR1 }, 100 OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DRR1 },
@@ -96,10 +102,43 @@ static const unsigned long omap2420_mcbsp_port[][2] = {
96 OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR1 }, 102 OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR1 },
97}; 103};
98#else 104#else
99static const int omap2420_dma_reqs[][2] = {};
100static const unsigned long omap2420_mcbsp_port[][2] = {}; 105static const unsigned long omap2420_mcbsp_port[][2] = {};
101#endif 106#endif
102 107
108#if defined(CONFIG_ARCH_OMAP2430)
109static const unsigned long omap2430_mcbsp_port[][2] = {
110 { OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR,
111 OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DRR },
112 { OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DXR,
113 OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR },
114 { OMAP2430_MCBSP3_BASE + OMAP_MCBSP_REG_DXR,
115 OMAP2430_MCBSP3_BASE + OMAP_MCBSP_REG_DRR },
116 { OMAP2430_MCBSP4_BASE + OMAP_MCBSP_REG_DXR,
117 OMAP2430_MCBSP4_BASE + OMAP_MCBSP_REG_DRR },
118 { OMAP2430_MCBSP5_BASE + OMAP_MCBSP_REG_DXR,
119 OMAP2430_MCBSP5_BASE + OMAP_MCBSP_REG_DRR },
120};
121#else
122static const unsigned long omap2430_mcbsp_port[][2] = {};
123#endif
124
125#if defined(CONFIG_ARCH_OMAP34XX)
126static const unsigned long omap34xx_mcbsp_port[][2] = {
127 { OMAP34XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR,
128 OMAP34XX_MCBSP1_BASE + OMAP_MCBSP_REG_DRR },
129 { OMAP34XX_MCBSP2_BASE + OMAP_MCBSP_REG_DXR,
130 OMAP34XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR },
131 { OMAP34XX_MCBSP3_BASE + OMAP_MCBSP_REG_DXR,
132 OMAP34XX_MCBSP3_BASE + OMAP_MCBSP_REG_DRR },
133 { OMAP34XX_MCBSP4_BASE + OMAP_MCBSP_REG_DXR,
134 OMAP34XX_MCBSP4_BASE + OMAP_MCBSP_REG_DRR },
135 { OMAP34XX_MCBSP5_BASE + OMAP_MCBSP_REG_DXR,
136 OMAP34XX_MCBSP5_BASE + OMAP_MCBSP_REG_DRR },
137};
138#else
139static const unsigned long omap34xx_mcbsp_port[][2] = {};
140#endif
141
103static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream) 142static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream)
104{ 143{
105 struct snd_soc_pcm_runtime *rtd = substream->private_data; 144 struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -167,14 +206,19 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
167 dma = omap1_dma_reqs[bus_id][substream->stream]; 206 dma = omap1_dma_reqs[bus_id][substream->stream];
168 port = omap1_mcbsp_port[bus_id][substream->stream]; 207 port = omap1_mcbsp_port[bus_id][substream->stream];
169 } else if (cpu_is_omap2420()) { 208 } else if (cpu_is_omap2420()) {
170 dma = omap2420_dma_reqs[bus_id][substream->stream]; 209 dma = omap24xx_dma_reqs[bus_id][substream->stream];
171 port = omap2420_mcbsp_port[bus_id][substream->stream]; 210 port = omap2420_mcbsp_port[bus_id][substream->stream];
211 } else if (cpu_is_omap2430()) {
212 dma = omap24xx_dma_reqs[bus_id][substream->stream];
213 port = omap2430_mcbsp_port[bus_id][substream->stream];
214 } else if (cpu_is_omap343x()) {
215 dma = omap24xx_dma_reqs[bus_id][substream->stream];
216 port = omap34xx_mcbsp_port[bus_id][substream->stream];
172 } else { 217 } else {
173 /*
174 * TODO: Add support for 2430 and 3430
175 */
176 return -ENODEV; 218 return -ENODEV;
177 } 219 }
220 omap_mcbsp_dai_dma_params[id][substream->stream].name =
221 substream->stream ? "Audio Capture" : "Audio Playback";
178 omap_mcbsp_dai_dma_params[id][substream->stream].dma_req = dma; 222 omap_mcbsp_dai_dma_params[id][substream->stream].dma_req = dma;
179 omap_mcbsp_dai_dma_params[id][substream->stream].port_addr = port; 223 omap_mcbsp_dai_dma_params[id][substream->stream].port_addr = port;
180 cpu_dai->dma_data = &omap_mcbsp_dai_dma_params[id][substream->stream]; 224 cpu_dai->dma_data = &omap_mcbsp_dai_dma_params[id][substream->stream];
@@ -245,6 +289,11 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
245 regs->rcr2 |= RDATDLY(1); 289 regs->rcr2 |= RDATDLY(1);
246 regs->xcr2 |= XDATDLY(1); 290 regs->xcr2 |= XDATDLY(1);
247 break; 291 break;
292 case SND_SOC_DAIFMT_DSP_A:
293 /* 0-bit data delay */
294 regs->rcr2 |= RDATDLY(0);
295 regs->xcr2 |= XDATDLY(0);
296 break;
248 default: 297 default:
249 /* Unsupported data format */ 298 /* Unsupported data format */
250 return -EINVAL; 299 return -EINVAL;
@@ -310,7 +359,7 @@ static int omap_mcbsp_dai_set_clks_src(struct omap_mcbsp_data *mcbsp_data,
310 int clk_id) 359 int clk_id)
311{ 360{
312 int sel_bit; 361 int sel_bit;
313 u16 reg; 362 u16 reg, reg_devconf1 = OMAP243X_CONTROL_DEVCONF1;
314 363
315 if (cpu_class_is_omap1()) { 364 if (cpu_class_is_omap1()) {
316 /* OMAP1's can use only external source clock */ 365 /* OMAP1's can use only external source clock */
@@ -320,6 +369,12 @@ static int omap_mcbsp_dai_set_clks_src(struct omap_mcbsp_data *mcbsp_data,
320 return 0; 369 return 0;
321 } 370 }
322 371
372 if (cpu_is_omap2420() && mcbsp_data->bus_id > 1)
373 return -EINVAL;
374
375 if (cpu_is_omap343x())
376 reg_devconf1 = OMAP343X_CONTROL_DEVCONF1;
377
323 switch (mcbsp_data->bus_id) { 378 switch (mcbsp_data->bus_id) {
324 case 0: 379 case 0:
325 reg = OMAP2_CONTROL_DEVCONF0; 380 reg = OMAP2_CONTROL_DEVCONF0;
@@ -329,20 +384,26 @@ static int omap_mcbsp_dai_set_clks_src(struct omap_mcbsp_data *mcbsp_data,
329 reg = OMAP2_CONTROL_DEVCONF0; 384 reg = OMAP2_CONTROL_DEVCONF0;
330 sel_bit = 6; 385 sel_bit = 6;
331 break; 386 break;
332 /* TODO: Support for ports 3 - 5 in OMAP2430 and OMAP34xx */ 387 case 2:
388 reg = reg_devconf1;
389 sel_bit = 0;
390 break;
391 case 3:
392 reg = reg_devconf1;
393 sel_bit = 2;
394 break;
395 case 4:
396 reg = reg_devconf1;
397 sel_bit = 4;
398 break;
333 default: 399 default:
334 return -EINVAL; 400 return -EINVAL;
335 } 401 }
336 402
337 if (cpu_class_is_omap2()) { 403 if (clk_id == OMAP_MCBSP_SYSCLK_CLKS_FCLK)
338 if (clk_id == OMAP_MCBSP_SYSCLK_CLKS_FCLK) { 404 omap_ctrl_writel(omap_ctrl_readl(reg) & ~(1 << sel_bit), reg);
339 omap_ctrl_writel(omap_ctrl_readl(reg) & 405 else
340 ~(1 << sel_bit), reg); 406 omap_ctrl_writel(omap_ctrl_readl(reg) | (1 << sel_bit), reg);
341 } else {
342 omap_ctrl_writel(omap_ctrl_readl(reg) |
343 (1 << sel_bit), reg);
344 }
345 }
346 407
347 return 0; 408 return 0;
348} 409}
@@ -376,37 +437,49 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
376 return err; 437 return err;
377} 438}
378 439
379struct snd_soc_dai omap_mcbsp_dai[NUM_LINKS] = { 440#define OMAP_MCBSP_DAI_BUILDER(link_id) \
380{ 441{ \
381 .name = "omap-mcbsp-dai", 442 .name = "omap-mcbsp-dai-(link_id)", \
382 .id = 0, 443 .id = (link_id), \
383 .type = SND_SOC_DAI_I2S, 444 .type = SND_SOC_DAI_I2S, \
384 .playback = { 445 .playback = { \
385 .channels_min = 2, 446 .channels_min = 2, \
386 .channels_max = 2, 447 .channels_max = 2, \
387 .rates = OMAP_MCBSP_RATES, 448 .rates = OMAP_MCBSP_RATES, \
388 .formats = SNDRV_PCM_FMTBIT_S16_LE, 449 .formats = SNDRV_PCM_FMTBIT_S16_LE, \
389 }, 450 }, \
390 .capture = { 451 .capture = { \
391 .channels_min = 2, 452 .channels_min = 2, \
392 .channels_max = 2, 453 .channels_max = 2, \
393 .rates = OMAP_MCBSP_RATES, 454 .rates = OMAP_MCBSP_RATES, \
394 .formats = SNDRV_PCM_FMTBIT_S16_LE, 455 .formats = SNDRV_PCM_FMTBIT_S16_LE, \
395 }, 456 }, \
396 .ops = { 457 .ops = { \
397 .startup = omap_mcbsp_dai_startup, 458 .startup = omap_mcbsp_dai_startup, \
398 .shutdown = omap_mcbsp_dai_shutdown, 459 .shutdown = omap_mcbsp_dai_shutdown, \
399 .trigger = omap_mcbsp_dai_trigger, 460 .trigger = omap_mcbsp_dai_trigger, \
400 .hw_params = omap_mcbsp_dai_hw_params, 461 .hw_params = omap_mcbsp_dai_hw_params, \
401 }, 462 }, \
402 .dai_ops = { 463 .dai_ops = { \
403 .set_fmt = omap_mcbsp_dai_set_dai_fmt, 464 .set_fmt = omap_mcbsp_dai_set_dai_fmt, \
404 .set_clkdiv = omap_mcbsp_dai_set_clkdiv, 465 .set_clkdiv = omap_mcbsp_dai_set_clkdiv, \
405 .set_sysclk = omap_mcbsp_dai_set_dai_sysclk, 466 .set_sysclk = omap_mcbsp_dai_set_dai_sysclk, \
406 }, 467 }, \
407 .private_data = &mcbsp_data[0].bus_id, 468 .private_data = &mcbsp_data[(link_id)].bus_id, \
408}, 469}
470
471struct snd_soc_dai omap_mcbsp_dai[] = {
472 OMAP_MCBSP_DAI_BUILDER(0),
473 OMAP_MCBSP_DAI_BUILDER(1),
474#if NUM_LINKS >= 3
475 OMAP_MCBSP_DAI_BUILDER(2),
476#endif
477#if NUM_LINKS == 5
478 OMAP_MCBSP_DAI_BUILDER(3),
479 OMAP_MCBSP_DAI_BUILDER(4),
480#endif
409}; 481};
482
410EXPORT_SYMBOL_GPL(omap_mcbsp_dai); 483EXPORT_SYMBOL_GPL(omap_mcbsp_dai);
411 484
412MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@nokia.com>"); 485MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@nokia.com>");
diff --git a/sound/soc/omap/omap-mcbsp.h b/sound/soc/omap/omap-mcbsp.h
index ed8afb550671..df7ad13ba73d 100644
--- a/sound/soc/omap/omap-mcbsp.h
+++ b/sound/soc/omap/omap-mcbsp.h
@@ -38,11 +38,17 @@ enum omap_mcbsp_div {
38 OMAP_MCBSP_CLKGDV, /* Sample rate generator divider */ 38 OMAP_MCBSP_CLKGDV, /* Sample rate generator divider */
39}; 39};
40 40
41/* 41#if defined(CONFIG_ARCH_OMAP2420)
42 * REVISIT: Preparation for the ASoC v2. Let the number of available links to 42#define NUM_LINKS 2
43 * be same than number of McBSP ports found in OMAP(s) we are compiling for. 43#endif
44 */ 44#if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX)
45#define NUM_LINKS 1 45#undef NUM_LINKS
46#define NUM_LINKS 3
47#endif
48#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP34XX)
49#undef NUM_LINKS
50#define NUM_LINKS 5
51#endif
46 52
47extern struct snd_soc_dai omap_mcbsp_dai[NUM_LINKS]; 53extern struct snd_soc_dai omap_mcbsp_dai[NUM_LINKS];
48 54
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c
index 690bfeaec4a0..e9084fdd2082 100644
--- a/sound/soc/omap/omap-pcm.c
+++ b/sound/soc/omap/omap-pcm.c
@@ -97,7 +97,7 @@ static int omap_pcm_hw_params(struct snd_pcm_substream *substream,
97 prtd->dma_data = dma_data; 97 prtd->dma_data = dma_data;
98 err = omap_request_dma(dma_data->dma_req, dma_data->name, 98 err = omap_request_dma(dma_data->dma_req, dma_data->name,
99 omap_pcm_dma_irq, substream, &prtd->dma_ch); 99 omap_pcm_dma_irq, substream, &prtd->dma_ch);
100 if (!cpu_is_omap1510()) { 100 if (!err & !cpu_is_omap1510()) {
101 /* 101 /*
102 * Link channel with itself so DMA doesn't need any 102 * Link channel with itself so DMA doesn't need any
103 * reprogramming while looping the buffer 103 * reprogramming while looping the buffer
@@ -147,12 +147,14 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream)
147 dma_params.src_or_dst_synch = OMAP_DMA_DST_SYNC; 147 dma_params.src_or_dst_synch = OMAP_DMA_DST_SYNC;
148 dma_params.src_start = runtime->dma_addr; 148 dma_params.src_start = runtime->dma_addr;
149 dma_params.dst_start = dma_data->port_addr; 149 dma_params.dst_start = dma_data->port_addr;
150 dma_params.dst_port = OMAP_DMA_PORT_MPUI;
150 } else { 151 } else {
151 dma_params.src_amode = OMAP_DMA_AMODE_CONSTANT; 152 dma_params.src_amode = OMAP_DMA_AMODE_CONSTANT;
152 dma_params.dst_amode = OMAP_DMA_AMODE_POST_INC; 153 dma_params.dst_amode = OMAP_DMA_AMODE_POST_INC;
153 dma_params.src_or_dst_synch = OMAP_DMA_SRC_SYNC; 154 dma_params.src_or_dst_synch = OMAP_DMA_SRC_SYNC;
154 dma_params.src_start = dma_data->port_addr; 155 dma_params.src_start = dma_data->port_addr;
155 dma_params.dst_start = runtime->dma_addr; 156 dma_params.dst_start = runtime->dma_addr;
157 dma_params.src_port = OMAP_DMA_PORT_MPUI;
156 } 158 }
157 /* 159 /*
158 * Set DMA transfer frame size equal to ALSA period size and frame 160 * Set DMA transfer frame size equal to ALSA period size and frame
diff --git a/sound/soc/omap/osk5912.c b/sound/soc/omap/osk5912.c
new file mode 100644
index 000000000000..0fe733796898
--- /dev/null
+++ b/sound/soc/omap/osk5912.c
@@ -0,0 +1,232 @@
1/*
2 * osk5912.c -- SoC audio for OSK 5912
3 *
4 * Copyright (C) 2008 Mistral Solutions
5 *
6 * Contact: Arun KS <arunks@mistralsolutions.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23
24#include <linux/clk.h>
25#include <linux/platform_device.h>
26#include <sound/core.h>
27#include <sound/pcm.h>
28#include <sound/soc.h>
29#include <sound/soc-dapm.h>
30
31#include <asm/mach-types.h>
32#include <mach/hardware.h>
33#include <linux/gpio.h>
34#include <mach/mcbsp.h>
35
36#include "omap-mcbsp.h"
37#include "omap-pcm.h"
38#include "../codecs/tlv320aic23.h"
39
40#define CODEC_CLOCK 12000000
41
42static struct clk *tlv320aic23_mclk;
43
44static int osk_startup(struct snd_pcm_substream *substream)
45{
46 return clk_enable(tlv320aic23_mclk);
47}
48
49static void osk_shutdown(struct snd_pcm_substream *substream)
50{
51 clk_disable(tlv320aic23_mclk);
52}
53
54static int osk_hw_params(struct snd_pcm_substream *substream,
55 struct snd_pcm_hw_params *params)
56{
57 struct snd_soc_pcm_runtime *rtd = substream->private_data;
58 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
59 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
60 int err;
61
62 /* Set codec DAI configuration */
63 err = snd_soc_dai_set_fmt(codec_dai,
64 SND_SOC_DAIFMT_DSP_A |
65 SND_SOC_DAIFMT_NB_IF |
66 SND_SOC_DAIFMT_CBM_CFM);
67 if (err < 0) {
68 printk(KERN_ERR "can't set codec DAI configuration\n");
69 return err;
70 }
71
72 /* Set cpu DAI configuration */
73 err = snd_soc_dai_set_fmt(cpu_dai,
74 SND_SOC_DAIFMT_DSP_A |
75 SND_SOC_DAIFMT_NB_IF |
76 SND_SOC_DAIFMT_CBM_CFM);
77 if (err < 0) {
78 printk(KERN_ERR "can't set cpu DAI configuration\n");
79 return err;
80 }
81
82 /* Set the codec system clock for DAC and ADC */
83 err =
84 snd_soc_dai_set_sysclk(codec_dai, 0, CODEC_CLOCK, SND_SOC_CLOCK_IN);
85
86 if (err < 0) {
87 printk(KERN_ERR "can't set codec system clock\n");
88 return err;
89 }
90
91 return err;
92}
93
94static struct snd_soc_ops osk_ops = {
95 .startup = osk_startup,
96 .hw_params = osk_hw_params,
97 .shutdown = osk_shutdown,
98};
99
100static const struct snd_soc_dapm_widget tlv320aic23_dapm_widgets[] = {
101 SND_SOC_DAPM_HP("Headphone Jack", NULL),
102 SND_SOC_DAPM_LINE("Line In", NULL),
103 SND_SOC_DAPM_MIC("Mic Jack", NULL),
104};
105
106static const struct snd_soc_dapm_route audio_map[] = {
107 {"Headphone Jack", NULL, "LHPOUT"},
108 {"Headphone Jack", NULL, "RHPOUT"},
109
110 {"LLINEIN", NULL, "Line In"},
111 {"RLINEIN", NULL, "Line In"},
112
113 {"MICIN", NULL, "Mic Jack"},
114};
115
116static int osk_tlv320aic23_init(struct snd_soc_codec *codec)
117{
118
119 /* Add osk5912 specific widgets */
120 snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets,
121 ARRAY_SIZE(tlv320aic23_dapm_widgets));
122
123 /* Set up osk5912 specific audio path audio_map */
124 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
125
126 snd_soc_dapm_enable_pin(codec, "Headphone Jack");
127 snd_soc_dapm_enable_pin(codec, "Line In");
128 snd_soc_dapm_enable_pin(codec, "Mic Jack");
129
130 snd_soc_dapm_sync(codec);
131
132 return 0;
133}
134
135/* Digital audio interface glue - connects codec <--> CPU */
136static struct snd_soc_dai_link osk_dai = {
137 .name = "TLV320AIC23",
138 .stream_name = "AIC23",
139 .cpu_dai = &omap_mcbsp_dai[0],
140 .codec_dai = &tlv320aic23_dai,
141 .init = osk_tlv320aic23_init,
142 .ops = &osk_ops,
143};
144
145/* Audio machine driver */
146static struct snd_soc_machine snd_soc_machine_osk = {
147 .name = "OSK5912",
148 .dai_link = &osk_dai,
149 .num_links = 1,
150};
151
152/* Audio subsystem */
153static struct snd_soc_device osk_snd_devdata = {
154 .machine = &snd_soc_machine_osk,
155 .platform = &omap_soc_platform,
156 .codec_dev = &soc_codec_dev_tlv320aic23,
157};
158
159static struct platform_device *osk_snd_device;
160
161static int __init osk_soc_init(void)
162{
163 int err;
164 u32 curRate;
165 struct device *dev;
166
167 if (!(machine_is_omap_osk()))
168 return -ENODEV;
169
170 osk_snd_device = platform_device_alloc("soc-audio", -1);
171 if (!osk_snd_device)
172 return -ENOMEM;
173
174 platform_set_drvdata(osk_snd_device, &osk_snd_devdata);
175 osk_snd_devdata.dev = &osk_snd_device->dev;
176 *(unsigned int *)osk_dai.cpu_dai->private_data = 0; /* McBSP1 */
177 err = platform_device_add(osk_snd_device);
178 if (err)
179 goto err1;
180
181 dev = &osk_snd_device->dev;
182
183 tlv320aic23_mclk = clk_get(dev, "mclk");
184 if (IS_ERR(tlv320aic23_mclk)) {
185 printk(KERN_ERR "Could not get mclk clock\n");
186 return -ENODEV;
187 }
188
189 if (clk_get_usecount(tlv320aic23_mclk) > 0) {
190 /* MCLK is already in use */
191 printk(KERN_WARNING
192 "MCLK in use at %d Hz. We change it to %d Hz\n",
193 (uint) clk_get_rate(tlv320aic23_mclk), CODEC_CLOCK);
194 }
195
196 /*
197 * Configure 12 MHz output on MCLK.
198 */
199 curRate = (uint) clk_get_rate(tlv320aic23_mclk);
200 if (curRate != CODEC_CLOCK) {
201 if (clk_set_rate(tlv320aic23_mclk, CODEC_CLOCK)) {
202 printk(KERN_ERR "Cannot set MCLK for AIC23 CODEC\n");
203 err = -ECANCELED;
204 goto err1;
205 }
206 }
207
208 printk(KERN_INFO "MCLK = %d [%d], usecount = %d\n",
209 (uint) clk_get_rate(tlv320aic23_mclk), CODEC_CLOCK,
210 clk_get_usecount(tlv320aic23_mclk));
211
212 return 0;
213err1:
214 clk_put(tlv320aic23_mclk);
215 platform_device_del(osk_snd_device);
216 platform_device_put(osk_snd_device);
217
218 return err;
219
220}
221
222static void __exit osk_soc_exit(void)
223{
224 platform_device_unregister(osk_snd_device);
225}
226
227module_init(osk_soc_init);
228module_exit(osk_soc_exit);
229
230MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>");
231MODULE_DESCRIPTION("ALSA SoC OSK 5912");
232MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig
index 9212c37a33b8..f8c1cdd940ac 100644
--- a/sound/soc/pxa/Kconfig
+++ b/sound/soc/pxa/Kconfig
@@ -1,6 +1,7 @@
1config SND_PXA2XX_SOC 1config SND_PXA2XX_SOC
2 tristate "SoC Audio for the Intel PXA2xx chip" 2 tristate "SoC Audio for the Intel PXA2xx chip"
3 depends on ARCH_PXA 3 depends on ARCH_PXA
4 select SND_PXA2XX_LIB
4 help 5 help
5 Say Y or M if you want to add support for codecs attached to 6 Say Y or M if you want to add support for codecs attached to
6 the PXA2xx AC97, I2S or SSP interface. You will also need 7 the PXA2xx AC97, I2S or SSP interface. You will also need
@@ -13,6 +14,8 @@ config SND_PXA2XX_AC97
13config SND_PXA2XX_SOC_AC97 14config SND_PXA2XX_SOC_AC97
14 tristate 15 tristate
15 select AC97_BUS 16 select AC97_BUS
17 select SND_ARM
18 select SND_PXA2XX_LIB_AC97
16 select SND_SOC_AC97_BUS 19 select SND_SOC_AC97_BUS
17 20
18config SND_PXA2XX_SOC_I2S 21config SND_PXA2XX_SOC_I2S
diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c
index 0a53f72077fd..2718eaf7895f 100644
--- a/sound/soc/pxa/corgi.c
+++ b/sound/soc/pxa/corgi.c
@@ -4,7 +4,7 @@
4 * Copyright 2005 Wolfson Microelectronics PLC. 4 * Copyright 2005 Wolfson Microelectronics PLC.
5 * Copyright 2005 Openedhand Ltd. 5 * Copyright 2005 Openedhand Ltd.
6 * 6 *
7 * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com> 7 * Authors: Liam Girdwood <lrg@slimlogic.co.uk>
8 * Richard Purdie <richard@openedhand.com> 8 * Richard Purdie <richard@openedhand.com>
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify it 10 * This program is free software; you can redistribute it and/or modify it
@@ -18,13 +18,13 @@
18#include <linux/timer.h> 18#include <linux/timer.h>
19#include <linux/interrupt.h> 19#include <linux/interrupt.h>
20#include <linux/platform_device.h> 20#include <linux/platform_device.h>
21#include <linux/gpio.h>
21#include <sound/core.h> 22#include <sound/core.h>
22#include <sound/pcm.h> 23#include <sound/pcm.h>
23#include <sound/soc.h> 24#include <sound/soc.h>
24#include <sound/soc-dapm.h> 25#include <sound/soc-dapm.h>
25 26
26#include <asm/mach-types.h> 27#include <asm/mach-types.h>
27#include <asm/hardware/scoop.h>
28#include <mach/pxa-regs.h> 28#include <mach/pxa-regs.h>
29#include <mach/hardware.h> 29#include <mach/hardware.h>
30#include <mach/corgi.h> 30#include <mach/corgi.h>
@@ -54,8 +54,8 @@ static void corgi_ext_control(struct snd_soc_codec *codec)
54 switch (corgi_jack_func) { 54 switch (corgi_jack_func) {
55 case CORGI_HP: 55 case CORGI_HP:
56 /* set = unmute headphone */ 56 /* set = unmute headphone */
57 set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L); 57 gpio_set_value(CORGI_GPIO_MUTE_L, 1);
58 set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R); 58 gpio_set_value(CORGI_GPIO_MUTE_R, 1);
59 snd_soc_dapm_disable_pin(codec, "Mic Jack"); 59 snd_soc_dapm_disable_pin(codec, "Mic Jack");
60 snd_soc_dapm_disable_pin(codec, "Line Jack"); 60 snd_soc_dapm_disable_pin(codec, "Line Jack");
61 snd_soc_dapm_enable_pin(codec, "Headphone Jack"); 61 snd_soc_dapm_enable_pin(codec, "Headphone Jack");
@@ -63,24 +63,24 @@ static void corgi_ext_control(struct snd_soc_codec *codec)
63 break; 63 break;
64 case CORGI_MIC: 64 case CORGI_MIC:
65 /* reset = mute headphone */ 65 /* reset = mute headphone */
66 reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L); 66 gpio_set_value(CORGI_GPIO_MUTE_L, 0);
67 reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R); 67 gpio_set_value(CORGI_GPIO_MUTE_R, 0);
68 snd_soc_dapm_enable_pin(codec, "Mic Jack"); 68 snd_soc_dapm_enable_pin(codec, "Mic Jack");
69 snd_soc_dapm_disable_pin(codec, "Line Jack"); 69 snd_soc_dapm_disable_pin(codec, "Line Jack");
70 snd_soc_dapm_disable_pin(codec, "Headphone Jack"); 70 snd_soc_dapm_disable_pin(codec, "Headphone Jack");
71 snd_soc_dapm_disable_pin(codec, "Headset Jack"); 71 snd_soc_dapm_disable_pin(codec, "Headset Jack");
72 break; 72 break;
73 case CORGI_LINE: 73 case CORGI_LINE:
74 reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L); 74 gpio_set_value(CORGI_GPIO_MUTE_L, 0);
75 reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R); 75 gpio_set_value(CORGI_GPIO_MUTE_R, 0);
76 snd_soc_dapm_disable_pin(codec, "Mic Jack"); 76 snd_soc_dapm_disable_pin(codec, "Mic Jack");
77 snd_soc_dapm_enable_pin(codec, "Line Jack"); 77 snd_soc_dapm_enable_pin(codec, "Line Jack");
78 snd_soc_dapm_disable_pin(codec, "Headphone Jack"); 78 snd_soc_dapm_disable_pin(codec, "Headphone Jack");
79 snd_soc_dapm_disable_pin(codec, "Headset Jack"); 79 snd_soc_dapm_disable_pin(codec, "Headset Jack");
80 break; 80 break;
81 case CORGI_HEADSET: 81 case CORGI_HEADSET:
82 reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L); 82 gpio_set_value(CORGI_GPIO_MUTE_L, 0);
83 set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R); 83 gpio_set_value(CORGI_GPIO_MUTE_R, 1);
84 snd_soc_dapm_enable_pin(codec, "Mic Jack"); 84 snd_soc_dapm_enable_pin(codec, "Mic Jack");
85 snd_soc_dapm_disable_pin(codec, "Line Jack"); 85 snd_soc_dapm_disable_pin(codec, "Line Jack");
86 snd_soc_dapm_disable_pin(codec, "Headphone Jack"); 86 snd_soc_dapm_disable_pin(codec, "Headphone Jack");
@@ -114,8 +114,8 @@ static int corgi_shutdown(struct snd_pcm_substream *substream)
114 struct snd_soc_codec *codec = rtd->socdev->codec; 114 struct snd_soc_codec *codec = rtd->socdev->codec;
115 115
116 /* set = unmute headphone */ 116 /* set = unmute headphone */
117 set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L); 117 gpio_set_value(CORGI_GPIO_MUTE_L, 1);
118 set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R); 118 gpio_set_value(CORGI_GPIO_MUTE_R, 1);
119 return 0; 119 return 0;
120} 120}
121 121
@@ -218,22 +218,14 @@ static int corgi_set_spk(struct snd_kcontrol *kcontrol,
218static int corgi_amp_event(struct snd_soc_dapm_widget *w, 218static int corgi_amp_event(struct snd_soc_dapm_widget *w,
219 struct snd_kcontrol *k, int event) 219 struct snd_kcontrol *k, int event)
220{ 220{
221 if (SND_SOC_DAPM_EVENT_ON(event)) 221 gpio_set_value(CORGI_GPIO_APM_ON, SND_SOC_DAPM_EVENT_ON(event));
222 set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_APM_ON);
223 else
224 reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_APM_ON);
225
226 return 0; 222 return 0;
227} 223}
228 224
229static int corgi_mic_event(struct snd_soc_dapm_widget *w, 225static int corgi_mic_event(struct snd_soc_dapm_widget *w,
230 struct snd_kcontrol *k, int event) 226 struct snd_kcontrol *k, int event)
231{ 227{
232 if (SND_SOC_DAPM_EVENT_ON(event)) 228 gpio_set_value(CORGI_GPIO_MIC_BIAS, SND_SOC_DAPM_EVENT_ON(event));
233 set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MIC_BIAS);
234 else
235 reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MIC_BIAS);
236
237 return 0; 229 return 0;
238} 230}
239 231
@@ -289,8 +281,8 @@ static int corgi_wm8731_init(struct snd_soc_codec *codec)
289{ 281{
290 int i, err; 282 int i, err;
291 283
292 snd_soc_dapm_disable_pin(codec, "LLINEIN"); 284 snd_soc_dapm_nc_pin(codec, "LLINEIN");
293 snd_soc_dapm_disable_pin(codec, "RLINEIN"); 285 snd_soc_dapm_nc_pin(codec, "RLINEIN");
294 286
295 /* Add corgi specific controls */ 287 /* Add corgi specific controls */
296 for (i = 0; i < ARRAY_SIZE(wm8731_corgi_controls); i++) { 288 for (i = 0; i < ARRAY_SIZE(wm8731_corgi_controls); i++) {
@@ -330,6 +322,7 @@ static struct snd_soc_machine snd_soc_machine_corgi = {
330 322
331/* corgi audio private data */ 323/* corgi audio private data */
332static struct wm8731_setup_data corgi_wm8731_setup = { 324static struct wm8731_setup_data corgi_wm8731_setup = {
325 .i2c_bus = 0,
333 .i2c_address = 0x1b, 326 .i2c_address = 0x1b,
334}; 327};
335 328
diff --git a/sound/soc/pxa/em-x270.c b/sound/soc/pxa/em-x270.c
index d9c3f7b28be2..e6ff6929ab4b 100644
--- a/sound/soc/pxa/em-x270.c
+++ b/sound/soc/pxa/em-x270.c
@@ -9,7 +9,7 @@
9 * Copyright 2005 Wolfson Microelectronics PLC. 9 * Copyright 2005 Wolfson Microelectronics PLC.
10 * Copyright 2005 Openedhand Ltd. 10 * Copyright 2005 Openedhand Ltd.
11 * 11 *
12 * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com> 12 * Authors: Liam Girdwood <lrg@slimlogic.co.uk>
13 * Richard Purdie <richard@openedhand.com> 13 * Richard Purdie <richard@openedhand.com>
14 * 14 *
15 * This program is free software; you can redistribute it and/or modify it 15 * This program is free software; you can redistribute it and/or modify it
diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c
index a4697f7e2921..4d9930c52789 100644
--- a/sound/soc/pxa/poodle.c
+++ b/sound/soc/pxa/poodle.c
@@ -4,7 +4,7 @@
4 * Copyright 2005 Wolfson Microelectronics PLC. 4 * Copyright 2005 Wolfson Microelectronics PLC.
5 * Copyright 2005 Openedhand Ltd. 5 * Copyright 2005 Openedhand Ltd.
6 * 6 *
7 * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com> 7 * Authors: Liam Girdwood <lrg@slimlogic.co.uk>
8 * Richard Purdie <richard@openedhand.com> 8 * Richard Purdie <richard@openedhand.com>
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify it 10 * This program is free software; you can redistribute it and/or modify it
@@ -242,8 +242,8 @@ static int poodle_wm8731_init(struct snd_soc_codec *codec)
242{ 242{
243 int i, err; 243 int i, err;
244 244
245 snd_soc_dapm_disable_pin(codec, "LLINEIN"); 245 snd_soc_dapm_nc_pin(codec, "LLINEIN");
246 snd_soc_dapm_disable_pin(codec, "RLINEIN"); 246 snd_soc_dapm_nc_pin(codec, "RLINEIN");
247 snd_soc_dapm_enable_pin(codec, "MICIN"); 247 snd_soc_dapm_enable_pin(codec, "MICIN");
248 248
249 /* Add poodle specific controls */ 249 /* Add poodle specific controls */
@@ -284,6 +284,7 @@ static struct snd_soc_machine snd_soc_machine_poodle = {
284 284
285/* poodle audio private data */ 285/* poodle audio private data */
286static struct wm8731_setup_data poodle_wm8731_setup = { 286static struct wm8731_setup_data poodle_wm8731_setup = {
287 .i2c_bus = 0,
287 .i2c_address = 0x1b, 288 .i2c_address = 0x1b,
288}; 289};
289 290
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c
index d94a495bd6bd..a7a3a9c5c6ff 100644
--- a/sound/soc/pxa/pxa2xx-ac97.c
+++ b/sound/soc/pxa/pxa2xx-ac97.c
@@ -13,225 +13,30 @@
13#include <linux/init.h> 13#include <linux/init.h>
14#include <linux/module.h> 14#include <linux/module.h>
15#include <linux/platform_device.h> 15#include <linux/platform_device.h>
16#include <linux/interrupt.h>
17#include <linux/wait.h>
18#include <linux/clk.h>
19#include <linux/delay.h>
20 16
21#include <sound/core.h> 17#include <sound/core.h>
22#include <sound/pcm.h>
23#include <sound/ac97_codec.h> 18#include <sound/ac97_codec.h>
24#include <sound/initval.h>
25#include <sound/soc.h> 19#include <sound/soc.h>
20#include <sound/pxa2xx-lib.h>
26 21
27#include <asm/irq.h>
28#include <linux/mutex.h>
29#include <mach/hardware.h> 22#include <mach/hardware.h>
30#include <mach/pxa-regs.h> 23#include <mach/pxa-regs.h>
31#include <mach/pxa2xx-gpio.h>
32#include <mach/audio.h>
33 24
34#include "pxa2xx-pcm.h" 25#include "pxa2xx-pcm.h"
35#include "pxa2xx-ac97.h" 26#include "pxa2xx-ac97.h"
36 27
37static DEFINE_MUTEX(car_mutex);
38static DECLARE_WAIT_QUEUE_HEAD(gsr_wq);
39static volatile long gsr_bits;
40static struct clk *ac97_clk;
41#ifdef CONFIG_PXA27x
42static struct clk *ac97conf_clk;
43#endif
44
45/*
46 * Beware PXA27x bugs:
47 *
48 * o Slot 12 read from modem space will hang controller.
49 * o CDONE, SDONE interrupt fails after any slot 12 IO.
50 *
51 * We therefore have an hybrid approach for waiting on SDONE (interrupt or
52 * 1 jiffy timeout if interrupt never comes).
53 */
54
55static unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97,
56 unsigned short reg)
57{
58 unsigned short val = -1;
59 volatile u32 *reg_addr;
60
61 mutex_lock(&car_mutex);
62
63 /* set up primary or secondary codec/modem space */
64#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
65 reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
66#else
67 if (reg == AC97_GPIO_STATUS)
68 reg_addr = ac97->num ? &SMC_REG_BASE : &PMC_REG_BASE;
69 else
70 reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
71#endif
72 reg_addr += (reg >> 1);
73
74#ifndef CONFIG_PXA27x
75 if (reg == AC97_GPIO_STATUS) {
76 /* read from controller cache */
77 val = *reg_addr;
78 goto out;
79 }
80#endif
81
82 /* start read access across the ac97 link */
83 GSR = GSR_CDONE | GSR_SDONE;
84 gsr_bits = 0;
85 val = *reg_addr;
86
87 wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1);
88 if (!((GSR | gsr_bits) & GSR_SDONE)) {
89 printk(KERN_ERR "%s: read error (ac97_reg=%x GSR=%#lx)\n",
90 __func__, reg, GSR | gsr_bits);
91 val = -1;
92 goto out;
93 }
94
95 /* valid data now */
96 GSR = GSR_CDONE | GSR_SDONE;
97 gsr_bits = 0;
98 val = *reg_addr;
99 /* but we've just started another cycle... */
100 wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1);
101
102out: mutex_unlock(&car_mutex);
103 return val;
104}
105
106static void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
107 unsigned short val)
108{
109 volatile u32 *reg_addr;
110
111 mutex_lock(&car_mutex);
112
113 /* set up primary or secondary codec/modem space */
114#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
115 reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
116#else
117 if (reg == AC97_GPIO_STATUS)
118 reg_addr = ac97->num ? &SMC_REG_BASE : &PMC_REG_BASE;
119 else
120 reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
121#endif
122 reg_addr += (reg >> 1);
123
124 GSR = GSR_CDONE | GSR_SDONE;
125 gsr_bits = 0;
126 *reg_addr = val;
127 wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_CDONE, 1);
128 if (!((GSR | gsr_bits) & GSR_CDONE))
129 printk(KERN_ERR "%s: write error (ac97_reg=%x GSR=%#lx)\n",
130 __func__, reg, GSR | gsr_bits);
131
132 mutex_unlock(&car_mutex);
133}
134
135static void pxa2xx_ac97_warm_reset(struct snd_ac97 *ac97) 28static void pxa2xx_ac97_warm_reset(struct snd_ac97 *ac97)
136{ 29{
137#ifdef CONFIG_PXA3xx 30 pxa2xx_ac97_try_warm_reset(ac97);
138 int timeout = 100;
139#endif
140 gsr_bits = 0;
141
142#ifdef CONFIG_PXA27x
143 /* warm reset broken on Bulverde,
144 so manually keep AC97 reset high */
145 pxa_gpio_mode(113 | GPIO_OUT | GPIO_DFLT_HIGH);
146 udelay(10);
147 GCR |= GCR_WARM_RST;
148 pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
149 udelay(500);
150#elif defined(CONFIG_PXA3xx)
151 /* Can't use interrupts */
152 GCR |= GCR_WARM_RST;
153 while (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)) && timeout--)
154 mdelay(1);
155#else
156 GCR |= GCR_WARM_RST | GCR_PRIRDY_IEN | GCR_SECRDY_IEN;
157 wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1);
158#endif
159
160 if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)))
161 printk(KERN_INFO "%s: warm reset timeout (GSR=%#lx)\n",
162 __func__, gsr_bits);
163 31
164 GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN); 32 pxa2xx_ac97_finish_reset(ac97);
165 GCR |= GCR_SDONE_IE|GCR_CDONE_IE;
166} 33}
167 34
168static void pxa2xx_ac97_cold_reset(struct snd_ac97 *ac97) 35static void pxa2xx_ac97_cold_reset(struct snd_ac97 *ac97)
169{ 36{
170#ifdef CONFIG_PXA3xx 37 pxa2xx_ac97_try_cold_reset(ac97);
171 int timeout = 1000;
172
173 /* Hold CLKBPB for 100us */
174 GCR = 0;
175 GCR = GCR_CLKBPB;
176 udelay(100);
177 GCR = 0;
178#endif
179 38
180 GCR &= GCR_COLD_RST; /* clear everything but nCRST */ 39 pxa2xx_ac97_finish_reset(ac97);
181 GCR &= ~GCR_COLD_RST; /* then assert nCRST */
182
183 gsr_bits = 0;
184#ifdef CONFIG_PXA27x
185 /* PXA27x Developers Manual section 13.5.2.2.1 */
186 clk_enable(ac97conf_clk);
187 udelay(5);
188 clk_disable(ac97conf_clk);
189 GCR = GCR_COLD_RST;
190 udelay(50);
191#elif defined(CONFIG_PXA3xx)
192 /* Can't use interrupts on PXA3xx */
193 GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
194
195 GCR = GCR_WARM_RST | GCR_COLD_RST;
196 while (!(GSR & (GSR_PCR | GSR_SCR)) && timeout--)
197 mdelay(10);
198#else
199 GCR = GCR_COLD_RST;
200 GCR |= GCR_CDONE_IE|GCR_SDONE_IE;
201 wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1);
202#endif
203
204 if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)))
205 printk(KERN_INFO "%s: cold reset timeout (GSR=%#lx)\n",
206 __func__, gsr_bits);
207
208 GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
209 GCR |= GCR_SDONE_IE|GCR_CDONE_IE;
210}
211
212static irqreturn_t pxa2xx_ac97_irq(int irq, void *dev_id)
213{
214 long status;
215
216 status = GSR;
217 if (status) {
218 GSR = status;
219 gsr_bits |= status;
220 wake_up(&gsr_wq);
221
222#ifdef CONFIG_PXA27x
223 /* Although we don't use those we still need to clear them
224 since they tend to spuriously trigger when MMC is used
225 (hardware bug? go figure)... */
226 MISR = MISR_EOC;
227 PISR = PISR_EOC;
228 MCSR = MCSR_EOC;
229#endif
230
231 return IRQ_HANDLED;
232 }
233
234 return IRQ_NONE;
235} 40}
236 41
237struct snd_ac97_bus_ops soc_ac97_ops = { 42struct snd_ac97_bus_ops soc_ac97_ops = {
@@ -244,7 +49,7 @@ struct snd_ac97_bus_ops soc_ac97_ops = {
244static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_out = { 49static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_out = {
245 .name = "AC97 PCM Stereo out", 50 .name = "AC97 PCM Stereo out",
246 .dev_addr = __PREG(PCDR), 51 .dev_addr = __PREG(PCDR),
247 .drcmr = &DRCMRTXPCDR, 52 .drcmr = &DRCMR(12),
248 .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | 53 .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
249 DCMD_BURST32 | DCMD_WIDTH4, 54 DCMD_BURST32 | DCMD_WIDTH4,
250}; 55};
@@ -252,7 +57,7 @@ static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_out = {
252static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_in = { 57static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_in = {
253 .name = "AC97 PCM Stereo in", 58 .name = "AC97 PCM Stereo in",
254 .dev_addr = __PREG(PCDR), 59 .dev_addr = __PREG(PCDR),
255 .drcmr = &DRCMRRXPCDR, 60 .drcmr = &DRCMR(11),
256 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | 61 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
257 DCMD_BURST32 | DCMD_WIDTH4, 62 DCMD_BURST32 | DCMD_WIDTH4,
258}; 63};
@@ -260,7 +65,7 @@ static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_in = {
260static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_aux_mono_out = { 65static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_aux_mono_out = {
261 .name = "AC97 Aux PCM (Slot 5) Mono out", 66 .name = "AC97 Aux PCM (Slot 5) Mono out",
262 .dev_addr = __PREG(MODR), 67 .dev_addr = __PREG(MODR),
263 .drcmr = &DRCMRTXMODR, 68 .drcmr = &DRCMR(10),
264 .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | 69 .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
265 DCMD_BURST16 | DCMD_WIDTH2, 70 DCMD_BURST16 | DCMD_WIDTH2,
266}; 71};
@@ -268,7 +73,7 @@ static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_aux_mono_out = {
268static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_aux_mono_in = { 73static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_aux_mono_in = {
269 .name = "AC97 Aux PCM (Slot 5) Mono in", 74 .name = "AC97 Aux PCM (Slot 5) Mono in",
270 .dev_addr = __PREG(MODR), 75 .dev_addr = __PREG(MODR),
271 .drcmr = &DRCMRRXMODR, 76 .drcmr = &DRCMR(9),
272 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | 77 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
273 DCMD_BURST16 | DCMD_WIDTH2, 78 DCMD_BURST16 | DCMD_WIDTH2,
274}; 79};
@@ -276,7 +81,7 @@ static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_aux_mono_in = {
276static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_mic_mono_in = { 81static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_mic_mono_in = {
277 .name = "AC97 Mic PCM (Slot 6) Mono in", 82 .name = "AC97 Mic PCM (Slot 6) Mono in",
278 .dev_addr = __PREG(MCDR), 83 .dev_addr = __PREG(MCDR),
279 .drcmr = &DRCMRRXMCDR, 84 .drcmr = &DRCMR(8),
280 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | 85 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
281 DCMD_BURST16 | DCMD_WIDTH2, 86 DCMD_BURST16 | DCMD_WIDTH2,
282}; 87};
@@ -285,24 +90,13 @@ static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_mic_mono_in = {
285static int pxa2xx_ac97_suspend(struct platform_device *pdev, 90static int pxa2xx_ac97_suspend(struct platform_device *pdev,
286 struct snd_soc_dai *dai) 91 struct snd_soc_dai *dai)
287{ 92{
288 GCR |= GCR_ACLINK_OFF; 93 return pxa2xx_ac97_hw_suspend();
289 clk_disable(ac97_clk);
290 return 0;
291} 94}
292 95
293static int pxa2xx_ac97_resume(struct platform_device *pdev, 96static int pxa2xx_ac97_resume(struct platform_device *pdev,
294 struct snd_soc_dai *dai) 97 struct snd_soc_dai *dai)
295{ 98{
296 pxa_gpio_mode(GPIO31_SYNC_AC97_MD); 99 return pxa2xx_ac97_hw_resume();
297 pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD);
298 pxa_gpio_mode(GPIO28_BITCLK_AC97_MD);
299 pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD);
300#ifdef CONFIG_PXA27x
301 /* Use GPIO 113 as AC97 Reset on Bulverde */
302 pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
303#endif
304 clk_enable(ac97_clk);
305 return 0;
306} 100}
307 101
308#else 102#else
@@ -313,61 +107,13 @@ static int pxa2xx_ac97_resume(struct platform_device *pdev,
313static int pxa2xx_ac97_probe(struct platform_device *pdev, 107static int pxa2xx_ac97_probe(struct platform_device *pdev,
314 struct snd_soc_dai *dai) 108 struct snd_soc_dai *dai)
315{ 109{
316 int ret; 110 return pxa2xx_ac97_hw_probe(pdev);
317
318 ret = request_irq(IRQ_AC97, pxa2xx_ac97_irq, IRQF_DISABLED, "AC97", NULL);
319 if (ret < 0)
320 goto err;
321
322 pxa_gpio_mode(GPIO31_SYNC_AC97_MD);
323 pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD);
324 pxa_gpio_mode(GPIO28_BITCLK_AC97_MD);
325 pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD);
326#ifdef CONFIG_PXA27x
327 /* Use GPIO 113 as AC97 Reset on Bulverde */
328 pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
329
330 ac97conf_clk = clk_get(&pdev->dev, "AC97CONFCLK");
331 if (IS_ERR(ac97conf_clk)) {
332 ret = PTR_ERR(ac97conf_clk);
333 ac97conf_clk = NULL;
334 goto err_irq;
335 }
336#endif
337 ac97_clk = clk_get(&pdev->dev, "AC97CLK");
338 if (IS_ERR(ac97_clk)) {
339 ret = PTR_ERR(ac97_clk);
340 ac97_clk = NULL;
341 goto err_irq;
342 }
343 clk_enable(ac97_clk);
344 return 0;
345
346 err_irq:
347 GCR |= GCR_ACLINK_OFF;
348#ifdef CONFIG_PXA27x
349 if (ac97conf_clk) {
350 clk_put(ac97conf_clk);
351 ac97conf_clk = NULL;
352 }
353#endif
354 free_irq(IRQ_AC97, NULL);
355 err:
356 return ret;
357} 111}
358 112
359static void pxa2xx_ac97_remove(struct platform_device *pdev, 113static void pxa2xx_ac97_remove(struct platform_device *pdev,
360 struct snd_soc_dai *dai) 114 struct snd_soc_dai *dai)
361{ 115{
362 GCR |= GCR_ACLINK_OFF; 116 pxa2xx_ac97_hw_remove(pdev);
363 free_irq(IRQ_AC97, NULL);
364#ifdef CONFIG_PXA27x
365 clk_put(ac97conf_clk);
366 ac97conf_clk = NULL;
367#endif
368 clk_disable(ac97_clk);
369 clk_put(ac97_clk);
370 ac97_clk = NULL;
371} 117}
372 118
373static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream, 119static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream,
diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c
index c796b1882776..e758034db5c3 100644
--- a/sound/soc/pxa/pxa2xx-i2s.c
+++ b/sound/soc/pxa/pxa2xx-i2s.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * Copyright 2005 Wolfson Microelectronics PLC. 4 * Copyright 2005 Wolfson Microelectronics PLC.
5 * Author: Liam Girdwood 5 * Author: Liam Girdwood
6 * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com 6 * lrg@slimlogic.co.uk
7 * 7 *
8 * This program is free software; you can redistribute it and/or modify it 8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the 9 * under the terms of the GNU General Public License as published by the
@@ -21,6 +21,7 @@
21#include <sound/pcm.h> 21#include <sound/pcm.h>
22#include <sound/initval.h> 22#include <sound/initval.h>
23#include <sound/soc.h> 23#include <sound/soc.h>
24#include <sound/pxa2xx-lib.h>
24 25
25#include <mach/hardware.h> 26#include <mach/hardware.h>
26#include <mach/pxa-regs.h> 27#include <mach/pxa-regs.h>
@@ -30,6 +31,54 @@
30#include "pxa2xx-pcm.h" 31#include "pxa2xx-pcm.h"
31#include "pxa2xx-i2s.h" 32#include "pxa2xx-i2s.h"
32 33
34struct pxa2xx_gpio {
35 u32 sys;
36 u32 rx;
37 u32 tx;
38 u32 clk;
39 u32 frm;
40};
41
42/*
43 * I2S Controller Register and Bit Definitions
44 */
45#define SACR0 __REG(0x40400000) /* Global Control Register */
46#define SACR1 __REG(0x40400004) /* Serial Audio I 2 S/MSB-Justified Control Register */
47#define SASR0 __REG(0x4040000C) /* Serial Audio I 2 S/MSB-Justified Interface and FIFO Status Register */
48#define SAIMR __REG(0x40400014) /* Serial Audio Interrupt Mask Register */
49#define SAICR __REG(0x40400018) /* Serial Audio Interrupt Clear Register */
50#define SADIV __REG(0x40400060) /* Audio Clock Divider Register. */
51#define SADR __REG(0x40400080) /* Serial Audio Data Register (TX and RX FIFO access Register). */
52
53#define SACR0_RFTH(x) ((x) << 12) /* Rx FIFO Interrupt or DMA Trigger Threshold */
54#define SACR0_TFTH(x) ((x) << 8) /* Tx FIFO Interrupt or DMA Trigger Threshold */
55#define SACR0_STRF (1 << 5) /* FIFO Select for EFWR Special Function */
56#define SACR0_EFWR (1 << 4) /* Enable EFWR Function */
57#define SACR0_RST (1 << 3) /* FIFO, i2s Register Reset */
58#define SACR0_BCKD (1 << 2) /* Bit Clock Direction */
59#define SACR0_ENB (1 << 0) /* Enable I2S Link */
60#define SACR1_ENLBF (1 << 5) /* Enable Loopback */
61#define SACR1_DRPL (1 << 4) /* Disable Replaying Function */
62#define SACR1_DREC (1 << 3) /* Disable Recording Function */
63#define SACR1_AMSL (1 << 0) /* Specify Alternate Mode */
64
65#define SASR0_I2SOFF (1 << 7) /* Controller Status */
66#define SASR0_ROR (1 << 6) /* Rx FIFO Overrun */
67#define SASR0_TUR (1 << 5) /* Tx FIFO Underrun */
68#define SASR0_RFS (1 << 4) /* Rx FIFO Service Request */
69#define SASR0_TFS (1 << 3) /* Tx FIFO Service Request */
70#define SASR0_BSY (1 << 2) /* I2S Busy */
71#define SASR0_RNE (1 << 1) /* Rx FIFO Not Empty */
72#define SASR0_TNF (1 << 0) /* Tx FIFO Not Empty */
73
74#define SAICR_ROR (1 << 6) /* Clear Rx FIFO Overrun Interrupt */
75#define SAICR_TUR (1 << 5) /* Clear Tx FIFO Underrun Interrupt */
76
77#define SAIMR_ROR (1 << 6) /* Enable Rx FIFO Overrun Condition Interrupt */
78#define SAIMR_TUR (1 << 5) /* Enable Tx FIFO Underrun Condition Interrupt */
79#define SAIMR_RFS (1 << 4) /* Enable Rx FIFO Service Interrupt */
80#define SAIMR_TFS (1 << 3) /* Enable Tx FIFO Service Interrupt */
81
33struct pxa_i2s_port { 82struct pxa_i2s_port {
34 u32 sadiv; 83 u32 sadiv;
35 u32 sacr0; 84 u32 sacr0;
@@ -44,7 +93,7 @@ static struct clk *clk_i2s;
44static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_out = { 93static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_out = {
45 .name = "I2S PCM Stereo out", 94 .name = "I2S PCM Stereo out",
46 .dev_addr = __PREG(SADR), 95 .dev_addr = __PREG(SADR),
47 .drcmr = &DRCMRTXSADR, 96 .drcmr = &DRCMR(3),
48 .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | 97 .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
49 DCMD_BURST32 | DCMD_WIDTH4, 98 DCMD_BURST32 | DCMD_WIDTH4,
50}; 99};
@@ -52,7 +101,7 @@ static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_out = {
52static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_in = { 101static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_in = {
53 .name = "I2S PCM Stereo in", 102 .name = "I2S PCM Stereo in",
54 .dev_addr = __PREG(SADR), 103 .dev_addr = __PREG(SADR),
55 .drcmr = &DRCMRRXSADR, 104 .drcmr = &DRCMR(2),
56 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | 105 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
57 DCMD_BURST32 | DCMD_WIDTH4, 106 DCMD_BURST32 | DCMD_WIDTH4,
58}; 107};
@@ -65,11 +114,6 @@ static struct pxa2xx_gpio gpio_bus[] = {
65 .frm = GPIO31_SYNC_I2S_MD, 114 .frm = GPIO31_SYNC_I2S_MD,
66 }, 115 },
67 { /* I2S SoC Master */ 116 { /* I2S SoC Master */
68#ifdef CONFIG_PXA27x
69 .sys = GPIO113_I2S_SYSCLK_MD,
70#else
71 .sys = GPIO32_SYSCLK_I2S_MD,
72#endif
73 .rx = GPIO29_SDATA_IN_I2S_MD, 117 .rx = GPIO29_SDATA_IN_I2S_MD,
74 .tx = GPIO30_SDATA_OUT_I2S_MD, 118 .tx = GPIO30_SDATA_OUT_I2S_MD,
75 .clk = GPIO28_BITCLK_OUT_I2S_MD, 119 .clk = GPIO28_BITCLK_OUT_I2S_MD,
@@ -343,6 +387,11 @@ static struct platform_driver pxa2xx_i2s_driver = {
343 387
344static int __init pxa2xx_i2s_init(void) 388static int __init pxa2xx_i2s_init(void)
345{ 389{
390 if (cpu_is_pxa27x())
391 gpio_bus[1].sys = GPIO113_I2S_SYSCLK_MD;
392 else
393 gpio_bus[1].sys = GPIO32_SYSCLK_I2S_MD;
394
346 clk_i2s = ERR_PTR(-ENOENT); 395 clk_i2s = ERR_PTR(-ENOENT);
347 return platform_driver_register(&pxa2xx_i2s_driver); 396 return platform_driver_register(&pxa2xx_i2s_driver);
348} 397}
@@ -356,6 +405,6 @@ module_init(pxa2xx_i2s_init);
356module_exit(pxa2xx_i2s_exit); 405module_exit(pxa2xx_i2s_exit);
357 406
358/* Module information */ 407/* Module information */
359MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com"); 408MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk");
360MODULE_DESCRIPTION("pxa2xx I2S SoC Interface"); 409MODULE_DESCRIPTION("pxa2xx I2S SoC Interface");
361MODULE_LICENSE("GPL"); 410MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c
index 4345f387fe41..afcd892cd2fa 100644
--- a/sound/soc/pxa/pxa2xx-pcm.c
+++ b/sound/soc/pxa/pxa2xx-pcm.c
@@ -10,64 +10,14 @@
10 * published by the Free Software Foundation. 10 * published by the Free Software Foundation.
11 */ 11 */
12 12
13#include <linux/module.h>
14#include <linux/init.h>
15#include <linux/platform_device.h>
16#include <linux/slab.h>
17#include <linux/dma-mapping.h> 13#include <linux/dma-mapping.h>
18 14
19#include <sound/core.h> 15#include <sound/core.h>
20#include <sound/pcm.h>
21#include <sound/pcm_params.h>
22#include <sound/soc.h> 16#include <sound/soc.h>
23 17#include <sound/pxa2xx-lib.h>
24#include <asm/dma.h>
25#include <mach/hardware.h>
26#include <mach/pxa-regs.h>
27#include <mach/audio.h>
28 18
29#include "pxa2xx-pcm.h" 19#include "pxa2xx-pcm.h"
30 20#include "../../arm/pxa2xx-pcm.h"
31static const struct snd_pcm_hardware pxa2xx_pcm_hardware = {
32 .info = SNDRV_PCM_INFO_MMAP |
33 SNDRV_PCM_INFO_MMAP_VALID |
34 SNDRV_PCM_INFO_INTERLEAVED |
35 SNDRV_PCM_INFO_PAUSE |
36 SNDRV_PCM_INFO_RESUME,
37 .formats = SNDRV_PCM_FMTBIT_S16_LE |
38 SNDRV_PCM_FMTBIT_S24_LE |
39 SNDRV_PCM_FMTBIT_S32_LE,
40 .period_bytes_min = 32,
41 .period_bytes_max = 8192 - 32,
42 .periods_min = 1,
43 .periods_max = PAGE_SIZE/sizeof(pxa_dma_desc),
44 .buffer_bytes_max = 128 * 1024,
45 .fifo_size = 32,
46};
47
48struct pxa2xx_runtime_data {
49 int dma_ch;
50 struct pxa2xx_pcm_dma_params *params;
51 pxa_dma_desc *dma_desc_array;
52 dma_addr_t dma_desc_array_phys;
53};
54
55static void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id)
56{
57 struct snd_pcm_substream *substream = dev_id;
58 struct pxa2xx_runtime_data *prtd = substream->runtime->private_data;
59 int dcsr;
60
61 dcsr = DCSR(dma_ch);
62 DCSR(dma_ch) = dcsr & ~DCSR_STOPIRQEN;
63
64 if (dcsr & DCSR_ENDINTR) {
65 snd_pcm_period_elapsed(substream);
66 } else {
67 printk(KERN_ERR "%s: DMA error on channel %d (DCSR=%#x)\n",
68 prtd->params->name, dma_ch, dcsr);
69 }
70}
71 21
72static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream, 22static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
73 struct snd_pcm_hw_params *params) 23 struct snd_pcm_hw_params *params)
@@ -76,10 +26,6 @@ static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
76 struct pxa2xx_runtime_data *prtd = runtime->private_data; 26 struct pxa2xx_runtime_data *prtd = runtime->private_data;
77 struct snd_soc_pcm_runtime *rtd = substream->private_data; 27 struct snd_soc_pcm_runtime *rtd = substream->private_data;
78 struct pxa2xx_pcm_dma_params *dma = rtd->dai->cpu_dai->dma_data; 28 struct pxa2xx_pcm_dma_params *dma = rtd->dai->cpu_dai->dma_data;
79 size_t totsize = params_buffer_bytes(params);
80 size_t period = params_period_bytes(params);
81 pxa_dma_desc *dma_desc;
82 dma_addr_t dma_buff_phys, next_desc_phys;
83 int ret; 29 int ret;
84 30
85 /* return if this is a bufferless transfer e.g. 31 /* return if this is a bufferless transfer e.g.
@@ -106,42 +52,16 @@ static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
106 prtd->dma_ch = ret; 52 prtd->dma_ch = ret;
107 } 53 }
108 54
109 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); 55 return __pxa2xx_pcm_hw_params(substream, params);
110 runtime->dma_bytes = totsize;
111
112 dma_desc = prtd->dma_desc_array;
113 next_desc_phys = prtd->dma_desc_array_phys;
114 dma_buff_phys = runtime->dma_addr;
115 do {
116 next_desc_phys += sizeof(pxa_dma_desc);
117 dma_desc->ddadr = next_desc_phys;
118 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
119 dma_desc->dsadr = dma_buff_phys;
120 dma_desc->dtadr = prtd->params->dev_addr;
121 } else {
122 dma_desc->dsadr = prtd->params->dev_addr;
123 dma_desc->dtadr = dma_buff_phys;
124 }
125 if (period > totsize)
126 period = totsize;
127 dma_desc->dcmd = prtd->params->dcmd | period | DCMD_ENDIRQEN;
128 dma_desc++;
129 dma_buff_phys += period;
130 } while (totsize -= period);
131 dma_desc[-1].ddadr = prtd->dma_desc_array_phys;
132
133 return 0;
134} 56}
135 57
136static int pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream) 58static int pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream)
137{ 59{
138 struct pxa2xx_runtime_data *prtd = substream->runtime->private_data; 60 struct pxa2xx_runtime_data *prtd = substream->runtime->private_data;
139 61
140 if (prtd && prtd->params) 62 __pxa2xx_pcm_hw_free(substream);
141 *prtd->params->drcmr = 0;
142 63
143 if (prtd->dma_ch) { 64 if (prtd->dma_ch) {
144 snd_pcm_set_runtime_buffer(substream, NULL);
145 pxa_free_dma(prtd->dma_ch); 65 pxa_free_dma(prtd->dma_ch);
146 prtd->dma_ch = 0; 66 prtd->dma_ch = 0;
147 } 67 }
@@ -149,188 +69,21 @@ static int pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream)
149 return 0; 69 return 0;
150} 70}
151 71
152static int pxa2xx_pcm_prepare(struct snd_pcm_substream *substream)
153{
154 struct pxa2xx_runtime_data *prtd = substream->runtime->private_data;
155
156 DCSR(prtd->dma_ch) &= ~DCSR_RUN;
157 DCSR(prtd->dma_ch) = 0;
158 DCMD(prtd->dma_ch) = 0;
159 *prtd->params->drcmr = prtd->dma_ch | DRCMR_MAPVLD;
160
161 return 0;
162}
163
164static int pxa2xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
165{
166 struct pxa2xx_runtime_data *prtd = substream->runtime->private_data;
167 int ret = 0;
168
169 switch (cmd) {
170 case SNDRV_PCM_TRIGGER_START:
171 DDADR(prtd->dma_ch) = prtd->dma_desc_array_phys;
172 DCSR(prtd->dma_ch) = DCSR_RUN;
173 break;
174
175 case SNDRV_PCM_TRIGGER_STOP:
176 case SNDRV_PCM_TRIGGER_SUSPEND:
177 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
178 DCSR(prtd->dma_ch) &= ~DCSR_RUN;
179 break;
180
181 case SNDRV_PCM_TRIGGER_RESUME:
182 DCSR(prtd->dma_ch) |= DCSR_RUN;
183 break;
184 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
185 DDADR(prtd->dma_ch) = prtd->dma_desc_array_phys;
186 DCSR(prtd->dma_ch) |= DCSR_RUN;
187 break;
188
189 default:
190 ret = -EINVAL;
191 }
192
193 return ret;
194}
195
196static snd_pcm_uframes_t
197pxa2xx_pcm_pointer(struct snd_pcm_substream *substream)
198{
199 struct snd_pcm_runtime *runtime = substream->runtime;
200 struct pxa2xx_runtime_data *prtd = runtime->private_data;
201
202 dma_addr_t ptr = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
203 DSADR(prtd->dma_ch) : DTADR(prtd->dma_ch);
204 snd_pcm_uframes_t x = bytes_to_frames(runtime, ptr - runtime->dma_addr);
205
206 if (x == runtime->buffer_size)
207 x = 0;
208 return x;
209}
210
211static int pxa2xx_pcm_open(struct snd_pcm_substream *substream)
212{
213 struct snd_pcm_runtime *runtime = substream->runtime;
214 struct pxa2xx_runtime_data *prtd;
215 int ret;
216
217 snd_soc_set_runtime_hwparams(substream, &pxa2xx_pcm_hardware);
218
219 /*
220 * For mysterious reasons (and despite what the manual says)
221 * playback samples are lost if the DMA count is not a multiple
222 * of the DMA burst size. Let's add a rule to enforce that.
223 */
224 ret = snd_pcm_hw_constraint_step(runtime, 0,
225 SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32);
226 if (ret)
227 goto out;
228
229 ret = snd_pcm_hw_constraint_step(runtime, 0,
230 SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32);
231 if (ret)
232 goto out;
233
234 ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
235 if (ret < 0)
236 goto out;
237
238 prtd = kzalloc(sizeof(struct pxa2xx_runtime_data), GFP_KERNEL);
239 if (prtd == NULL) {
240 ret = -ENOMEM;
241 goto out;
242 }
243
244 prtd->dma_desc_array =
245 dma_alloc_writecombine(substream->pcm->card->dev, PAGE_SIZE,
246 &prtd->dma_desc_array_phys, GFP_KERNEL);
247 if (!prtd->dma_desc_array) {
248 ret = -ENOMEM;
249 goto err1;
250 }
251
252 runtime->private_data = prtd;
253 return 0;
254
255 err1:
256 kfree(prtd);
257 out:
258 return ret;
259}
260
261static int pxa2xx_pcm_close(struct snd_pcm_substream *substream)
262{
263 struct snd_pcm_runtime *runtime = substream->runtime;
264 struct pxa2xx_runtime_data *prtd = runtime->private_data;
265
266 dma_free_writecombine(substream->pcm->card->dev, PAGE_SIZE,
267 prtd->dma_desc_array, prtd->dma_desc_array_phys);
268 kfree(prtd);
269 return 0;
270}
271
272static int pxa2xx_pcm_mmap(struct snd_pcm_substream *substream,
273 struct vm_area_struct *vma)
274{
275 struct snd_pcm_runtime *runtime = substream->runtime;
276 return dma_mmap_writecombine(substream->pcm->card->dev, vma,
277 runtime->dma_area,
278 runtime->dma_addr,
279 runtime->dma_bytes);
280}
281
282struct snd_pcm_ops pxa2xx_pcm_ops = { 72struct snd_pcm_ops pxa2xx_pcm_ops = {
283 .open = pxa2xx_pcm_open, 73 .open = __pxa2xx_pcm_open,
284 .close = pxa2xx_pcm_close, 74 .close = __pxa2xx_pcm_close,
285 .ioctl = snd_pcm_lib_ioctl, 75 .ioctl = snd_pcm_lib_ioctl,
286 .hw_params = pxa2xx_pcm_hw_params, 76 .hw_params = pxa2xx_pcm_hw_params,
287 .hw_free = pxa2xx_pcm_hw_free, 77 .hw_free = pxa2xx_pcm_hw_free,
288 .prepare = pxa2xx_pcm_prepare, 78 .prepare = __pxa2xx_pcm_prepare,
289 .trigger = pxa2xx_pcm_trigger, 79 .trigger = pxa2xx_pcm_trigger,
290 .pointer = pxa2xx_pcm_pointer, 80 .pointer = pxa2xx_pcm_pointer,
291 .mmap = pxa2xx_pcm_mmap, 81 .mmap = pxa2xx_pcm_mmap,
292}; 82};
293 83
294static int pxa2xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
295{
296 struct snd_pcm_substream *substream = pcm->streams[stream].substream;
297 struct snd_dma_buffer *buf = &substream->dma_buffer;
298 size_t size = pxa2xx_pcm_hardware.buffer_bytes_max;
299 buf->dev.type = SNDRV_DMA_TYPE_DEV;
300 buf->dev.dev = pcm->card->dev;
301 buf->private_data = NULL;
302 buf->area = dma_alloc_writecombine(pcm->card->dev, size,
303 &buf->addr, GFP_KERNEL);
304 if (!buf->area)
305 return -ENOMEM;
306 buf->bytes = size;
307 return 0;
308}
309
310static void pxa2xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
311{
312 struct snd_pcm_substream *substream;
313 struct snd_dma_buffer *buf;
314 int stream;
315
316 for (stream = 0; stream < 2; stream++) {
317 substream = pcm->streams[stream].substream;
318 if (!substream)
319 continue;
320
321 buf = &substream->dma_buffer;
322 if (!buf->area)
323 continue;
324
325 dma_free_writecombine(pcm->card->dev, buf->bytes,
326 buf->area, buf->addr);
327 buf->area = NULL;
328 }
329}
330
331static u64 pxa2xx_pcm_dmamask = DMA_32BIT_MASK; 84static u64 pxa2xx_pcm_dmamask = DMA_32BIT_MASK;
332 85
333int pxa2xx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, 86static int pxa2xx_soc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
334 struct snd_pcm *pcm) 87 struct snd_pcm *pcm)
335{ 88{
336 int ret = 0; 89 int ret = 0;
@@ -360,7 +113,7 @@ int pxa2xx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
360struct snd_soc_platform pxa2xx_soc_platform = { 113struct snd_soc_platform pxa2xx_soc_platform = {
361 .name = "pxa2xx-audio", 114 .name = "pxa2xx-audio",
362 .pcm_ops = &pxa2xx_pcm_ops, 115 .pcm_ops = &pxa2xx_pcm_ops,
363 .pcm_new = pxa2xx_pcm_new, 116 .pcm_new = pxa2xx_soc_pcm_new,
364 .pcm_free = pxa2xx_pcm_free_dma_buffers, 117 .pcm_free = pxa2xx_pcm_free_dma_buffers,
365}; 118};
366EXPORT_SYMBOL_GPL(pxa2xx_soc_platform); 119EXPORT_SYMBOL_GPL(pxa2xx_soc_platform);
diff --git a/sound/soc/pxa/pxa2xx-pcm.h b/sound/soc/pxa/pxa2xx-pcm.h
index 54c9c755e508..60c3b20aeeb4 100644
--- a/sound/soc/pxa/pxa2xx-pcm.h
+++ b/sound/soc/pxa/pxa2xx-pcm.h
@@ -13,21 +13,6 @@
13#ifndef _PXA2XX_PCM_H 13#ifndef _PXA2XX_PCM_H
14#define _PXA2XX_PCM_H 14#define _PXA2XX_PCM_H
15 15
16struct pxa2xx_pcm_dma_params {
17 char *name; /* stream identifier */
18 u32 dcmd; /* DMA descriptor dcmd field */
19 volatile u32 *drcmr; /* the DMA request channel to use */
20 u32 dev_addr; /* device physical address for DMA */
21};
22
23struct pxa2xx_gpio {
24 u32 sys;
25 u32 rx;
26 u32 tx;
27 u32 clk;
28 u32 frm;
29};
30
31/* platform data */ 16/* platform data */
32extern struct snd_soc_platform pxa2xx_soc_platform; 17extern struct snd_soc_platform pxa2xx_soc_platform;
33 18
diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c
index 37cb768fc933..d307b6757e95 100644
--- a/sound/soc/pxa/spitz.c
+++ b/sound/soc/pxa/spitz.c
@@ -4,7 +4,7 @@
4 * Copyright 2005 Wolfson Microelectronics PLC. 4 * Copyright 2005 Wolfson Microelectronics PLC.
5 * Copyright 2005 Openedhand Ltd. 5 * Copyright 2005 Openedhand Ltd.
6 * 6 *
7 * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com> 7 * Authors: Liam Girdwood <lrg@slimlogic.co.uk>
8 * Richard Purdie <richard@openedhand.com> 8 * Richard Purdie <richard@openedhand.com>
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify it 10 * This program is free software; you can redistribute it and/or modify it
@@ -19,16 +19,15 @@
19#include <linux/timer.h> 19#include <linux/timer.h>
20#include <linux/interrupt.h> 20#include <linux/interrupt.h>
21#include <linux/platform_device.h> 21#include <linux/platform_device.h>
22#include <linux/gpio.h>
22#include <sound/core.h> 23#include <sound/core.h>
23#include <sound/pcm.h> 24#include <sound/pcm.h>
24#include <sound/soc.h> 25#include <sound/soc.h>
25#include <sound/soc-dapm.h> 26#include <sound/soc-dapm.h>
26 27
27#include <asm/mach-types.h> 28#include <asm/mach-types.h>
28#include <asm/hardware/scoop.h>
29#include <mach/pxa-regs.h> 29#include <mach/pxa-regs.h>
30#include <mach/hardware.h> 30#include <mach/hardware.h>
31#include <mach/akita.h>
32#include <mach/spitz.h> 31#include <mach/spitz.h>
33#include "../codecs/wm8750.h" 32#include "../codecs/wm8750.h"
34#include "pxa2xx-pcm.h" 33#include "pxa2xx-pcm.h"
@@ -63,8 +62,8 @@ static void spitz_ext_control(struct snd_soc_codec *codec)
63 snd_soc_dapm_disable_pin(codec, "Mic Jack"); 62 snd_soc_dapm_disable_pin(codec, "Mic Jack");
64 snd_soc_dapm_disable_pin(codec, "Line Jack"); 63 snd_soc_dapm_disable_pin(codec, "Line Jack");
65 snd_soc_dapm_enable_pin(codec, "Headphone Jack"); 64 snd_soc_dapm_enable_pin(codec, "Headphone Jack");
66 set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L); 65 gpio_set_value(SPITZ_GPIO_MUTE_L, 1);
67 set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R); 66 gpio_set_value(SPITZ_GPIO_MUTE_R, 1);
68 break; 67 break;
69 case SPITZ_MIC: 68 case SPITZ_MIC:
70 /* enable mic jack and bias, mute hp */ 69 /* enable mic jack and bias, mute hp */
@@ -72,8 +71,8 @@ static void spitz_ext_control(struct snd_soc_codec *codec)
72 snd_soc_dapm_disable_pin(codec, "Headset Jack"); 71 snd_soc_dapm_disable_pin(codec, "Headset Jack");
73 snd_soc_dapm_disable_pin(codec, "Line Jack"); 72 snd_soc_dapm_disable_pin(codec, "Line Jack");
74 snd_soc_dapm_enable_pin(codec, "Mic Jack"); 73 snd_soc_dapm_enable_pin(codec, "Mic Jack");
75 reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L); 74 gpio_set_value(SPITZ_GPIO_MUTE_L, 0);
76 reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R); 75 gpio_set_value(SPITZ_GPIO_MUTE_R, 0);
77 break; 76 break;
78 case SPITZ_LINE: 77 case SPITZ_LINE:
79 /* enable line jack, disable mic bias and mute hp */ 78 /* enable line jack, disable mic bias and mute hp */
@@ -81,8 +80,8 @@ static void spitz_ext_control(struct snd_soc_codec *codec)
81 snd_soc_dapm_disable_pin(codec, "Headset Jack"); 80 snd_soc_dapm_disable_pin(codec, "Headset Jack");
82 snd_soc_dapm_disable_pin(codec, "Mic Jack"); 81 snd_soc_dapm_disable_pin(codec, "Mic Jack");
83 snd_soc_dapm_enable_pin(codec, "Line Jack"); 82 snd_soc_dapm_enable_pin(codec, "Line Jack");
84 reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L); 83 gpio_set_value(SPITZ_GPIO_MUTE_L, 0);
85 reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R); 84 gpio_set_value(SPITZ_GPIO_MUTE_R, 0);
86 break; 85 break;
87 case SPITZ_HEADSET: 86 case SPITZ_HEADSET:
88 /* enable and unmute headset jack enable mic bias, mute L hp */ 87 /* enable and unmute headset jack enable mic bias, mute L hp */
@@ -90,8 +89,8 @@ static void spitz_ext_control(struct snd_soc_codec *codec)
90 snd_soc_dapm_enable_pin(codec, "Mic Jack"); 89 snd_soc_dapm_enable_pin(codec, "Mic Jack");
91 snd_soc_dapm_disable_pin(codec, "Line Jack"); 90 snd_soc_dapm_disable_pin(codec, "Line Jack");
92 snd_soc_dapm_enable_pin(codec, "Headset Jack"); 91 snd_soc_dapm_enable_pin(codec, "Headset Jack");
93 reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L); 92 gpio_set_value(SPITZ_GPIO_MUTE_L, 0);
94 set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R); 93 gpio_set_value(SPITZ_GPIO_MUTE_R, 1);
95 break; 94 break;
96 case SPITZ_HP_OFF: 95 case SPITZ_HP_OFF:
97 96
@@ -100,8 +99,8 @@ static void spitz_ext_control(struct snd_soc_codec *codec)
100 snd_soc_dapm_disable_pin(codec, "Headset Jack"); 99 snd_soc_dapm_disable_pin(codec, "Headset Jack");
101 snd_soc_dapm_disable_pin(codec, "Mic Jack"); 100 snd_soc_dapm_disable_pin(codec, "Mic Jack");
102 snd_soc_dapm_disable_pin(codec, "Line Jack"); 101 snd_soc_dapm_disable_pin(codec, "Line Jack");
103 reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L); 102 gpio_set_value(SPITZ_GPIO_MUTE_L, 0);
104 reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R); 103 gpio_set_value(SPITZ_GPIO_MUTE_R, 0);
105 break; 104 break;
106 } 105 }
107 snd_soc_dapm_sync(codec); 106 snd_soc_dapm_sync(codec);
@@ -215,23 +214,14 @@ static int spitz_set_spk(struct snd_kcontrol *kcontrol,
215static int spitz_mic_bias(struct snd_soc_dapm_widget *w, 214static int spitz_mic_bias(struct snd_soc_dapm_widget *w,
216 struct snd_kcontrol *k, int event) 215 struct snd_kcontrol *k, int event)
217{ 216{
218 if (machine_is_borzoi() || machine_is_spitz()) { 217 if (machine_is_borzoi() || machine_is_spitz())
219 if (SND_SOC_DAPM_EVENT_ON(event)) 218 gpio_set_value(SPITZ_GPIO_MIC_BIAS,
220 set_scoop_gpio(&spitzscoop2_device.dev, 219 SND_SOC_DAPM_EVENT_ON(event));
221 SPITZ_SCP2_MIC_BIAS); 220
222 else 221 if (machine_is_akita())
223 reset_scoop_gpio(&spitzscoop2_device.dev, 222 gpio_set_value(AKITA_GPIO_MIC_BIAS,
224 SPITZ_SCP2_MIC_BIAS); 223 SND_SOC_DAPM_EVENT_ON(event));
225 }
226 224
227 if (machine_is_akita()) {
228 if (SND_SOC_DAPM_EVENT_ON(event))
229 akita_set_ioexp(&akitaioexp_device.dev,
230 AKITA_IOEXP_MIC_BIAS);
231 else
232 akita_reset_ioexp(&akitaioexp_device.dev,
233 AKITA_IOEXP_MIC_BIAS);
234 }
235 return 0; 225 return 0;
236} 226}
237 227
@@ -291,13 +281,13 @@ static int spitz_wm8750_init(struct snd_soc_codec *codec)
291 int i, err; 281 int i, err;
292 282
293 /* NC codec pins */ 283 /* NC codec pins */
294 snd_soc_dapm_disable_pin(codec, "RINPUT1"); 284 snd_soc_dapm_nc_pin(codec, "RINPUT1");
295 snd_soc_dapm_disable_pin(codec, "LINPUT2"); 285 snd_soc_dapm_nc_pin(codec, "LINPUT2");
296 snd_soc_dapm_disable_pin(codec, "RINPUT2"); 286 snd_soc_dapm_nc_pin(codec, "RINPUT2");
297 snd_soc_dapm_disable_pin(codec, "LINPUT3"); 287 snd_soc_dapm_nc_pin(codec, "LINPUT3");
298 snd_soc_dapm_disable_pin(codec, "RINPUT3"); 288 snd_soc_dapm_nc_pin(codec, "RINPUT3");
299 snd_soc_dapm_disable_pin(codec, "OUT3"); 289 snd_soc_dapm_nc_pin(codec, "OUT3");
300 snd_soc_dapm_disable_pin(codec, "MONO1"); 290 snd_soc_dapm_nc_pin(codec, "MONO1");
301 291
302 /* Add spitz specific controls */ 292 /* Add spitz specific controls */
303 for (i = 0; i < ARRAY_SIZE(wm8750_spitz_controls); i++) { 293 for (i = 0; i < ARRAY_SIZE(wm8750_spitz_controls); i++) {
@@ -337,6 +327,7 @@ static struct snd_soc_machine snd_soc_machine_spitz = {
337 327
338/* spitz audio private data */ 328/* spitz audio private data */
339static struct wm8750_setup_data spitz_wm8750_setup = { 329static struct wm8750_setup_data spitz_wm8750_setup = {
330 .i2c_bus = 0,
340 .i2c_address = 0x1b, 331 .i2c_address = 0x1b,
341}; 332};
342 333
diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c
index 2baaa750f123..afefe41b8c46 100644
--- a/sound/soc/pxa/tosa.c
+++ b/sound/soc/pxa/tosa.c
@@ -4,7 +4,7 @@
4 * Copyright 2005 Wolfson Microelectronics PLC. 4 * Copyright 2005 Wolfson Microelectronics PLC.
5 * Copyright 2005 Openedhand Ltd. 5 * Copyright 2005 Openedhand Ltd.
6 * 6 *
7 * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com> 7 * Authors: Liam Girdwood <lrg@slimlogic.co.uk>
8 * Richard Purdie <richard@openedhand.com> 8 * Richard Purdie <richard@openedhand.com>
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify it 10 * This program is free software; you can redistribute it and/or modify it
@@ -190,8 +190,8 @@ static int tosa_ac97_init(struct snd_soc_codec *codec)
190{ 190{
191 int i, err; 191 int i, err;
192 192
193 snd_soc_dapm_disable_pin(codec, "OUT3"); 193 snd_soc_dapm_nc_pin(codec, "OUT3");
194 snd_soc_dapm_disable_pin(codec, "MONOOUT"); 194 snd_soc_dapm_nc_pin(codec, "MONOOUT");
195 195
196 /* add tosa specific controls */ 196 /* add tosa specific controls */
197 for (i = 0; i < ARRAY_SIZE(tosa_controls); i++) { 197 for (i = 0; i < ARRAY_SIZE(tosa_controls); i++) {
diff --git a/sound/soc/s3c24xx/neo1973_wm8753.c b/sound/soc/s3c24xx/neo1973_wm8753.c
index 8089f8ee05c0..87ddfefcc2fb 100644
--- a/sound/soc/s3c24xx/neo1973_wm8753.c
+++ b/sound/soc/s3c24xx/neo1973_wm8753.c
@@ -24,6 +24,7 @@
24#include <sound/soc-dapm.h> 24#include <sound/soc-dapm.h>
25#include <sound/tlv.h> 25#include <sound/tlv.h>
26 26
27#include <asm/mach-types.h>
27#include <asm/hardware/scoop.h> 28#include <asm/hardware/scoop.h>
28#include <mach/regs-clock.h> 29#include <mach/regs-clock.h>
29#include <mach/regs-gpio.h> 30#include <mach/regs-gpio.h>
@@ -510,21 +511,20 @@ static int neo1973_wm8753_init(struct snd_soc_codec *codec)
510 DBG("Entered %s\n", __func__); 511 DBG("Entered %s\n", __func__);
511 512
512 /* set up NC codec pins */ 513 /* set up NC codec pins */
513 snd_soc_dapm_disable_pin(codec, "LOUT2"); 514 snd_soc_dapm_nc_pin(codec, "LOUT2");
514 snd_soc_dapm_disable_pin(codec, "ROUT2"); 515 snd_soc_dapm_nc_pin(codec, "ROUT2");
515 snd_soc_dapm_disable_pin(codec, "OUT3"); 516 snd_soc_dapm_nc_pin(codec, "OUT3");
516 snd_soc_dapm_disable_pin(codec, "OUT4"); 517 snd_soc_dapm_nc_pin(codec, "OUT4");
517 snd_soc_dapm_disable_pin(codec, "LINE1"); 518 snd_soc_dapm_nc_pin(codec, "LINE1");
518 snd_soc_dapm_disable_pin(codec, "LINE2"); 519 snd_soc_dapm_nc_pin(codec, "LINE2");
519
520
521 /* set endpoints to default mode */
522 set_scenario_endpoints(codec, NEO_AUDIO_OFF);
523 520
524 /* Add neo1973 specific widgets */ 521 /* Add neo1973 specific widgets */
525 snd_soc_dapm_new_controls(codec, wm8753_dapm_widgets, 522 snd_soc_dapm_new_controls(codec, wm8753_dapm_widgets,
526 ARRAY_SIZE(wm8753_dapm_widgets)); 523 ARRAY_SIZE(wm8753_dapm_widgets));
527 524
525 /* set endpoints to default mode */
526 set_scenario_endpoints(codec, NEO_AUDIO_OFF);
527
528 /* add neo1973 specific controls */ 528 /* add neo1973 specific controls */
529 for (i = 0; i < ARRAY_SIZE(wm8753_neo1973_controls); i++) { 529 for (i = 0; i < ARRAY_SIZE(wm8753_neo1973_controls); i++) {
530 err = snd_ctl_add(codec->card, 530 err = snd_ctl_add(codec->card,
@@ -586,6 +586,7 @@ static struct snd_soc_machine neo1973 = {
586}; 586};
587 587
588static struct wm8753_setup_data neo1973_wm8753_setup = { 588static struct wm8753_setup_data neo1973_wm8753_setup = {
589 .i2c_bus = 0,
589 .i2c_address = 0x1a, 590 .i2c_address = 0x1a,
590}; 591};
591 592
@@ -596,54 +597,24 @@ static struct snd_soc_device neo1973_snd_devdata = {
596 .codec_data = &neo1973_wm8753_setup, 597 .codec_data = &neo1973_wm8753_setup,
597}; 598};
598 599
599static struct i2c_client client_template; 600static int lm4857_i2c_probe(struct i2c_client *client,
600 601 const struct i2c_device_id *id)
601static const unsigned short normal_i2c[] = { 0x7C, I2C_CLIENT_END };
602
603/* Magic definition of all other variables and things */
604I2C_CLIENT_INSMOD;
605
606static int lm4857_amp_probe(struct i2c_adapter *adap, int addr, int kind)
607{ 602{
608 int ret;
609
610 DBG("Entered %s\n", __func__); 603 DBG("Entered %s\n", __func__);
611 604
612 client_template.adapter = adap; 605 i2c = client;
613 client_template.addr = addr;
614
615 i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
616 if (i2c == NULL)
617 return -ENOMEM;
618
619 ret = i2c_attach_client(i2c);
620 if (ret < 0) {
621 printk(KERN_ERR "LM4857 failed to attach at addr %x\n", addr);
622 goto exit_err;
623 }
624 606
625 lm4857_write_regs(); 607 lm4857_write_regs();
626 return ret;
627
628exit_err:
629 kfree(i2c);
630 return ret;
631}
632
633static int lm4857_i2c_detach(struct i2c_client *client)
634{
635 DBG("Entered %s\n", __func__);
636
637 i2c_detach_client(client);
638 kfree(client);
639 return 0; 608 return 0;
640} 609}
641 610
642static int lm4857_i2c_attach(struct i2c_adapter *adap) 611static int lm4857_i2c_remove(struct i2c_client *client)
643{ 612{
644 DBG("Entered %s\n", __func__); 613 DBG("Entered %s\n", __func__);
645 614
646 return i2c_probe(adap, &addr_data, lm4857_amp_probe); 615 i2c = NULL;
616
617 return 0;
647} 618}
648 619
649static u8 lm4857_state; 620static u8 lm4857_state;
@@ -681,24 +652,22 @@ static void lm4857_shutdown(struct i2c_client *dev)
681 lm4857_write_regs(); 652 lm4857_write_regs();
682} 653}
683 654
684/* corgi i2c codec control layer */ 655static const struct i2c_device_id lm4857_i2c_id[] = {
656 { "neo1973_lm4857", 0 },
657 { }
658};
659
685static struct i2c_driver lm4857_i2c_driver = { 660static struct i2c_driver lm4857_i2c_driver = {
686 .driver = { 661 .driver = {
687 .name = "LM4857 I2C Amp", 662 .name = "LM4857 I2C Amp",
688 .owner = THIS_MODULE, 663 .owner = THIS_MODULE,
689 }, 664 },
690 .id = I2C_DRIVERID_LM4857,
691 .suspend = lm4857_suspend, 665 .suspend = lm4857_suspend,
692 .resume = lm4857_resume, 666 .resume = lm4857_resume,
693 .shutdown = lm4857_shutdown, 667 .shutdown = lm4857_shutdown,
694 .attach_adapter = lm4857_i2c_attach, 668 .probe = lm4857_i2c_probe,
695 .detach_client = lm4857_i2c_detach, 669 .remove = lm4857_i2c_remove,
696 .command = NULL, 670 .id_table = lm4857_i2c_id,
697};
698
699static struct i2c_client client_template = {
700 .name = "LM4857",
701 .driver = &lm4857_i2c_driver,
702}; 671};
703 672
704static struct platform_device *neo1973_snd_device; 673static struct platform_device *neo1973_snd_device;
@@ -709,6 +678,12 @@ static int __init neo1973_init(void)
709 678
710 DBG("Entered %s\n", __func__); 679 DBG("Entered %s\n", __func__);
711 680
681 if (!machine_is_neo1973_gta01()) {
682 printk(KERN_INFO
683 "Only GTA01 hardware supported by ASoC driver\n");
684 return -ENODEV;
685 }
686
712 neo1973_snd_device = platform_device_alloc("soc-audio", -1); 687 neo1973_snd_device = platform_device_alloc("soc-audio", -1);
713 if (!neo1973_snd_device) 688 if (!neo1973_snd_device)
714 return -ENOMEM; 689 return -ENOMEM;
@@ -717,12 +692,15 @@ static int __init neo1973_init(void)
717 neo1973_snd_devdata.dev = &neo1973_snd_device->dev; 692 neo1973_snd_devdata.dev = &neo1973_snd_device->dev;
718 ret = platform_device_add(neo1973_snd_device); 693 ret = platform_device_add(neo1973_snd_device);
719 694
720 if (ret) 695 if (ret) {
721 platform_device_put(neo1973_snd_device); 696 platform_device_put(neo1973_snd_device);
697 return ret;
698 }
722 699
723 ret = i2c_add_driver(&lm4857_i2c_driver); 700 ret = i2c_add_driver(&lm4857_i2c_driver);
701
724 if (ret != 0) 702 if (ret != 0)
725 printk(KERN_ERR "can't add i2c driver"); 703 platform_device_unregister(neo1973_snd_device);
726 704
727 return ret; 705 return ret;
728} 706}
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 83f1190293a8..462e635dfc74 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -4,8 +4,7 @@
4 * Copyright 2005 Wolfson Microelectronics PLC. 4 * Copyright 2005 Wolfson Microelectronics PLC.
5 * Copyright 2005 Openedhand Ltd. 5 * Copyright 2005 Openedhand Ltd.
6 * 6 *
7 * Author: Liam Girdwood 7 * Author: Liam Girdwood <lrg@slimlogic.co.uk>
8 * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
9 * with code, comments and ideas from :- 8 * with code, comments and ideas from :-
10 * Richard Purdie <richard@openedhand.com> 9 * Richard Purdie <richard@openedhand.com>
11 * 10 *
@@ -340,6 +339,12 @@ static int soc_codec_close(struct snd_pcm_substream *substream)
340 } 339 }
341 codec->active--; 340 codec->active--;
342 341
342 /* Muting the DAC suppresses artifacts caused during digital
343 * shutdown, for example from stopping clocks.
344 */
345 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
346 snd_soc_dai_digital_mute(codec_dai, 1);
347
343 if (cpu_dai->ops.shutdown) 348 if (cpu_dai->ops.shutdown)
344 cpu_dai->ops.shutdown(substream); 349 cpu_dai->ops.shutdown(substream);
345 350
@@ -970,9 +975,29 @@ static ssize_t codec_reg_show(struct device *dev,
970 step = codec->reg_cache_step; 975 step = codec->reg_cache_step;
971 976
972 count += sprintf(buf, "%s registers\n", codec->name); 977 count += sprintf(buf, "%s registers\n", codec->name);
973 for (i = 0; i < codec->reg_cache_size; i += step) 978 for (i = 0; i < codec->reg_cache_size; i += step) {
974 count += sprintf(buf + count, "%2x: %4x\n", i, 979 count += sprintf(buf + count, "%2x: ", i);
975 codec->read(codec, i)); 980 if (count >= PAGE_SIZE - 1)
981 break;
982
983 if (codec->display_register)
984 count += codec->display_register(codec, buf + count,
985 PAGE_SIZE - count, i);
986 else
987 count += snprintf(buf + count, PAGE_SIZE - count,
988 "%4x", codec->read(codec, i));
989
990 if (count >= PAGE_SIZE - 1)
991 break;
992
993 count += snprintf(buf + count, PAGE_SIZE - count, "\n");
994 if (count >= PAGE_SIZE - 1)
995 break;
996 }
997
998 /* Truncate count; min() would cause a warning */
999 if (count >= PAGE_SIZE)
1000 count = PAGE_SIZE - 1;
976 1001
977 return count; 1002 return count;
978} 1003}
@@ -1296,10 +1321,10 @@ int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol,
1296 1321
1297 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 1322 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1298 uinfo->count = e->shift_l == e->shift_r ? 1 : 2; 1323 uinfo->count = e->shift_l == e->shift_r ? 1 : 2;
1299 uinfo->value.enumerated.items = e->mask; 1324 uinfo->value.enumerated.items = e->max;
1300 1325
1301 if (uinfo->value.enumerated.item > e->mask - 1) 1326 if (uinfo->value.enumerated.item > e->max - 1)
1302 uinfo->value.enumerated.item = e->mask - 1; 1327 uinfo->value.enumerated.item = e->max - 1;
1303 strcpy(uinfo->value.enumerated.name, 1328 strcpy(uinfo->value.enumerated.name,
1304 e->texts[uinfo->value.enumerated.item]); 1329 e->texts[uinfo->value.enumerated.item]);
1305 return 0; 1330 return 0;
@@ -1322,7 +1347,7 @@ int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol,
1322 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 1347 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1323 unsigned short val, bitmask; 1348 unsigned short val, bitmask;
1324 1349
1325 for (bitmask = 1; bitmask < e->mask; bitmask <<= 1) 1350 for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
1326 ; 1351 ;
1327 val = snd_soc_read(codec, e->reg); 1352 val = snd_soc_read(codec, e->reg);
1328 ucontrol->value.enumerated.item[0] 1353 ucontrol->value.enumerated.item[0]
@@ -1352,14 +1377,14 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol,
1352 unsigned short val; 1377 unsigned short val;
1353 unsigned short mask, bitmask; 1378 unsigned short mask, bitmask;
1354 1379
1355 for (bitmask = 1; bitmask < e->mask; bitmask <<= 1) 1380 for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
1356 ; 1381 ;
1357 if (ucontrol->value.enumerated.item[0] > e->mask - 1) 1382 if (ucontrol->value.enumerated.item[0] > e->max - 1)
1358 return -EINVAL; 1383 return -EINVAL;
1359 val = ucontrol->value.enumerated.item[0] << e->shift_l; 1384 val = ucontrol->value.enumerated.item[0] << e->shift_l;
1360 mask = (bitmask - 1) << e->shift_l; 1385 mask = (bitmask - 1) << e->shift_l;
1361 if (e->shift_l != e->shift_r) { 1386 if (e->shift_l != e->shift_r) {
1362 if (ucontrol->value.enumerated.item[1] > e->mask - 1) 1387 if (ucontrol->value.enumerated.item[1] > e->max - 1)
1363 return -EINVAL; 1388 return -EINVAL;
1364 val |= ucontrol->value.enumerated.item[1] << e->shift_r; 1389 val |= ucontrol->value.enumerated.item[1] << e->shift_r;
1365 mask |= (bitmask - 1) << e->shift_r; 1390 mask |= (bitmask - 1) << e->shift_r;
@@ -1386,10 +1411,10 @@ int snd_soc_info_enum_ext(struct snd_kcontrol *kcontrol,
1386 1411
1387 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 1412 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1388 uinfo->count = 1; 1413 uinfo->count = 1;
1389 uinfo->value.enumerated.items = e->mask; 1414 uinfo->value.enumerated.items = e->max;
1390 1415
1391 if (uinfo->value.enumerated.item > e->mask - 1) 1416 if (uinfo->value.enumerated.item > e->max - 1)
1392 uinfo->value.enumerated.item = e->mask - 1; 1417 uinfo->value.enumerated.item = e->max - 1;
1393 strcpy(uinfo->value.enumerated.name, 1418 strcpy(uinfo->value.enumerated.name,
1394 e->texts[uinfo->value.enumerated.item]); 1419 e->texts[uinfo->value.enumerated.item]);
1395 return 0; 1420 return 0;
@@ -1434,9 +1459,11 @@ EXPORT_SYMBOL_GPL(snd_soc_info_volsw_ext);
1434int snd_soc_info_volsw(struct snd_kcontrol *kcontrol, 1459int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
1435 struct snd_ctl_elem_info *uinfo) 1460 struct snd_ctl_elem_info *uinfo)
1436{ 1461{
1437 int max = (kcontrol->private_value >> 16) & 0xff; 1462 struct soc_mixer_control *mc =
1438 int shift = (kcontrol->private_value >> 8) & 0x0f; 1463 (struct soc_mixer_control *)kcontrol->private_value;
1439 int rshift = (kcontrol->private_value >> 12) & 0x0f; 1464 int max = mc->max;
1465 unsigned int shift = mc->min;
1466 unsigned int rshift = mc->rshift;
1440 1467
1441 if (max == 1) 1468 if (max == 1)
1442 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 1469 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
@@ -1462,13 +1489,15 @@ EXPORT_SYMBOL_GPL(snd_soc_info_volsw);
1462int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, 1489int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
1463 struct snd_ctl_elem_value *ucontrol) 1490 struct snd_ctl_elem_value *ucontrol)
1464{ 1491{
1492 struct soc_mixer_control *mc =
1493 (struct soc_mixer_control *)kcontrol->private_value;
1465 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 1494 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1466 int reg = kcontrol->private_value & 0xff; 1495 unsigned int reg = mc->reg;
1467 int shift = (kcontrol->private_value >> 8) & 0x0f; 1496 unsigned int shift = mc->shift;
1468 int rshift = (kcontrol->private_value >> 12) & 0x0f; 1497 unsigned int rshift = mc->rshift;
1469 int max = (kcontrol->private_value >> 16) & 0xff; 1498 int max = mc->max;
1470 int mask = (1 << fls(max)) - 1; 1499 unsigned int mask = (1 << fls(max)) - 1;
1471 int invert = (kcontrol->private_value >> 24) & 0x01; 1500 unsigned int invert = mc->invert;
1472 1501
1473 ucontrol->value.integer.value[0] = 1502 ucontrol->value.integer.value[0] =
1474 (snd_soc_read(codec, reg) >> shift) & mask; 1503 (snd_soc_read(codec, reg) >> shift) & mask;
@@ -1499,13 +1528,15 @@ EXPORT_SYMBOL_GPL(snd_soc_get_volsw);
1499int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, 1528int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
1500 struct snd_ctl_elem_value *ucontrol) 1529 struct snd_ctl_elem_value *ucontrol)
1501{ 1530{
1531 struct soc_mixer_control *mc =
1532 (struct soc_mixer_control *)kcontrol->private_value;
1502 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 1533 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1503 int reg = kcontrol->private_value & 0xff; 1534 unsigned int reg = mc->reg;
1504 int shift = (kcontrol->private_value >> 8) & 0x0f; 1535 unsigned int shift = mc->shift;
1505 int rshift = (kcontrol->private_value >> 12) & 0x0f; 1536 unsigned int rshift = mc->rshift;
1506 int max = (kcontrol->private_value >> 16) & 0xff; 1537 int max = mc->max;
1507 int mask = (1 << fls(max)) - 1; 1538 unsigned int mask = (1 << fls(max)) - 1;
1508 int invert = (kcontrol->private_value >> 24) & 0x01; 1539 unsigned int invert = mc->invert;
1509 unsigned short val, val2, val_mask; 1540 unsigned short val, val2, val_mask;
1510 1541
1511 val = (ucontrol->value.integer.value[0] & mask); 1542 val = (ucontrol->value.integer.value[0] & mask);
@@ -1537,7 +1568,9 @@ EXPORT_SYMBOL_GPL(snd_soc_put_volsw);
1537int snd_soc_info_volsw_2r(struct snd_kcontrol *kcontrol, 1568int snd_soc_info_volsw_2r(struct snd_kcontrol *kcontrol,
1538 struct snd_ctl_elem_info *uinfo) 1569 struct snd_ctl_elem_info *uinfo)
1539{ 1570{
1540 int max = (kcontrol->private_value >> 12) & 0xff; 1571 struct soc_mixer_control *mc =
1572 (struct soc_mixer_control *)kcontrol->private_value;
1573 int max = mc->max;
1541 1574
1542 if (max == 1) 1575 if (max == 1)
1543 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 1576 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
@@ -1563,13 +1596,15 @@ EXPORT_SYMBOL_GPL(snd_soc_info_volsw_2r);
1563int snd_soc_get_volsw_2r(struct snd_kcontrol *kcontrol, 1596int snd_soc_get_volsw_2r(struct snd_kcontrol *kcontrol,
1564 struct snd_ctl_elem_value *ucontrol) 1597 struct snd_ctl_elem_value *ucontrol)
1565{ 1598{
1599 struct soc_mixer_control *mc =
1600 (struct soc_mixer_control *)kcontrol->private_value;
1566 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 1601 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1567 int reg = kcontrol->private_value & 0xff; 1602 unsigned int reg = mc->reg;
1568 int reg2 = (kcontrol->private_value >> 24) & 0xff; 1603 unsigned int reg2 = mc->rreg;
1569 int shift = (kcontrol->private_value >> 8) & 0x0f; 1604 unsigned int shift = mc->shift;
1570 int max = (kcontrol->private_value >> 12) & 0xff; 1605 int max = mc->max;
1571 int mask = (1<<fls(max))-1; 1606 unsigned int mask = (1<<fls(max))-1;
1572 int invert = (kcontrol->private_value >> 20) & 0x01; 1607 unsigned int invert = mc->invert;
1573 1608
1574 ucontrol->value.integer.value[0] = 1609 ucontrol->value.integer.value[0] =
1575 (snd_soc_read(codec, reg) >> shift) & mask; 1610 (snd_soc_read(codec, reg) >> shift) & mask;
@@ -1598,13 +1633,15 @@ EXPORT_SYMBOL_GPL(snd_soc_get_volsw_2r);
1598int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol, 1633int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol,
1599 struct snd_ctl_elem_value *ucontrol) 1634 struct snd_ctl_elem_value *ucontrol)
1600{ 1635{
1636 struct soc_mixer_control *mc =
1637 (struct soc_mixer_control *)kcontrol->private_value;
1601 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 1638 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1602 int reg = kcontrol->private_value & 0xff; 1639 unsigned int reg = mc->reg;
1603 int reg2 = (kcontrol->private_value >> 24) & 0xff; 1640 unsigned int reg2 = mc->rreg;
1604 int shift = (kcontrol->private_value >> 8) & 0x0f; 1641 unsigned int shift = mc->shift;
1605 int max = (kcontrol->private_value >> 12) & 0xff; 1642 int max = mc->max;
1606 int mask = (1 << fls(max)) - 1; 1643 unsigned int mask = (1 << fls(max)) - 1;
1607 int invert = (kcontrol->private_value >> 20) & 0x01; 1644 unsigned int invert = mc->invert;
1608 int err; 1645 int err;
1609 unsigned short val, val2, val_mask; 1646 unsigned short val, val2, val_mask;
1610 1647
@@ -1641,8 +1678,10 @@ EXPORT_SYMBOL_GPL(snd_soc_put_volsw_2r);
1641int snd_soc_info_volsw_s8(struct snd_kcontrol *kcontrol, 1678int snd_soc_info_volsw_s8(struct snd_kcontrol *kcontrol,
1642 struct snd_ctl_elem_info *uinfo) 1679 struct snd_ctl_elem_info *uinfo)
1643{ 1680{
1644 int max = (signed char)((kcontrol->private_value >> 16) & 0xff); 1681 struct soc_mixer_control *mc =
1645 int min = (signed char)((kcontrol->private_value >> 24) & 0xff); 1682 (struct soc_mixer_control *)kcontrol->private_value;
1683 int max = mc->max;
1684 int min = mc->min;
1646 1685
1647 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 1686 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1648 uinfo->count = 2; 1687 uinfo->count = 2;
@@ -1664,9 +1703,11 @@ EXPORT_SYMBOL_GPL(snd_soc_info_volsw_s8);
1664int snd_soc_get_volsw_s8(struct snd_kcontrol *kcontrol, 1703int snd_soc_get_volsw_s8(struct snd_kcontrol *kcontrol,
1665 struct snd_ctl_elem_value *ucontrol) 1704 struct snd_ctl_elem_value *ucontrol)
1666{ 1705{
1706 struct soc_mixer_control *mc =
1707 (struct soc_mixer_control *)kcontrol->private_value;
1667 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 1708 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1668 int reg = kcontrol->private_value & 0xff; 1709 unsigned int reg = mc->reg;
1669 int min = (signed char)((kcontrol->private_value >> 24) & 0xff); 1710 int min = mc->min;
1670 int val = snd_soc_read(codec, reg); 1711 int val = snd_soc_read(codec, reg);
1671 1712
1672 ucontrol->value.integer.value[0] = 1713 ucontrol->value.integer.value[0] =
@@ -1689,9 +1730,11 @@ EXPORT_SYMBOL_GPL(snd_soc_get_volsw_s8);
1689int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol, 1730int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol,
1690 struct snd_ctl_elem_value *ucontrol) 1731 struct snd_ctl_elem_value *ucontrol)
1691{ 1732{
1733 struct soc_mixer_control *mc =
1734 (struct soc_mixer_control *)kcontrol->private_value;
1692 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 1735 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1693 int reg = kcontrol->private_value & 0xff; 1736 unsigned int reg = mc->reg;
1694 int min = (signed char)((kcontrol->private_value >> 24) & 0xff); 1737 int min = mc->min;
1695 unsigned short val; 1738 unsigned short val;
1696 1739
1697 val = (ucontrol->value.integer.value[0]+min) & 0xff; 1740 val = (ucontrol->value.integer.value[0]+min) & 0xff;
@@ -1842,7 +1885,7 @@ module_init(snd_soc_init);
1842module_exit(snd_soc_exit); 1885module_exit(snd_soc_exit);
1843 1886
1844/* Module information */ 1887/* Module information */
1845MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com"); 1888MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk");
1846MODULE_DESCRIPTION("ALSA SoC Core"); 1889MODULE_DESCRIPTION("ALSA SoC Core");
1847MODULE_LICENSE("GPL"); 1890MODULE_LICENSE("GPL");
1848MODULE_ALIAS("platform:soc-audio"); 1891MODULE_ALIAS("platform:soc-audio");
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index f9d100bc8479..efbd0b37810a 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -2,8 +2,7 @@
2 * soc-dapm.c -- ALSA SoC Dynamic Audio Power Management 2 * soc-dapm.c -- ALSA SoC Dynamic Audio Power Management
3 * 3 *
4 * Copyright 2005 Wolfson Microelectronics PLC. 4 * Copyright 2005 Wolfson Microelectronics PLC.
5 * Author: Liam Girdwood 5 * Author: Liam Girdwood <lrg@slimlogic.co.uk>
6 * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
7 * 6 *
8 * This program is free software; you can redistribute it and/or modify it 7 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the 8 * under the terms of the GNU General Public License as published by the
@@ -38,6 +37,7 @@
38#include <linux/bitops.h> 37#include <linux/bitops.h>
39#include <linux/platform_device.h> 38#include <linux/platform_device.h>
40#include <linux/jiffies.h> 39#include <linux/jiffies.h>
40#include <linux/debugfs.h>
41#include <sound/core.h> 41#include <sound/core.h>
42#include <sound/pcm.h> 42#include <sound/pcm.h>
43#include <sound/pcm_params.h> 43#include <sound/pcm_params.h>
@@ -67,7 +67,9 @@ static int dapm_status = 1;
67module_param(dapm_status, int, 0); 67module_param(dapm_status, int, 0);
68MODULE_PARM_DESC(dapm_status, "enable DPM sysfs entries"); 68MODULE_PARM_DESC(dapm_status, "enable DPM sysfs entries");
69 69
70static unsigned int pop_time; 70static struct dentry *asoc_debugfs;
71
72static u32 pop_time;
71 73
72static void pop_wait(void) 74static void pop_wait(void)
73{ 75{
@@ -104,10 +106,13 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
104 case snd_soc_dapm_switch: 106 case snd_soc_dapm_switch:
105 case snd_soc_dapm_mixer: { 107 case snd_soc_dapm_mixer: {
106 int val; 108 int val;
107 int reg = w->kcontrols[i].private_value & 0xff; 109 struct soc_mixer_control *mc = (struct soc_mixer_control *)
108 int shift = (w->kcontrols[i].private_value >> 8) & 0x0f; 110 w->kcontrols[i].private_value;
109 int mask = (w->kcontrols[i].private_value >> 16) & 0xff; 111 unsigned int reg = mc->reg;
110 int invert = (w->kcontrols[i].private_value >> 24) & 0x01; 112 unsigned int shift = mc->shift;
113 int max = mc->max;
114 unsigned int mask = (1 << fls(max)) - 1;
115 unsigned int invert = mc->invert;
111 116
112 val = snd_soc_read(w->codec, reg); 117 val = snd_soc_read(w->codec, reg);
113 val = (val >> shift) & mask; 118 val = (val >> shift) & mask;
@@ -122,13 +127,13 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
122 struct soc_enum *e = (struct soc_enum *)w->kcontrols[i].private_value; 127 struct soc_enum *e = (struct soc_enum *)w->kcontrols[i].private_value;
123 int val, item, bitmask; 128 int val, item, bitmask;
124 129
125 for (bitmask = 1; bitmask < e->mask; bitmask <<= 1) 130 for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
126 ; 131 ;
127 val = snd_soc_read(w->codec, e->reg); 132 val = snd_soc_read(w->codec, e->reg);
128 item = (val >> e->shift_l) & (bitmask - 1); 133 item = (val >> e->shift_l) & (bitmask - 1);
129 134
130 p->connect = 0; 135 p->connect = 0;
131 for (i = 0; i < e->mask; i++) { 136 for (i = 0; i < e->max; i++) {
132 if (!(strcmp(p->name, e->texts[i])) && item == i) 137 if (!(strcmp(p->name, e->texts[i])) && item == i)
133 p->connect = 1; 138 p->connect = 1;
134 } 139 }
@@ -165,7 +170,7 @@ static int dapm_connect_mux(struct snd_soc_codec *codec,
165 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 170 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
166 int i; 171 int i;
167 172
168 for (i = 0; i < e->mask; i++) { 173 for (i = 0; i < e->max; i++) {
169 if (!(strcmp(control_name, e->texts[i]))) { 174 if (!(strcmp(control_name, e->texts[i]))) {
170 list_add(&path->list, &codec->dapm_paths); 175 list_add(&path->list, &codec->dapm_paths);
171 list_add(&path->list_sink, &dest->sources); 176 list_add(&path->list_sink, &dest->sources);
@@ -247,16 +252,19 @@ static int dapm_set_pga(struct snd_soc_dapm_widget *widget, int power)
247 return 0; 252 return 0;
248 253
249 if (widget->num_kcontrols && k) { 254 if (widget->num_kcontrols && k) {
250 int reg = k->private_value & 0xff; 255 struct soc_mixer_control *mc =
251 int shift = (k->private_value >> 8) & 0x0f; 256 (struct soc_mixer_control *)k->private_value;
252 int mask = (k->private_value >> 16) & 0xff; 257 unsigned int reg = mc->reg;
253 int invert = (k->private_value >> 24) & 0x01; 258 unsigned int shift = mc->shift;
259 int max = mc->max;
260 unsigned int mask = (1 << fls(max)) - 1;
261 unsigned int invert = mc->invert;
254 262
255 if (power) { 263 if (power) {
256 int i; 264 int i;
257 /* power up has happended, increase volume to last level */ 265 /* power up has happended, increase volume to last level */
258 if (invert) { 266 if (invert) {
259 for (i = mask; i > widget->saved_value; i--) 267 for (i = max; i > widget->saved_value; i--)
260 snd_soc_update_bits(widget->codec, reg, mask, i); 268 snd_soc_update_bits(widget->codec, reg, mask, i);
261 } else { 269 } else {
262 for (i = 0; i < widget->saved_value; i++) 270 for (i = 0; i < widget->saved_value; i++)
@@ -684,7 +692,7 @@ static void dbg_dump_dapm(struct snd_soc_codec* codec, const char *action)
684/* test and update the power status of a mux widget */ 692/* test and update the power status of a mux widget */
685static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget, 693static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
686 struct snd_kcontrol *kcontrol, int mask, 694 struct snd_kcontrol *kcontrol, int mask,
687 int val, struct soc_enum* e) 695 int mux, int val, struct soc_enum *e)
688{ 696{
689 struct snd_soc_dapm_path *path; 697 struct snd_soc_dapm_path *path;
690 int found = 0; 698 int found = 0;
@@ -700,12 +708,12 @@ static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
700 if (path->kcontrol != kcontrol) 708 if (path->kcontrol != kcontrol)
701 continue; 709 continue;
702 710
703 if (!path->name || ! e->texts[val]) 711 if (!path->name || !e->texts[mux])
704 continue; 712 continue;
705 713
706 found = 1; 714 found = 1;
707 /* we now need to match the string in the enum to the path */ 715 /* we now need to match the string in the enum to the path */
708 if (!(strcmp(path->name, e->texts[val]))) 716 if (!(strcmp(path->name, e->texts[mux])))
709 path->connect = 1; /* new connection */ 717 path->connect = 1; /* new connection */
710 else 718 else
711 path->connect = 0; /* old connection must be powered down */ 719 path->connect = 0; /* old connection must be powered down */
@@ -811,51 +819,35 @@ static ssize_t dapm_widget_show(struct device *dev,
811 819
812static DEVICE_ATTR(dapm_widget, 0444, dapm_widget_show, NULL); 820static DEVICE_ATTR(dapm_widget, 0444, dapm_widget_show, NULL);
813 821
814/* pop/click delay times */
815static ssize_t dapm_pop_time_show(struct device *dev,
816 struct device_attribute *attr, char *buf)
817{
818 return sprintf(buf, "%d\n", pop_time);
819}
820
821static ssize_t dapm_pop_time_store(struct device *dev,
822 struct device_attribute *attr,
823 const char *buf, size_t count)
824
825{
826 unsigned long val;
827
828 if (strict_strtoul(buf, 10, &val) >= 0)
829 pop_time = val;
830 else
831 printk(KERN_ERR "Unable to parse pop_time setting\n");
832
833 return count;
834}
835
836static DEVICE_ATTR(dapm_pop_time, 0744, dapm_pop_time_show,
837 dapm_pop_time_store);
838
839int snd_soc_dapm_sys_add(struct device *dev) 822int snd_soc_dapm_sys_add(struct device *dev)
840{ 823{
841 int ret = 0; 824 int ret = 0;
842 825
843 if (dapm_status) { 826 if (!dapm_status)
844 ret = device_create_file(dev, &dev_attr_dapm_widget); 827 return 0;
845 828
846 if (ret == 0) 829 ret = device_create_file(dev, &dev_attr_dapm_widget);
847 ret = device_create_file(dev, &dev_attr_dapm_pop_time); 830 if (ret != 0)
848 } 831 return ret;
849 832
850 return ret; 833 asoc_debugfs = debugfs_create_dir("asoc", NULL);
834 if (!IS_ERR(asoc_debugfs))
835 debugfs_create_u32("dapm_pop_time", 0744, asoc_debugfs,
836 &pop_time);
837 else
838 asoc_debugfs = NULL;
839
840 return 0;
851} 841}
852 842
853static void snd_soc_dapm_sys_remove(struct device *dev) 843static void snd_soc_dapm_sys_remove(struct device *dev)
854{ 844{
855 if (dapm_status) { 845 if (dapm_status) {
856 device_remove_file(dev, &dev_attr_dapm_pop_time);
857 device_remove_file(dev, &dev_attr_dapm_widget); 846 device_remove_file(dev, &dev_attr_dapm_widget);
858 } 847 }
848
849 if (asoc_debugfs)
850 debugfs_remove_recursive(asoc_debugfs);
859} 851}
860 852
861/* free all dapm widgets and resources */ 853/* free all dapm widgets and resources */
@@ -1133,12 +1125,14 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
1133 struct snd_ctl_elem_value *ucontrol) 1125 struct snd_ctl_elem_value *ucontrol)
1134{ 1126{
1135 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); 1127 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1136 int reg = kcontrol->private_value & 0xff; 1128 struct soc_mixer_control *mc =
1137 int shift = (kcontrol->private_value >> 8) & 0x0f; 1129 (struct soc_mixer_control *)kcontrol->private_value;
1138 int rshift = (kcontrol->private_value >> 12) & 0x0f; 1130 unsigned int reg = mc->reg;
1139 int max = (kcontrol->private_value >> 16) & 0xff; 1131 unsigned int shift = mc->shift;
1140 int invert = (kcontrol->private_value >> 24) & 0x01; 1132 unsigned int rshift = mc->rshift;
1141 int mask = (1 << fls(max)) - 1; 1133 int max = mc->max;
1134 unsigned int invert = mc->invert;
1135 unsigned int mask = (1 << fls(max)) - 1;
1142 1136
1143 /* return the saved value if we are powered down */ 1137 /* return the saved value if we are powered down */
1144 if (widget->id == snd_soc_dapm_pga && !widget->power) { 1138 if (widget->id == snd_soc_dapm_pga && !widget->power) {
@@ -1176,12 +1170,14 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
1176 struct snd_ctl_elem_value *ucontrol) 1170 struct snd_ctl_elem_value *ucontrol)
1177{ 1171{
1178 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); 1172 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1179 int reg = kcontrol->private_value & 0xff; 1173 struct soc_mixer_control *mc =
1180 int shift = (kcontrol->private_value >> 8) & 0x0f; 1174 (struct soc_mixer_control *)kcontrol->private_value;
1181 int rshift = (kcontrol->private_value >> 12) & 0x0f; 1175 unsigned int reg = mc->reg;
1182 int max = (kcontrol->private_value >> 16) & 0xff; 1176 unsigned int shift = mc->shift;
1183 int mask = (1 << fls(max)) - 1; 1177 unsigned int rshift = mc->rshift;
1184 int invert = (kcontrol->private_value >> 24) & 0x01; 1178 int max = mc->max;
1179 unsigned int mask = (1 << fls(max)) - 1;
1180 unsigned int invert = mc->invert;
1185 unsigned short val, val2, val_mask; 1181 unsigned short val, val2, val_mask;
1186 int ret; 1182 int ret;
1187 1183
@@ -1248,7 +1244,7 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,
1248 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 1244 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1249 unsigned short val, bitmask; 1245 unsigned short val, bitmask;
1250 1246
1251 for (bitmask = 1; bitmask < e->mask; bitmask <<= 1) 1247 for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
1252 ; 1248 ;
1253 val = snd_soc_read(widget->codec, e->reg); 1249 val = snd_soc_read(widget->codec, e->reg);
1254 ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (bitmask - 1); 1250 ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (bitmask - 1);
@@ -1278,15 +1274,15 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
1278 unsigned short mask, bitmask; 1274 unsigned short mask, bitmask;
1279 int ret = 0; 1275 int ret = 0;
1280 1276
1281 for (bitmask = 1; bitmask < e->mask; bitmask <<= 1) 1277 for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
1282 ; 1278 ;
1283 if (ucontrol->value.enumerated.item[0] > e->mask - 1) 1279 if (ucontrol->value.enumerated.item[0] > e->max - 1)
1284 return -EINVAL; 1280 return -EINVAL;
1285 mux = ucontrol->value.enumerated.item[0]; 1281 mux = ucontrol->value.enumerated.item[0];
1286 val = mux << e->shift_l; 1282 val = mux << e->shift_l;
1287 mask = (bitmask - 1) << e->shift_l; 1283 mask = (bitmask - 1) << e->shift_l;
1288 if (e->shift_l != e->shift_r) { 1284 if (e->shift_l != e->shift_r) {
1289 if (ucontrol->value.enumerated.item[1] > e->mask - 1) 1285 if (ucontrol->value.enumerated.item[1] > e->max - 1)
1290 return -EINVAL; 1286 return -EINVAL;
1291 val |= ucontrol->value.enumerated.item[1] << e->shift_r; 1287 val |= ucontrol->value.enumerated.item[1] << e->shift_r;
1292 mask |= (bitmask - 1) << e->shift_r; 1288 mask |= (bitmask - 1) << e->shift_r;
@@ -1294,7 +1290,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
1294 1290
1295 mutex_lock(&widget->codec->mutex); 1291 mutex_lock(&widget->codec->mutex);
1296 widget->value = val; 1292 widget->value = val;
1297 dapm_mux_update_power(widget, kcontrol, mask, mux, e); 1293 dapm_mux_update_power(widget, kcontrol, mask, mux, val, e);
1298 if (widget->event) { 1294 if (widget->event) {
1299 if (widget->event_flags & SND_SOC_DAPM_PRE_REG) { 1295 if (widget->event_flags & SND_SOC_DAPM_PRE_REG) {
1300 ret = widget->event(widget, 1296 ret = widget->event(widget,
@@ -1487,6 +1483,26 @@ int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, char *pin)
1487EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin); 1483EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin);
1488 1484
1489/** 1485/**
1486 * snd_soc_dapm_nc_pin - permanently disable pin.
1487 * @codec: SoC codec
1488 * @pin: pin name
1489 *
1490 * Marks the specified pin as being not connected, disabling it along
1491 * any parent or child widgets. At present this is identical to
1492 * snd_soc_dapm_disable_pin() but in future it will be extended to do
1493 * additional things such as disabling controls which only affect
1494 * paths through the pin.
1495 *
1496 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
1497 * do any widget power switching.
1498 */
1499int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, char *pin)
1500{
1501 return snd_soc_dapm_set_pin(codec, pin, 0);
1502}
1503EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin);
1504
1505/**
1490 * snd_soc_dapm_get_pin_status - get audio pin status 1506 * snd_soc_dapm_get_pin_status - get audio pin status
1491 * @codec: audio codec 1507 * @codec: audio codec
1492 * @pin: audio signal pin endpoint (or start point) 1508 * @pin: audio signal pin endpoint (or start point)
@@ -1524,6 +1540,6 @@ void snd_soc_dapm_free(struct snd_soc_device *socdev)
1524EXPORT_SYMBOL_GPL(snd_soc_dapm_free); 1540EXPORT_SYMBOL_GPL(snd_soc_dapm_free);
1525 1541
1526/* Module information */ 1542/* Module information */
1527MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com"); 1543MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk");
1528MODULE_DESCRIPTION("Dynamic Audio Power Management core for ALSA SoC"); 1544MODULE_DESCRIPTION("Dynamic Audio Power Management core for ALSA SoC");
1529MODULE_LICENSE("GPL"); 1545MODULE_LICENSE("GPL");