aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/Kconfig2
-rw-r--r--sound/soc/Makefile2
-rw-r--r--sound/soc/codecs/Kconfig12
-rw-r--r--sound/soc/codecs/Makefile6
-rw-r--r--sound/soc/codecs/ak4642.c24
-rw-r--r--sound/soc/codecs/cs4270.c4
-rw-r--r--sound/soc/codecs/cs4271.c659
-rw-r--r--sound/soc/codecs/max98088.c2
-rw-r--r--sound/soc/codecs/sn95031.c495
-rw-r--r--sound/soc/codecs/sn95031.h99
-rw-r--r--sound/soc/codecs/wm8523.c8
-rw-r--r--sound/soc/codecs/wm8741.c13
-rw-r--r--sound/soc/codecs/wm8804.c2
-rw-r--r--sound/soc/codecs/wm8900.c2
-rw-r--r--sound/soc/codecs/wm8903.c128
-rw-r--r--sound/soc/codecs/wm8904.c43
-rw-r--r--sound/soc/codecs/wm8955.c27
-rw-r--r--sound/soc/codecs/wm8961.c2
-rw-r--r--sound/soc/codecs/wm8962.c34
-rw-r--r--sound/soc/codecs/wm8978.c2
-rw-r--r--sound/soc/codecs/wm8991.c1427
-rw-r--r--sound/soc/codecs/wm8991.h833
-rw-r--r--sound/soc/codecs/wm8993.c2
-rw-r--r--sound/soc/codecs/wm8994.c10
-rw-r--r--sound/soc/codecs/wm8995.c103
-rw-r--r--sound/soc/codecs/wm9081.c2
-rw-r--r--sound/soc/codecs/wm9090.c45
-rw-r--r--sound/soc/ep93xx/Kconfig9
-rw-r--r--sound/soc/ep93xx/Makefile2
-rw-r--r--sound/soc/ep93xx/edb93xx.c142
-rw-r--r--sound/soc/mid-x86/Kconfig14
-rw-r--r--sound/soc/mid-x86/Makefile5
-rw-r--r--sound/soc/mid-x86/mfld_machine.c296
-rw-r--r--sound/soc/mid-x86/sst_platform.c459
-rw-r--r--sound/soc/mid-x86/sst_platform.h63
-rw-r--r--sound/soc/samsung/ac97.c8
-rw-r--r--sound/soc/samsung/ac97.h21
-rw-r--r--sound/soc/samsung/dma.c11
-rw-r--r--sound/soc/samsung/dma.h8
-rw-r--r--sound/soc/samsung/goni_wm8994.c10
-rw-r--r--sound/soc/samsung/h1940_uda1380.c9
-rw-r--r--sound/soc/samsung/i2s.c3
-rw-r--r--sound/soc/samsung/jive_wm8750.c11
-rw-r--r--sound/soc/samsung/ln2440sbc_alc650.c7
-rw-r--r--sound/soc/samsung/neo1973_gta02_wm8753.c14
-rw-r--r--sound/soc/samsung/pcm.c118
-rw-r--r--sound/soc/samsung/pcm.h107
-rw-r--r--sound/soc/samsung/rx1950_uda1380.c11
-rw-r--r--sound/soc/samsung/s3c-i2s-v2.c3
-rw-r--r--sound/soc/samsung/s3c2412-i2s.c12
-rw-r--r--sound/soc/samsung/s3c24xx-i2s.c14
-rw-r--r--sound/soc/samsung/s3c24xx_simtec.c7
-rw-r--r--sound/soc/samsung/s3c24xx_simtec_hermes.c10
-rw-r--r--sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c12
-rw-r--r--sound/soc/samsung/s3c24xx_uda134x.c9
-rw-r--r--sound/soc/samsung/smartq_wm8987.c6
-rw-r--r--sound/soc/samsung/smdk2443_wm9710.c7
-rw-r--r--sound/soc/samsung/smdk_spdif.c5
-rw-r--r--sound/soc/samsung/smdk_wm8580.c7
-rw-r--r--sound/soc/samsung/smdk_wm9713.c5
-rw-r--r--sound/soc/samsung/spdif.c3
-rw-r--r--sound/soc/sh/fsi-ak4642.c23
-rw-r--r--sound/soc/sh/fsi-da7210.c12
-rw-r--r--sound/soc/sh/fsi-hdmi.c77
-rw-r--r--sound/soc/sh/fsi.c62
-rw-r--r--sound/soc/soc-cache.c367
-rw-r--r--sound/soc/soc-core.c169
-rw-r--r--sound/soc/soc-dapm.c64
-rw-r--r--sound/soc/tegra/Kconfig26
-rw-r--r--sound/soc/tegra/Makefile14
-rw-r--r--sound/soc/tegra/harmony.c210
-rw-r--r--sound/soc/tegra/tegra_asoc_utils.c152
-rw-r--r--sound/soc/tegra/tegra_asoc_utils.h31
-rw-r--r--sound/soc/tegra/tegra_das.c264
-rw-r--r--sound/soc/tegra/tegra_das.h135
-rw-r--r--sound/soc/tegra/tegra_i2s.c502
-rw-r--r--sound/soc/tegra/tegra_i2s.h165
-rw-r--r--sound/soc/tegra/tegra_pcm.c401
-rw-r--r--sound/soc/tegra/tegra_pcm.h55
79 files changed, 7435 insertions, 710 deletions
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index a3efc52a34da..8224db5f0434 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -50,10 +50,12 @@ source "sound/soc/jz4740/Kconfig"
50source "sound/soc/nuc900/Kconfig" 50source "sound/soc/nuc900/Kconfig"
51source "sound/soc/omap/Kconfig" 51source "sound/soc/omap/Kconfig"
52source "sound/soc/kirkwood/Kconfig" 52source "sound/soc/kirkwood/Kconfig"
53source "sound/soc/mid-x86/Kconfig"
53source "sound/soc/pxa/Kconfig" 54source "sound/soc/pxa/Kconfig"
54source "sound/soc/samsung/Kconfig" 55source "sound/soc/samsung/Kconfig"
55source "sound/soc/s6000/Kconfig" 56source "sound/soc/s6000/Kconfig"
56source "sound/soc/sh/Kconfig" 57source "sound/soc/sh/Kconfig"
58source "sound/soc/tegra/Kconfig"
57source "sound/soc/txx9/Kconfig" 59source "sound/soc/txx9/Kconfig"
58 60
59# Supported codecs 61# Supported codecs
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index ce913bf5213c..1ed61c5df2c5 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_SND_SOC) += ep93xx/
10obj-$(CONFIG_SND_SOC) += fsl/ 10obj-$(CONFIG_SND_SOC) += fsl/
11obj-$(CONFIG_SND_SOC) += imx/ 11obj-$(CONFIG_SND_SOC) += imx/
12obj-$(CONFIG_SND_SOC) += jz4740/ 12obj-$(CONFIG_SND_SOC) += jz4740/
13obj-$(CONFIG_SND_SOC) += mid-x86/
13obj-$(CONFIG_SND_SOC) += nuc900/ 14obj-$(CONFIG_SND_SOC) += nuc900/
14obj-$(CONFIG_SND_SOC) += omap/ 15obj-$(CONFIG_SND_SOC) += omap/
15obj-$(CONFIG_SND_SOC) += kirkwood/ 16obj-$(CONFIG_SND_SOC) += kirkwood/
@@ -17,4 +18,5 @@ obj-$(CONFIG_SND_SOC) += pxa/
17obj-$(CONFIG_SND_SOC) += samsung/ 18obj-$(CONFIG_SND_SOC) += samsung/
18obj-$(CONFIG_SND_SOC) += s6000/ 19obj-$(CONFIG_SND_SOC) += s6000/
19obj-$(CONFIG_SND_SOC) += sh/ 20obj-$(CONFIG_SND_SOC) += sh/
21obj-$(CONFIG_SND_SOC) += tegra/
20obj-$(CONFIG_SND_SOC) += txx9/ 22obj-$(CONFIG_SND_SOC) += txx9/
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index c48b23c1d4fc..e239345a4d5d 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -26,12 +26,14 @@ config SND_SOC_ALL_CODECS
26 select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC 26 select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC
27 select SND_SOC_CS42L51 if I2C 27 select SND_SOC_CS42L51 if I2C
28 select SND_SOC_CS4270 if I2C 28 select SND_SOC_CS4270 if I2C
29 select SND_SOC_CS4271 if SND_SOC_I2C_AND_SPI
29 select SND_SOC_CX20442 30 select SND_SOC_CX20442
30 select SND_SOC_DA7210 if I2C 31 select SND_SOC_DA7210 if I2C
31 select SND_SOC_JZ4740_CODEC if SOC_JZ4740 32 select SND_SOC_JZ4740_CODEC if SOC_JZ4740
32 select SND_SOC_MAX98088 if I2C 33 select SND_SOC_MAX98088 if I2C
33 select SND_SOC_MAX9877 if I2C 34 select SND_SOC_MAX9877 if I2C
34 select SND_SOC_PCM3008 35 select SND_SOC_PCM3008
36 select SND_SOC_SN95031 if INTEL_SCU_IPC
35 select SND_SOC_SPDIF 37 select SND_SOC_SPDIF
36 select SND_SOC_SSM2602 if I2C 38 select SND_SOC_SSM2602 if I2C
37 select SND_SOC_STAC9766 if SND_SOC_AC97_BUS 39 select SND_SOC_STAC9766 if SND_SOC_AC97_BUS
@@ -76,6 +78,7 @@ config SND_SOC_ALL_CODECS
76 select SND_SOC_WM8985 if SND_SOC_I2C_AND_SPI 78 select SND_SOC_WM8985 if SND_SOC_I2C_AND_SPI
77 select SND_SOC_WM8988 if SND_SOC_I2C_AND_SPI 79 select SND_SOC_WM8988 if SND_SOC_I2C_AND_SPI
78 select SND_SOC_WM8990 if I2C 80 select SND_SOC_WM8990 if I2C
81 select SND_SOC_WM8991 if I2C
79 select SND_SOC_WM8993 if I2C 82 select SND_SOC_WM8993 if I2C
80 select SND_SOC_WM8994 if MFD_WM8994 83 select SND_SOC_WM8994 if MFD_WM8994
81 select SND_SOC_WM8995 if SND_SOC_I2C_AND_SPI 84 select SND_SOC_WM8995 if SND_SOC_I2C_AND_SPI
@@ -155,6 +158,9 @@ config SND_SOC_CS4270_VD33_ERRATA
155 bool 158 bool
156 depends on SND_SOC_CS4270 159 depends on SND_SOC_CS4270
157 160
161config SND_SOC_CS4271
162 tristate
163
158config SND_SOC_CX20442 164config SND_SOC_CX20442
159 tristate 165 tristate
160 166
@@ -176,6 +182,9 @@ config SND_SOC_MAX98088
176config SND_SOC_PCM3008 182config SND_SOC_PCM3008
177 tristate 183 tristate
178 184
185config SND_SOC_SN95031
186 tristate
187
179config SND_SOC_SPDIF 188config SND_SOC_SPDIF
180 tristate 189 tristate
181 190
@@ -304,6 +313,9 @@ config SND_SOC_WM8988
304config SND_SOC_WM8990 313config SND_SOC_WM8990
305 tristate 314 tristate
306 315
316config SND_SOC_WM8991
317 tristate
318
307config SND_SOC_WM8993 319config SND_SOC_WM8993
308 tristate 320 tristate
309 321
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 579af9c4f128..83b7accd7037 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -12,6 +12,7 @@ snd-soc-ak4671-objs := ak4671.o
12snd-soc-cq93vc-objs := cq93vc.o 12snd-soc-cq93vc-objs := cq93vc.o
13snd-soc-cs42l51-objs := cs42l51.o 13snd-soc-cs42l51-objs := cs42l51.o
14snd-soc-cs4270-objs := cs4270.o 14snd-soc-cs4270-objs := cs4270.o
15snd-soc-cs4271-objs := cs4271.o
15snd-soc-cx20442-objs := cx20442.o 16snd-soc-cx20442-objs := cx20442.o
16snd-soc-da7210-objs := da7210.o 17snd-soc-da7210-objs := da7210.o
17snd-soc-dmic-objs := dmic.o 18snd-soc-dmic-objs := dmic.o
@@ -19,6 +20,7 @@ snd-soc-l3-objs := l3.o
19snd-soc-max98088-objs := max98088.o 20snd-soc-max98088-objs := max98088.o
20snd-soc-pcm3008-objs := pcm3008.o 21snd-soc-pcm3008-objs := pcm3008.o
21snd-soc-alc5623-objs := alc5623.o 22snd-soc-alc5623-objs := alc5623.o
23snd-soc-sn95031-objs := sn95031.o
22snd-soc-spdif-objs := spdif_transciever.o 24snd-soc-spdif-objs := spdif_transciever.o
23snd-soc-ssm2602-objs := ssm2602.o 25snd-soc-ssm2602-objs := ssm2602.o
24snd-soc-stac9766-objs := stac9766.o 26snd-soc-stac9766-objs := stac9766.o
@@ -61,6 +63,7 @@ snd-soc-wm8978-objs := wm8978.o
61snd-soc-wm8985-objs := wm8985.o 63snd-soc-wm8985-objs := wm8985.o
62snd-soc-wm8988-objs := wm8988.o 64snd-soc-wm8988-objs := wm8988.o
63snd-soc-wm8990-objs := wm8990.o 65snd-soc-wm8990-objs := wm8990.o
66snd-soc-wm8991-objs := wm8991.o
64snd-soc-wm8993-objs := wm8993.o 67snd-soc-wm8993-objs := wm8993.o
65snd-soc-wm8994-objs := wm8994.o wm8994-tables.o 68snd-soc-wm8994-objs := wm8994.o wm8994-tables.o
66snd-soc-wm8995-objs := wm8995.o 69snd-soc-wm8995-objs := wm8995.o
@@ -91,6 +94,7 @@ obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o
91obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.o 94obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.o
92obj-$(CONFIG_SND_SOC_CS42L51) += snd-soc-cs42l51.o 95obj-$(CONFIG_SND_SOC_CS42L51) += snd-soc-cs42l51.o
93obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o 96obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o
97obj-$(CONFIG_SND_SOC_CS4271) += snd-soc-cs4271.o
94obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o 98obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o
95obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o 99obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o
96obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o 100obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o
@@ -99,6 +103,7 @@ obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o
99obj-$(CONFIG_SND_SOC_MAX98088) += snd-soc-max98088.o 103obj-$(CONFIG_SND_SOC_MAX98088) += snd-soc-max98088.o
100obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o 104obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o
101obj-$(CONFIG_SND_SOC_ALC5623) += snd-soc-alc5623.o 105obj-$(CONFIG_SND_SOC_ALC5623) += snd-soc-alc5623.o
106obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o
102obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif.o 107obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif.o
103obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o 108obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o
104obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o 109obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o
@@ -141,6 +146,7 @@ obj-$(CONFIG_SND_SOC_WM8978) += snd-soc-wm8978.o
141obj-$(CONFIG_SND_SOC_WM8985) += snd-soc-wm8985.o 146obj-$(CONFIG_SND_SOC_WM8985) += snd-soc-wm8985.o
142obj-$(CONFIG_SND_SOC_WM8988) += snd-soc-wm8988.o 147obj-$(CONFIG_SND_SOC_WM8988) += snd-soc-wm8988.o
143obj-$(CONFIG_SND_SOC_WM8990) += snd-soc-wm8990.o 148obj-$(CONFIG_SND_SOC_WM8990) += snd-soc-wm8990.o
149obj-$(CONFIG_SND_SOC_WM8991) += snd-soc-wm8991.o
144obj-$(CONFIG_SND_SOC_WM8993) += snd-soc-wm8993.o 150obj-$(CONFIG_SND_SOC_WM8993) += snd-soc-wm8993.o
145obj-$(CONFIG_SND_SOC_WM8994) += snd-soc-wm8994.o 151obj-$(CONFIG_SND_SOC_WM8994) += snd-soc-wm8994.o
146obj-$(CONFIG_SND_SOC_WM8995) += snd-soc-wm8995.o 152obj-$(CONFIG_SND_SOC_WM8995) += snd-soc-wm8995.o
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c
index f00eba313dfd..4be0570e3f1f 100644
--- a/sound/soc/codecs/ak4642.c
+++ b/sound/soc/codecs/ak4642.c
@@ -116,6 +116,12 @@
116#define BCKO_MASK (1 << 3) 116#define BCKO_MASK (1 << 3)
117#define BCKO_64 BCKO_MASK 117#define BCKO_64 BCKO_MASK
118 118
119#define DIF_MASK (3 << 0)
120#define DSP (0 << 0)
121#define RIGHT_J (1 << 0)
122#define LEFT_J (2 << 0)
123#define I2S (3 << 0)
124
119/* MD_CTL2 */ 125/* MD_CTL2 */
120#define FS0 (1 << 0) 126#define FS0 (1 << 0)
121#define FS1 (1 << 1) 127#define FS1 (1 << 1)
@@ -354,6 +360,24 @@ static int ak4642_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
354 snd_soc_update_bits(codec, PW_MGMT2, MS, data); 360 snd_soc_update_bits(codec, PW_MGMT2, MS, data);
355 snd_soc_update_bits(codec, MD_CTL1, BCKO_MASK, bcko); 361 snd_soc_update_bits(codec, MD_CTL1, BCKO_MASK, bcko);
356 362
363 /* format type */
364 data = 0;
365 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
366 case SND_SOC_DAIFMT_LEFT_J:
367 data = LEFT_J;
368 break;
369 case SND_SOC_DAIFMT_I2S:
370 data = I2S;
371 break;
372 /* FIXME
373 * Please add RIGHT_J / DSP support here
374 */
375 default:
376 return -EINVAL;
377 break;
378 }
379 snd_soc_update_bits(codec, MD_CTL1, DIF_MASK, data);
380
357 return 0; 381 return 0;
358} 382}
359 383
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index 8b51245f2318..c0fccadaea9a 100644
--- a/sound/soc/codecs/cs4270.c
+++ b/sound/soc/codecs/cs4270.c
@@ -193,12 +193,12 @@ static struct cs4270_mode_ratios cs4270_mode_ratios[] = {
193/* The number of MCLK/LRCK ratios supported by the CS4270 */ 193/* The number of MCLK/LRCK ratios supported by the CS4270 */
194#define NUM_MCLK_RATIOS ARRAY_SIZE(cs4270_mode_ratios) 194#define NUM_MCLK_RATIOS ARRAY_SIZE(cs4270_mode_ratios)
195 195
196static int cs4270_reg_is_readable(unsigned int reg) 196static int cs4270_reg_is_readable(struct snd_soc_codec *codec, unsigned int reg)
197{ 197{
198 return (reg >= CS4270_FIRSTREG) && (reg <= CS4270_LASTREG); 198 return (reg >= CS4270_FIRSTREG) && (reg <= CS4270_LASTREG);
199} 199}
200 200
201static int cs4270_reg_is_volatile(unsigned int reg) 201static int cs4270_reg_is_volatile(struct snd_soc_codec *codec, unsigned int reg)
202{ 202{
203 /* Unreadable registers are considered volatile */ 203 /* Unreadable registers are considered volatile */
204 if ((reg < CS4270_FIRSTREG) || (reg > CS4270_LASTREG)) 204 if ((reg < CS4270_FIRSTREG) || (reg > CS4270_LASTREG))
diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c
new file mode 100644
index 000000000000..5357ec5f5d7c
--- /dev/null
+++ b/sound/soc/codecs/cs4271.c
@@ -0,0 +1,659 @@
1/*
2 * CS4271 ASoC codec driver
3 *
4 * Copyright (c) 2010 Alexander Sverdlin <subaparts@yandex.ru>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * This driver support CS4271 codec being master or slave, working
17 * in control port mode, connected either via SPI or I2C.
18 * The data format accepted is I2S or left-justified.
19 * DAPM support not implemented.
20 */
21
22#include <linux/module.h>
23#include <linux/slab.h>
24#include <linux/delay.h>
25#include <sound/pcm.h>
26#include <sound/soc.h>
27#include <sound/tlv.h>
28#include <linux/gpio.h>
29#include <linux/i2c.h>
30#include <linux/spi/spi.h>
31#include <sound/cs4271.h>
32
33#define CS4271_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
34 SNDRV_PCM_FMTBIT_S24_LE | \
35 SNDRV_PCM_FMTBIT_S32_LE)
36
37/*
38 * CS4271 registers
39 * High byte represents SPI chip address (0x10) + write command (0)
40 * Low byte - codec register address
41 */
42#define CS4271_MODE1 0x2001 /* Mode Control 1 */
43#define CS4271_DACCTL 0x2002 /* DAC Control */
44#define CS4271_DACVOL 0x2003 /* DAC Volume & Mixing Control */
45#define CS4271_VOLA 0x2004 /* DAC Channel A Volume Control */
46#define CS4271_VOLB 0x2005 /* DAC Channel B Volume Control */
47#define CS4271_ADCCTL 0x2006 /* ADC Control */
48#define CS4271_MODE2 0x2007 /* Mode Control 2 */
49#define CS4271_CHIPID 0x2008 /* Chip ID */
50
51#define CS4271_FIRSTREG CS4271_MODE1
52#define CS4271_LASTREG CS4271_MODE2
53#define CS4271_NR_REGS ((CS4271_LASTREG & 0xFF) + 1)
54
55/* Bit masks for the CS4271 registers */
56#define CS4271_MODE1_MODE_MASK 0xC0
57#define CS4271_MODE1_MODE_1X 0x00
58#define CS4271_MODE1_MODE_2X 0x80
59#define CS4271_MODE1_MODE_4X 0xC0
60
61#define CS4271_MODE1_DIV_MASK 0x30
62#define CS4271_MODE1_DIV_1 0x00
63#define CS4271_MODE1_DIV_15 0x10
64#define CS4271_MODE1_DIV_2 0x20
65#define CS4271_MODE1_DIV_3 0x30
66
67#define CS4271_MODE1_MASTER 0x08
68
69#define CS4271_MODE1_DAC_DIF_MASK 0x07
70#define CS4271_MODE1_DAC_DIF_LJ 0x00
71#define CS4271_MODE1_DAC_DIF_I2S 0x01
72#define CS4271_MODE1_DAC_DIF_RJ16 0x02
73#define CS4271_MODE1_DAC_DIF_RJ24 0x03
74#define CS4271_MODE1_DAC_DIF_RJ20 0x04
75#define CS4271_MODE1_DAC_DIF_RJ18 0x05
76
77#define CS4271_DACCTL_AMUTE 0x80
78#define CS4271_DACCTL_IF_SLOW 0x40
79
80#define CS4271_DACCTL_DEM_MASK 0x30
81#define CS4271_DACCTL_DEM_DIS 0x00
82#define CS4271_DACCTL_DEM_441 0x10
83#define CS4271_DACCTL_DEM_48 0x20
84#define CS4271_DACCTL_DEM_32 0x30
85
86#define CS4271_DACCTL_SVRU 0x08
87#define CS4271_DACCTL_SRD 0x04
88#define CS4271_DACCTL_INVA 0x02
89#define CS4271_DACCTL_INVB 0x01
90
91#define CS4271_DACVOL_BEQUA 0x40
92#define CS4271_DACVOL_SOFT 0x20
93#define CS4271_DACVOL_ZEROC 0x10
94
95#define CS4271_DACVOL_ATAPI_MASK 0x0F
96#define CS4271_DACVOL_ATAPI_M_M 0x00
97#define CS4271_DACVOL_ATAPI_M_BR 0x01
98#define CS4271_DACVOL_ATAPI_M_BL 0x02
99#define CS4271_DACVOL_ATAPI_M_BLR2 0x03
100#define CS4271_DACVOL_ATAPI_AR_M 0x04
101#define CS4271_DACVOL_ATAPI_AR_BR 0x05
102#define CS4271_DACVOL_ATAPI_AR_BL 0x06
103#define CS4271_DACVOL_ATAPI_AR_BLR2 0x07
104#define CS4271_DACVOL_ATAPI_AL_M 0x08
105#define CS4271_DACVOL_ATAPI_AL_BR 0x09
106#define CS4271_DACVOL_ATAPI_AL_BL 0x0A
107#define CS4271_DACVOL_ATAPI_AL_BLR2 0x0B
108#define CS4271_DACVOL_ATAPI_ALR2_M 0x0C
109#define CS4271_DACVOL_ATAPI_ALR2_BR 0x0D
110#define CS4271_DACVOL_ATAPI_ALR2_BL 0x0E
111#define CS4271_DACVOL_ATAPI_ALR2_BLR2 0x0F
112
113#define CS4271_VOLA_MUTE 0x80
114#define CS4271_VOLA_VOL_MASK 0x7F
115#define CS4271_VOLB_MUTE 0x80
116#define CS4271_VOLB_VOL_MASK 0x7F
117
118#define CS4271_ADCCTL_DITHER16 0x20
119
120#define CS4271_ADCCTL_ADC_DIF_MASK 0x10
121#define CS4271_ADCCTL_ADC_DIF_LJ 0x00
122#define CS4271_ADCCTL_ADC_DIF_I2S 0x10
123
124#define CS4271_ADCCTL_MUTEA 0x08
125#define CS4271_ADCCTL_MUTEB 0x04
126#define CS4271_ADCCTL_HPFDA 0x02
127#define CS4271_ADCCTL_HPFDB 0x01
128
129#define CS4271_MODE2_LOOP 0x10
130#define CS4271_MODE2_MUTECAEQUB 0x08
131#define CS4271_MODE2_FREEZE 0x04
132#define CS4271_MODE2_CPEN 0x02
133#define CS4271_MODE2_PDN 0x01
134
135#define CS4271_CHIPID_PART_MASK 0xF0
136#define CS4271_CHIPID_REV_MASK 0x0F
137
138/*
139 * Default CS4271 power-up configuration
140 * Array contains non-existing in hw register at address 0
141 * Array do not include Chip ID, as codec driver does not use
142 * registers read operations at all
143 */
144static const u8 cs4271_dflt_reg[CS4271_NR_REGS] = {
145 0,
146 0,
147 CS4271_DACCTL_AMUTE,
148 CS4271_DACVOL_SOFT | CS4271_DACVOL_ATAPI_AL_BR,
149 0,
150 0,
151 0,
152 0,
153};
154
155struct cs4271_private {
156 /* SND_SOC_I2C or SND_SOC_SPI */
157 enum snd_soc_control_type bus_type;
158 void *control_data;
159 unsigned int mclk;
160 bool master;
161 bool deemph;
162 /* Current sample rate for de-emphasis control */
163 int rate;
164 /* GPIO driving Reset pin, if any */
165 int gpio_nreset;
166 /* GPIO that disable serial bus, if any */
167 int gpio_disable;
168};
169
170struct cs4271_clk_cfg {
171 unsigned int ratio; /* MCLK / sample rate */
172 u8 speed_mode; /* codec speed mode: 1x, 2x, 4x */
173 u8 mclk_master; /* ratio bit mask for Master mode */
174 u8 mclk_slave; /* ratio bit mask for Slave mode */
175};
176
177static struct cs4271_clk_cfg cs4271_clk_tab[] = {
178 {64, CS4271_MODE1_MODE_4X, CS4271_MODE1_DIV_1, CS4271_MODE1_DIV_1},
179 {96, CS4271_MODE1_MODE_4X, CS4271_MODE1_DIV_15, CS4271_MODE1_DIV_1},
180 {128, CS4271_MODE1_MODE_2X, CS4271_MODE1_DIV_1, CS4271_MODE1_DIV_1},
181 {192, CS4271_MODE1_MODE_2X, CS4271_MODE1_DIV_15, CS4271_MODE1_DIV_1},
182 {256, CS4271_MODE1_MODE_1X, CS4271_MODE1_DIV_1, CS4271_MODE1_DIV_1},
183 {384, CS4271_MODE1_MODE_1X, CS4271_MODE1_DIV_15, CS4271_MODE1_DIV_1},
184 {512, CS4271_MODE1_MODE_1X, CS4271_MODE1_DIV_2, CS4271_MODE1_DIV_1},
185 {768, CS4271_MODE1_MODE_1X, CS4271_MODE1_DIV_3, CS4271_MODE1_DIV_3},
186 {1024, CS4271_MODE1_MODE_1X, CS4271_MODE1_DIV_3, CS4271_MODE1_DIV_3}
187};
188
189#define CS4171_NR_RATIOS ARRAY_SIZE(cs4271_clk_tab)
190
191/*
192 * @freq is the desired MCLK rate
193 * MCLK rate should (c) be the sample rate, multiplied by one of the
194 * ratios listed in cs4271_mclk_fs_ratios table
195 */
196static int cs4271_set_dai_sysclk(struct snd_soc_dai *codec_dai,
197 int clk_id, unsigned int freq, int dir)
198{
199 struct snd_soc_codec *codec = codec_dai->codec;
200 struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
201
202 cs4271->mclk = freq;
203 return 0;
204}
205
206static int cs4271_set_dai_fmt(struct snd_soc_dai *codec_dai,
207 unsigned int format)
208{
209 struct snd_soc_codec *codec = codec_dai->codec;
210 struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
211 unsigned int val = 0;
212 int ret;
213
214 switch (format & SND_SOC_DAIFMT_MASTER_MASK) {
215 case SND_SOC_DAIFMT_CBS_CFS:
216 cs4271->master = 0;
217 break;
218 case SND_SOC_DAIFMT_CBM_CFM:
219 cs4271->master = 1;
220 val |= CS4271_MODE1_MASTER;
221 break;
222 default:
223 dev_err(codec->dev, "Invalid DAI format\n");
224 return -EINVAL;
225 }
226
227 switch (format & SND_SOC_DAIFMT_FORMAT_MASK) {
228 case SND_SOC_DAIFMT_LEFT_J:
229 val |= CS4271_MODE1_DAC_DIF_LJ;
230 ret = snd_soc_update_bits(codec, CS4271_ADCCTL,
231 CS4271_ADCCTL_ADC_DIF_MASK, CS4271_ADCCTL_ADC_DIF_LJ);
232 if (ret < 0)
233 return ret;
234 break;
235 case SND_SOC_DAIFMT_I2S:
236 val |= CS4271_MODE1_DAC_DIF_I2S;
237 ret = snd_soc_update_bits(codec, CS4271_ADCCTL,
238 CS4271_ADCCTL_ADC_DIF_MASK, CS4271_ADCCTL_ADC_DIF_I2S);
239 if (ret < 0)
240 return ret;
241 break;
242 default:
243 dev_err(codec->dev, "Invalid DAI format\n");
244 return -EINVAL;
245 }
246
247 ret = snd_soc_update_bits(codec, CS4271_MODE1,
248 CS4271_MODE1_DAC_DIF_MASK | CS4271_MODE1_MASTER, val);
249 if (ret < 0)
250 return ret;
251 return 0;
252}
253
254static int cs4271_deemph[] = {0, 44100, 48000, 32000};
255
256static int cs4271_set_deemph(struct snd_soc_codec *codec)
257{
258 struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
259 int i, ret;
260 int val = CS4271_DACCTL_DEM_DIS;
261
262 if (cs4271->deemph) {
263 /* Find closest de-emphasis freq */
264 val = 1;
265 for (i = 2; i < ARRAY_SIZE(cs4271_deemph); i++)
266 if (abs(cs4271_deemph[i] - cs4271->rate) <
267 abs(cs4271_deemph[val] - cs4271->rate))
268 val = i;
269 val <<= 4;
270 }
271
272 ret = snd_soc_update_bits(codec, CS4271_DACCTL,
273 CS4271_DACCTL_DEM_MASK, val);
274 if (ret < 0)
275 return ret;
276 return 0;
277}
278
279static int cs4271_get_deemph(struct snd_kcontrol *kcontrol,
280 struct snd_ctl_elem_value *ucontrol)
281{
282 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
283 struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
284
285 ucontrol->value.enumerated.item[0] = cs4271->deemph;
286 return 0;
287}
288
289static int cs4271_put_deemph(struct snd_kcontrol *kcontrol,
290 struct snd_ctl_elem_value *ucontrol)
291{
292 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
293 struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
294
295 cs4271->deemph = ucontrol->value.enumerated.item[0];
296 return cs4271_set_deemph(codec);
297}
298
299static int cs4271_hw_params(struct snd_pcm_substream *substream,
300 struct snd_pcm_hw_params *params,
301 struct snd_soc_dai *dai)
302{
303 struct snd_soc_pcm_runtime *rtd = substream->private_data;
304 struct snd_soc_codec *codec = rtd->codec;
305 struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
306 int i, ret;
307 unsigned int ratio, val;
308
309 cs4271->rate = params_rate(params);
310 ratio = cs4271->mclk / cs4271->rate;
311 for (i = 0; i < CS4171_NR_RATIOS; i++)
312 if (cs4271_clk_tab[i].ratio == ratio)
313 break;
314
315 if ((i == CS4171_NR_RATIOS) || ((ratio == 1024) && cs4271->master)) {
316 dev_err(codec->dev, "Invalid sample rate\n");
317 return -EINVAL;
318 }
319
320 /* Configure DAC */
321 val = cs4271_clk_tab[i].speed_mode;
322
323 if (cs4271->master)
324 val |= cs4271_clk_tab[i].mclk_master;
325 else
326 val |= cs4271_clk_tab[i].mclk_slave;
327
328 ret = snd_soc_update_bits(codec, CS4271_MODE1,
329 CS4271_MODE1_MODE_MASK | CS4271_MODE1_DIV_MASK, val);
330 if (ret < 0)
331 return ret;
332
333 return cs4271_set_deemph(codec);
334}
335
336static int cs4271_digital_mute(struct snd_soc_dai *dai, int mute)
337{
338 struct snd_soc_codec *codec = dai->codec;
339 int ret;
340 int val_a = 0;
341 int val_b = 0;
342
343 if (mute) {
344 val_a = CS4271_VOLA_MUTE;
345 val_b = CS4271_VOLB_MUTE;
346 }
347
348 ret = snd_soc_update_bits(codec, CS4271_VOLA, CS4271_VOLA_MUTE, val_a);
349 if (ret < 0)
350 return ret;
351 ret = snd_soc_update_bits(codec, CS4271_VOLB, CS4271_VOLB_MUTE, val_b);
352 if (ret < 0)
353 return ret;
354
355 return 0;
356}
357
358/* CS4271 controls */
359static DECLARE_TLV_DB_SCALE(cs4271_dac_tlv, -12700, 100, 0);
360
361static const struct snd_kcontrol_new cs4271_snd_controls[] = {
362 SOC_DOUBLE_R_TLV("Master Playback Volume", CS4271_VOLA, CS4271_VOLB,
363 0, 0x7F, 1, cs4271_dac_tlv),
364 SOC_SINGLE("Digital Loopback Switch", CS4271_MODE2, 4, 1, 0),
365 SOC_SINGLE("Soft Ramp Switch", CS4271_DACVOL, 5, 1, 0),
366 SOC_SINGLE("Zero Cross Switch", CS4271_DACVOL, 4, 1, 0),
367 SOC_SINGLE_BOOL_EXT("De-emphasis Switch", 0,
368 cs4271_get_deemph, cs4271_put_deemph),
369 SOC_SINGLE("Auto-Mute Switch", CS4271_DACCTL, 7, 1, 0),
370 SOC_SINGLE("Slow Roll Off Filter Switch", CS4271_DACCTL, 6, 1, 0),
371 SOC_SINGLE("Soft Volume Ramp-Up Switch", CS4271_DACCTL, 3, 1, 0),
372 SOC_SINGLE("Soft Ramp-Down Switch", CS4271_DACCTL, 2, 1, 0),
373 SOC_SINGLE("Left Channel Inversion Switch", CS4271_DACCTL, 1, 1, 0),
374 SOC_SINGLE("Right Channel Inversion Switch", CS4271_DACCTL, 0, 1, 0),
375 SOC_DOUBLE("Master Capture Switch", CS4271_ADCCTL, 3, 2, 1, 1),
376 SOC_SINGLE("Dither 16-Bit Data Switch", CS4271_ADCCTL, 5, 1, 0),
377 SOC_DOUBLE("High Pass Filter Switch", CS4271_ADCCTL, 1, 0, 1, 1),
378 SOC_DOUBLE_R("Master Playback Switch", CS4271_VOLA, CS4271_VOLB,
379 7, 1, 1),
380};
381
382static struct snd_soc_dai_ops cs4271_dai_ops = {
383 .hw_params = cs4271_hw_params,
384 .set_sysclk = cs4271_set_dai_sysclk,
385 .set_fmt = cs4271_set_dai_fmt,
386 .digital_mute = cs4271_digital_mute,
387};
388
389struct snd_soc_dai_driver cs4271_dai = {
390 .name = "cs4271-hifi",
391 .playback = {
392 .stream_name = "Playback",
393 .channels_min = 2,
394 .channels_max = 2,
395 .rates = SNDRV_PCM_RATE_8000_96000,
396 .formats = CS4271_PCM_FORMATS,
397 },
398 .capture = {
399 .stream_name = "Capture",
400 .channels_min = 2,
401 .channels_max = 2,
402 .rates = SNDRV_PCM_RATE_8000_96000,
403 .formats = CS4271_PCM_FORMATS,
404 },
405 .ops = &cs4271_dai_ops,
406 .symmetric_rates = 1,
407};
408
409#ifdef CONFIG_PM
410static int cs4271_soc_suspend(struct snd_soc_codec *codec, pm_message_t mesg)
411{
412 int ret;
413 /* Set power-down bit */
414 ret = snd_soc_update_bits(codec, CS4271_MODE2, 0, CS4271_MODE2_PDN);
415 if (ret < 0)
416 return ret;
417 return 0;
418}
419
420static int cs4271_soc_resume(struct snd_soc_codec *codec)
421{
422 int ret;
423 /* Restore codec state */
424 ret = snd_soc_cache_sync(codec);
425 if (ret < 0)
426 return ret;
427 /* then disable the power-down bit */
428 ret = snd_soc_update_bits(codec, CS4271_MODE2, CS4271_MODE2_PDN, 0);
429 if (ret < 0)
430 return ret;
431 return 0;
432}
433#else
434#define cs4271_soc_suspend NULL
435#define cs4271_soc_resume NULL
436#endif /* CONFIG_PM */
437
438static int cs4271_probe(struct snd_soc_codec *codec)
439{
440 struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
441 struct cs4271_platform_data *cs4271plat = codec->dev->platform_data;
442 int ret;
443 int gpio_nreset = -EINVAL;
444 int gpio_disable = -EINVAL;
445
446 codec->control_data = cs4271->control_data;
447
448 if (cs4271plat) {
449 if (gpio_is_valid(cs4271plat->gpio_nreset))
450 gpio_nreset = cs4271plat->gpio_nreset;
451 if (gpio_is_valid(cs4271plat->gpio_disable))
452 gpio_disable = cs4271plat->gpio_disable;
453 }
454
455 if (gpio_disable >= 0)
456 if (gpio_request(gpio_disable, "CS4271 Disable"))
457 gpio_disable = -EINVAL;
458 if (gpio_disable >= 0)
459 gpio_direction_output(gpio_disable, 0);
460
461 if (gpio_nreset >= 0)
462 if (gpio_request(gpio_nreset, "CS4271 Reset"))
463 gpio_nreset = -EINVAL;
464 if (gpio_nreset >= 0) {
465 /* Reset codec */
466 gpio_direction_output(gpio_nreset, 0);
467 udelay(1);
468 gpio_set_value(gpio_nreset, 1);
469 /* Give the codec time to wake up */
470 udelay(1);
471 }
472
473 cs4271->gpio_nreset = gpio_nreset;
474 cs4271->gpio_disable = gpio_disable;
475
476 /*
477 * In case of I2C, chip address specified in board data.
478 * So cache IO operations use 8 bit codec register address.
479 * In case of SPI, chip address and register address
480 * passed together as 16 bit value.
481 * Anyway, register address is masked with 0xFF inside
482 * soc-cache code.
483 */
484 if (cs4271->bus_type == SND_SOC_SPI)
485 ret = snd_soc_codec_set_cache_io(codec, 16, 8,
486 cs4271->bus_type);
487 else
488 ret = snd_soc_codec_set_cache_io(codec, 8, 8,
489 cs4271->bus_type);
490 if (ret) {
491 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
492 return ret;
493 }
494
495 ret = snd_soc_update_bits(codec, CS4271_MODE2, 0,
496 CS4271_MODE2_PDN | CS4271_MODE2_CPEN);
497 if (ret < 0)
498 return ret;
499 ret = snd_soc_update_bits(codec, CS4271_MODE2, CS4271_MODE2_PDN, 0);
500 if (ret < 0)
501 return ret;
502 /* Power-up sequence requires 85 uS */
503 udelay(85);
504
505 return snd_soc_add_controls(codec, cs4271_snd_controls,
506 ARRAY_SIZE(cs4271_snd_controls));
507}
508
509static int cs4271_remove(struct snd_soc_codec *codec)
510{
511 struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
512 int gpio_nreset, gpio_disable;
513
514 gpio_nreset = cs4271->gpio_nreset;
515 gpio_disable = cs4271->gpio_disable;
516
517 if (gpio_is_valid(gpio_nreset)) {
518 /* Set codec to the reset state */
519 gpio_set_value(gpio_nreset, 0);
520 gpio_free(gpio_nreset);
521 }
522
523 if (gpio_is_valid(gpio_disable))
524 gpio_free(gpio_disable);
525
526 return 0;
527};
528
529struct snd_soc_codec_driver soc_codec_dev_cs4271 = {
530 .probe = cs4271_probe,
531 .remove = cs4271_remove,
532 .suspend = cs4271_soc_suspend,
533 .resume = cs4271_soc_resume,
534 .reg_cache_default = cs4271_dflt_reg,
535 .reg_cache_size = ARRAY_SIZE(cs4271_dflt_reg),
536 .reg_word_size = sizeof(cs4271_dflt_reg[0]),
537 .compress_type = SND_SOC_FLAT_COMPRESSION,
538};
539
540#if defined(CONFIG_SPI_MASTER)
541static int __devinit cs4271_spi_probe(struct spi_device *spi)
542{
543 struct cs4271_private *cs4271;
544
545 cs4271 = devm_kzalloc(&spi->dev, sizeof(*cs4271), GFP_KERNEL);
546 if (!cs4271)
547 return -ENOMEM;
548
549 spi_set_drvdata(spi, cs4271);
550 cs4271->control_data = spi;
551 cs4271->bus_type = SND_SOC_SPI;
552
553 return snd_soc_register_codec(&spi->dev, &soc_codec_dev_cs4271,
554 &cs4271_dai, 1);
555}
556
557static int __devexit cs4271_spi_remove(struct spi_device *spi)
558{
559 snd_soc_unregister_codec(&spi->dev);
560 return 0;
561}
562
563static struct spi_driver cs4271_spi_driver = {
564 .driver = {
565 .name = "cs4271",
566 .owner = THIS_MODULE,
567 },
568 .probe = cs4271_spi_probe,
569 .remove = __devexit_p(cs4271_spi_remove),
570};
571#endif /* defined(CONFIG_SPI_MASTER) */
572
573#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
574static struct i2c_device_id cs4271_i2c_id[] = {
575 {"cs4271", 0},
576 {}
577};
578MODULE_DEVICE_TABLE(i2c, cs4271_i2c_id);
579
580static int __devinit cs4271_i2c_probe(struct i2c_client *client,
581 const struct i2c_device_id *id)
582{
583 struct cs4271_private *cs4271;
584
585 cs4271 = devm_kzalloc(&client->dev, sizeof(*cs4271), GFP_KERNEL);
586 if (!cs4271)
587 return -ENOMEM;
588
589 i2c_set_clientdata(client, cs4271);
590 cs4271->control_data = client;
591 cs4271->bus_type = SND_SOC_I2C;
592
593 return snd_soc_register_codec(&client->dev, &soc_codec_dev_cs4271,
594 &cs4271_dai, 1);
595}
596
597static int __devexit cs4271_i2c_remove(struct i2c_client *client)
598{
599 snd_soc_unregister_codec(&client->dev);
600 return 0;
601}
602
603static struct i2c_driver cs4271_i2c_driver = {
604 .driver = {
605 .name = "cs4271",
606 .owner = THIS_MODULE,
607 },
608 .id_table = cs4271_i2c_id,
609 .probe = cs4271_i2c_probe,
610 .remove = __devexit_p(cs4271_i2c_remove),
611};
612#endif /* defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) */
613
614/*
615 * We only register our serial bus driver here without
616 * assignment to particular chip. So if any of the below
617 * fails, there is some problem with I2C or SPI subsystem.
618 * In most cases this module will be compiled with support
619 * of only one serial bus.
620 */
621static int __init cs4271_modinit(void)
622{
623 int ret;
624
625#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
626 ret = i2c_add_driver(&cs4271_i2c_driver);
627 if (ret) {
628 pr_err("Failed to register CS4271 I2C driver: %d\n", ret);
629 return ret;
630 }
631#endif
632
633#if defined(CONFIG_SPI_MASTER)
634 ret = spi_register_driver(&cs4271_spi_driver);
635 if (ret) {
636 pr_err("Failed to register CS4271 SPI driver: %d\n", ret);
637 return ret;
638 }
639#endif
640
641 return 0;
642}
643module_init(cs4271_modinit);
644
645static void __exit cs4271_modexit(void)
646{
647#if defined(CONFIG_SPI_MASTER)
648 spi_unregister_driver(&cs4271_spi_driver);
649#endif
650
651#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
652 i2c_del_driver(&cs4271_i2c_driver);
653#endif
654}
655module_exit(cs4271_modexit);
656
657MODULE_AUTHOR("Alexander Sverdlin <subaparts@yandex.ru>");
658MODULE_DESCRIPTION("Cirrus Logic CS4271 ALSA SoC Codec Driver");
659MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c
index 89498f9ad2e5..bd0517cb7980 100644
--- a/sound/soc/codecs/max98088.c
+++ b/sound/soc/codecs/max98088.c
@@ -608,7 +608,7 @@ static struct {
608 { 0xFF, 0x00, 1 }, /* FF */ 608 { 0xFF, 0x00, 1 }, /* FF */
609}; 609};
610 610
611static int max98088_volatile_register(unsigned int reg) 611static int max98088_volatile_register(struct snd_soc_codec *codec, unsigned int reg)
612{ 612{
613 return max98088_access[reg].vol; 613 return max98088_access[reg].vol;
614} 614}
diff --git a/sound/soc/codecs/sn95031.c b/sound/soc/codecs/sn95031.c
new file mode 100644
index 000000000000..593632cf791d
--- /dev/null
+++ b/sound/soc/codecs/sn95031.c
@@ -0,0 +1,495 @@
1/*
2 * sn95031.c - TI sn95031 Codec driver
3 *
4 * Copyright (C) 2010 Intel Corp
5 * Author: Vinod Koul <vinod.koul@intel.com>
6 * Author: Harsha Priya <priya.harsha@intel.com>
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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 as published by
11 * the Free Software Foundation; version 2 of the License.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
21 *
22 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23 *
24 *
25 */
26#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
27
28#include <linux/platform_device.h>
29#include <linux/slab.h>
30#include <asm/intel_scu_ipc.h>
31#include <sound/pcm.h>
32#include <sound/pcm_params.h>
33#include <sound/soc.h>
34#include <sound/soc-dapm.h>
35#include <sound/initval.h>
36#include "sn95031.h"
37
38#define SN95031_RATES (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100)
39#define SN95031_FORMATS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE)
40
41/*
42 * todo:
43 * capture paths
44 * jack detection
45 * PM functions
46 */
47
48static inline unsigned int sn95031_read(struct snd_soc_codec *codec,
49 unsigned int reg)
50{
51 u8 value = 0;
52 int ret;
53
54 ret = intel_scu_ipc_ioread8(reg, &value);
55 if (ret)
56 pr_err("read of %x failed, err %d\n", reg, ret);
57 return value;
58
59}
60
61static inline int sn95031_write(struct snd_soc_codec *codec,
62 unsigned int reg, unsigned int value)
63{
64 int ret;
65
66 ret = intel_scu_ipc_iowrite8(reg, value);
67 if (ret)
68 pr_err("write of %x failed, err %d\n", reg, ret);
69 return ret;
70}
71
72static int sn95031_set_vaud_bias(struct snd_soc_codec *codec,
73 enum snd_soc_bias_level level)
74{
75 switch (level) {
76 case SND_SOC_BIAS_ON:
77 break;
78
79 case SND_SOC_BIAS_PREPARE:
80 if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) {
81 pr_debug("vaud_bias powering up pll\n");
82 /* power up the pll */
83 snd_soc_write(codec, SN95031_AUDPLLCTRL, BIT(5));
84 /* enable pcm 2 */
85 snd_soc_update_bits(codec, SN95031_PCM2C2,
86 BIT(0), BIT(0));
87 }
88 break;
89
90 case SND_SOC_BIAS_STANDBY:
91 if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
92 pr_debug("vaud_bias power up rail\n");
93 /* power up the rail */
94 snd_soc_write(codec, SN95031_VAUD,
95 BIT(2)|BIT(1)|BIT(0));
96 msleep(1);
97 } else if (codec->dapm.bias_level == SND_SOC_BIAS_PREPARE) {
98 /* turn off pcm */
99 pr_debug("vaud_bias power dn pcm\n");
100 snd_soc_update_bits(codec, SN95031_PCM2C2, BIT(0), 0);
101 snd_soc_write(codec, SN95031_AUDPLLCTRL, 0);
102 }
103 break;
104
105
106 case SND_SOC_BIAS_OFF:
107 pr_debug("vaud_bias _OFF doing rail shutdown\n");
108 snd_soc_write(codec, SN95031_VAUD, BIT(3));
109 break;
110 }
111
112 codec->dapm.bias_level = level;
113 return 0;
114}
115
116static int sn95031_vhs_event(struct snd_soc_dapm_widget *w,
117 struct snd_kcontrol *kcontrol, int event)
118{
119 if (SND_SOC_DAPM_EVENT_ON(event)) {
120 pr_debug("VHS SND_SOC_DAPM_EVENT_ON doing rail startup now\n");
121 /* power up the rail */
122 snd_soc_write(w->codec, SN95031_VHSP, 0x3D);
123 snd_soc_write(w->codec, SN95031_VHSN, 0x3F);
124 msleep(1);
125 } else if (SND_SOC_DAPM_EVENT_OFF(event)) {
126 pr_debug("VHS SND_SOC_DAPM_EVENT_OFF doing rail shutdown\n");
127 snd_soc_write(w->codec, SN95031_VHSP, 0xC4);
128 snd_soc_write(w->codec, SN95031_VHSN, 0x04);
129 }
130 return 0;
131}
132
133static int sn95031_vihf_event(struct snd_soc_dapm_widget *w,
134 struct snd_kcontrol *kcontrol, int event)
135{
136 if (SND_SOC_DAPM_EVENT_ON(event)) {
137 pr_debug("VIHF SND_SOC_DAPM_EVENT_ON doing rail startup now\n");
138 /* power up the rail */
139 snd_soc_write(w->codec, SN95031_VIHF, 0x27);
140 msleep(1);
141 } else if (SND_SOC_DAPM_EVENT_OFF(event)) {
142 pr_debug("VIHF SND_SOC_DAPM_EVENT_OFF doing rail shutdown\n");
143 snd_soc_write(w->codec, SN95031_VIHF, 0x24);
144 }
145 return 0;
146}
147
148/* DAPM widgets */
149static const struct snd_soc_dapm_widget sn95031_dapm_widgets[] = {
150
151 /* all end points mic, hs etc */
152 SND_SOC_DAPM_OUTPUT("HPOUTL"),
153 SND_SOC_DAPM_OUTPUT("HPOUTR"),
154 SND_SOC_DAPM_OUTPUT("EPOUT"),
155 SND_SOC_DAPM_OUTPUT("IHFOUTL"),
156 SND_SOC_DAPM_OUTPUT("IHFOUTR"),
157 SND_SOC_DAPM_OUTPUT("LINEOUTL"),
158 SND_SOC_DAPM_OUTPUT("LINEOUTR"),
159 SND_SOC_DAPM_OUTPUT("VIB1OUT"),
160 SND_SOC_DAPM_OUTPUT("VIB2OUT"),
161
162 SND_SOC_DAPM_SUPPLY("Headset Rail", SND_SOC_NOPM, 0, 0,
163 sn95031_vhs_event,
164 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
165 SND_SOC_DAPM_SUPPLY("Speaker Rail", SND_SOC_NOPM, 0, 0,
166 sn95031_vihf_event,
167 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
168
169 /* playback path driver enables */
170 SND_SOC_DAPM_PGA("Headset Left Playback",
171 SN95031_DRIVEREN, 0, 0, NULL, 0),
172 SND_SOC_DAPM_PGA("Headset Right Playback",
173 SN95031_DRIVEREN, 1, 0, NULL, 0),
174 SND_SOC_DAPM_PGA("Speaker Left Playback",
175 SN95031_DRIVEREN, 2, 0, NULL, 0),
176 SND_SOC_DAPM_PGA("Speaker Right Playback",
177 SN95031_DRIVEREN, 3, 0, NULL, 0),
178 SND_SOC_DAPM_PGA("Vibra1 Playback",
179 SN95031_DRIVEREN, 4, 0, NULL, 0),
180 SND_SOC_DAPM_PGA("Vibra2 Playback",
181 SN95031_DRIVEREN, 5, 0, NULL, 0),
182 SND_SOC_DAPM_PGA("Earpiece Playback",
183 SN95031_DRIVEREN, 6, 0, NULL, 0),
184 SND_SOC_DAPM_PGA("Lineout Left Playback",
185 SN95031_LOCTL, 0, 0, NULL, 0),
186 SND_SOC_DAPM_PGA("Lineout Right Playback",
187 SN95031_LOCTL, 4, 0, NULL, 0),
188
189 /* playback path filter enable */
190 SND_SOC_DAPM_PGA("Headset Left Filter",
191 SN95031_HSEPRXCTRL, 4, 0, NULL, 0),
192 SND_SOC_DAPM_PGA("Headset Right Filter",
193 SN95031_HSEPRXCTRL, 5, 0, NULL, 0),
194 SND_SOC_DAPM_PGA("Speaker Left Filter",
195 SN95031_IHFRXCTRL, 0, 0, NULL, 0),
196 SND_SOC_DAPM_PGA("Speaker Right Filter",
197 SN95031_IHFRXCTRL, 1, 0, NULL, 0),
198
199 /* DACs */
200 SND_SOC_DAPM_DAC("HSDAC Left", "Headset",
201 SN95031_DACCONFIG, 0, 0),
202 SND_SOC_DAPM_DAC("HSDAC Right", "Headset",
203 SN95031_DACCONFIG, 1, 0),
204 SND_SOC_DAPM_DAC("IHFDAC Left", "Speaker",
205 SN95031_DACCONFIG, 2, 0),
206 SND_SOC_DAPM_DAC("IHFDAC Right", "Speaker",
207 SN95031_DACCONFIG, 3, 0),
208 SND_SOC_DAPM_DAC("Vibra1 DAC", "Vibra1",
209 SN95031_VIB1C5, 1, 0),
210 SND_SOC_DAPM_DAC("Vibra2 DAC", "Vibra2",
211 SN95031_VIB2C5, 1, 0),
212};
213
214static const struct snd_soc_dapm_route sn95031_audio_map[] = {
215 /* headset and earpiece map */
216 { "HPOUTL", NULL, "Headset Left Playback" },
217 { "HPOUTR", NULL, "Headset Right Playback" },
218 { "EPOUT", NULL, "Earpiece Playback" },
219 { "Headset Left Playback", NULL, "Headset Left Filter"},
220 { "Headset Right Playback", NULL, "Headset Right Filter"},
221 { "Earpiece Playback", NULL, "Headset Left Filter"},
222 { "Headset Left Filter", NULL, "HSDAC Left"},
223 { "Headset Right Filter", NULL, "HSDAC Right"},
224 { "HSDAC Left", NULL, "Headset Rail"},
225 { "HSDAC Right", NULL, "Headset Rail"},
226
227 /* speaker map */
228 { "IHFOUTL", "NULL", "Speaker Left Playback"},
229 { "IHFOUTR", "NULL", "Speaker Right Playback"},
230 { "Speaker Left Playback", NULL, "Speaker Left Filter"},
231 { "Speaker Right Playback", NULL, "Speaker Right Filter"},
232 { "Speaker Left Filter", NULL, "IHFDAC Left"},
233 { "Speaker Right Filter", NULL, "IHFDAC Right"},
234 { "IHFDAC Left", NULL, "Speaker Rail"},
235 { "IHFDAC Right", NULL, "Speaker Rail"},
236
237 /* vibra map */
238 { "VIB1OUT", NULL, "Vibra1 Playback"},
239 { "Vibra1 Playback", NULL, "Vibra1 DAC"},
240
241 { "VIB2OUT", NULL, "Vibra2 Playback"},
242 { "Vibra2 Playback", NULL, "Vibra2 DAC"},
243
244 /* lineout */
245 { "LINEOUTL", NULL, "Lineout Left Playback"},
246 { "LINEOUTR", NULL, "Lineout Right Playback"},
247 { "Lineout Left Playback", NULL, "Headset Left Filter"},
248 { "Lineout Left Playback", NULL, "Speaker Left Filter"},
249 { "Lineout Left Playback", NULL, "Vibra1 DAC"},
250 { "Lineout Right Playback", NULL, "Headset Right Filter"},
251 { "Lineout Right Playback", NULL, "Speaker Right Filter"},
252 { "Lineout Right Playback", NULL, "Vibra2 DAC"},
253};
254
255/* speaker and headset mutes, for audio pops and clicks */
256static int sn95031_pcm_hs_mute(struct snd_soc_dai *dai, int mute)
257{
258 snd_soc_update_bits(dai->codec,
259 SN95031_HSLVOLCTRL, BIT(7), (!mute << 7));
260 snd_soc_update_bits(dai->codec,
261 SN95031_HSRVOLCTRL, BIT(7), (!mute << 7));
262 return 0;
263}
264
265static int sn95031_pcm_spkr_mute(struct snd_soc_dai *dai, int mute)
266{
267 snd_soc_update_bits(dai->codec,
268 SN95031_IHFLVOLCTRL, BIT(7), (!mute << 7));
269 snd_soc_update_bits(dai->codec,
270 SN95031_IHFRVOLCTRL, BIT(7), (!mute << 7));
271 return 0;
272}
273
274int sn95031_pcm_hw_params(struct snd_pcm_substream *substream,
275 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
276{
277 unsigned int format, rate;
278
279 switch (params_format(params)) {
280 case SNDRV_PCM_FORMAT_S16_LE:
281 format = BIT(4)|BIT(5);
282 break;
283
284 case SNDRV_PCM_FORMAT_S24_LE:
285 format = 0;
286 break;
287 default:
288 return -EINVAL;
289 }
290 snd_soc_update_bits(dai->codec, SN95031_PCM2C2,
291 BIT(4)|BIT(5), format);
292
293 switch (params_rate(params)) {
294 case 48000:
295 pr_debug("RATE_48000\n");
296 rate = 0;
297 break;
298
299 case 44100:
300 pr_debug("RATE_44100\n");
301 rate = BIT(7);
302 break;
303
304 default:
305 pr_err("ERR rate %d\n", params_rate(params));
306 return -EINVAL;
307 }
308 snd_soc_update_bits(dai->codec, SN95031_PCM1C1, BIT(7), rate);
309
310 return 0;
311}
312
313/* Codec DAI section */
314static struct snd_soc_dai_ops sn95031_headset_dai_ops = {
315 .digital_mute = sn95031_pcm_hs_mute,
316 .hw_params = sn95031_pcm_hw_params,
317};
318
319static struct snd_soc_dai_ops sn95031_speaker_dai_ops = {
320 .digital_mute = sn95031_pcm_spkr_mute,
321 .hw_params = sn95031_pcm_hw_params,
322};
323
324static struct snd_soc_dai_ops sn95031_vib1_dai_ops = {
325 .hw_params = sn95031_pcm_hw_params,
326};
327
328static struct snd_soc_dai_ops sn95031_vib2_dai_ops = {
329 .hw_params = sn95031_pcm_hw_params,
330};
331
332struct snd_soc_dai_driver sn95031_dais[] = {
333{
334 .name = "SN95031 Headset",
335 .playback = {
336 .stream_name = "Headset",
337 .channels_min = 2,
338 .channels_max = 2,
339 .rates = SN95031_RATES,
340 .formats = SN95031_FORMATS,
341 },
342 .ops = &sn95031_headset_dai_ops,
343},
344{ .name = "SN95031 Speaker",
345 .playback = {
346 .stream_name = "Speaker",
347 .channels_min = 2,
348 .channels_max = 2,
349 .rates = SN95031_RATES,
350 .formats = SN95031_FORMATS,
351 },
352 .ops = &sn95031_speaker_dai_ops,
353},
354{ .name = "SN95031 Vibra1",
355 .playback = {
356 .stream_name = "Vibra1",
357 .channels_min = 1,
358 .channels_max = 1,
359 .rates = SN95031_RATES,
360 .formats = SN95031_FORMATS,
361 },
362 .ops = &sn95031_vib1_dai_ops,
363},
364{ .name = "SN95031 Vibra2",
365 .playback = {
366 .stream_name = "Vibra2",
367 .channels_min = 1,
368 .channels_max = 1,
369 .rates = SN95031_RATES,
370 .formats = SN95031_FORMATS,
371 },
372 .ops = &sn95031_vib2_dai_ops,
373},
374};
375
376/* codec registration */
377static int sn95031_codec_probe(struct snd_soc_codec *codec)
378{
379 int ret;
380
381 pr_debug("codec_probe called\n");
382
383 codec->dapm.bias_level = SND_SOC_BIAS_OFF;
384 codec->dapm.idle_bias_off = 1;
385
386 /* PCM interface config
387 * This sets the pcm rx slot conguration to max 6 slots
388 * for max 4 dais (2 stereo and 2 mono)
389 */
390 snd_soc_write(codec, SN95031_PCM2RXSLOT01, 0x10);
391 snd_soc_write(codec, SN95031_PCM2RXSLOT23, 0x32);
392 snd_soc_write(codec, SN95031_PCM2RXSLOT45, 0x54);
393 /* pcm port setting
394 * This sets the pcm port to slave and clock at 19.2Mhz which
395 * can support 6slots, sampling rate set per stream in hw-params
396 */
397 snd_soc_write(codec, SN95031_PCM1C1, 0x00);
398 snd_soc_write(codec, SN95031_PCM2C1, 0x01);
399 snd_soc_write(codec, SN95031_PCM2C2, 0x0A);
400 snd_soc_write(codec, SN95031_HSMIXER, BIT(0)|BIT(4));
401 /* vendor vibra workround, the vibras are muted by
402 * custom register so unmute them
403 */
404 snd_soc_write(codec, SN95031_SSR5, 0x80);
405 snd_soc_write(codec, SN95031_SSR6, 0x80);
406 snd_soc_write(codec, SN95031_VIB1C5, 0x00);
407 snd_soc_write(codec, SN95031_VIB2C5, 0x00);
408 /* configure vibras for pcm port */
409 snd_soc_write(codec, SN95031_VIB1C3, 0x00);
410 snd_soc_write(codec, SN95031_VIB2C3, 0x00);
411
412 /* soft mute ramp time */
413 snd_soc_write(codec, SN95031_SOFTMUTE, 0x3);
414 /* fix the initial volume at 1dB,
415 * default in +9dB,
416 * 1dB give optimal swing on DAC, amps
417 */
418 snd_soc_write(codec, SN95031_HSLVOLCTRL, 0x08);
419 snd_soc_write(codec, SN95031_HSRVOLCTRL, 0x08);
420 snd_soc_write(codec, SN95031_IHFLVOLCTRL, 0x08);
421 snd_soc_write(codec, SN95031_IHFRVOLCTRL, 0x08);
422 /* dac mode and lineout workaround */
423 snd_soc_write(codec, SN95031_SSR2, 0x10);
424 snd_soc_write(codec, SN95031_SSR3, 0x40);
425
426 ret = snd_soc_dapm_new_controls(&codec->dapm, sn95031_dapm_widgets,
427 ARRAY_SIZE(sn95031_dapm_widgets));
428 if (ret)
429 pr_err("soc_dapm_new_control failed %d", ret);
430 ret = snd_soc_dapm_add_routes(&codec->dapm, sn95031_audio_map,
431 ARRAY_SIZE(sn95031_audio_map));
432 if (ret)
433 pr_err("soc_dapm_add_routes failed %d", ret);
434
435 return ret;
436}
437
438static int sn95031_codec_remove(struct snd_soc_codec *codec)
439{
440 pr_debug("codec_remove called\n");
441 sn95031_set_vaud_bias(codec, SND_SOC_BIAS_OFF);
442
443 return 0;
444}
445
446struct snd_soc_codec_driver sn95031_codec = {
447 .probe = sn95031_codec_probe,
448 .remove = sn95031_codec_remove,
449 .read = sn95031_read,
450 .write = sn95031_write,
451 .set_bias_level = sn95031_set_vaud_bias,
452};
453
454static int __devinit sn95031_device_probe(struct platform_device *pdev)
455{
456 pr_debug("codec device probe called for %s\n", dev_name(&pdev->dev));
457 return snd_soc_register_codec(&pdev->dev, &sn95031_codec,
458 sn95031_dais, ARRAY_SIZE(sn95031_dais));
459}
460
461static int __devexit sn95031_device_remove(struct platform_device *pdev)
462{
463 pr_debug("codec device remove called\n");
464 snd_soc_unregister_codec(&pdev->dev);
465 return 0;
466}
467
468static struct platform_driver sn95031_codec_driver = {
469 .driver = {
470 .name = "sn95031",
471 .owner = THIS_MODULE,
472 },
473 .probe = sn95031_device_probe,
474 .remove = sn95031_device_remove,
475};
476
477static int __init sn95031_init(void)
478{
479 pr_debug("driver init called\n");
480 return platform_driver_register(&sn95031_codec_driver);
481}
482module_init(sn95031_init);
483
484static void __exit sn95031_exit(void)
485{
486 pr_debug("driver exit called\n");
487 platform_driver_unregister(&sn95031_codec_driver);
488}
489module_exit(sn95031_exit);
490
491MODULE_DESCRIPTION("ASoC TI SN95031 codec driver");
492MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
493MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>");
494MODULE_LICENSE("GPL v2");
495MODULE_ALIAS("platform:sn95031");
diff --git a/sound/soc/codecs/sn95031.h b/sound/soc/codecs/sn95031.h
new file mode 100644
index 000000000000..e2b17d908aeb
--- /dev/null
+++ b/sound/soc/codecs/sn95031.h
@@ -0,0 +1,99 @@
1/*
2 * sn95031.h - TI sn95031 Codec driver
3 *
4 * Copyright (C) 2010 Intel Corp
5 * Author: Vinod Koul <vinod.koul@intel.com>
6 * Author: Harsha Priya <priya.harsha@intel.com>
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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 as published by
11 * the Free Software Foundation; version 2 of the License.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
21 *
22 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23 *
24 *
25 */
26#ifndef _SN95031_H
27#define _SN95031_H
28
29/*register map*/
30#define SN95031_VAUD 0xDB
31#define SN95031_VHSP 0xDC
32#define SN95031_VHSN 0xDD
33#define SN95031_VIHF 0xC9
34
35#define SN95031_AUDPLLCTRL 0x240
36#define SN95031_DMICBUF0123 0x241
37#define SN95031_DMICBUF45 0x242
38#define SN95031_DMICGPO 0x244
39#define SN95031_DMICMUX 0x245
40#define SN95031_DMICLK 0x246
41#define SN95031_MICBIAS 0x247
42#define SN95031_ADCCONFIG 0x248
43#define SN95031_MICAMP1 0x249
44#define SN95031_MICAMP2 0x24A
45#define SN95031_NOISEMUX 0x24B
46#define SN95031_AUDIOMUX12 0x24C
47#define SN95031_AUDIOMUX34 0x24D
48#define SN95031_AUDIOSINC 0x24E
49#define SN95031_AUDIOTXEN 0x24F
50#define SN95031_HSEPRXCTRL 0x250
51#define SN95031_IHFRXCTRL 0x251
52#define SN95031_HSMIXER 0x256
53#define SN95031_DACCONFIG 0x257
54#define SN95031_SOFTMUTE 0x258
55#define SN95031_HSLVOLCTRL 0x259
56#define SN95031_HSRVOLCTRL 0x25A
57#define SN95031_IHFLVOLCTRL 0x25B
58#define SN95031_IHFRVOLCTRL 0x25C
59#define SN95031_DRIVEREN 0x25D
60#define SN95031_LOCTL 0x25E
61#define SN95031_VIB1C1 0x25F
62#define SN95031_VIB1C2 0x260
63#define SN95031_VIB1C3 0x261
64#define SN95031_VIB1SPIPCM1 0x262
65#define SN95031_VIB1SPIPCM2 0x263
66#define SN95031_VIB1C5 0x264
67#define SN95031_VIB2C1 0x265
68#define SN95031_VIB2C2 0x266
69#define SN95031_VIB2C3 0x267
70#define SN95031_VIB2SPIPCM1 0x268
71#define SN95031_VIB2SPIPCM2 0x269
72#define SN95031_VIB2C5 0x26A
73#define SN95031_BTNCTRL1 0x26B
74#define SN95031_BTNCTRL2 0x26C
75#define SN95031_PCM1TXSLOT01 0x26D
76#define SN95031_PCM1TXSLOT23 0x26E
77#define SN95031_PCM1TXSLOT45 0x26F
78#define SN95031_PCM1RXSLOT0_3 0x270
79#define SN95031_PCM1RXSLOT45 0x271
80#define SN95031_PCM2TXSLOT01 0x272
81#define SN95031_PCM2TXSLOT23 0x273
82#define SN95031_PCM2TXSLOT45 0x274
83#define SN95031_PCM2RXSLOT01 0x275
84#define SN95031_PCM2RXSLOT23 0x276
85#define SN95031_PCM2RXSLOT45 0x277
86#define SN95031_PCM1C1 0x278
87#define SN95031_PCM1C2 0x279
88#define SN95031_PCM1C3 0x27A
89#define SN95031_PCM2C1 0x27B
90#define SN95031_PCM2C2 0x27C
91/*end codec register defn*/
92
93/*vendor defn these are not part of avp*/
94#define SN95031_SSR2 0x381
95#define SN95031_SSR3 0x382
96#define SN95031_SSR5 0x384
97#define SN95031_SSR6 0x385
98
99#endif
diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c
index 5eb2f501ce32..4fd4d8dca0fc 100644
--- a/sound/soc/codecs/wm8523.c
+++ b/sound/soc/codecs/wm8523.c
@@ -58,7 +58,7 @@ static const u16 wm8523_reg[WM8523_REGISTER_COUNT] = {
58 0x0000, /* R8 - ZERO_DETECT */ 58 0x0000, /* R8 - ZERO_DETECT */
59}; 59};
60 60
61static int wm8523_volatile_register(unsigned int reg) 61static int wm8523_volatile_register(struct snd_soc_codec *codec, unsigned int reg)
62{ 62{
63 switch (reg) { 63 switch (reg) {
64 case WM8523_DEVICE_ID: 64 case WM8523_DEVICE_ID:
@@ -414,7 +414,6 @@ static int wm8523_resume(struct snd_soc_codec *codec)
414static int wm8523_probe(struct snd_soc_codec *codec) 414static int wm8523_probe(struct snd_soc_codec *codec)
415{ 415{
416 struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); 416 struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec);
417 u16 *reg_cache = codec->reg_cache;
418 int ret, i; 417 int ret, i;
419 418
420 codec->hw_write = (hw_write_t)i2c_master_send; 419 codec->hw_write = (hw_write_t)i2c_master_send;
@@ -471,8 +470,9 @@ static int wm8523_probe(struct snd_soc_codec *codec)
471 } 470 }
472 471
473 /* Change some default settings - latch VU and enable ZC */ 472 /* Change some default settings - latch VU and enable ZC */
474 reg_cache[WM8523_DAC_GAINR] |= WM8523_DACR_VU; 473 snd_soc_update_bits(codec, WM8523_DAC_GAINR,
475 reg_cache[WM8523_DAC_CTRL3] |= WM8523_ZC; 474 WM8523_DACR_VU, WM8523_DACR_VU);
475 snd_soc_update_bits(codec, WM8523_DAC_CTRL3, WM8523_ZC, WM8523_ZC);
476 476
477 wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 477 wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
478 478
diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c
index 494f2d31d75b..25af901fe813 100644
--- a/sound/soc/codecs/wm8741.c
+++ b/sound/soc/codecs/wm8741.c
@@ -421,7 +421,6 @@ static int wm8741_resume(struct snd_soc_codec *codec)
421static int wm8741_probe(struct snd_soc_codec *codec) 421static int wm8741_probe(struct snd_soc_codec *codec)
422{ 422{
423 struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); 423 struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec);
424 u16 *reg_cache = codec->reg_cache;
425 int ret = 0; 424 int ret = 0;
426 425
427 ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8741->control_type); 426 ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8741->control_type);
@@ -437,10 +436,14 @@ static int wm8741_probe(struct snd_soc_codec *codec)
437 } 436 }
438 437
439 /* Change some default settings - latch VU */ 438 /* Change some default settings - latch VU */
440 reg_cache[WM8741_DACLLSB_ATTENUATION] |= WM8741_UPDATELL; 439 snd_soc_update_bits(codec, WM8741_DACLLSB_ATTENUATION,
441 reg_cache[WM8741_DACLMSB_ATTENUATION] |= WM8741_UPDATELM; 440 WM8741_UPDATELL, WM8741_UPDATELL);
442 reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERL; 441 snd_soc_update_bits(codec, WM8741_DACLMSB_ATTENUATION,
443 reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERM; 442 WM8741_UPDATELM, WM8741_UPDATELM);
443 snd_soc_update_bits(codec, WM8741_DACRLSB_ATTENUATION,
444 WM8741_UPDATERL, WM8741_UPDATERL);
445 snd_soc_update_bits(codec, WM8741_DACRLSB_ATTENUATION,
446 WM8741_UPDATERM, WM8741_UPDATERM);
444 447
445 snd_soc_add_controls(codec, wm8741_snd_controls, 448 snd_soc_add_controls(codec, wm8741_snd_controls,
446 ARRAY_SIZE(wm8741_snd_controls)); 449 ARRAY_SIZE(wm8741_snd_controls));
diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c
index 6dae1b40c9f7..6785688f8806 100644
--- a/sound/soc/codecs/wm8804.c
+++ b/sound/soc/codecs/wm8804.c
@@ -175,7 +175,7 @@ static int txsrc_put(struct snd_kcontrol *kcontrol,
175 return 0; 175 return 0;
176} 176}
177 177
178static int wm8804_volatile(unsigned int reg) 178static int wm8804_volatile(struct snd_soc_codec *codec, unsigned int reg)
179{ 179{
180 switch (reg) { 180 switch (reg) {
181 case WM8804_RST_DEVID1: 181 case WM8804_RST_DEVID1:
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c
index cd0959926d12..449ea09a193d 100644
--- a/sound/soc/codecs/wm8900.c
+++ b/sound/soc/codecs/wm8900.c
@@ -180,7 +180,7 @@ static const u16 wm8900_reg_defaults[WM8900_MAXREG] = {
180 /* Remaining registers all zero */ 180 /* Remaining registers all zero */
181}; 181};
182 182
183static int wm8900_volatile_register(unsigned int reg) 183static int wm8900_volatile_register(struct snd_soc_codec *codec, unsigned int reg)
184{ 184{
185 switch (reg) { 185 switch (reg) {
186 case WM8900_REG_ID: 186 case WM8900_REG_ID:
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index 987476a5895f..9c4f2c4febc2 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -2,6 +2,7 @@
2 * wm8903.c -- WM8903 ALSA SoC Audio driver 2 * wm8903.c -- WM8903 ALSA SoC Audio driver
3 * 3 *
4 * Copyright 2008 Wolfson Microelectronics 4 * Copyright 2008 Wolfson Microelectronics
5 * Copyright 2011 NVIDIA, Inc.
5 * 6 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> 7 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 * 8 *
@@ -19,6 +20,7 @@
19#include <linux/init.h> 20#include <linux/init.h>
20#include <linux/completion.h> 21#include <linux/completion.h>
21#include <linux/delay.h> 22#include <linux/delay.h>
23#include <linux/gpio.h>
22#include <linux/pm.h> 24#include <linux/pm.h>
23#include <linux/i2c.h> 25#include <linux/i2c.h>
24#include <linux/platform_device.h> 26#include <linux/platform_device.h>
@@ -213,6 +215,7 @@ static u16 wm8903_reg_defaults[] = {
213}; 215};
214 216
215struct wm8903_priv { 217struct wm8903_priv {
218 struct snd_soc_codec *codec;
216 219
217 int sysclk; 220 int sysclk;
218 int irq; 221 int irq;
@@ -230,9 +233,13 @@ struct wm8903_priv {
230 int mic_short; 233 int mic_short;
231 int mic_last_report; 234 int mic_last_report;
232 int mic_delay; 235 int mic_delay;
236
237#ifdef CONFIG_GPIOLIB
238 struct gpio_chip gpio_chip;
239#endif
233}; 240};
234 241
235static int wm8903_volatile_register(unsigned int reg) 242static int wm8903_volatile_register(struct snd_soc_codec *codec, unsigned int reg)
236{ 243{
237 switch (reg) { 244 switch (reg) {
238 case WM8903_SW_RESET_AND_ID: 245 case WM8903_SW_RESET_AND_ID:
@@ -1635,6 +1642,119 @@ static int wm8903_resume(struct snd_soc_codec *codec)
1635 return 0; 1642 return 0;
1636} 1643}
1637 1644
1645#ifdef CONFIG_GPIOLIB
1646static inline struct wm8903_priv *gpio_to_wm8903(struct gpio_chip *chip)
1647{
1648 return container_of(chip, struct wm8903_priv, gpio_chip);
1649}
1650
1651static int wm8903_gpio_request(struct gpio_chip *chip, unsigned offset)
1652{
1653 if (offset >= WM8903_NUM_GPIO)
1654 return -EINVAL;
1655
1656 return 0;
1657}
1658
1659static int wm8903_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
1660{
1661 struct wm8903_priv *wm8903 = gpio_to_wm8903(chip);
1662 struct snd_soc_codec *codec = wm8903->codec;
1663 unsigned int mask, val;
1664
1665 mask = WM8903_GP1_FN_MASK | WM8903_GP1_DIR_MASK;
1666 val = (WM8903_GPn_FN_GPIO_INPUT << WM8903_GP1_FN_SHIFT) |
1667 WM8903_GP1_DIR;
1668
1669 return snd_soc_update_bits(codec, WM8903_GPIO_CONTROL_1 + offset,
1670 mask, val);
1671}
1672
1673static int wm8903_gpio_get(struct gpio_chip *chip, unsigned offset)
1674{
1675 struct wm8903_priv *wm8903 = gpio_to_wm8903(chip);
1676 struct snd_soc_codec *codec = wm8903->codec;
1677 int reg;
1678
1679 reg = snd_soc_read(codec, WM8903_GPIO_CONTROL_1 + offset);
1680
1681 return (reg & WM8903_GP1_LVL_MASK) >> WM8903_GP1_LVL_SHIFT;
1682}
1683
1684static int wm8903_gpio_direction_out(struct gpio_chip *chip,
1685 unsigned offset, int value)
1686{
1687 struct wm8903_priv *wm8903 = gpio_to_wm8903(chip);
1688 struct snd_soc_codec *codec = wm8903->codec;
1689 unsigned int mask, val;
1690
1691 mask = WM8903_GP1_FN_MASK | WM8903_GP1_DIR_MASK | WM8903_GP1_LVL_MASK;
1692 val = (WM8903_GPn_FN_GPIO_OUTPUT << WM8903_GP1_FN_SHIFT) |
1693 (value << WM8903_GP2_LVL_SHIFT);
1694
1695 return snd_soc_update_bits(codec, WM8903_GPIO_CONTROL_1 + offset,
1696 mask, val);
1697}
1698
1699static void wm8903_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
1700{
1701 struct wm8903_priv *wm8903 = gpio_to_wm8903(chip);
1702 struct snd_soc_codec *codec = wm8903->codec;
1703
1704 snd_soc_update_bits(codec, WM8903_GPIO_CONTROL_1 + offset,
1705 WM8903_GP1_LVL_MASK, value << WM8903_GP1_LVL_SHIFT);
1706}
1707
1708static struct gpio_chip wm8903_template_chip = {
1709 .label = "wm8903",
1710 .owner = THIS_MODULE,
1711 .request = wm8903_gpio_request,
1712 .direction_input = wm8903_gpio_direction_in,
1713 .get = wm8903_gpio_get,
1714 .direction_output = wm8903_gpio_direction_out,
1715 .set = wm8903_gpio_set,
1716 .can_sleep = 1,
1717};
1718
1719static void wm8903_init_gpio(struct snd_soc_codec *codec)
1720{
1721 struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
1722 struct wm8903_platform_data *pdata = dev_get_platdata(codec->dev);
1723 int ret;
1724
1725 wm8903->gpio_chip = wm8903_template_chip;
1726 wm8903->gpio_chip.ngpio = WM8903_NUM_GPIO;
1727 wm8903->gpio_chip.dev = codec->dev;
1728
1729 if (pdata && pdata->gpio_base)
1730 wm8903->gpio_chip.base = pdata->gpio_base;
1731 else
1732 wm8903->gpio_chip.base = -1;
1733
1734 ret = gpiochip_add(&wm8903->gpio_chip);
1735 if (ret != 0)
1736 dev_err(codec->dev, "Failed to add GPIOs: %d\n", ret);
1737}
1738
1739static void wm8903_free_gpio(struct snd_soc_codec *codec)
1740{
1741 struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
1742 int ret;
1743
1744 ret = gpiochip_remove(&wm8903->gpio_chip);
1745 if (ret != 0)
1746 dev_err(codec->dev, "Failed to remove GPIOs: %d\n", ret);
1747}
1748#else
1749static void wm8903_init_gpio(struct snd_soc_codec *codec)
1750{
1751}
1752
1753static void wm8903_free_gpio(struct snd_soc_codec *codec)
1754{
1755}
1756#endif
1757
1638static int wm8903_probe(struct snd_soc_codec *codec) 1758static int wm8903_probe(struct snd_soc_codec *codec)
1639{ 1759{
1640 struct wm8903_platform_data *pdata = dev_get_platdata(codec->dev); 1760 struct wm8903_platform_data *pdata = dev_get_platdata(codec->dev);
@@ -1643,6 +1763,7 @@ static int wm8903_probe(struct snd_soc_codec *codec)
1643 int trigger, irq_pol; 1763 int trigger, irq_pol;
1644 u16 val; 1764 u16 val;
1645 1765
1766 wm8903->codec = codec;
1646 init_completion(&wm8903->wseq); 1767 init_completion(&wm8903->wseq);
1647 1768
1648 ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); 1769 ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
@@ -1667,7 +1788,7 @@ static int wm8903_probe(struct snd_soc_codec *codec)
1667 /* Set up GPIOs and microphone detection */ 1788 /* Set up GPIOs and microphone detection */
1668 if (pdata) { 1789 if (pdata) {
1669 for (i = 0; i < ARRAY_SIZE(pdata->gpio_cfg); i++) { 1790 for (i = 0; i < ARRAY_SIZE(pdata->gpio_cfg); i++) {
1670 if (!pdata->gpio_cfg[i]) 1791 if (pdata->gpio_cfg[i] == WM8903_GPIO_NO_CONFIG)
1671 continue; 1792 continue;
1672 1793
1673 snd_soc_write(codec, WM8903_GPIO_CONTROL_1 + i, 1794 snd_soc_write(codec, WM8903_GPIO_CONTROL_1 + i,
@@ -1749,12 +1870,15 @@ static int wm8903_probe(struct snd_soc_codec *codec)
1749 ARRAY_SIZE(wm8903_snd_controls)); 1870 ARRAY_SIZE(wm8903_snd_controls));
1750 wm8903_add_widgets(codec); 1871 wm8903_add_widgets(codec);
1751 1872
1873 wm8903_init_gpio(codec);
1874
1752 return ret; 1875 return ret;
1753} 1876}
1754 1877
1755/* power down chip */ 1878/* power down chip */
1756static int wm8903_remove(struct snd_soc_codec *codec) 1879static int wm8903_remove(struct snd_soc_codec *codec)
1757{ 1880{
1881 wm8903_free_gpio(codec);
1758 wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); 1882 wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF);
1759 return 0; 1883 return 0;
1760} 1884}
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
index 9de44a4c05c0..443ae580445c 100644
--- a/sound/soc/codecs/wm8904.c
+++ b/sound/soc/codecs/wm8904.c
@@ -596,7 +596,7 @@ static struct {
596 { 0x003F, 0x003F, 0 }, /* R248 - FLL NCO Test 1 */ 596 { 0x003F, 0x003F, 0 }, /* R248 - FLL NCO Test 1 */
597}; 597};
598 598
599static int wm8904_volatile_register(unsigned int reg) 599static int wm8904_volatile_register(struct snd_soc_codec *codec, unsigned int reg)
600{ 600{
601 return wm8904_access[reg].vol; 601 return wm8904_access[reg].vol;
602} 602}
@@ -2436,19 +2436,28 @@ static int wm8904_probe(struct snd_soc_codec *codec)
2436 } 2436 }
2437 2437
2438 /* Change some default settings - latch VU and enable ZC */ 2438 /* Change some default settings - latch VU and enable ZC */
2439 reg_cache[WM8904_ADC_DIGITAL_VOLUME_LEFT] |= WM8904_ADC_VU; 2439 snd_soc_update_bits(codec, WM8904_ADC_DIGITAL_VOLUME_LEFT,
2440 reg_cache[WM8904_ADC_DIGITAL_VOLUME_RIGHT] |= WM8904_ADC_VU; 2440 WM8904_ADC_VU, WM8904_ADC_VU);
2441 reg_cache[WM8904_DAC_DIGITAL_VOLUME_LEFT] |= WM8904_DAC_VU; 2441 snd_soc_update_bits(codec, WM8904_ADC_DIGITAL_VOLUME_RIGHT,
2442 reg_cache[WM8904_DAC_DIGITAL_VOLUME_RIGHT] |= WM8904_DAC_VU; 2442 WM8904_ADC_VU, WM8904_ADC_VU);
2443 reg_cache[WM8904_ANALOGUE_OUT1_LEFT] |= WM8904_HPOUT_VU | 2443 snd_soc_update_bits(codec, WM8904_DAC_DIGITAL_VOLUME_LEFT,
2444 WM8904_HPOUTLZC; 2444 WM8904_DAC_VU, WM8904_DAC_VU);
2445 reg_cache[WM8904_ANALOGUE_OUT1_RIGHT] |= WM8904_HPOUT_VU | 2445 snd_soc_update_bits(codec, WM8904_DAC_DIGITAL_VOLUME_RIGHT,
2446 WM8904_HPOUTRZC; 2446 WM8904_DAC_VU, WM8904_DAC_VU);
2447 reg_cache[WM8904_ANALOGUE_OUT2_LEFT] |= WM8904_LINEOUT_VU | 2447 snd_soc_update_bits(codec, WM8904_ANALOGUE_OUT1_LEFT,
2448 WM8904_LINEOUTLZC; 2448 WM8904_HPOUT_VU | WM8904_HPOUTLZC,
2449 reg_cache[WM8904_ANALOGUE_OUT2_RIGHT] |= WM8904_LINEOUT_VU | 2449 WM8904_HPOUT_VU | WM8904_HPOUTLZC);
2450 WM8904_LINEOUTRZC; 2450 snd_soc_update_bits(codec, WM8904_ANALOGUE_OUT1_RIGHT,
2451 reg_cache[WM8904_CLOCK_RATES_0] &= ~WM8904_SR_MODE; 2451 WM8904_HPOUT_VU | WM8904_HPOUTRZC,
2452 WM8904_HPOUT_VU | WM8904_HPOUTRZC);
2453 snd_soc_update_bits(codec, WM8904_ANALOGUE_OUT2_LEFT,
2454 WM8904_LINEOUT_VU | WM8904_LINEOUTLZC,
2455 WM8904_LINEOUT_VU | WM8904_LINEOUTLZC);
2456 snd_soc_update_bits(codec, WM8904_ANALOGUE_OUT2_RIGHT,
2457 WM8904_LINEOUT_VU | WM8904_LINEOUTRZC,
2458 WM8904_LINEOUT_VU | WM8904_LINEOUTRZC);
2459 snd_soc_update_bits(codec, WM8904_CLOCK_RATES_0,
2460 WM8904_SR_MODE, 0);
2452 2461
2453 /* Apply configuration from the platform data. */ 2462 /* Apply configuration from the platform data. */
2454 if (wm8904->pdata) { 2463 if (wm8904->pdata) {
@@ -2469,10 +2478,12 @@ static int wm8904_probe(struct snd_soc_codec *codec)
2469 /* Set Class W by default - this will be managed by the Class 2478 /* Set Class W by default - this will be managed by the Class
2470 * G widget at runtime where bypass paths are available. 2479 * G widget at runtime where bypass paths are available.
2471 */ 2480 */
2472 reg_cache[WM8904_CLASS_W_0] |= WM8904_CP_DYN_PWR; 2481 snd_soc_update_bits(codec, WM8904_CLASS_W_0,
2482 WM8904_CP_DYN_PWR, WM8904_CP_DYN_PWR);
2473 2483
2474 /* Use normal bias source */ 2484 /* Use normal bias source */
2475 reg_cache[WM8904_BIAS_CONTROL_0] &= ~WM8904_POBCTRL; 2485 snd_soc_update_bits(codec, WM8904_BIAS_CONTROL_0,
2486 WM8904_POBCTRL, 0);
2476 2487
2477 wm8904_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 2488 wm8904_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
2478 2489
diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c
index 7167dfc96aa7..5e0214d6293e 100644
--- a/sound/soc/codecs/wm8955.c
+++ b/sound/soc/codecs/wm8955.c
@@ -934,16 +934,27 @@ static int wm8955_probe(struct snd_soc_codec *codec)
934 } 934 }
935 935
936 /* Change some default settings - latch VU and enable ZC */ 936 /* Change some default settings - latch VU and enable ZC */
937 reg_cache[WM8955_LEFT_DAC_VOLUME] |= WM8955_LDVU; 937 snd_soc_update_bits(codec, WM8955_LEFT_DAC_VOLUME,
938 reg_cache[WM8955_RIGHT_DAC_VOLUME] |= WM8955_RDVU; 938 WM8955_LDVU, WM8955_LDVU);
939 reg_cache[WM8955_LOUT1_VOLUME] |= WM8955_LO1VU | WM8955_LO1ZC; 939 snd_soc_update_bits(codec, WM8955_RIGHT_DAC_VOLUME,
940 reg_cache[WM8955_ROUT1_VOLUME] |= WM8955_RO1VU | WM8955_RO1ZC; 940 WM8955_RDVU, WM8955_RDVU);
941 reg_cache[WM8955_LOUT2_VOLUME] |= WM8955_LO2VU | WM8955_LO2ZC; 941 snd_soc_update_bits(codec, WM8955_LOUT1_VOLUME,
942 reg_cache[WM8955_ROUT2_VOLUME] |= WM8955_RO2VU | WM8955_RO2ZC; 942 WM8955_LO1VU | WM8955_LO1ZC,
943 reg_cache[WM8955_MONOOUT_VOLUME] |= WM8955_MOZC; 943 WM8955_LO1VU | WM8955_LO1ZC);
944 snd_soc_update_bits(codec, WM8955_ROUT1_VOLUME,
945 WM8955_RO1VU | WM8955_RO1ZC,
946 WM8955_RO1VU | WM8955_RO1ZC);
947 snd_soc_update_bits(codec, WM8955_LOUT2_VOLUME,
948 WM8955_LO2VU | WM8955_LO2ZC,
949 WM8955_LO2VU | WM8955_LO2ZC);
950 snd_soc_update_bits(codec, WM8955_ROUT2_VOLUME,
951 WM8955_RO2VU | WM8955_RO2ZC,
952 WM8955_RO2VU | WM8955_RO2ZC);
953 snd_soc_update_bits(codec, WM8955_MONOOUT_VOLUME,
954 WM8955_MOZC, WM8955_MOZC);
944 955
945 /* Also enable adaptive bass boost by default */ 956 /* Also enable adaptive bass boost by default */
946 reg_cache[WM8955_BASS_CONTROL] |= WM8955_BB; 957 snd_soc_update_bits(codec, WM8955_BASS_CONTROL, WM8955_BB, WM8955_BB);
947 958
948 /* Set platform data values */ 959 /* Set platform data values */
949 if (pdata) { 960 if (pdata) {
diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c
index 55252e7d02c9..cdee8103d09b 100644
--- a/sound/soc/codecs/wm8961.c
+++ b/sound/soc/codecs/wm8961.c
@@ -291,7 +291,7 @@ struct wm8961_priv {
291 int sysclk; 291 int sysclk;
292}; 292};
293 293
294static int wm8961_volatile_register(unsigned int reg) 294static int wm8961_volatile_register(struct snd_soc_codec *codec, unsigned int reg)
295{ 295{
296 switch (reg) { 296 switch (reg) {
297 case WM8961_SOFTWARE_RESET: 297 case WM8961_SOFTWARE_RESET:
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index b9cb1fcf8c92..5c7b730a864f 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -1938,7 +1938,7 @@ static const struct wm8962_reg_access {
1938 [21139] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21139 - VSS_XTS32_0 */ 1938 [21139] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21139 - VSS_XTS32_0 */
1939}; 1939};
1940 1940
1941static int wm8962_volatile_register(unsigned int reg) 1941static int wm8962_volatile_register(struct snd_soc_codec *codec, unsigned int reg)
1942{ 1942{
1943 if (wm8962_reg_access[reg].vol) 1943 if (wm8962_reg_access[reg].vol)
1944 return 1; 1944 return 1;
@@ -1946,7 +1946,7 @@ static int wm8962_volatile_register(unsigned int reg)
1946 return 0; 1946 return 0;
1947} 1947}
1948 1948
1949static int wm8962_readable_register(unsigned int reg) 1949static int wm8962_readable_register(struct snd_soc_codec *codec, unsigned int reg)
1950{ 1950{
1951 if (wm8962_reg_access[reg].read) 1951 if (wm8962_reg_access[reg].read)
1952 return 1; 1952 return 1;
@@ -3822,16 +3822,26 @@ static int wm8962_probe(struct snd_soc_codec *codec)
3822 } 3822 }
3823 3823
3824 /* Latch volume update bits */ 3824 /* Latch volume update bits */
3825 reg_cache[WM8962_LEFT_INPUT_VOLUME] |= WM8962_IN_VU; 3825 snd_soc_update_bits(codec, WM8962_LEFT_INPUT_VOLUME,
3826 reg_cache[WM8962_RIGHT_INPUT_VOLUME] |= WM8962_IN_VU; 3826 WM8962_IN_VU, WM8962_IN_VU);
3827 reg_cache[WM8962_LEFT_ADC_VOLUME] |= WM8962_ADC_VU; 3827 snd_soc_update_bits(codec, WM8962_RIGHT_INPUT_VOLUME,
3828 reg_cache[WM8962_RIGHT_ADC_VOLUME] |= WM8962_ADC_VU; 3828 WM8962_IN_VU, WM8962_IN_VU);
3829 reg_cache[WM8962_LEFT_DAC_VOLUME] |= WM8962_DAC_VU; 3829 snd_soc_update_bits(codec, WM8962_LEFT_ADC_VOLUME,
3830 reg_cache[WM8962_RIGHT_DAC_VOLUME] |= WM8962_DAC_VU; 3830 WM8962_ADC_VU, WM8962_ADC_VU);
3831 reg_cache[WM8962_SPKOUTL_VOLUME] |= WM8962_SPKOUT_VU; 3831 snd_soc_update_bits(codec, WM8962_RIGHT_ADC_VOLUME,
3832 reg_cache[WM8962_SPKOUTR_VOLUME] |= WM8962_SPKOUT_VU; 3832 WM8962_ADC_VU, WM8962_ADC_VU);
3833 reg_cache[WM8962_HPOUTL_VOLUME] |= WM8962_HPOUT_VU; 3833 snd_soc_update_bits(codec, WM8962_LEFT_DAC_VOLUME,
3834 reg_cache[WM8962_HPOUTR_VOLUME] |= WM8962_HPOUT_VU; 3834 WM8962_DAC_VU, WM8962_DAC_VU);
3835 snd_soc_update_bits(codec, WM8962_RIGHT_DAC_VOLUME,
3836 WM8962_DAC_VU, WM8962_DAC_VU);
3837 snd_soc_update_bits(codec, WM8962_SPKOUTL_VOLUME,
3838 WM8962_SPKOUT_VU, WM8962_SPKOUT_VU);
3839 snd_soc_update_bits(codec, WM8962_SPKOUTR_VOLUME,
3840 WM8962_SPKOUT_VU, WM8962_SPKOUT_VU);
3841 snd_soc_update_bits(codec, WM8962_HPOUTL_VOLUME,
3842 WM8962_HPOUT_VU, WM8962_HPOUT_VU);
3843 snd_soc_update_bits(codec, WM8962_HPOUTR_VOLUME,
3844 WM8962_HPOUT_VU, WM8962_HPOUT_VU);
3835 3845
3836 wm8962_add_widgets(codec); 3846 wm8962_add_widgets(codec);
3837 3847
diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c
index 4bbc3442703f..30fb48ec2799 100644
--- a/sound/soc/codecs/wm8978.c
+++ b/sound/soc/codecs/wm8978.c
@@ -965,7 +965,7 @@ static int wm8978_probe(struct snd_soc_codec *codec)
965 * written. 965 * written.
966 */ 966 */
967 for (i = 0; i < ARRAY_SIZE(update_reg); i++) 967 for (i = 0; i < ARRAY_SIZE(update_reg); i++)
968 ((u16 *)codec->reg_cache)[update_reg[i]] |= 0x100; 968 snd_soc_update_bits(codec, update_reg[i], 0x100, 0x100);
969 969
970 /* Reset the codec */ 970 /* Reset the codec */
971 ret = snd_soc_write(codec, WM8978_RESET, 0); 971 ret = snd_soc_write(codec, WM8978_RESET, 0);
diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c
new file mode 100644
index 000000000000..28fdfd66661d
--- /dev/null
+++ b/sound/soc/codecs/wm8991.c
@@ -0,0 +1,1427 @@
1/*
2 * wm8991.c -- WM8991 ALSA Soc Audio driver
3 *
4 * Copyright 2007-2010 Wolfson Microelectronics PLC.
5 * Author: Graeme Gregory
6 * linux@wolfsonmicro.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/module.h>
15#include <linux/moduleparam.h>
16#include <linux/version.h>
17#include <linux/kernel.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 <linux/slab.h>
24#include <sound/core.h>
25#include <sound/pcm.h>
26#include <sound/pcm_params.h>
27#include <sound/soc.h>
28#include <sound/soc-dapm.h>
29#include <sound/initval.h>
30#include <sound/tlv.h>
31#include <asm/div64.h>
32
33#include "wm8991.h"
34
35struct wm8991_priv {
36 enum snd_soc_control_type control_type;
37 unsigned int pcmclk;
38};
39
40static const u16 wm8991_reg_defs[] = {
41 0x8991, /* R0 - Reset */
42 0x0000, /* R1 - Power Management (1) */
43 0x6000, /* R2 - Power Management (2) */
44 0x0000, /* R3 - Power Management (3) */
45 0x4050, /* R4 - Audio Interface (1) */
46 0x4000, /* R5 - Audio Interface (2) */
47 0x01C8, /* R6 - Clocking (1) */
48 0x0000, /* R7 - Clocking (2) */
49 0x0040, /* R8 - Audio Interface (3) */
50 0x0040, /* R9 - Audio Interface (4) */
51 0x0004, /* R10 - DAC CTRL */
52 0x00C0, /* R11 - Left DAC Digital Volume */
53 0x00C0, /* R12 - Right DAC Digital Volume */
54 0x0000, /* R13 - Digital Side Tone */
55 0x0100, /* R14 - ADC CTRL */
56 0x00C0, /* R15 - Left ADC Digital Volume */
57 0x00C0, /* R16 - Right ADC Digital Volume */
58 0x0000, /* R17 */
59 0x0000, /* R18 - GPIO CTRL 1 */
60 0x1000, /* R19 - GPIO1 & GPIO2 */
61 0x1010, /* R20 - GPIO3 & GPIO4 */
62 0x1010, /* R21 - GPIO5 & GPIO6 */
63 0x8000, /* R22 - GPIOCTRL 2 */
64 0x0800, /* R23 - GPIO_POL */
65 0x008B, /* R24 - Left Line Input 1&2 Volume */
66 0x008B, /* R25 - Left Line Input 3&4 Volume */
67 0x008B, /* R26 - Right Line Input 1&2 Volume */
68 0x008B, /* R27 - Right Line Input 3&4 Volume */
69 0x0000, /* R28 - Left Output Volume */
70 0x0000, /* R29 - Right Output Volume */
71 0x0066, /* R30 - Line Outputs Volume */
72 0x0022, /* R31 - Out3/4 Volume */
73 0x0079, /* R32 - Left OPGA Volume */
74 0x0079, /* R33 - Right OPGA Volume */
75 0x0003, /* R34 - Speaker Volume */
76 0x0003, /* R35 - ClassD1 */
77 0x0000, /* R36 */
78 0x0100, /* R37 - ClassD3 */
79 0x0000, /* R38 */
80 0x0000, /* R39 - Input Mixer1 */
81 0x0000, /* R40 - Input Mixer2 */
82 0x0000, /* R41 - Input Mixer3 */
83 0x0000, /* R42 - Input Mixer4 */
84 0x0000, /* R43 - Input Mixer5 */
85 0x0000, /* R44 - Input Mixer6 */
86 0x0000, /* R45 - Output Mixer1 */
87 0x0000, /* R46 - Output Mixer2 */
88 0x0000, /* R47 - Output Mixer3 */
89 0x0000, /* R48 - Output Mixer4 */
90 0x0000, /* R49 - Output Mixer5 */
91 0x0000, /* R50 - Output Mixer6 */
92 0x0180, /* R51 - Out3/4 Mixer */
93 0x0000, /* R52 - Line Mixer1 */
94 0x0000, /* R53 - Line Mixer2 */
95 0x0000, /* R54 - Speaker Mixer */
96 0x0000, /* R55 - Additional Control */
97 0x0000, /* R56 - AntiPOP1 */
98 0x0000, /* R57 - AntiPOP2 */
99 0x0000, /* R58 - MICBIAS */
100 0x0000, /* R59 */
101 0x0008, /* R60 - PLL1 */
102 0x0031, /* R61 - PLL2 */
103 0x0026, /* R62 - PLL3 */
104};
105
106#define wm8991_reset(c) snd_soc_write(c, WM8991_RESET, 0)
107
108static const unsigned int rec_mix_tlv[] = {
109 TLV_DB_RANGE_HEAD(1),
110 0, 7, TLV_DB_LINEAR_ITEM(-1500, 600),
111};
112
113static const unsigned int in_pga_tlv[] = {
114 TLV_DB_RANGE_HEAD(1),
115 0, 0x1F, TLV_DB_LINEAR_ITEM(-1650, 3000),
116};
117
118static const unsigned int out_mix_tlv[] = {
119 TLV_DB_RANGE_HEAD(1),
120 0, 7, TLV_DB_LINEAR_ITEM(0, -2100),
121};
122
123static const unsigned int out_pga_tlv[] = {
124 TLV_DB_RANGE_HEAD(1),
125 0, 127, TLV_DB_LINEAR_ITEM(-7300, 600),
126};
127
128static const unsigned int out_omix_tlv[] = {
129 TLV_DB_RANGE_HEAD(1),
130 0, 7, TLV_DB_LINEAR_ITEM(-600, 0),
131};
132
133static const unsigned int out_dac_tlv[] = {
134 TLV_DB_RANGE_HEAD(1),
135 0, 255, TLV_DB_LINEAR_ITEM(-7163, 0),
136};
137
138static const unsigned int in_adc_tlv[] = {
139 TLV_DB_RANGE_HEAD(1),
140 0, 255, TLV_DB_LINEAR_ITEM(-7163, 1763),
141};
142
143static const unsigned int out_sidetone_tlv[] = {
144 TLV_DB_RANGE_HEAD(1),
145 0, 31, TLV_DB_LINEAR_ITEM(-3600, 0),
146};
147
148static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol,
149 struct snd_ctl_elem_value *ucontrol)
150{
151 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
152 int reg = kcontrol->private_value & 0xff;
153 int ret;
154 u16 val;
155
156 ret = snd_soc_put_volsw(kcontrol, ucontrol);
157 if (ret < 0)
158 return ret;
159
160 /* now hit the volume update bits (always bit 8) */
161 val = snd_soc_read(codec, reg);
162 return snd_soc_write(codec, reg, val | 0x0100);
163}
164
165static const char *wm8991_digital_sidetone[] =
166{"None", "Left ADC", "Right ADC", "Reserved"};
167
168static const struct soc_enum wm8991_left_digital_sidetone_enum =
169 SOC_ENUM_SINGLE(WM8991_DIGITAL_SIDE_TONE,
170 WM8991_ADC_TO_DACL_SHIFT,
171 WM8991_ADC_TO_DACL_MASK,
172 wm8991_digital_sidetone);
173
174static const struct soc_enum wm8991_right_digital_sidetone_enum =
175 SOC_ENUM_SINGLE(WM8991_DIGITAL_SIDE_TONE,
176 WM8991_ADC_TO_DACR_SHIFT,
177 WM8991_ADC_TO_DACR_MASK,
178 wm8991_digital_sidetone);
179
180static const char *wm8991_adcmode[] =
181{"Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"};
182
183static const struct soc_enum wm8991_right_adcmode_enum =
184 SOC_ENUM_SINGLE(WM8991_ADC_CTRL,
185 WM8991_ADC_HPF_CUT_SHIFT,
186 WM8991_ADC_HPF_CUT_MASK,
187 wm8991_adcmode);
188
189static const struct snd_kcontrol_new wm8991_snd_controls[] = {
190 /* INMIXL */
191 SOC_SINGLE("LIN12 PGA Boost", WM8991_INPUT_MIXER3, WM8991_L12MNBST_BIT, 1, 0),
192 SOC_SINGLE("LIN34 PGA Boost", WM8991_INPUT_MIXER3, WM8991_L34MNBST_BIT, 1, 0),
193 /* INMIXR */
194 SOC_SINGLE("RIN12 PGA Boost", WM8991_INPUT_MIXER3, WM8991_R12MNBST_BIT, 1, 0),
195 SOC_SINGLE("RIN34 PGA Boost", WM8991_INPUT_MIXER3, WM8991_R34MNBST_BIT, 1, 0),
196
197 /* LOMIX */
198 SOC_SINGLE_TLV("LOMIX LIN3 Bypass Volume", WM8991_OUTPUT_MIXER3,
199 WM8991_LLI3LOVOL_SHIFT, WM8991_LLI3LOVOL_MASK, 1, out_mix_tlv),
200 SOC_SINGLE_TLV("LOMIX RIN12 PGA Bypass Volume", WM8991_OUTPUT_MIXER3,
201 WM8991_LR12LOVOL_SHIFT, WM8991_LR12LOVOL_MASK, 1, out_mix_tlv),
202 SOC_SINGLE_TLV("LOMIX LIN12 PGA Bypass Volume", WM8991_OUTPUT_MIXER3,
203 WM8991_LL12LOVOL_SHIFT, WM8991_LL12LOVOL_MASK, 1, out_mix_tlv),
204 SOC_SINGLE_TLV("LOMIX RIN3 Bypass Volume", WM8991_OUTPUT_MIXER5,
205 WM8991_LRI3LOVOL_SHIFT, WM8991_LRI3LOVOL_MASK, 1, out_mix_tlv),
206 SOC_SINGLE_TLV("LOMIX AINRMUX Bypass Volume", WM8991_OUTPUT_MIXER5,
207 WM8991_LRBLOVOL_SHIFT, WM8991_LRBLOVOL_MASK, 1, out_mix_tlv),
208 SOC_SINGLE_TLV("LOMIX AINLMUX Bypass Volume", WM8991_OUTPUT_MIXER5,
209 WM8991_LRBLOVOL_SHIFT, WM8991_LRBLOVOL_MASK, 1, out_mix_tlv),
210
211 /* ROMIX */
212 SOC_SINGLE_TLV("ROMIX RIN3 Bypass Volume", WM8991_OUTPUT_MIXER4,
213 WM8991_RRI3ROVOL_SHIFT, WM8991_RRI3ROVOL_MASK, 1, out_mix_tlv),
214 SOC_SINGLE_TLV("ROMIX LIN12 PGA Bypass Volume", WM8991_OUTPUT_MIXER4,
215 WM8991_RL12ROVOL_SHIFT, WM8991_RL12ROVOL_MASK, 1, out_mix_tlv),
216 SOC_SINGLE_TLV("ROMIX RIN12 PGA Bypass Volume", WM8991_OUTPUT_MIXER4,
217 WM8991_RR12ROVOL_SHIFT, WM8991_RR12ROVOL_MASK, 1, out_mix_tlv),
218 SOC_SINGLE_TLV("ROMIX LIN3 Bypass Volume", WM8991_OUTPUT_MIXER6,
219 WM8991_RLI3ROVOL_SHIFT, WM8991_RLI3ROVOL_MASK, 1, out_mix_tlv),
220 SOC_SINGLE_TLV("ROMIX AINLMUX Bypass Volume", WM8991_OUTPUT_MIXER6,
221 WM8991_RLBROVOL_SHIFT, WM8991_RLBROVOL_MASK, 1, out_mix_tlv),
222 SOC_SINGLE_TLV("ROMIX AINRMUX Bypass Volume", WM8991_OUTPUT_MIXER6,
223 WM8991_RRBROVOL_SHIFT, WM8991_RRBROVOL_MASK, 1, out_mix_tlv),
224
225 /* LOUT */
226 SOC_WM899X_OUTPGA_SINGLE_R_TLV("LOUT Volume", WM8991_LEFT_OUTPUT_VOLUME,
227 WM8991_LOUTVOL_SHIFT, WM8991_LOUTVOL_MASK, 0, out_pga_tlv),
228 SOC_SINGLE("LOUT ZC", WM8991_LEFT_OUTPUT_VOLUME, WM8991_LOZC_BIT, 1, 0),
229
230 /* ROUT */
231 SOC_WM899X_OUTPGA_SINGLE_R_TLV("ROUT Volume", WM8991_RIGHT_OUTPUT_VOLUME,
232 WM8991_ROUTVOL_SHIFT, WM8991_ROUTVOL_MASK, 0, out_pga_tlv),
233 SOC_SINGLE("ROUT ZC", WM8991_RIGHT_OUTPUT_VOLUME, WM8991_ROZC_BIT, 1, 0),
234
235 /* LOPGA */
236 SOC_WM899X_OUTPGA_SINGLE_R_TLV("LOPGA Volume", WM8991_LEFT_OPGA_VOLUME,
237 WM8991_LOPGAVOL_SHIFT, WM8991_LOPGAVOL_MASK, 0, out_pga_tlv),
238 SOC_SINGLE("LOPGA ZC Switch", WM8991_LEFT_OPGA_VOLUME,
239 WM8991_LOPGAZC_BIT, 1, 0),
240
241 /* ROPGA */
242 SOC_WM899X_OUTPGA_SINGLE_R_TLV("ROPGA Volume", WM8991_RIGHT_OPGA_VOLUME,
243 WM8991_ROPGAVOL_SHIFT, WM8991_ROPGAVOL_MASK, 0, out_pga_tlv),
244 SOC_SINGLE("ROPGA ZC Switch", WM8991_RIGHT_OPGA_VOLUME,
245 WM8991_ROPGAZC_BIT, 1, 0),
246
247 SOC_SINGLE("LON Mute Switch", WM8991_LINE_OUTPUTS_VOLUME,
248 WM8991_LONMUTE_BIT, 1, 0),
249 SOC_SINGLE("LOP Mute Switch", WM8991_LINE_OUTPUTS_VOLUME,
250 WM8991_LOPMUTE_BIT, 1, 0),
251 SOC_SINGLE("LOP Attenuation Switch", WM8991_LINE_OUTPUTS_VOLUME,
252 WM8991_LOATTN_BIT, 1, 0),
253 SOC_SINGLE("RON Mute Switch", WM8991_LINE_OUTPUTS_VOLUME,
254 WM8991_RONMUTE_BIT, 1, 0),
255 SOC_SINGLE("ROP Mute Switch", WM8991_LINE_OUTPUTS_VOLUME,
256 WM8991_ROPMUTE_BIT, 1, 0),
257 SOC_SINGLE("ROP Attenuation Switch", WM8991_LINE_OUTPUTS_VOLUME,
258 WM8991_ROATTN_BIT, 1, 0),
259
260 SOC_SINGLE("OUT3 Mute Switch", WM8991_OUT3_4_VOLUME,
261 WM8991_OUT3MUTE_BIT, 1, 0),
262 SOC_SINGLE("OUT3 Attenuation Switch", WM8991_OUT3_4_VOLUME,
263 WM8991_OUT3ATTN_BIT, 1, 0),
264
265 SOC_SINGLE("OUT4 Mute Switch", WM8991_OUT3_4_VOLUME,
266 WM8991_OUT4MUTE_BIT, 1, 0),
267 SOC_SINGLE("OUT4 Attenuation Switch", WM8991_OUT3_4_VOLUME,
268 WM8991_OUT4ATTN_BIT, 1, 0),
269
270 SOC_SINGLE("Speaker Mode Switch", WM8991_CLASSD1,
271 WM8991_CDMODE_BIT, 1, 0),
272
273 SOC_SINGLE("Speaker Output Attenuation Volume", WM8991_SPEAKER_VOLUME,
274 WM8991_SPKVOL_SHIFT, WM8991_SPKVOL_MASK, 0),
275 SOC_SINGLE("Speaker DC Boost Volume", WM8991_CLASSD3,
276 WM8991_DCGAIN_SHIFT, WM8991_DCGAIN_MASK, 0),
277 SOC_SINGLE("Speaker AC Boost Volume", WM8991_CLASSD3,
278 WM8991_ACGAIN_SHIFT, WM8991_ACGAIN_MASK, 0),
279
280 SOC_WM899X_OUTPGA_SINGLE_R_TLV("Left DAC Digital Volume",
281 WM8991_LEFT_DAC_DIGITAL_VOLUME,
282 WM8991_DACL_VOL_SHIFT,
283 WM8991_DACL_VOL_MASK,
284 0,
285 out_dac_tlv),
286
287 SOC_WM899X_OUTPGA_SINGLE_R_TLV("Right DAC Digital Volume",
288 WM8991_RIGHT_DAC_DIGITAL_VOLUME,
289 WM8991_DACR_VOL_SHIFT,
290 WM8991_DACR_VOL_MASK,
291 0,
292 out_dac_tlv),
293
294 SOC_ENUM("Left Digital Sidetone", wm8991_left_digital_sidetone_enum),
295 SOC_ENUM("Right Digital Sidetone", wm8991_right_digital_sidetone_enum),
296
297 SOC_SINGLE_TLV("Left Digital Sidetone Volume", WM8991_DIGITAL_SIDE_TONE,
298 WM8991_ADCL_DAC_SVOL_SHIFT, WM8991_ADCL_DAC_SVOL_MASK, 0,
299 out_sidetone_tlv),
300 SOC_SINGLE_TLV("Right Digital Sidetone Volume", WM8991_DIGITAL_SIDE_TONE,
301 WM8991_ADCR_DAC_SVOL_SHIFT, WM8991_ADCR_DAC_SVOL_MASK, 0,
302 out_sidetone_tlv),
303
304 SOC_SINGLE("ADC Digital High Pass Filter Switch", WM8991_ADC_CTRL,
305 WM8991_ADC_HPF_ENA_BIT, 1, 0),
306
307 SOC_ENUM("ADC HPF Mode", wm8991_right_adcmode_enum),
308
309 SOC_WM899X_OUTPGA_SINGLE_R_TLV("Left ADC Digital Volume",
310 WM8991_LEFT_ADC_DIGITAL_VOLUME,
311 WM8991_ADCL_VOL_SHIFT,
312 WM8991_ADCL_VOL_MASK,
313 0,
314 in_adc_tlv),
315
316 SOC_WM899X_OUTPGA_SINGLE_R_TLV("Right ADC Digital Volume",
317 WM8991_RIGHT_ADC_DIGITAL_VOLUME,
318 WM8991_ADCR_VOL_SHIFT,
319 WM8991_ADCR_VOL_MASK,
320 0,
321 in_adc_tlv),
322
323 SOC_WM899X_OUTPGA_SINGLE_R_TLV("LIN12 Volume",
324 WM8991_LEFT_LINE_INPUT_1_2_VOLUME,
325 WM8991_LIN12VOL_SHIFT,
326 WM8991_LIN12VOL_MASK,
327 0,
328 in_pga_tlv),
329
330 SOC_SINGLE("LIN12 ZC Switch", WM8991_LEFT_LINE_INPUT_1_2_VOLUME,
331 WM8991_LI12ZC_BIT, 1, 0),
332
333 SOC_SINGLE("LIN12 Mute Switch", WM8991_LEFT_LINE_INPUT_1_2_VOLUME,
334 WM8991_LI12MUTE_BIT, 1, 0),
335
336 SOC_WM899X_OUTPGA_SINGLE_R_TLV("LIN34 Volume",
337 WM8991_LEFT_LINE_INPUT_3_4_VOLUME,
338 WM8991_LIN34VOL_SHIFT,
339 WM8991_LIN34VOL_MASK,
340 0,
341 in_pga_tlv),
342
343 SOC_SINGLE("LIN34 ZC Switch", WM8991_LEFT_LINE_INPUT_3_4_VOLUME,
344 WM8991_LI34ZC_BIT, 1, 0),
345
346 SOC_SINGLE("LIN34 Mute Switch", WM8991_LEFT_LINE_INPUT_3_4_VOLUME,
347 WM8991_LI34MUTE_BIT, 1, 0),
348
349 SOC_WM899X_OUTPGA_SINGLE_R_TLV("RIN12 Volume",
350 WM8991_RIGHT_LINE_INPUT_1_2_VOLUME,
351 WM8991_RIN12VOL_SHIFT,
352 WM8991_RIN12VOL_MASK,
353 0,
354 in_pga_tlv),
355
356 SOC_SINGLE("RIN12 ZC Switch", WM8991_RIGHT_LINE_INPUT_1_2_VOLUME,
357 WM8991_RI12ZC_BIT, 1, 0),
358
359 SOC_SINGLE("RIN12 Mute Switch", WM8991_RIGHT_LINE_INPUT_1_2_VOLUME,
360 WM8991_RI12MUTE_BIT, 1, 0),
361
362 SOC_WM899X_OUTPGA_SINGLE_R_TLV("RIN34 Volume",
363 WM8991_RIGHT_LINE_INPUT_3_4_VOLUME,
364 WM8991_RIN34VOL_SHIFT,
365 WM8991_RIN34VOL_MASK,
366 0,
367 in_pga_tlv),
368
369 SOC_SINGLE("RIN34 ZC Switch", WM8991_RIGHT_LINE_INPUT_3_4_VOLUME,
370 WM8991_RI34ZC_BIT, 1, 0),
371
372 SOC_SINGLE("RIN34 Mute Switch", WM8991_RIGHT_LINE_INPUT_3_4_VOLUME,
373 WM8991_RI34MUTE_BIT, 1, 0),
374};
375
376/*
377 * _DAPM_ Controls
378 */
379static int inmixer_event(struct snd_soc_dapm_widget *w,
380 struct snd_kcontrol *kcontrol, int event)
381{
382 u16 reg, fakepower;
383
384 reg = snd_soc_read(w->codec, WM8991_POWER_MANAGEMENT_2);
385 fakepower = snd_soc_read(w->codec, WM8991_INTDRIVBITS);
386
387 if (fakepower & ((1 << WM8991_INMIXL_PWR_BIT) |
388 (1 << WM8991_AINLMUX_PWR_BIT)))
389 reg |= WM8991_AINL_ENA;
390 else
391 reg &= ~WM8991_AINL_ENA;
392
393 if (fakepower & ((1 << WM8991_INMIXR_PWR_BIT) |
394 (1 << WM8991_AINRMUX_PWR_BIT)))
395 reg |= WM8991_AINR_ENA;
396 else
397 reg &= ~WM8991_AINL_ENA;
398
399 snd_soc_write(w->codec, WM8991_POWER_MANAGEMENT_2, reg);
400 return 0;
401}
402
403static int outmixer_event(struct snd_soc_dapm_widget *w,
404 struct snd_kcontrol *kcontrol, int event)
405{
406 u32 reg_shift = kcontrol->private_value & 0xfff;
407 int ret = 0;
408 u16 reg;
409
410 switch (reg_shift) {
411 case WM8991_SPEAKER_MIXER | (WM8991_LDSPK_BIT << 8):
412 reg = snd_soc_read(w->codec, WM8991_OUTPUT_MIXER1);
413 if (reg & WM8991_LDLO) {
414 printk(KERN_WARNING
415 "Cannot set as Output Mixer 1 LDLO Set\n");
416 ret = -1;
417 }
418 break;
419
420 case WM8991_SPEAKER_MIXER | (WM8991_RDSPK_BIT << 8):
421 reg = snd_soc_read(w->codec, WM8991_OUTPUT_MIXER2);
422 if (reg & WM8991_RDRO) {
423 printk(KERN_WARNING
424 "Cannot set as Output Mixer 2 RDRO Set\n");
425 ret = -1;
426 }
427 break;
428
429 case WM8991_OUTPUT_MIXER1 | (WM8991_LDLO_BIT << 8):
430 reg = snd_soc_read(w->codec, WM8991_SPEAKER_MIXER);
431 if (reg & WM8991_LDSPK) {
432 printk(KERN_WARNING
433 "Cannot set as Speaker Mixer LDSPK Set\n");
434 ret = -1;
435 }
436 break;
437
438 case WM8991_OUTPUT_MIXER2 | (WM8991_RDRO_BIT << 8):
439 reg = snd_soc_read(w->codec, WM8991_SPEAKER_MIXER);
440 if (reg & WM8991_RDSPK) {
441 printk(KERN_WARNING
442 "Cannot set as Speaker Mixer RDSPK Set\n");
443 ret = -1;
444 }
445 break;
446 }
447
448 return ret;
449}
450
451/* INMIX dB values */
452static const unsigned int in_mix_tlv[] = {
453 TLV_DB_RANGE_HEAD(1),
454 0, 7, TLV_DB_LINEAR_ITEM(-1200, 600),
455};
456
457/* Left In PGA Connections */
458static const struct snd_kcontrol_new wm8991_dapm_lin12_pga_controls[] = {
459 SOC_DAPM_SINGLE("LIN1 Switch", WM8991_INPUT_MIXER2, WM8991_LMN1_BIT, 1, 0),
460 SOC_DAPM_SINGLE("LIN2 Switch", WM8991_INPUT_MIXER2, WM8991_LMP2_BIT, 1, 0),
461};
462
463static const struct snd_kcontrol_new wm8991_dapm_lin34_pga_controls[] = {
464 SOC_DAPM_SINGLE("LIN3 Switch", WM8991_INPUT_MIXER2, WM8991_LMN3_BIT, 1, 0),
465 SOC_DAPM_SINGLE("LIN4 Switch", WM8991_INPUT_MIXER2, WM8991_LMP4_BIT, 1, 0),
466};
467
468/* Right In PGA Connections */
469static const struct snd_kcontrol_new wm8991_dapm_rin12_pga_controls[] = {
470 SOC_DAPM_SINGLE("RIN1 Switch", WM8991_INPUT_MIXER2, WM8991_RMN1_BIT, 1, 0),
471 SOC_DAPM_SINGLE("RIN2 Switch", WM8991_INPUT_MIXER2, WM8991_RMP2_BIT, 1, 0),
472};
473
474static const struct snd_kcontrol_new wm8991_dapm_rin34_pga_controls[] = {
475 SOC_DAPM_SINGLE("RIN3 Switch", WM8991_INPUT_MIXER2, WM8991_RMN3_BIT, 1, 0),
476 SOC_DAPM_SINGLE("RIN4 Switch", WM8991_INPUT_MIXER2, WM8991_RMP4_BIT, 1, 0),
477};
478
479/* INMIXL */
480static const struct snd_kcontrol_new wm8991_dapm_inmixl_controls[] = {
481 SOC_DAPM_SINGLE_TLV("Record Left Volume", WM8991_INPUT_MIXER3,
482 WM8991_LDBVOL_SHIFT, WM8991_LDBVOL_MASK, 0, in_mix_tlv),
483 SOC_DAPM_SINGLE_TLV("LIN2 Volume", WM8991_INPUT_MIXER5, WM8991_LI2BVOL_SHIFT,
484 7, 0, in_mix_tlv),
485 SOC_DAPM_SINGLE("LINPGA12 Switch", WM8991_INPUT_MIXER3, WM8991_L12MNB_BIT,
486 1, 0),
487 SOC_DAPM_SINGLE("LINPGA34 Switch", WM8991_INPUT_MIXER3, WM8991_L34MNB_BIT,
488 1, 0),
489};
490
491/* INMIXR */
492static const struct snd_kcontrol_new wm8991_dapm_inmixr_controls[] = {
493 SOC_DAPM_SINGLE_TLV("Record Right Volume", WM8991_INPUT_MIXER4,
494 WM8991_RDBVOL_SHIFT, WM8991_RDBVOL_MASK, 0, in_mix_tlv),
495 SOC_DAPM_SINGLE_TLV("RIN2 Volume", WM8991_INPUT_MIXER6, WM8991_RI2BVOL_SHIFT,
496 7, 0, in_mix_tlv),
497 SOC_DAPM_SINGLE("RINPGA12 Switch", WM8991_INPUT_MIXER3, WM8991_L12MNB_BIT,
498 1, 0),
499 SOC_DAPM_SINGLE("RINPGA34 Switch", WM8991_INPUT_MIXER3, WM8991_L34MNB_BIT,
500 1, 0),
501};
502
503/* AINLMUX */
504static const char *wm8991_ainlmux[] =
505{"INMIXL Mix", "RXVOICE Mix", "DIFFINL Mix"};
506
507static const struct soc_enum wm8991_ainlmux_enum =
508 SOC_ENUM_SINGLE(WM8991_INPUT_MIXER1, WM8991_AINLMODE_SHIFT,
509 ARRAY_SIZE(wm8991_ainlmux), wm8991_ainlmux);
510
511static const struct snd_kcontrol_new wm8991_dapm_ainlmux_controls =
512 SOC_DAPM_ENUM("Route", wm8991_ainlmux_enum);
513
514/* DIFFINL */
515
516/* AINRMUX */
517static const char *wm8991_ainrmux[] =
518{"INMIXR Mix", "RXVOICE Mix", "DIFFINR Mix"};
519
520static const struct soc_enum wm8991_ainrmux_enum =
521 SOC_ENUM_SINGLE(WM8991_INPUT_MIXER1, WM8991_AINRMODE_SHIFT,
522 ARRAY_SIZE(wm8991_ainrmux), wm8991_ainrmux);
523
524static const struct snd_kcontrol_new wm8991_dapm_ainrmux_controls =
525 SOC_DAPM_ENUM("Route", wm8991_ainrmux_enum);
526
527/* RXVOICE */
528static const struct snd_kcontrol_new wm8991_dapm_rxvoice_controls[] = {
529 SOC_DAPM_SINGLE_TLV("LIN4RXN", WM8991_INPUT_MIXER5, WM8991_LR4BVOL_SHIFT,
530 WM8991_LR4BVOL_MASK, 0, in_mix_tlv),
531 SOC_DAPM_SINGLE_TLV("RIN4RXP", WM8991_INPUT_MIXER6, WM8991_RL4BVOL_SHIFT,
532 WM8991_RL4BVOL_MASK, 0, in_mix_tlv),
533};
534
535/* LOMIX */
536static const struct snd_kcontrol_new wm8991_dapm_lomix_controls[] = {
537 SOC_DAPM_SINGLE("LOMIX Right ADC Bypass Switch", WM8991_OUTPUT_MIXER1,
538 WM8991_LRBLO_BIT, 1, 0),
539 SOC_DAPM_SINGLE("LOMIX Left ADC Bypass Switch", WM8991_OUTPUT_MIXER1,
540 WM8991_LLBLO_BIT, 1, 0),
541 SOC_DAPM_SINGLE("LOMIX RIN3 Bypass Switch", WM8991_OUTPUT_MIXER1,
542 WM8991_LRI3LO_BIT, 1, 0),
543 SOC_DAPM_SINGLE("LOMIX LIN3 Bypass Switch", WM8991_OUTPUT_MIXER1,
544 WM8991_LLI3LO_BIT, 1, 0),
545 SOC_DAPM_SINGLE("LOMIX RIN12 PGA Bypass Switch", WM8991_OUTPUT_MIXER1,
546 WM8991_LR12LO_BIT, 1, 0),
547 SOC_DAPM_SINGLE("LOMIX LIN12 PGA Bypass Switch", WM8991_OUTPUT_MIXER1,
548 WM8991_LL12LO_BIT, 1, 0),
549 SOC_DAPM_SINGLE("LOMIX Left DAC Switch", WM8991_OUTPUT_MIXER1,
550 WM8991_LDLO_BIT, 1, 0),
551};
552
553/* ROMIX */
554static const struct snd_kcontrol_new wm8991_dapm_romix_controls[] = {
555 SOC_DAPM_SINGLE("ROMIX Left ADC Bypass Switch", WM8991_OUTPUT_MIXER2,
556 WM8991_RLBRO_BIT, 1, 0),
557 SOC_DAPM_SINGLE("ROMIX Right ADC Bypass Switch", WM8991_OUTPUT_MIXER2,
558 WM8991_RRBRO_BIT, 1, 0),
559 SOC_DAPM_SINGLE("ROMIX LIN3 Bypass Switch", WM8991_OUTPUT_MIXER2,
560 WM8991_RLI3RO_BIT, 1, 0),
561 SOC_DAPM_SINGLE("ROMIX RIN3 Bypass Switch", WM8991_OUTPUT_MIXER2,
562 WM8991_RRI3RO_BIT, 1, 0),
563 SOC_DAPM_SINGLE("ROMIX LIN12 PGA Bypass Switch", WM8991_OUTPUT_MIXER2,
564 WM8991_RL12RO_BIT, 1, 0),
565 SOC_DAPM_SINGLE("ROMIX RIN12 PGA Bypass Switch", WM8991_OUTPUT_MIXER2,
566 WM8991_RR12RO_BIT, 1, 0),
567 SOC_DAPM_SINGLE("ROMIX Right DAC Switch", WM8991_OUTPUT_MIXER2,
568 WM8991_RDRO_BIT, 1, 0),
569};
570
571/* LONMIX */
572static const struct snd_kcontrol_new wm8991_dapm_lonmix_controls[] = {
573 SOC_DAPM_SINGLE("LONMIX Left Mixer PGA Switch", WM8991_LINE_MIXER1,
574 WM8991_LLOPGALON_BIT, 1, 0),
575 SOC_DAPM_SINGLE("LONMIX Right Mixer PGA Switch", WM8991_LINE_MIXER1,
576 WM8991_LROPGALON_BIT, 1, 0),
577 SOC_DAPM_SINGLE("LONMIX Inverted LOP Switch", WM8991_LINE_MIXER1,
578 WM8991_LOPLON_BIT, 1, 0),
579};
580
581/* LOPMIX */
582static const struct snd_kcontrol_new wm8991_dapm_lopmix_controls[] = {
583 SOC_DAPM_SINGLE("LOPMIX Right Mic Bypass Switch", WM8991_LINE_MIXER1,
584 WM8991_LR12LOP_BIT, 1, 0),
585 SOC_DAPM_SINGLE("LOPMIX Left Mic Bypass Switch", WM8991_LINE_MIXER1,
586 WM8991_LL12LOP_BIT, 1, 0),
587 SOC_DAPM_SINGLE("LOPMIX Left Mixer PGA Switch", WM8991_LINE_MIXER1,
588 WM8991_LLOPGALOP_BIT, 1, 0),
589};
590
591/* RONMIX */
592static const struct snd_kcontrol_new wm8991_dapm_ronmix_controls[] = {
593 SOC_DAPM_SINGLE("RONMIX Right Mixer PGA Switch", WM8991_LINE_MIXER2,
594 WM8991_RROPGARON_BIT, 1, 0),
595 SOC_DAPM_SINGLE("RONMIX Left Mixer PGA Switch", WM8991_LINE_MIXER2,
596 WM8991_RLOPGARON_BIT, 1, 0),
597 SOC_DAPM_SINGLE("RONMIX Inverted ROP Switch", WM8991_LINE_MIXER2,
598 WM8991_ROPRON_BIT, 1, 0),
599};
600
601/* ROPMIX */
602static const struct snd_kcontrol_new wm8991_dapm_ropmix_controls[] = {
603 SOC_DAPM_SINGLE("ROPMIX Left Mic Bypass Switch", WM8991_LINE_MIXER2,
604 WM8991_RL12ROP_BIT, 1, 0),
605 SOC_DAPM_SINGLE("ROPMIX Right Mic Bypass Switch", WM8991_LINE_MIXER2,
606 WM8991_RR12ROP_BIT, 1, 0),
607 SOC_DAPM_SINGLE("ROPMIX Right Mixer PGA Switch", WM8991_LINE_MIXER2,
608 WM8991_RROPGAROP_BIT, 1, 0),
609};
610
611/* OUT3MIX */
612static const struct snd_kcontrol_new wm8991_dapm_out3mix_controls[] = {
613 SOC_DAPM_SINGLE("OUT3MIX LIN4RXN Bypass Switch", WM8991_OUT3_4_MIXER,
614 WM8991_LI4O3_BIT, 1, 0),
615 SOC_DAPM_SINGLE("OUT3MIX Left Out PGA Switch", WM8991_OUT3_4_MIXER,
616 WM8991_LPGAO3_BIT, 1, 0),
617};
618
619/* OUT4MIX */
620static const struct snd_kcontrol_new wm8991_dapm_out4mix_controls[] = {
621 SOC_DAPM_SINGLE("OUT4MIX Right Out PGA Switch", WM8991_OUT3_4_MIXER,
622 WM8991_RPGAO4_BIT, 1, 0),
623 SOC_DAPM_SINGLE("OUT4MIX RIN4RXP Bypass Switch", WM8991_OUT3_4_MIXER,
624 WM8991_RI4O4_BIT, 1, 0),
625};
626
627/* SPKMIX */
628static const struct snd_kcontrol_new wm8991_dapm_spkmix_controls[] = {
629 SOC_DAPM_SINGLE("SPKMIX LIN2 Bypass Switch", WM8991_SPEAKER_MIXER,
630 WM8991_LI2SPK_BIT, 1, 0),
631 SOC_DAPM_SINGLE("SPKMIX LADC Bypass Switch", WM8991_SPEAKER_MIXER,
632 WM8991_LB2SPK_BIT, 1, 0),
633 SOC_DAPM_SINGLE("SPKMIX Left Mixer PGA Switch", WM8991_SPEAKER_MIXER,
634 WM8991_LOPGASPK_BIT, 1, 0),
635 SOC_DAPM_SINGLE("SPKMIX Left DAC Switch", WM8991_SPEAKER_MIXER,
636 WM8991_LDSPK_BIT, 1, 0),
637 SOC_DAPM_SINGLE("SPKMIX Right DAC Switch", WM8991_SPEAKER_MIXER,
638 WM8991_RDSPK_BIT, 1, 0),
639 SOC_DAPM_SINGLE("SPKMIX Right Mixer PGA Switch", WM8991_SPEAKER_MIXER,
640 WM8991_ROPGASPK_BIT, 1, 0),
641 SOC_DAPM_SINGLE("SPKMIX RADC Bypass Switch", WM8991_SPEAKER_MIXER,
642 WM8991_RL12ROP_BIT, 1, 0),
643 SOC_DAPM_SINGLE("SPKMIX RIN2 Bypass Switch", WM8991_SPEAKER_MIXER,
644 WM8991_RI2SPK_BIT, 1, 0),
645};
646
647static const struct snd_soc_dapm_widget wm8991_dapm_widgets[] = {
648 /* Input Side */
649 /* Input Lines */
650 SND_SOC_DAPM_INPUT("LIN1"),
651 SND_SOC_DAPM_INPUT("LIN2"),
652 SND_SOC_DAPM_INPUT("LIN3"),
653 SND_SOC_DAPM_INPUT("LIN4RXN"),
654 SND_SOC_DAPM_INPUT("RIN3"),
655 SND_SOC_DAPM_INPUT("RIN4RXP"),
656 SND_SOC_DAPM_INPUT("RIN1"),
657 SND_SOC_DAPM_INPUT("RIN2"),
658 SND_SOC_DAPM_INPUT("Internal ADC Source"),
659
660 /* DACs */
661 SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8991_POWER_MANAGEMENT_2,
662 WM8991_ADCL_ENA_BIT, 0),
663 SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8991_POWER_MANAGEMENT_2,
664 WM8991_ADCR_ENA_BIT, 0),
665
666 /* Input PGAs */
667 SND_SOC_DAPM_MIXER("LIN12 PGA", WM8991_POWER_MANAGEMENT_2, WM8991_LIN12_ENA_BIT,
668 0, &wm8991_dapm_lin12_pga_controls[0],
669 ARRAY_SIZE(wm8991_dapm_lin12_pga_controls)),
670 SND_SOC_DAPM_MIXER("LIN34 PGA", WM8991_POWER_MANAGEMENT_2, WM8991_LIN34_ENA_BIT,
671 0, &wm8991_dapm_lin34_pga_controls[0],
672 ARRAY_SIZE(wm8991_dapm_lin34_pga_controls)),
673 SND_SOC_DAPM_MIXER("RIN12 PGA", WM8991_POWER_MANAGEMENT_2, WM8991_RIN12_ENA_BIT,
674 0, &wm8991_dapm_rin12_pga_controls[0],
675 ARRAY_SIZE(wm8991_dapm_rin12_pga_controls)),
676 SND_SOC_DAPM_MIXER("RIN34 PGA", WM8991_POWER_MANAGEMENT_2, WM8991_RIN34_ENA_BIT,
677 0, &wm8991_dapm_rin34_pga_controls[0],
678 ARRAY_SIZE(wm8991_dapm_rin34_pga_controls)),
679
680 /* INMIXL */
681 SND_SOC_DAPM_MIXER_E("INMIXL", WM8991_INTDRIVBITS, WM8991_INMIXL_PWR_BIT, 0,
682 &wm8991_dapm_inmixl_controls[0],
683 ARRAY_SIZE(wm8991_dapm_inmixl_controls),
684 inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
685
686 /* AINLMUX */
687 SND_SOC_DAPM_MUX_E("AINLMUX", WM8991_INTDRIVBITS, WM8991_AINLMUX_PWR_BIT, 0,
688 &wm8991_dapm_ainlmux_controls, inmixer_event,
689 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
690
691 /* INMIXR */
692 SND_SOC_DAPM_MIXER_E("INMIXR", WM8991_INTDRIVBITS, WM8991_INMIXR_PWR_BIT, 0,
693 &wm8991_dapm_inmixr_controls[0],
694 ARRAY_SIZE(wm8991_dapm_inmixr_controls),
695 inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
696
697 /* AINRMUX */
698 SND_SOC_DAPM_MUX_E("AINRMUX", WM8991_INTDRIVBITS, WM8991_AINRMUX_PWR_BIT, 0,
699 &wm8991_dapm_ainrmux_controls, inmixer_event,
700 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
701
702 /* Output Side */
703 /* DACs */
704 SND_SOC_DAPM_DAC("Left DAC", "Left Playback", WM8991_POWER_MANAGEMENT_3,
705 WM8991_DACL_ENA_BIT, 0),
706 SND_SOC_DAPM_DAC("Right DAC", "Right Playback", WM8991_POWER_MANAGEMENT_3,
707 WM8991_DACR_ENA_BIT, 0),
708
709 /* LOMIX */
710 SND_SOC_DAPM_MIXER_E("LOMIX", WM8991_POWER_MANAGEMENT_3, WM8991_LOMIX_ENA_BIT,
711 0, &wm8991_dapm_lomix_controls[0],
712 ARRAY_SIZE(wm8991_dapm_lomix_controls),
713 outmixer_event, SND_SOC_DAPM_PRE_REG),
714
715 /* LONMIX */
716 SND_SOC_DAPM_MIXER("LONMIX", WM8991_POWER_MANAGEMENT_3, WM8991_LON_ENA_BIT, 0,
717 &wm8991_dapm_lonmix_controls[0],
718 ARRAY_SIZE(wm8991_dapm_lonmix_controls)),
719
720 /* LOPMIX */
721 SND_SOC_DAPM_MIXER("LOPMIX", WM8991_POWER_MANAGEMENT_3, WM8991_LOP_ENA_BIT, 0,
722 &wm8991_dapm_lopmix_controls[0],
723 ARRAY_SIZE(wm8991_dapm_lopmix_controls)),
724
725 /* OUT3MIX */
726 SND_SOC_DAPM_MIXER("OUT3MIX", WM8991_POWER_MANAGEMENT_1, WM8991_OUT3_ENA_BIT, 0,
727 &wm8991_dapm_out3mix_controls[0],
728 ARRAY_SIZE(wm8991_dapm_out3mix_controls)),
729
730 /* SPKMIX */
731 SND_SOC_DAPM_MIXER_E("SPKMIX", WM8991_POWER_MANAGEMENT_1, WM8991_SPK_ENA_BIT, 0,
732 &wm8991_dapm_spkmix_controls[0],
733 ARRAY_SIZE(wm8991_dapm_spkmix_controls), outmixer_event,
734 SND_SOC_DAPM_PRE_REG),
735
736 /* OUT4MIX */
737 SND_SOC_DAPM_MIXER("OUT4MIX", WM8991_POWER_MANAGEMENT_1, WM8991_OUT4_ENA_BIT, 0,
738 &wm8991_dapm_out4mix_controls[0],
739 ARRAY_SIZE(wm8991_dapm_out4mix_controls)),
740
741 /* ROPMIX */
742 SND_SOC_DAPM_MIXER("ROPMIX", WM8991_POWER_MANAGEMENT_3, WM8991_ROP_ENA_BIT, 0,
743 &wm8991_dapm_ropmix_controls[0],
744 ARRAY_SIZE(wm8991_dapm_ropmix_controls)),
745
746 /* RONMIX */
747 SND_SOC_DAPM_MIXER("RONMIX", WM8991_POWER_MANAGEMENT_3, WM8991_RON_ENA_BIT, 0,
748 &wm8991_dapm_ronmix_controls[0],
749 ARRAY_SIZE(wm8991_dapm_ronmix_controls)),
750
751 /* ROMIX */
752 SND_SOC_DAPM_MIXER_E("ROMIX", WM8991_POWER_MANAGEMENT_3, WM8991_ROMIX_ENA_BIT,
753 0, &wm8991_dapm_romix_controls[0],
754 ARRAY_SIZE(wm8991_dapm_romix_controls),
755 outmixer_event, SND_SOC_DAPM_PRE_REG),
756
757 /* LOUT PGA */
758 SND_SOC_DAPM_PGA("LOUT PGA", WM8991_POWER_MANAGEMENT_1, WM8991_LOUT_ENA_BIT, 0,
759 NULL, 0),
760
761 /* ROUT PGA */
762 SND_SOC_DAPM_PGA("ROUT PGA", WM8991_POWER_MANAGEMENT_1, WM8991_ROUT_ENA_BIT, 0,
763 NULL, 0),
764
765 /* LOPGA */
766 SND_SOC_DAPM_PGA("LOPGA", WM8991_POWER_MANAGEMENT_3, WM8991_LOPGA_ENA_BIT, 0,
767 NULL, 0),
768
769 /* ROPGA */
770 SND_SOC_DAPM_PGA("ROPGA", WM8991_POWER_MANAGEMENT_3, WM8991_ROPGA_ENA_BIT, 0,
771 NULL, 0),
772
773 /* MICBIAS */
774 SND_SOC_DAPM_MICBIAS("MICBIAS", WM8991_POWER_MANAGEMENT_1,
775 WM8991_MICBIAS_ENA_BIT, 0),
776
777 SND_SOC_DAPM_OUTPUT("LON"),
778 SND_SOC_DAPM_OUTPUT("LOP"),
779 SND_SOC_DAPM_OUTPUT("OUT3"),
780 SND_SOC_DAPM_OUTPUT("LOUT"),
781 SND_SOC_DAPM_OUTPUT("SPKN"),
782 SND_SOC_DAPM_OUTPUT("SPKP"),
783 SND_SOC_DAPM_OUTPUT("ROUT"),
784 SND_SOC_DAPM_OUTPUT("OUT4"),
785 SND_SOC_DAPM_OUTPUT("ROP"),
786 SND_SOC_DAPM_OUTPUT("RON"),
787 SND_SOC_DAPM_OUTPUT("OUT"),
788
789 SND_SOC_DAPM_OUTPUT("Internal DAC Sink"),
790};
791
792static const struct snd_soc_dapm_route audio_map[] = {
793 /* Make DACs turn on when playing even if not mixed into any outputs */
794 {"Internal DAC Sink", NULL, "Left DAC"},
795 {"Internal DAC Sink", NULL, "Right DAC"},
796
797 /* Make ADCs turn on when recording even if not mixed from any inputs */
798 {"Left ADC", NULL, "Internal ADC Source"},
799 {"Right ADC", NULL, "Internal ADC Source"},
800
801 /* Input Side */
802 /* LIN12 PGA */
803 {"LIN12 PGA", "LIN1 Switch", "LIN1"},
804 {"LIN12 PGA", "LIN2 Switch", "LIN2"},
805 /* LIN34 PGA */
806 {"LIN34 PGA", "LIN3 Switch", "LIN3"},
807 {"LIN34 PGA", "LIN4 Switch", "LIN4RXN"},
808 /* INMIXL */
809 {"INMIXL", "Record Left Volume", "LOMIX"},
810 {"INMIXL", "LIN2 Volume", "LIN2"},
811 {"INMIXL", "LINPGA12 Switch", "LIN12 PGA"},
812 {"INMIXL", "LINPGA34 Switch", "LIN34 PGA"},
813 /* AINLMUX */
814 {"AINLMUX", "INMIXL Mix", "INMIXL"},
815 {"AINLMUX", "DIFFINL Mix", "LIN12 PGA"},
816 {"AINLMUX", "DIFFINL Mix", "LIN34 PGA"},
817 {"AINLMUX", "RXVOICE Mix", "LIN4RXN"},
818 {"AINLMUX", "RXVOICE Mix", "RIN4RXP"},
819 /* ADC */
820 {"Left ADC", NULL, "AINLMUX"},
821
822 /* RIN12 PGA */
823 {"RIN12 PGA", "RIN1 Switch", "RIN1"},
824 {"RIN12 PGA", "RIN2 Switch", "RIN2"},
825 /* RIN34 PGA */
826 {"RIN34 PGA", "RIN3 Switch", "RIN3"},
827 {"RIN34 PGA", "RIN4 Switch", "RIN4RXP"},
828 /* INMIXL */
829 {"INMIXR", "Record Right Volume", "ROMIX"},
830 {"INMIXR", "RIN2 Volume", "RIN2"},
831 {"INMIXR", "RINPGA12 Switch", "RIN12 PGA"},
832 {"INMIXR", "RINPGA34 Switch", "RIN34 PGA"},
833 /* AINRMUX */
834 {"AINRMUX", "INMIXR Mix", "INMIXR"},
835 {"AINRMUX", "DIFFINR Mix", "RIN12 PGA"},
836 {"AINRMUX", "DIFFINR Mix", "RIN34 PGA"},
837 {"AINRMUX", "RXVOICE Mix", "LIN4RXN"},
838 {"AINRMUX", "RXVOICE Mix", "RIN4RXP"},
839 /* ADC */
840 {"Right ADC", NULL, "AINRMUX"},
841
842 /* LOMIX */
843 {"LOMIX", "LOMIX RIN3 Bypass Switch", "RIN3"},
844 {"LOMIX", "LOMIX LIN3 Bypass Switch", "LIN3"},
845 {"LOMIX", "LOMIX LIN12 PGA Bypass Switch", "LIN12 PGA"},
846 {"LOMIX", "LOMIX RIN12 PGA Bypass Switch", "RIN12 PGA"},
847 {"LOMIX", "LOMIX Right ADC Bypass Switch", "AINRMUX"},
848 {"LOMIX", "LOMIX Left ADC Bypass Switch", "AINLMUX"},
849 {"LOMIX", "LOMIX Left DAC Switch", "Left DAC"},
850
851 /* ROMIX */
852 {"ROMIX", "ROMIX RIN3 Bypass Switch", "RIN3"},
853 {"ROMIX", "ROMIX LIN3 Bypass Switch", "LIN3"},
854 {"ROMIX", "ROMIX LIN12 PGA Bypass Switch", "LIN12 PGA"},
855 {"ROMIX", "ROMIX RIN12 PGA Bypass Switch", "RIN12 PGA"},
856 {"ROMIX", "ROMIX Right ADC Bypass Switch", "AINRMUX"},
857 {"ROMIX", "ROMIX Left ADC Bypass Switch", "AINLMUX"},
858 {"ROMIX", "ROMIX Right DAC Switch", "Right DAC"},
859
860 /* SPKMIX */
861 {"SPKMIX", "SPKMIX LIN2 Bypass Switch", "LIN2"},
862 {"SPKMIX", "SPKMIX RIN2 Bypass Switch", "RIN2"},
863 {"SPKMIX", "SPKMIX LADC Bypass Switch", "AINLMUX"},
864 {"SPKMIX", "SPKMIX RADC Bypass Switch", "AINRMUX"},
865 {"SPKMIX", "SPKMIX Left Mixer PGA Switch", "LOPGA"},
866 {"SPKMIX", "SPKMIX Right Mixer PGA Switch", "ROPGA"},
867 {"SPKMIX", "SPKMIX Right DAC Switch", "Right DAC"},
868 {"SPKMIX", "SPKMIX Left DAC Switch", "Right DAC"},
869
870 /* LONMIX */
871 {"LONMIX", "LONMIX Left Mixer PGA Switch", "LOPGA"},
872 {"LONMIX", "LONMIX Right Mixer PGA Switch", "ROPGA"},
873 {"LONMIX", "LONMIX Inverted LOP Switch", "LOPMIX"},
874
875 /* LOPMIX */
876 {"LOPMIX", "LOPMIX Right Mic Bypass Switch", "RIN12 PGA"},
877 {"LOPMIX", "LOPMIX Left Mic Bypass Switch", "LIN12 PGA"},
878 {"LOPMIX", "LOPMIX Left Mixer PGA Switch", "LOPGA"},
879
880 /* OUT3MIX */
881 {"OUT3MIX", "OUT3MIX LIN4RXN Bypass Switch", "LIN4RXN"},
882 {"OUT3MIX", "OUT3MIX Left Out PGA Switch", "LOPGA"},
883
884 /* OUT4MIX */
885 {"OUT4MIX", "OUT4MIX Right Out PGA Switch", "ROPGA"},
886 {"OUT4MIX", "OUT4MIX RIN4RXP Bypass Switch", "RIN4RXP"},
887
888 /* RONMIX */
889 {"RONMIX", "RONMIX Right Mixer PGA Switch", "ROPGA"},
890 {"RONMIX", "RONMIX Left Mixer PGA Switch", "LOPGA"},
891 {"RONMIX", "RONMIX Inverted ROP Switch", "ROPMIX"},
892
893 /* ROPMIX */
894 {"ROPMIX", "ROPMIX Left Mic Bypass Switch", "LIN12 PGA"},
895 {"ROPMIX", "ROPMIX Right Mic Bypass Switch", "RIN12 PGA"},
896 {"ROPMIX", "ROPMIX Right Mixer PGA Switch", "ROPGA"},
897
898 /* Out Mixer PGAs */
899 {"LOPGA", NULL, "LOMIX"},
900 {"ROPGA", NULL, "ROMIX"},
901
902 {"LOUT PGA", NULL, "LOMIX"},
903 {"ROUT PGA", NULL, "ROMIX"},
904
905 /* Output Pins */
906 {"LON", NULL, "LONMIX"},
907 {"LOP", NULL, "LOPMIX"},
908 {"OUT", NULL, "OUT3MIX"},
909 {"LOUT", NULL, "LOUT PGA"},
910 {"SPKN", NULL, "SPKMIX"},
911 {"ROUT", NULL, "ROUT PGA"},
912 {"OUT4", NULL, "OUT4MIX"},
913 {"ROP", NULL, "ROPMIX"},
914 {"RON", NULL, "RONMIX"},
915};
916
917/* PLL divisors */
918struct _pll_div {
919 u32 div2;
920 u32 n;
921 u32 k;
922};
923
924/* The size in bits of the pll divide multiplied by 10
925 * to allow rounding later */
926#define FIXED_PLL_SIZE ((1 << 16) * 10)
927
928static void pll_factors(struct _pll_div *pll_div, unsigned int target,
929 unsigned int source)
930{
931 u64 Kpart;
932 unsigned int K, Ndiv, Nmod;
933
934
935 Ndiv = target / source;
936 if (Ndiv < 6) {
937 source >>= 1;
938 pll_div->div2 = 1;
939 Ndiv = target / source;
940 } else
941 pll_div->div2 = 0;
942
943 if ((Ndiv < 6) || (Ndiv > 12))
944 printk(KERN_WARNING
945 "WM8991 N value outwith recommended range! N = %d\n", Ndiv);
946
947 pll_div->n = Ndiv;
948 Nmod = target % source;
949 Kpart = FIXED_PLL_SIZE * (long long)Nmod;
950
951 do_div(Kpart, source);
952
953 K = Kpart & 0xFFFFFFFF;
954
955 /* Check if we need to round */
956 if ((K % 10) >= 5)
957 K += 5;
958
959 /* Move down to proper range now rounding is done */
960 K /= 10;
961
962 pll_div->k = K;
963}
964
965static int wm8991_set_dai_pll(struct snd_soc_dai *codec_dai,
966 int pll_id, int src, unsigned int freq_in, unsigned int freq_out)
967{
968 u16 reg;
969 struct snd_soc_codec *codec = codec_dai->codec;
970 struct _pll_div pll_div;
971
972 if (freq_in && freq_out) {
973 pll_factors(&pll_div, freq_out * 4, freq_in);
974
975 /* Turn on PLL */
976 reg = snd_soc_read(codec, WM8991_POWER_MANAGEMENT_2);
977 reg |= WM8991_PLL_ENA;
978 snd_soc_write(codec, WM8991_POWER_MANAGEMENT_2, reg);
979
980 /* sysclk comes from PLL */
981 reg = snd_soc_read(codec, WM8991_CLOCKING_2);
982 snd_soc_write(codec, WM8991_CLOCKING_2, reg | WM8991_SYSCLK_SRC);
983
984 /* set up N , fractional mode and pre-divisor if neccessary */
985 snd_soc_write(codec, WM8991_PLL1, pll_div.n | WM8991_SDM |
986 (pll_div.div2 ? WM8991_PRESCALE : 0));
987 snd_soc_write(codec, WM8991_PLL2, (u8)(pll_div.k>>8));
988 snd_soc_write(codec, WM8991_PLL3, (u8)(pll_div.k & 0xFF));
989 } else {
990 /* Turn on PLL */
991 reg = snd_soc_read(codec, WM8991_POWER_MANAGEMENT_2);
992 reg &= ~WM8991_PLL_ENA;
993 snd_soc_write(codec, WM8991_POWER_MANAGEMENT_2, reg);
994 }
995 return 0;
996}
997
998/*
999 * Set's ADC and Voice DAC format.
1000 */
1001static int wm8991_set_dai_fmt(struct snd_soc_dai *codec_dai,
1002 unsigned int fmt)
1003{
1004 struct snd_soc_codec *codec = codec_dai->codec;
1005 u16 audio1, audio3;
1006
1007 audio1 = snd_soc_read(codec, WM8991_AUDIO_INTERFACE_1);
1008 audio3 = snd_soc_read(codec, WM8991_AUDIO_INTERFACE_3);
1009
1010 /* set master/slave audio interface */
1011 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
1012 case SND_SOC_DAIFMT_CBS_CFS:
1013 audio3 &= ~WM8991_AIF_MSTR1;
1014 break;
1015 case SND_SOC_DAIFMT_CBM_CFM:
1016 audio3 |= WM8991_AIF_MSTR1;
1017 break;
1018 default:
1019 return -EINVAL;
1020 }
1021
1022 audio1 &= ~WM8991_AIF_FMT_MASK;
1023
1024 /* interface format */
1025 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
1026 case SND_SOC_DAIFMT_I2S:
1027 audio1 |= WM8991_AIF_TMF_I2S;
1028 audio1 &= ~WM8991_AIF_LRCLK_INV;
1029 break;
1030 case SND_SOC_DAIFMT_RIGHT_J:
1031 audio1 |= WM8991_AIF_TMF_RIGHTJ;
1032 audio1 &= ~WM8991_AIF_LRCLK_INV;
1033 break;
1034 case SND_SOC_DAIFMT_LEFT_J:
1035 audio1 |= WM8991_AIF_TMF_LEFTJ;
1036 audio1 &= ~WM8991_AIF_LRCLK_INV;
1037 break;
1038 case SND_SOC_DAIFMT_DSP_A:
1039 audio1 |= WM8991_AIF_TMF_DSP;
1040 audio1 &= ~WM8991_AIF_LRCLK_INV;
1041 break;
1042 case SND_SOC_DAIFMT_DSP_B:
1043 audio1 |= WM8991_AIF_TMF_DSP | WM8991_AIF_LRCLK_INV;
1044 break;
1045 default:
1046 return -EINVAL;
1047 }
1048
1049 snd_soc_write(codec, WM8991_AUDIO_INTERFACE_1, audio1);
1050 snd_soc_write(codec, WM8991_AUDIO_INTERFACE_3, audio3);
1051 return 0;
1052}
1053
1054static int wm8991_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
1055 int div_id, int div)
1056{
1057 struct snd_soc_codec *codec = codec_dai->codec;
1058 u16 reg;
1059
1060 switch (div_id) {
1061 case WM8991_MCLK_DIV:
1062 reg = snd_soc_read(codec, WM8991_CLOCKING_2) &
1063 ~WM8991_MCLK_DIV_MASK;
1064 snd_soc_write(codec, WM8991_CLOCKING_2, reg | div);
1065 break;
1066 case WM8991_DACCLK_DIV:
1067 reg = snd_soc_read(codec, WM8991_CLOCKING_2) &
1068 ~WM8991_DAC_CLKDIV_MASK;
1069 snd_soc_write(codec, WM8991_CLOCKING_2, reg | div);
1070 break;
1071 case WM8991_ADCCLK_DIV:
1072 reg = snd_soc_read(codec, WM8991_CLOCKING_2) &
1073 ~WM8991_ADC_CLKDIV_MASK;
1074 snd_soc_write(codec, WM8991_CLOCKING_2, reg | div);
1075 break;
1076 case WM8991_BCLK_DIV:
1077 reg = snd_soc_read(codec, WM8991_CLOCKING_1) &
1078 ~WM8991_BCLK_DIV_MASK;
1079 snd_soc_write(codec, WM8991_CLOCKING_1, reg | div);
1080 break;
1081 default:
1082 return -EINVAL;
1083 }
1084
1085 return 0;
1086}
1087
1088/*
1089 * Set PCM DAI bit size and sample rate.
1090 */
1091static int wm8991_hw_params(struct snd_pcm_substream *substream,
1092 struct snd_pcm_hw_params *params,
1093 struct snd_soc_dai *dai)
1094{
1095 struct snd_soc_codec *codec = dai->codec;
1096 u16 audio1 = snd_soc_read(codec, WM8991_AUDIO_INTERFACE_1);
1097
1098 audio1 &= ~WM8991_AIF_WL_MASK;
1099 /* bit size */
1100 switch (params_format(params)) {
1101 case SNDRV_PCM_FORMAT_S16_LE:
1102 break;
1103 case SNDRV_PCM_FORMAT_S20_3LE:
1104 audio1 |= WM8991_AIF_WL_20BITS;
1105 break;
1106 case SNDRV_PCM_FORMAT_S24_LE:
1107 audio1 |= WM8991_AIF_WL_24BITS;
1108 break;
1109 case SNDRV_PCM_FORMAT_S32_LE:
1110 audio1 |= WM8991_AIF_WL_32BITS;
1111 break;
1112 }
1113
1114 snd_soc_write(codec, WM8991_AUDIO_INTERFACE_1, audio1);
1115 return 0;
1116}
1117
1118static int wm8991_mute(struct snd_soc_dai *dai, int mute)
1119{
1120 struct snd_soc_codec *codec = dai->codec;
1121 u16 val;
1122
1123 val = snd_soc_read(codec, WM8991_DAC_CTRL) & ~WM8991_DAC_MUTE;
1124 if (mute)
1125 snd_soc_write(codec, WM8991_DAC_CTRL, val | WM8991_DAC_MUTE);
1126 else
1127 snd_soc_write(codec, WM8991_DAC_CTRL, val);
1128 return 0;
1129}
1130
1131static int wm8991_set_bias_level(struct snd_soc_codec *codec,
1132 enum snd_soc_bias_level level)
1133{
1134 u16 val;
1135
1136 switch (level) {
1137 case SND_SOC_BIAS_ON:
1138 break;
1139
1140 case SND_SOC_BIAS_PREPARE:
1141 /* VMID=2*50k */
1142 val = snd_soc_read(codec, WM8991_POWER_MANAGEMENT_1) &
1143 ~WM8991_VMID_MODE_MASK;
1144 snd_soc_write(codec, WM8991_POWER_MANAGEMENT_1, val | 0x2);
1145 break;
1146
1147 case SND_SOC_BIAS_STANDBY:
1148 if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
1149 snd_soc_cache_sync(codec);
1150 /* Enable all output discharge bits */
1151 snd_soc_write(codec, WM8991_ANTIPOP1, WM8991_DIS_LLINE |
1152 WM8991_DIS_RLINE | WM8991_DIS_OUT3 |
1153 WM8991_DIS_OUT4 | WM8991_DIS_LOUT |
1154 WM8991_DIS_ROUT);
1155
1156 /* Enable POBCTRL, SOFT_ST, VMIDTOG and BUFDCOPEN */
1157 snd_soc_write(codec, WM8991_ANTIPOP2, WM8991_SOFTST |
1158 WM8991_BUFDCOPEN | WM8991_POBCTRL |
1159 WM8991_VMIDTOG);
1160
1161 /* Delay to allow output caps to discharge */
1162 msleep(300);
1163
1164 /* Disable VMIDTOG */
1165 snd_soc_write(codec, WM8991_ANTIPOP2, WM8991_SOFTST |
1166 WM8991_BUFDCOPEN | WM8991_POBCTRL);
1167
1168 /* disable all output discharge bits */
1169 snd_soc_write(codec, WM8991_ANTIPOP1, 0);
1170
1171 /* Enable outputs */
1172 snd_soc_write(codec, WM8991_POWER_MANAGEMENT_1, 0x1b00);
1173
1174 msleep(50);
1175
1176 /* Enable VMID at 2x50k */
1177 snd_soc_write(codec, WM8991_POWER_MANAGEMENT_1, 0x1f02);
1178
1179 msleep(100);
1180
1181 /* Enable VREF */
1182 snd_soc_write(codec, WM8991_POWER_MANAGEMENT_1, 0x1f03);
1183
1184 msleep(600);
1185
1186 /* Enable BUFIOEN */
1187 snd_soc_write(codec, WM8991_ANTIPOP2, WM8991_SOFTST |
1188 WM8991_BUFDCOPEN | WM8991_POBCTRL |
1189 WM8991_BUFIOEN);
1190
1191 /* Disable outputs */
1192 snd_soc_write(codec, WM8991_POWER_MANAGEMENT_1, 0x3);
1193
1194 /* disable POBCTRL, SOFT_ST and BUFDCOPEN */
1195 snd_soc_write(codec, WM8991_ANTIPOP2, WM8991_BUFIOEN);
1196 }
1197
1198 /* VMID=2*250k */
1199 val = snd_soc_read(codec, WM8991_POWER_MANAGEMENT_1) &
1200 ~WM8991_VMID_MODE_MASK;
1201 snd_soc_write(codec, WM8991_POWER_MANAGEMENT_1, val | 0x4);
1202 break;
1203
1204 case SND_SOC_BIAS_OFF:
1205 /* Enable POBCTRL and SOFT_ST */
1206 snd_soc_write(codec, WM8991_ANTIPOP2, WM8991_SOFTST |
1207 WM8991_POBCTRL | WM8991_BUFIOEN);
1208
1209 /* Enable POBCTRL, SOFT_ST and BUFDCOPEN */
1210 snd_soc_write(codec, WM8991_ANTIPOP2, WM8991_SOFTST |
1211 WM8991_BUFDCOPEN | WM8991_POBCTRL |
1212 WM8991_BUFIOEN);
1213
1214 /* mute DAC */
1215 val = snd_soc_read(codec, WM8991_DAC_CTRL);
1216 snd_soc_write(codec, WM8991_DAC_CTRL, val | WM8991_DAC_MUTE);
1217
1218 /* Enable any disabled outputs */
1219 snd_soc_write(codec, WM8991_POWER_MANAGEMENT_1, 0x1f03);
1220
1221 /* Disable VMID */
1222 snd_soc_write(codec, WM8991_POWER_MANAGEMENT_1, 0x1f01);
1223
1224 msleep(300);
1225
1226 /* Enable all output discharge bits */
1227 snd_soc_write(codec, WM8991_ANTIPOP1, WM8991_DIS_LLINE |
1228 WM8991_DIS_RLINE | WM8991_DIS_OUT3 |
1229 WM8991_DIS_OUT4 | WM8991_DIS_LOUT |
1230 WM8991_DIS_ROUT);
1231
1232 /* Disable VREF */
1233 snd_soc_write(codec, WM8991_POWER_MANAGEMENT_1, 0x0);
1234
1235 /* disable POBCTRL, SOFT_ST and BUFDCOPEN */
1236 snd_soc_write(codec, WM8991_ANTIPOP2, 0x0);
1237 codec->cache_sync = 1;
1238 break;
1239 }
1240
1241 codec->dapm.bias_level = level;
1242 return 0;
1243}
1244
1245static int wm8991_suspend(struct snd_soc_codec *codec, pm_message_t state)
1246{
1247 wm8991_set_bias_level(codec, SND_SOC_BIAS_OFF);
1248 return 0;
1249}
1250
1251static int wm8991_resume(struct snd_soc_codec *codec)
1252{
1253 wm8991_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1254 return 0;
1255}
1256
1257/* power down chip */
1258static int wm8991_remove(struct snd_soc_codec *codec)
1259{
1260 wm8991_set_bias_level(codec, SND_SOC_BIAS_OFF);
1261 return 0;
1262}
1263
1264static int wm8991_probe(struct snd_soc_codec *codec)
1265{
1266 struct wm8991_priv *wm8991;
1267 int ret;
1268 unsigned int reg;
1269
1270 wm8991 = snd_soc_codec_get_drvdata(codec);
1271
1272 ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8991->control_type);
1273 if (ret < 0) {
1274 dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret);
1275 return ret;
1276 }
1277
1278 ret = wm8991_reset(codec);
1279 if (ret < 0) {
1280 dev_err(codec->dev, "Failed to issue reset\n");
1281 return ret;
1282 }
1283
1284 wm8991_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1285
1286 reg = snd_soc_read(codec, WM8991_AUDIO_INTERFACE_4);
1287 snd_soc_write(codec, WM8991_AUDIO_INTERFACE_4, reg | WM8991_ALRCGPIO1);
1288
1289 reg = snd_soc_read(codec, WM8991_GPIO1_GPIO2) &
1290 ~WM8991_GPIO1_SEL_MASK;
1291 snd_soc_write(codec, WM8991_GPIO1_GPIO2, reg | 1);
1292
1293 reg = snd_soc_read(codec, WM8991_POWER_MANAGEMENT_1);
1294 snd_soc_write(codec, WM8991_POWER_MANAGEMENT_1, reg | WM8991_VREF_ENA|
1295 WM8991_VMID_MODE_MASK);
1296
1297 reg = snd_soc_read(codec, WM8991_POWER_MANAGEMENT_2);
1298 snd_soc_write(codec, WM8991_POWER_MANAGEMENT_2, reg | WM8991_OPCLK_ENA);
1299
1300 snd_soc_write(codec, WM8991_DAC_CTRL, 0);
1301 snd_soc_write(codec, WM8991_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8));
1302 snd_soc_write(codec, WM8991_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8));
1303
1304 snd_soc_add_controls(codec, wm8991_snd_controls,
1305 ARRAY_SIZE(wm8991_snd_controls));
1306
1307 snd_soc_dapm_new_controls(&codec->dapm, wm8991_dapm_widgets,
1308 ARRAY_SIZE(wm8991_dapm_widgets));
1309 snd_soc_dapm_add_routes(&codec->dapm, audio_map,
1310 ARRAY_SIZE(audio_map));
1311 return 0;
1312}
1313
1314#define WM8991_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
1315 SNDRV_PCM_FMTBIT_S24_LE)
1316
1317static struct snd_soc_dai_ops wm8991_ops = {
1318 .hw_params = wm8991_hw_params,
1319 .digital_mute = wm8991_mute,
1320 .set_fmt = wm8991_set_dai_fmt,
1321 .set_clkdiv = wm8991_set_dai_clkdiv,
1322 .set_pll = wm8991_set_dai_pll
1323};
1324
1325/*
1326 * The WM8991 supports 2 different and mutually exclusive DAI
1327 * configurations.
1328 *
1329 * 1. ADC/DAC on Primary Interface
1330 * 2. ADC on Primary Interface/DAC on secondary
1331 */
1332static struct snd_soc_dai_driver wm8991_dai = {
1333 /* ADC/DAC on primary */
1334 .name = "wm8991",
1335 .id = 1,
1336 .playback = {
1337 .stream_name = "Playback",
1338 .channels_min = 1,
1339 .channels_max = 2,
1340 .rates = SNDRV_PCM_RATE_8000_96000,
1341 .formats = WM8991_FORMATS
1342 },
1343 .capture = {
1344 .stream_name = "Capture",
1345 .channels_min = 1,
1346 .channels_max = 2,
1347 .rates = SNDRV_PCM_RATE_8000_96000,
1348 .formats = WM8991_FORMATS
1349 },
1350 .ops = &wm8991_ops
1351};
1352
1353static struct snd_soc_codec_driver soc_codec_dev_wm8991 = {
1354 .probe = wm8991_probe,
1355 .remove = wm8991_remove,
1356 .suspend = wm8991_suspend,
1357 .resume = wm8991_resume,
1358 .set_bias_level = wm8991_set_bias_level,
1359 .reg_cache_size = WM8991_MAX_REGISTER + 1,
1360 .reg_word_size = sizeof(u16),
1361 .reg_cache_default = wm8991_reg_defs
1362};
1363
1364static __devinit int wm8991_i2c_probe(struct i2c_client *i2c,
1365 const struct i2c_device_id *id)
1366{
1367 struct wm8991_priv *wm8991;
1368 int ret;
1369
1370 wm8991 = kzalloc(sizeof *wm8991, GFP_KERNEL);
1371 if (!wm8991)
1372 return -ENOMEM;
1373
1374 wm8991->control_type = SND_SOC_I2C;
1375 i2c_set_clientdata(i2c, wm8991);
1376
1377 ret = snd_soc_register_codec(&i2c->dev,
1378 &soc_codec_dev_wm8991, &wm8991_dai, 1);
1379 if (ret < 0)
1380 kfree(wm8991);
1381 return ret;
1382}
1383
1384static __devexit int wm8991_i2c_remove(struct i2c_client *client)
1385{
1386 snd_soc_unregister_codec(&client->dev);
1387 kfree(i2c_get_clientdata(client));
1388 return 0;
1389}
1390
1391static const struct i2c_device_id wm8991_i2c_id[] = {
1392 { "wm8991", 0 },
1393 { }
1394};
1395MODULE_DEVICE_TABLE(i2c, wm8991_i2c_id);
1396
1397static struct i2c_driver wm8991_i2c_driver = {
1398 .driver = {
1399 .name = "wm8991",
1400 .owner = THIS_MODULE,
1401 },
1402 .probe = wm8991_i2c_probe,
1403 .remove = __devexit_p(wm8991_i2c_remove),
1404 .id_table = wm8991_i2c_id,
1405};
1406
1407static int __init wm8991_modinit(void)
1408{
1409 int ret;
1410 ret = i2c_add_driver(&wm8991_i2c_driver);
1411 if (ret != 0) {
1412 printk(KERN_ERR "Failed to register WM8991 I2C driver: %d\n",
1413 ret);
1414 }
1415 return 0;
1416}
1417module_init(wm8991_modinit);
1418
1419static void __exit wm8991_exit(void)
1420{
1421 i2c_del_driver(&wm8991_i2c_driver);
1422}
1423module_exit(wm8991_exit);
1424
1425MODULE_DESCRIPTION("ASoC WM8991 driver");
1426MODULE_AUTHOR("Graeme Gregory");
1427MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8991.h b/sound/soc/codecs/wm8991.h
new file mode 100644
index 000000000000..8a942efd18a5
--- /dev/null
+++ b/sound/soc/codecs/wm8991.h
@@ -0,0 +1,833 @@
1/*
2 * wm8991.h -- audio driver for WM8991
3 *
4 * Copyright 2007 Wolfson Microelectronics PLC.
5 * Author: Graeme Gregory
6 * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.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#ifndef _WM8991_H
15#define _WM8991_H
16
17/*
18 * Register values.
19 */
20#define WM8991_RESET 0x00
21#define WM8991_POWER_MANAGEMENT_1 0x01
22#define WM8991_POWER_MANAGEMENT_2 0x02
23#define WM8991_POWER_MANAGEMENT_3 0x03
24#define WM8991_AUDIO_INTERFACE_1 0x04
25#define WM8991_AUDIO_INTERFACE_2 0x05
26#define WM8991_CLOCKING_1 0x06
27#define WM8991_CLOCKING_2 0x07
28#define WM8991_AUDIO_INTERFACE_3 0x08
29#define WM8991_AUDIO_INTERFACE_4 0x09
30#define WM8991_DAC_CTRL 0x0A
31#define WM8991_LEFT_DAC_DIGITAL_VOLUME 0x0B
32#define WM8991_RIGHT_DAC_DIGITAL_VOLUME 0x0C
33#define WM8991_DIGITAL_SIDE_TONE 0x0D
34#define WM8991_ADC_CTRL 0x0E
35#define WM8991_LEFT_ADC_DIGITAL_VOLUME 0x0F
36#define WM8991_RIGHT_ADC_DIGITAL_VOLUME 0x10
37#define WM8991_GPIO_CTRL_1 0x12
38#define WM8991_GPIO1_GPIO2 0x13
39#define WM8991_GPIO3_GPIO4 0x14
40#define WM8991_GPIO5_GPIO6 0x15
41#define WM8991_GPIOCTRL_2 0x16
42#define WM8991_GPIO_POL 0x17
43#define WM8991_LEFT_LINE_INPUT_1_2_VOLUME 0x18
44#define WM8991_LEFT_LINE_INPUT_3_4_VOLUME 0x19
45#define WM8991_RIGHT_LINE_INPUT_1_2_VOLUME 0x1A
46#define WM8991_RIGHT_LINE_INPUT_3_4_VOLUME 0x1B
47#define WM8991_LEFT_OUTPUT_VOLUME 0x1C
48#define WM8991_RIGHT_OUTPUT_VOLUME 0x1D
49#define WM8991_LINE_OUTPUTS_VOLUME 0x1E
50#define WM8991_OUT3_4_VOLUME 0x1F
51#define WM8991_LEFT_OPGA_VOLUME 0x20
52#define WM8991_RIGHT_OPGA_VOLUME 0x21
53#define WM8991_SPEAKER_VOLUME 0x22
54#define WM8991_CLASSD1 0x23
55#define WM8991_CLASSD3 0x25
56#define WM8991_INPUT_MIXER1 0x27
57#define WM8991_INPUT_MIXER2 0x28
58#define WM8991_INPUT_MIXER3 0x29
59#define WM8991_INPUT_MIXER4 0x2A
60#define WM8991_INPUT_MIXER5 0x2B
61#define WM8991_INPUT_MIXER6 0x2C
62#define WM8991_OUTPUT_MIXER1 0x2D
63#define WM8991_OUTPUT_MIXER2 0x2E
64#define WM8991_OUTPUT_MIXER3 0x2F
65#define WM8991_OUTPUT_MIXER4 0x30
66#define WM8991_OUTPUT_MIXER5 0x31
67#define WM8991_OUTPUT_MIXER6 0x32
68#define WM8991_OUT3_4_MIXER 0x33
69#define WM8991_LINE_MIXER1 0x34
70#define WM8991_LINE_MIXER2 0x35
71#define WM8991_SPEAKER_MIXER 0x36
72#define WM8991_ADDITIONAL_CONTROL 0x37
73#define WM8991_ANTIPOP1 0x38
74#define WM8991_ANTIPOP2 0x39
75#define WM8991_MICBIAS 0x3A
76#define WM8991_PLL1 0x3C
77#define WM8991_PLL2 0x3D
78#define WM8991_PLL3 0x3E
79#define WM8991_INTDRIVBITS 0x3F
80
81#define WM8991_REGISTER_COUNT 60
82#define WM8991_MAX_REGISTER 0x3F
83
84/*
85 * Field Definitions.
86 */
87
88/*
89 * R0 (0x00) - Reset
90 */
91#define WM8991_SW_RESET_CHIP_ID_MASK 0xFFFF /* SW_RESET_CHIP_ID - [15:0] */
92
93/*
94 * R1 (0x01) - Power Management (1)
95 */
96#define WM8991_SPK_ENA 0x1000 /* SPK_ENA */
97#define WM8991_SPK_ENA_BIT 12
98#define WM8991_OUT3_ENA 0x0800 /* OUT3_ENA */
99#define WM8991_OUT3_ENA_BIT 11
100#define WM8991_OUT4_ENA 0x0400 /* OUT4_ENA */
101#define WM8991_OUT4_ENA_BIT 10
102#define WM8991_LOUT_ENA 0x0200 /* LOUT_ENA */
103#define WM8991_LOUT_ENA_BIT 9
104#define WM8991_ROUT_ENA 0x0100 /* ROUT_ENA */
105#define WM8991_ROUT_ENA_BIT 8
106#define WM8991_MICBIAS_ENA 0x0010 /* MICBIAS_ENA */
107#define WM8991_MICBIAS_ENA_BIT 4
108#define WM8991_VMID_MODE_MASK 0x0006 /* VMID_MODE - [2:1] */
109#define WM8991_VREF_ENA 0x0001 /* VREF_ENA */
110#define WM8991_VREF_ENA_BIT 0
111
112/*
113 * R2 (0x02) - Power Management (2)
114 */
115#define WM8991_PLL_ENA 0x8000 /* PLL_ENA */
116#define WM8991_PLL_ENA_BIT 15
117#define WM8991_TSHUT_ENA 0x4000 /* TSHUT_ENA */
118#define WM8991_TSHUT_ENA_BIT 14
119#define WM8991_TSHUT_OPDIS 0x2000 /* TSHUT_OPDIS */
120#define WM8991_TSHUT_OPDIS_BIT 13
121#define WM8991_OPCLK_ENA 0x0800 /* OPCLK_ENA */
122#define WM8991_OPCLK_ENA_BIT 11
123#define WM8991_AINL_ENA 0x0200 /* AINL_ENA */
124#define WM8991_AINL_ENA_BIT 9
125#define WM8991_AINR_ENA 0x0100 /* AINR_ENA */
126#define WM8991_AINR_ENA_BIT 8
127#define WM8991_LIN34_ENA 0x0080 /* LIN34_ENA */
128#define WM8991_LIN34_ENA_BIT 7
129#define WM8991_LIN12_ENA 0x0040 /* LIN12_ENA */
130#define WM8991_LIN12_ENA_BIT 6
131#define WM8991_RIN34_ENA 0x0020 /* RIN34_ENA */
132#define WM8991_RIN34_ENA_BIT 5
133#define WM8991_RIN12_ENA 0x0010 /* RIN12_ENA */
134#define WM8991_RIN12_ENA_BIT 4
135#define WM8991_ADCL_ENA 0x0002 /* ADCL_ENA */
136#define WM8991_ADCL_ENA_BIT 1
137#define WM8991_ADCR_ENA 0x0001 /* ADCR_ENA */
138#define WM8991_ADCR_ENA_BIT 0
139
140/*
141 * R3 (0x03) - Power Management (3)
142 */
143#define WM8991_LON_ENA 0x2000 /* LON_ENA */
144#define WM8991_LON_ENA_BIT 13
145#define WM8991_LOP_ENA 0x1000 /* LOP_ENA */
146#define WM8991_LOP_ENA_BIT 12
147#define WM8991_RON_ENA 0x0800 /* RON_ENA */
148#define WM8991_RON_ENA_BIT 11
149#define WM8991_ROP_ENA 0x0400 /* ROP_ENA */
150#define WM8991_ROP_ENA_BIT 10
151#define WM8991_LOPGA_ENA 0x0080 /* LOPGA_ENA */
152#define WM8991_LOPGA_ENA_BIT 7
153#define WM8991_ROPGA_ENA 0x0040 /* ROPGA_ENA */
154#define WM8991_ROPGA_ENA_BIT 6
155#define WM8991_LOMIX_ENA 0x0020 /* LOMIX_ENA */
156#define WM8991_LOMIX_ENA_BIT 5
157#define WM8991_ROMIX_ENA 0x0010 /* ROMIX_ENA */
158#define WM8991_ROMIX_ENA_BIT 4
159#define WM8991_DACL_ENA 0x0002 /* DACL_ENA */
160#define WM8991_DACL_ENA_BIT 1
161#define WM8991_DACR_ENA 0x0001 /* DACR_ENA */
162#define WM8991_DACR_ENA_BIT 0
163
164/*
165 * R4 (0x04) - Audio Interface (1)
166 */
167#define WM8991_AIFADCL_SRC 0x8000 /* AIFADCL_SRC */
168#define WM8991_AIFADCR_SRC 0x4000 /* AIFADCR_SRC */
169#define WM8991_AIFADC_TDM 0x2000 /* AIFADC_TDM */
170#define WM8991_AIFADC_TDM_CHAN 0x1000 /* AIFADC_TDM_CHAN */
171#define WM8991_AIF_BCLK_INV 0x0100 /* AIF_BCLK_INV */
172#define WM8991_AIF_LRCLK_INV 0x0080 /* AIF_LRCLK_INV */
173#define WM8991_AIF_WL_MASK 0x0060 /* AIF_WL - [6:5] */
174#define WM8991_AIF_WL_16BITS (0 << 5)
175#define WM8991_AIF_WL_20BITS (1 << 5)
176#define WM8991_AIF_WL_24BITS (2 << 5)
177#define WM8991_AIF_WL_32BITS (3 << 5)
178#define WM8991_AIF_FMT_MASK 0x0018 /* AIF_FMT - [4:3] */
179#define WM8991_AIF_TMF_RIGHTJ (0 << 3)
180#define WM8991_AIF_TMF_LEFTJ (1 << 3)
181#define WM8991_AIF_TMF_I2S (2 << 3)
182#define WM8991_AIF_TMF_DSP (3 << 3)
183
184/*
185 * R5 (0x05) - Audio Interface (2)
186 */
187#define WM8991_DACL_SRC 0x8000 /* DACL_SRC */
188#define WM8991_DACR_SRC 0x4000 /* DACR_SRC */
189#define WM8991_AIFDAC_TDM 0x2000 /* AIFDAC_TDM */
190#define WM8991_AIFDAC_TDM_CHAN 0x1000 /* AIFDAC_TDM_CHAN */
191#define WM8991_DAC_BOOST_MASK 0x0C00 /* DAC_BOOST - [11:10] */
192#define WM8991_DAC_COMP 0x0010 /* DAC_COMP */
193#define WM8991_DAC_COMPMODE 0x0008 /* DAC_COMPMODE */
194#define WM8991_ADC_COMP 0x0004 /* ADC_COMP */
195#define WM8991_ADC_COMPMODE 0x0002 /* ADC_COMPMODE */
196#define WM8991_LOOPBACK 0x0001 /* LOOPBACK */
197
198/*
199 * R6 (0x06) - Clocking (1)
200 */
201#define WM8991_TOCLK_RATE 0x8000 /* TOCLK_RATE */
202#define WM8991_TOCLK_ENA 0x4000 /* TOCLK_ENA */
203#define WM8991_OPCLKDIV_MASK 0x1E00 /* OPCLKDIV - [12:9] */
204#define WM8991_DCLKDIV_MASK 0x01C0 /* DCLKDIV - [8:6] */
205#define WM8991_BCLK_DIV_MASK 0x001E /* BCLK_DIV - [4:1] */
206#define WM8991_BCLK_DIV_1 (0x0 << 1)
207#define WM8991_BCLK_DIV_1_5 (0x1 << 1)
208#define WM8991_BCLK_DIV_2 (0x2 << 1)
209#define WM8991_BCLK_DIV_3 (0x3 << 1)
210#define WM8991_BCLK_DIV_4 (0x4 << 1)
211#define WM8991_BCLK_DIV_5_5 (0x5 << 1)
212#define WM8991_BCLK_DIV_6 (0x6 << 1)
213#define WM8991_BCLK_DIV_8 (0x7 << 1)
214#define WM8991_BCLK_DIV_11 (0x8 << 1)
215#define WM8991_BCLK_DIV_12 (0x9 << 1)
216#define WM8991_BCLK_DIV_16 (0xA << 1)
217#define WM8991_BCLK_DIV_22 (0xB << 1)
218#define WM8991_BCLK_DIV_24 (0xC << 1)
219#define WM8991_BCLK_DIV_32 (0xD << 1)
220#define WM8991_BCLK_DIV_44 (0xE << 1)
221#define WM8991_BCLK_DIV_48 (0xF << 1)
222
223/*
224 * R7 (0x07) - Clocking (2)
225 */
226#define WM8991_MCLK_SRC 0x8000 /* MCLK_SRC */
227#define WM8991_SYSCLK_SRC 0x4000 /* SYSCLK_SRC */
228#define WM8991_CLK_FORCE 0x2000 /* CLK_FORCE */
229#define WM8991_MCLK_DIV_MASK 0x1800 /* MCLK_DIV - [12:11] */
230#define WM8991_MCLK_DIV_1 (0 << 11)
231#define WM8991_MCLK_DIV_2 ( 2 << 11)
232#define WM8991_MCLK_INV 0x0400 /* MCLK_INV */
233#define WM8991_ADC_CLKDIV_MASK 0x00E0 /* ADC_CLKDIV - [7:5] */
234#define WM8991_ADC_CLKDIV_1 (0 << 5)
235#define WM8991_ADC_CLKDIV_1_5 (1 << 5)
236#define WM8991_ADC_CLKDIV_2 (2 << 5)
237#define WM8991_ADC_CLKDIV_3 (3 << 5)
238#define WM8991_ADC_CLKDIV_4 (4 << 5)
239#define WM8991_ADC_CLKDIV_5_5 (5 << 5)
240#define WM8991_ADC_CLKDIV_6 (6 << 5)
241#define WM8991_DAC_CLKDIV_MASK 0x001C /* DAC_CLKDIV - [4:2] */
242#define WM8991_DAC_CLKDIV_1 (0 << 2)
243#define WM8991_DAC_CLKDIV_1_5 (1 << 2)
244#define WM8991_DAC_CLKDIV_2 (2 << 2)
245#define WM8991_DAC_CLKDIV_3 (3 << 2)
246#define WM8991_DAC_CLKDIV_4 (4 << 2)
247#define WM8991_DAC_CLKDIV_5_5 (5 << 2)
248#define WM8991_DAC_CLKDIV_6 (6 << 2)
249
250/*
251 * R8 (0x08) - Audio Interface (3)
252 */
253#define WM8991_AIF_MSTR1 0x8000 /* AIF_MSTR1 */
254#define WM8991_AIF_MSTR2 0x4000 /* AIF_MSTR2 */
255#define WM8991_AIF_SEL 0x2000 /* AIF_SEL */
256#define WM8991_ADCLRC_DIR 0x0800 /* ADCLRC_DIR */
257#define WM8991_ADCLRC_RATE_MASK 0x07FF /* ADCLRC_RATE - [10:0] */
258
259/*
260 * R9 (0x09) - Audio Interface (4)
261 */
262#define WM8991_ALRCGPIO1 0x8000 /* ALRCGPIO1 */
263#define WM8991_ALRCBGPIO6 0x4000 /* ALRCBGPIO6 */
264#define WM8991_AIF_TRIS 0x2000 /* AIF_TRIS */
265#define WM8991_DACLRC_DIR 0x0800 /* DACLRC_DIR */
266#define WM8991_DACLRC_RATE_MASK 0x07FF /* DACLRC_RATE - [10:0] */
267
268/*
269 * R10 (0x0A) - DAC CTRL
270 */
271#define WM8991_AIF_LRCLKRATE 0x0400 /* AIF_LRCLKRATE */
272#define WM8991_DAC_MONO 0x0200 /* DAC_MONO */
273#define WM8991_DAC_SB_FILT 0x0100 /* DAC_SB_FILT */
274#define WM8991_DAC_MUTERATE 0x0080 /* DAC_MUTERATE */
275#define WM8991_DAC_MUTEMODE 0x0040 /* DAC_MUTEMODE */
276#define WM8991_DEEMP_MASK 0x0030 /* DEEMP - [5:4] */
277#define WM8991_DAC_MUTE 0x0004 /* DAC_MUTE */
278#define WM8991_DACL_DATINV 0x0002 /* DACL_DATINV */
279#define WM8991_DACR_DATINV 0x0001 /* DACR_DATINV */
280
281/*
282 * R11 (0x0B) - Left DAC Digital Volume
283 */
284#define WM8991_DAC_VU 0x0100 /* DAC_VU */
285#define WM8991_DACL_VOL_MASK 0x00FF /* DACL_VOL - [7:0] */
286#define WM8991_DACL_VOL_SHIFT 0
287/*
288 * R12 (0x0C) - Right DAC Digital Volume
289 */
290#define WM8991_DAC_VU 0x0100 /* DAC_VU */
291#define WM8991_DACR_VOL_MASK 0x00FF /* DACR_VOL - [7:0] */
292#define WM8991_DACR_VOL_SHIFT 0
293/*
294 * R13 (0x0D) - Digital Side Tone
295 */
296#define WM8991_ADCL_DAC_SVOL_MASK 0x0F /* ADCL_DAC_SVOL - [12:9] */
297#define WM8991_ADCL_DAC_SVOL_SHIFT 9
298#define WM8991_ADCR_DAC_SVOL_MASK 0x0F /* ADCR_DAC_SVOL - [8:5] */
299#define WM8991_ADCR_DAC_SVOL_SHIFT 5
300#define WM8991_ADC_TO_DACL_MASK 0x03 /* ADC_TO_DACL - [3:2] */
301#define WM8991_ADC_TO_DACL_SHIFT 2
302#define WM8991_ADC_TO_DACR_MASK 0x03 /* ADC_TO_DACR - [1:0] */
303#define WM8991_ADC_TO_DACR_SHIFT 0
304
305/*
306 * R14 (0x0E) - ADC CTRL
307 */
308#define WM8991_ADC_HPF_ENA 0x0100 /* ADC_HPF_ENA */
309#define WM8991_ADC_HPF_ENA_BIT 8
310#define WM8991_ADC_HPF_CUT_MASK 0x03 /* ADC_HPF_CUT - [6:5] */
311#define WM8991_ADC_HPF_CUT_SHIFT 5
312#define WM8991_ADCL_DATINV 0x0002 /* ADCL_DATINV */
313#define WM8991_ADCL_DATINV_BIT 1
314#define WM8991_ADCR_DATINV 0x0001 /* ADCR_DATINV */
315#define WM8991_ADCR_DATINV_BIT 0
316
317/*
318 * R15 (0x0F) - Left ADC Digital Volume
319 */
320#define WM8991_ADC_VU 0x0100 /* ADC_VU */
321#define WM8991_ADCL_VOL_MASK 0x00FF /* ADCL_VOL - [7:0] */
322#define WM8991_ADCL_VOL_SHIFT 0
323
324/*
325 * R16 (0x10) - Right ADC Digital Volume
326 */
327#define WM8991_ADC_VU 0x0100 /* ADC_VU */
328#define WM8991_ADCR_VOL_MASK 0x00FF /* ADCR_VOL - [7:0] */
329#define WM8991_ADCR_VOL_SHIFT 0
330
331/*
332 * R18 (0x12) - GPIO CTRL 1
333 */
334#define WM8991_IRQ 0x1000 /* IRQ */
335#define WM8991_TEMPOK 0x0800 /* TEMPOK */
336#define WM8991_MICSHRT 0x0400 /* MICSHRT */
337#define WM8991_MICDET 0x0200 /* MICDET */
338#define WM8991_PLL_LCK 0x0100 /* PLL_LCK */
339#define WM8991_GPI8_STATUS 0x0080 /* GPI8_STATUS */
340#define WM8991_GPI7_STATUS 0x0040 /* GPI7_STATUS */
341#define WM8991_GPIO6_STATUS 0x0020 /* GPIO6_STATUS */
342#define WM8991_GPIO5_STATUS 0x0010 /* GPIO5_STATUS */
343#define WM8991_GPIO4_STATUS 0x0008 /* GPIO4_STATUS */
344#define WM8991_GPIO3_STATUS 0x0004 /* GPIO3_STATUS */
345#define WM8991_GPIO2_STATUS 0x0002 /* GPIO2_STATUS */
346#define WM8991_GPIO1_STATUS 0x0001 /* GPIO1_STATUS */
347
348/*
349 * R19 (0x13) - GPIO1 & GPIO2
350 */
351#define WM8991_GPIO2_DEB_ENA 0x8000 /* GPIO2_DEB_ENA */
352#define WM8991_GPIO2_IRQ_ENA 0x4000 /* GPIO2_IRQ_ENA */
353#define WM8991_GPIO2_PU 0x2000 /* GPIO2_PU */
354#define WM8991_GPIO2_PD 0x1000 /* GPIO2_PD */
355#define WM8991_GPIO2_SEL_MASK 0x0F00 /* GPIO2_SEL - [11:8] */
356#define WM8991_GPIO1_DEB_ENA 0x0080 /* GPIO1_DEB_ENA */
357#define WM8991_GPIO1_IRQ_ENA 0x0040 /* GPIO1_IRQ_ENA */
358#define WM8991_GPIO1_PU 0x0020 /* GPIO1_PU */
359#define WM8991_GPIO1_PD 0x0010 /* GPIO1_PD */
360#define WM8991_GPIO1_SEL_MASK 0x000F /* GPIO1_SEL - [3:0] */
361
362/*
363 * R20 (0x14) - GPIO3 & GPIO4
364 */
365#define WM8991_GPIO4_DEB_ENA 0x8000 /* GPIO4_DEB_ENA */
366#define WM8991_GPIO4_IRQ_ENA 0x4000 /* GPIO4_IRQ_ENA */
367#define WM8991_GPIO4_PU 0x2000 /* GPIO4_PU */
368#define WM8991_GPIO4_PD 0x1000 /* GPIO4_PD */
369#define WM8991_GPIO4_SEL_MASK 0x0F00 /* GPIO4_SEL - [11:8] */
370#define WM8991_GPIO3_DEB_ENA 0x0080 /* GPIO3_DEB_ENA */
371#define WM8991_GPIO3_IRQ_ENA 0x0040 /* GPIO3_IRQ_ENA */
372#define WM8991_GPIO3_PU 0x0020 /* GPIO3_PU */
373#define WM8991_GPIO3_PD 0x0010 /* GPIO3_PD */
374#define WM8991_GPIO3_SEL_MASK 0x000F /* GPIO3_SEL - [3:0] */
375
376/*
377 * R21 (0x15) - GPIO5 & GPIO6
378 */
379#define WM8991_GPIO6_DEB_ENA 0x8000 /* GPIO6_DEB_ENA */
380#define WM8991_GPIO6_IRQ_ENA 0x4000 /* GPIO6_IRQ_ENA */
381#define WM8991_GPIO6_PU 0x2000 /* GPIO6_PU */
382#define WM8991_GPIO6_PD 0x1000 /* GPIO6_PD */
383#define WM8991_GPIO6_SEL_MASK 0x0F00 /* GPIO6_SEL - [11:8] */
384#define WM8991_GPIO5_DEB_ENA 0x0080 /* GPIO5_DEB_ENA */
385#define WM8991_GPIO5_IRQ_ENA 0x0040 /* GPIO5_IRQ_ENA */
386#define WM8991_GPIO5_PU 0x0020 /* GPIO5_PU */
387#define WM8991_GPIO5_PD 0x0010 /* GPIO5_PD */
388#define WM8991_GPIO5_SEL_MASK 0x000F /* GPIO5_SEL - [3:0] */
389
390/*
391 * R22 (0x16) - GPIOCTRL 2
392 */
393#define WM8991_RD_3W_ENA 0x8000 /* RD_3W_ENA */
394#define WM8991_MODE_3W4W 0x4000 /* MODE_3W4W */
395#define WM8991_TEMPOK_IRQ_ENA 0x0800 /* TEMPOK_IRQ_ENA */
396#define WM8991_MICSHRT_IRQ_ENA 0x0400 /* MICSHRT_IRQ_ENA */
397#define WM8991_MICDET_IRQ_ENA 0x0200 /* MICDET_IRQ_ENA */
398#define WM8991_PLL_LCK_IRQ_ENA 0x0100 /* PLL_LCK_IRQ_ENA */
399#define WM8991_GPI8_DEB_ENA 0x0080 /* GPI8_DEB_ENA */
400#define WM8991_GPI8_IRQ_ENA 0x0040 /* GPI8_IRQ_ENA */
401#define WM8991_GPI8_ENA 0x0010 /* GPI8_ENA */
402#define WM8991_GPI7_DEB_ENA 0x0008 /* GPI7_DEB_ENA */
403#define WM8991_GPI7_IRQ_ENA 0x0004 /* GPI7_IRQ_ENA */
404#define WM8991_GPI7_ENA 0x0001 /* GPI7_ENA */
405
406/*
407 * R23 (0x17) - GPIO_POL
408 */
409#define WM8991_IRQ_INV 0x1000 /* IRQ_INV */
410#define WM8991_TEMPOK_POL 0x0800 /* TEMPOK_POL */
411#define WM8991_MICSHRT_POL 0x0400 /* MICSHRT_POL */
412#define WM8991_MICDET_POL 0x0200 /* MICDET_POL */
413#define WM8991_PLL_LCK_POL 0x0100 /* PLL_LCK_POL */
414#define WM8991_GPI8_POL 0x0080 /* GPI8_POL */
415#define WM8991_GPI7_POL 0x0040 /* GPI7_POL */
416#define WM8991_GPIO6_POL 0x0020 /* GPIO6_POL */
417#define WM8991_GPIO5_POL 0x0010 /* GPIO5_POL */
418#define WM8991_GPIO4_POL 0x0008 /* GPIO4_POL */
419#define WM8991_GPIO3_POL 0x0004 /* GPIO3_POL */
420#define WM8991_GPIO2_POL 0x0002 /* GPIO2_POL */
421#define WM8991_GPIO1_POL 0x0001 /* GPIO1_POL */
422
423/*
424 * R24 (0x18) - Left Line Input 1&2 Volume
425 */
426#define WM8991_IPVU 0x0100 /* IPVU */
427#define WM8991_LI12MUTE 0x0080 /* LI12MUTE */
428#define WM8991_LI12MUTE_BIT 7
429#define WM8991_LI12ZC 0x0040 /* LI12ZC */
430#define WM8991_LI12ZC_BIT 6
431#define WM8991_LIN12VOL_MASK 0x001F /* LIN12VOL - [4:0] */
432#define WM8991_LIN12VOL_SHIFT 0
433/*
434 * R25 (0x19) - Left Line Input 3&4 Volume
435 */
436#define WM8991_IPVU 0x0100 /* IPVU */
437#define WM8991_LI34MUTE 0x0080 /* LI34MUTE */
438#define WM8991_LI34MUTE_BIT 7
439#define WM8991_LI34ZC 0x0040 /* LI34ZC */
440#define WM8991_LI34ZC_BIT 6
441#define WM8991_LIN34VOL_MASK 0x001F /* LIN34VOL - [4:0] */
442#define WM8991_LIN34VOL_SHIFT 0
443
444/*
445 * R26 (0x1A) - Right Line Input 1&2 Volume
446 */
447#define WM8991_IPVU 0x0100 /* IPVU */
448#define WM8991_RI12MUTE 0x0080 /* RI12MUTE */
449#define WM8991_RI12MUTE_BIT 7
450#define WM8991_RI12ZC 0x0040 /* RI12ZC */
451#define WM8991_RI12ZC_BIT 6
452#define WM8991_RIN12VOL_MASK 0x001F /* RIN12VOL - [4:0] */
453#define WM8991_RIN12VOL_SHIFT 0
454
455/*
456 * R27 (0x1B) - Right Line Input 3&4 Volume
457 */
458#define WM8991_IPVU 0x0100 /* IPVU */
459#define WM8991_RI34MUTE 0x0080 /* RI34MUTE */
460#define WM8991_RI34MUTE_BIT 7
461#define WM8991_RI34ZC 0x0040 /* RI34ZC */
462#define WM8991_RI34ZC_BIT 6
463#define WM8991_RIN34VOL_MASK 0x001F /* RIN34VOL - [4:0] */
464#define WM8991_RIN34VOL_SHIFT 0
465
466/*
467 * R28 (0x1C) - Left Output Volume
468 */
469#define WM8991_OPVU 0x0100 /* OPVU */
470#define WM8991_LOZC 0x0080 /* LOZC */
471#define WM8991_LOZC_BIT 7
472#define WM8991_LOUTVOL_MASK 0x007F /* LOUTVOL - [6:0] */
473#define WM8991_LOUTVOL_SHIFT 0
474/*
475 * R29 (0x1D) - Right Output Volume
476 */
477#define WM8991_OPVU 0x0100 /* OPVU */
478#define WM8991_ROZC 0x0080 /* ROZC */
479#define WM8991_ROZC_BIT 7
480#define WM8991_ROUTVOL_MASK 0x007F /* ROUTVOL - [6:0] */
481#define WM8991_ROUTVOL_SHIFT 0
482/*
483 * R30 (0x1E) - Line Outputs Volume
484 */
485#define WM8991_LONMUTE 0x0040 /* LONMUTE */
486#define WM8991_LONMUTE_BIT 6
487#define WM8991_LOPMUTE 0x0020 /* LOPMUTE */
488#define WM8991_LOPMUTE_BIT 5
489#define WM8991_LOATTN 0x0010 /* LOATTN */
490#define WM8991_LOATTN_BIT 4
491#define WM8991_RONMUTE 0x0004 /* RONMUTE */
492#define WM8991_RONMUTE_BIT 2
493#define WM8991_ROPMUTE 0x0002 /* ROPMUTE */
494#define WM8991_ROPMUTE_BIT 1
495#define WM8991_ROATTN 0x0001 /* ROATTN */
496#define WM8991_ROATTN_BIT 0
497
498/*
499 * R31 (0x1F) - Out3/4 Volume
500 */
501#define WM8991_OUT3MUTE 0x0020 /* OUT3MUTE */
502#define WM8991_OUT3MUTE_BIT 5
503#define WM8991_OUT3ATTN 0x0010 /* OUT3ATTN */
504#define WM8991_OUT3ATTN_BIT 4
505#define WM8991_OUT4MUTE 0x0002 /* OUT4MUTE */
506#define WM8991_OUT4MUTE_BIT 1
507#define WM8991_OUT4ATTN 0x0001 /* OUT4ATTN */
508#define WM8991_OUT4ATTN_BIT 0
509
510/*
511 * R32 (0x20) - Left OPGA Volume
512 */
513#define WM8991_OPVU 0x0100 /* OPVU */
514#define WM8991_LOPGAZC 0x0080 /* LOPGAZC */
515#define WM8991_LOPGAZC_BIT 7
516#define WM8991_LOPGAVOL_MASK 0x007F /* LOPGAVOL - [6:0] */
517#define WM8991_LOPGAVOL_SHIFT 0
518
519/*
520 * R33 (0x21) - Right OPGA Volume
521 */
522#define WM8991_OPVU 0x0100 /* OPVU */
523#define WM8991_ROPGAZC 0x0080 /* ROPGAZC */
524#define WM8991_ROPGAZC_BIT 7
525#define WM8991_ROPGAVOL_MASK 0x007F /* ROPGAVOL - [6:0] */
526#define WM8991_ROPGAVOL_SHIFT 0
527/*
528 * R34 (0x22) - Speaker Volume
529 */
530#define WM8991_SPKVOL_MASK 0x0003 /* SPKVOL - [1:0] */
531#define WM8991_SPKVOL_SHIFT 0
532
533/*
534 * R35 (0x23) - ClassD1
535 */
536#define WM8991_CDMODE 0x0100 /* CDMODE */
537#define WM8991_CDMODE_BIT 8
538
539/*
540 * R37 (0x25) - ClassD3
541 */
542#define WM8991_DCGAIN_MASK 0x0007 /* DCGAIN - [5:3] */
543#define WM8991_DCGAIN_SHIFT 3
544#define WM8991_ACGAIN_MASK 0x0007 /* ACGAIN - [2:0] */
545#define WM8991_ACGAIN_SHIFT 0
546/*
547 * R39 (0x27) - Input Mixer1
548 */
549#define WM8991_AINLMODE_MASK 0x000C /* AINLMODE - [3:2] */
550#define WM8991_AINLMODE_SHIFT 2
551#define WM8991_AINRMODE_MASK 0x0003 /* AINRMODE - [1:0] */
552#define WM8991_AINRMODE_SHIFT 0
553
554/*
555 * R40 (0x28) - Input Mixer2
556 */
557#define WM8991_LMP4 0x0080 /* LMP4 */
558#define WM8991_LMP4_BIT 7 /* LMP4 */
559#define WM8991_LMN3 0x0040 /* LMN3 */
560#define WM8991_LMN3_BIT 6 /* LMN3 */
561#define WM8991_LMP2 0x0020 /* LMP2 */
562#define WM8991_LMP2_BIT 5 /* LMP2 */
563#define WM8991_LMN1 0x0010 /* LMN1 */
564#define WM8991_LMN1_BIT 4 /* LMN1 */
565#define WM8991_RMP4 0x0008 /* RMP4 */
566#define WM8991_RMP4_BIT 3 /* RMP4 */
567#define WM8991_RMN3 0x0004 /* RMN3 */
568#define WM8991_RMN3_BIT 2 /* RMN3 */
569#define WM8991_RMP2 0x0002 /* RMP2 */
570#define WM8991_RMP2_BIT 1 /* RMP2 */
571#define WM8991_RMN1 0x0001 /* RMN1 */
572#define WM8991_RMN1_BIT 0 /* RMN1 */
573
574/*
575 * R41 (0x29) - Input Mixer3
576 */
577#define WM8991_L34MNB 0x0100 /* L34MNB */
578#define WM8991_L34MNB_BIT 8
579#define WM8991_L34MNBST 0x0080 /* L34MNBST */
580#define WM8991_L34MNBST_BIT 7
581#define WM8991_L12MNB 0x0020 /* L12MNB */
582#define WM8991_L12MNB_BIT 5
583#define WM8991_L12MNBST 0x0010 /* L12MNBST */
584#define WM8991_L12MNBST_BIT 4
585#define WM8991_LDBVOL_MASK 0x0007 /* LDBVOL - [2:0] */
586#define WM8991_LDBVOL_SHIFT 0
587
588/*
589 * R42 (0x2A) - Input Mixer4
590 */
591#define WM8991_R34MNB 0x0100 /* R34MNB */
592#define WM8991_R34MNB_BIT 8
593#define WM8991_R34MNBST 0x0080 /* R34MNBST */
594#define WM8991_R34MNBST_BIT 7
595#define WM8991_R12MNB 0x0020 /* R12MNB */
596#define WM8991_R12MNB_BIT 5
597#define WM8991_R12MNBST 0x0010 /* R12MNBST */
598#define WM8991_R12MNBST_BIT 4
599#define WM8991_RDBVOL_MASK 0x0007 /* RDBVOL - [2:0] */
600#define WM8991_RDBVOL_SHIFT 0
601
602/*
603 * R43 (0x2B) - Input Mixer5
604 */
605#define WM8991_LI2BVOL_MASK 0x07 /* LI2BVOL - [8:6] */
606#define WM8991_LI2BVOL_SHIFT 6
607#define WM8991_LR4BVOL_MASK 0x07 /* LR4BVOL - [5:3] */
608#define WM8991_LR4BVOL_SHIFT 3
609#define WM8991_LL4BVOL_MASK 0x07 /* LL4BVOL - [2:0] */
610#define WM8991_LL4BVOL_SHIFT 0
611
612/*
613 * R44 (0x2C) - Input Mixer6
614 */
615#define WM8991_RI2BVOL_MASK 0x07 /* RI2BVOL - [8:6] */
616#define WM8991_RI2BVOL_SHIFT 6
617#define WM8991_RL4BVOL_MASK 0x07 /* RL4BVOL - [5:3] */
618#define WM8991_RL4BVOL_SHIFT 3
619#define WM8991_RR4BVOL_MASK 0x07 /* RR4BVOL - [2:0] */
620#define WM8991_RR4BVOL_SHIFT 0
621
622/*
623 * R45 (0x2D) - Output Mixer1
624 */
625#define WM8991_LRBLO 0x0080 /* LRBLO */
626#define WM8991_LRBLO_BIT 7
627#define WM8991_LLBLO 0x0040 /* LLBLO */
628#define WM8991_LLBLO_BIT 6
629#define WM8991_LRI3LO 0x0020 /* LRI3LO */
630#define WM8991_LRI3LO_BIT 5
631#define WM8991_LLI3LO 0x0010 /* LLI3LO */
632#define WM8991_LLI3LO_BIT 4
633#define WM8991_LR12LO 0x0008 /* LR12LO */
634#define WM8991_LR12LO_BIT 3
635#define WM8991_LL12LO 0x0004 /* LL12LO */
636#define WM8991_LL12LO_BIT 2
637#define WM8991_LDLO 0x0001 /* LDLO */
638#define WM8991_LDLO_BIT 0
639
640/*
641 * R46 (0x2E) - Output Mixer2
642 */
643#define WM8991_RLBRO 0x0080 /* RLBRO */
644#define WM8991_RLBRO_BIT 7
645#define WM8991_RRBRO 0x0040 /* RRBRO */
646#define WM8991_RRBRO_BIT 6
647#define WM8991_RLI3RO 0x0020 /* RLI3RO */
648#define WM8991_RLI3RO_BIT 5
649#define WM8991_RRI3RO 0x0010 /* RRI3RO */
650#define WM8991_RRI3RO_BIT 4
651#define WM8991_RL12RO 0x0008 /* RL12RO */
652#define WM8991_RL12RO_BIT 3
653#define WM8991_RR12RO 0x0004 /* RR12RO */
654#define WM8991_RR12RO_BIT 2
655#define WM8991_RDRO 0x0001 /* RDRO */
656#define WM8991_RDRO_BIT 0
657
658/*
659 * R47 (0x2F) - Output Mixer3
660 */
661#define WM8991_LLI3LOVOL_MASK 0x07 /* LLI3LOVOL - [8:6] */
662#define WM8991_LLI3LOVOL_SHIFT 6
663#define WM8991_LR12LOVOL_MASK 0x07 /* LR12LOVOL - [5:3] */
664#define WM8991_LR12LOVOL_SHIFT 3
665#define WM8991_LL12LOVOL_MASK 0x07 /* LL12LOVOL - [2:0] */
666#define WM8991_LL12LOVOL_SHIFT 0
667
668/*
669 * R48 (0x30) - Output Mixer4
670 */
671#define WM8991_RRI3ROVOL_MASK 0x07 /* RRI3ROVOL - [8:6] */
672#define WM8991_RRI3ROVOL_SHIFT 6
673#define WM8991_RL12ROVOL_MASK 0x07 /* RL12ROVOL - [5:3] */
674#define WM8991_RL12ROVOL_SHIFT 3
675#define WM8991_RR12ROVOL_MASK 0x07 /* RR12ROVOL - [2:0] */
676#define WM8991_RR12ROVOL_SHIFT 0
677
678/*
679 * R49 (0x31) - Output Mixer5
680 */
681#define WM8991_LRI3LOVOL_MASK 0x07 /* LRI3LOVOL - [8:6] */
682#define WM8991_LRI3LOVOL_SHIFT 6
683#define WM8991_LRBLOVOL_MASK 0x07 /* LRBLOVOL - [5:3] */
684#define WM8991_LRBLOVOL_SHIFT 3
685#define WM8991_LLBLOVOL_MASK 0x07 /* LLBLOVOL - [2:0] */
686#define WM8991_LLBLOVOL_SHIFT 0
687
688/*
689 * R50 (0x32) - Output Mixer6
690 */
691#define WM8991_RLI3ROVOL_MASK 0x07 /* RLI3ROVOL - [8:6] */
692#define WM8991_RLI3ROVOL_SHIFT 6
693#define WM8991_RLBROVOL_MASK 0x07 /* RLBROVOL - [5:3] */
694#define WM8991_RLBROVOL_SHIFT 3
695#define WM8991_RRBROVOL_MASK 0x07 /* RRBROVOL - [2:0] */
696#define WM8991_RRBROVOL_SHIFT 0
697
698/*
699 * R51 (0x33) - Out3/4 Mixer
700 */
701#define WM8991_VSEL_MASK 0x0180 /* VSEL - [8:7] */
702#define WM8991_LI4O3 0x0020 /* LI4O3 */
703#define WM8991_LI4O3_BIT 5
704#define WM8991_LPGAO3 0x0010 /* LPGAO3 */
705#define WM8991_LPGAO3_BIT 4
706#define WM8991_RI4O4 0x0002 /* RI4O4 */
707#define WM8991_RI4O4_BIT 1
708#define WM8991_RPGAO4 0x0001 /* RPGAO4 */
709#define WM8991_RPGAO4_BIT 0
710/*
711 * R52 (0x34) - Line Mixer1
712 */
713#define WM8991_LLOPGALON 0x0040 /* LLOPGALON */
714#define WM8991_LLOPGALON_BIT 6
715#define WM8991_LROPGALON 0x0020 /* LROPGALON */
716#define WM8991_LROPGALON_BIT 5
717#define WM8991_LOPLON 0x0010 /* LOPLON */
718#define WM8991_LOPLON_BIT 4
719#define WM8991_LR12LOP 0x0004 /* LR12LOP */
720#define WM8991_LR12LOP_BIT 2
721#define WM8991_LL12LOP 0x0002 /* LL12LOP */
722#define WM8991_LL12LOP_BIT 1
723#define WM8991_LLOPGALOP 0x0001 /* LLOPGALOP */
724#define WM8991_LLOPGALOP_BIT 0
725/*
726 * R53 (0x35) - Line Mixer2
727 */
728#define WM8991_RROPGARON 0x0040 /* RROPGARON */
729#define WM8991_RROPGARON_BIT 6
730#define WM8991_RLOPGARON 0x0020 /* RLOPGARON */
731#define WM8991_RLOPGARON_BIT 5
732#define WM8991_ROPRON 0x0010 /* ROPRON */
733#define WM8991_ROPRON_BIT 4
734#define WM8991_RL12ROP 0x0004 /* RL12ROP */
735#define WM8991_RL12ROP_BIT 2
736#define WM8991_RR12ROP 0x0002 /* RR12ROP */
737#define WM8991_RR12ROP_BIT 1
738#define WM8991_RROPGAROP 0x0001 /* RROPGAROP */
739#define WM8991_RROPGAROP_BIT 0
740
741/*
742 * R54 (0x36) - Speaker Mixer
743 */
744#define WM8991_LB2SPK 0x0080 /* LB2SPK */
745#define WM8991_LB2SPK_BIT 7
746#define WM8991_RB2SPK 0x0040 /* RB2SPK */
747#define WM8991_RB2SPK_BIT 6
748#define WM8991_LI2SPK 0x0020 /* LI2SPK */
749#define WM8991_LI2SPK_BIT 5
750#define WM8991_RI2SPK 0x0010 /* RI2SPK */
751#define WM8991_RI2SPK_BIT 4
752#define WM8991_LOPGASPK 0x0008 /* LOPGASPK */
753#define WM8991_LOPGASPK_BIT 3
754#define WM8991_ROPGASPK 0x0004 /* ROPGASPK */
755#define WM8991_ROPGASPK_BIT 2
756#define WM8991_LDSPK 0x0002 /* LDSPK */
757#define WM8991_LDSPK_BIT 1
758#define WM8991_RDSPK 0x0001 /* RDSPK */
759#define WM8991_RDSPK_BIT 0
760
761/*
762 * R55 (0x37) - Additional Control
763 */
764#define WM8991_VROI 0x0001 /* VROI */
765
766/*
767 * R56 (0x38) - AntiPOP1
768 */
769#define WM8991_DIS_LLINE 0x0020 /* DIS_LLINE */
770#define WM8991_DIS_RLINE 0x0010 /* DIS_RLINE */
771#define WM8991_DIS_OUT3 0x0008 /* DIS_OUT3 */
772#define WM8991_DIS_OUT4 0x0004 /* DIS_OUT4 */
773#define WM8991_DIS_LOUT 0x0002 /* DIS_LOUT */
774#define WM8991_DIS_ROUT 0x0001 /* DIS_ROUT */
775
776/*
777 * R57 (0x39) - AntiPOP2
778 */
779#define WM8991_SOFTST 0x0040 /* SOFTST */
780#define WM8991_BUFIOEN 0x0008 /* BUFIOEN */
781#define WM8991_BUFDCOPEN 0x0004 /* BUFDCOPEN */
782#define WM8991_POBCTRL 0x0002 /* POBCTRL */
783#define WM8991_VMIDTOG 0x0001 /* VMIDTOG */
784
785/*
786 * R58 (0x3A) - MICBIAS
787 */
788#define WM8991_MCDSCTH_MASK 0x00C0 /* MCDSCTH - [7:6] */
789#define WM8991_MCDTHR_MASK 0x0038 /* MCDTHR - [5:3] */
790#define WM8991_MCD 0x0004 /* MCD */
791#define WM8991_MBSEL 0x0001 /* MBSEL */
792
793/*
794 * R60 (0x3C) - PLL1
795 */
796#define WM8991_SDM 0x0080 /* SDM */
797#define WM8991_PRESCALE 0x0040 /* PRESCALE */
798#define WM8991_PLLN_MASK 0x000F /* PLLN - [3:0] */
799
800/*
801 * R61 (0x3D) - PLL2
802 */
803#define WM8991_PLLK1_MASK 0x00FF /* PLLK1 - [7:0] */
804
805/*
806 * R62 (0x3E) - PLL3
807 */
808#define WM8991_PLLK2_MASK 0x00FF /* PLLK2 - [7:0] */
809
810/*
811 * R63 (0x3F) - Internal Driver Bits
812 */
813#define WM8991_INMIXL_PWR_BIT 0
814#define WM8991_AINLMUX_PWR_BIT 1
815#define WM8991_INMIXR_PWR_BIT 2
816#define WM8991_AINRMUX_PWR_BIT 3
817
818#define WM8991_MCLK_DIV 0
819#define WM8991_DACCLK_DIV 1
820#define WM8991_ADCCLK_DIV 2
821#define WM8991_BCLK_DIV 3
822
823#define SOC_WM899X_OUTPGA_SINGLE_R_TLV(xname, reg, shift, max, invert,\
824 tlv_array) \
825{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
826 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
827 SNDRV_CTL_ELEM_ACCESS_READWRITE,\
828 .tlv.p = (tlv_array), \
829 .info = snd_soc_info_volsw, \
830 .get = snd_soc_get_volsw, .put = wm899x_outpga_put_volsw_vu, \
831 .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) }
832
833#endif /* _WM8991_H */
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c
index 18c0d9ce7c32..379fa22c5b6c 100644
--- a/sound/soc/codecs/wm8993.c
+++ b/sound/soc/codecs/wm8993.c
@@ -242,7 +242,7 @@ struct wm8993_priv {
242 int fll_src; 242 int fll_src;
243}; 243};
244 244
245static int wm8993_volatile(unsigned int reg) 245static int wm8993_volatile(struct snd_soc_codec *codec, unsigned int reg)
246{ 246{
247 switch (reg) { 247 switch (reg) {
248 case WM8993_SOFTWARE_RESET: 248 case WM8993_SOFTWARE_RESET:
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index 3351f77607b3..0ca81d3c64e8 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -109,7 +109,7 @@ struct wm8994_priv {
109 struct wm8994_pdata *pdata; 109 struct wm8994_pdata *pdata;
110}; 110};
111 111
112static int wm8994_readable(unsigned int reg) 112static int wm8994_readable(struct snd_soc_codec *codec, unsigned int reg)
113{ 113{
114 switch (reg) { 114 switch (reg) {
115 case WM8994_GPIO_1: 115 case WM8994_GPIO_1:
@@ -136,7 +136,7 @@ static int wm8994_readable(unsigned int reg)
136 return wm8994_access_masks[reg].readable != 0; 136 return wm8994_access_masks[reg].readable != 0;
137} 137}
138 138
139static int wm8994_volatile(unsigned int reg) 139static int wm8994_volatile(struct snd_soc_codec *codec, unsigned int reg)
140{ 140{
141 if (reg >= WM8994_CACHE_SIZE) 141 if (reg >= WM8994_CACHE_SIZE)
142 return 1; 142 return 1;
@@ -164,7 +164,7 @@ static int wm8994_write(struct snd_soc_codec *codec, unsigned int reg,
164 164
165 BUG_ON(reg > WM8994_MAX_REGISTER); 165 BUG_ON(reg > WM8994_MAX_REGISTER);
166 166
167 if (!wm8994_volatile(reg)) { 167 if (!wm8994_volatile(codec, reg)) {
168 ret = snd_soc_cache_write(codec, reg, value); 168 ret = snd_soc_cache_write(codec, reg, value);
169 if (ret != 0) 169 if (ret != 0)
170 dev_err(codec->dev, "Cache write to %x failed: %d\n", 170 dev_err(codec->dev, "Cache write to %x failed: %d\n",
@@ -182,7 +182,7 @@ static unsigned int wm8994_read(struct snd_soc_codec *codec,
182 182
183 BUG_ON(reg > WM8994_MAX_REGISTER); 183 BUG_ON(reg > WM8994_MAX_REGISTER);
184 184
185 if (!wm8994_volatile(reg) && wm8994_readable(reg) && 185 if (!wm8994_volatile(codec, reg) && wm8994_readable(codec, reg) &&
186 reg < codec->driver->reg_cache_size) { 186 reg < codec->driver->reg_cache_size) {
187 ret = snd_soc_cache_read(codec, reg, &val); 187 ret = snd_soc_cache_read(codec, reg, &val);
188 if (ret >= 0) 188 if (ret >= 0)
@@ -2943,7 +2943,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
2943 /* Read our current status back from the chip - we don't want to 2943 /* Read our current status back from the chip - we don't want to
2944 * reset as this may interfere with the GPIO or LDO operation. */ 2944 * reset as this may interfere with the GPIO or LDO operation. */
2945 for (i = 0; i < WM8994_CACHE_SIZE; i++) { 2945 for (i = 0; i < WM8994_CACHE_SIZE; i++) {
2946 if (!wm8994_readable(i) || wm8994_volatile(i)) 2946 if (!wm8994_readable(codec, i) || wm8994_volatile(codec, i))
2947 continue; 2947 continue;
2948 2948
2949 ret = wm8994_reg_read(codec->control_data, i); 2949 ret = wm8994_reg_read(codec->control_data, i);
diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c
index 608c84c5aa8e..67eaaecbb42e 100644
--- a/sound/soc/codecs/wm8995.c
+++ b/sound/soc/codecs/wm8995.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/spi/spi.h> 21#include <linux/spi/spi.h>
22#include <linux/regulator/consumer.h>
22#include <linux/slab.h> 23#include <linux/slab.h>
23#include <sound/core.h> 24#include <sound/core.h>
24#include <sound/pcm.h> 25#include <sound/pcm.h>
@@ -30,6 +31,18 @@
30 31
31#include "wm8995.h" 32#include "wm8995.h"
32 33
34#define WM8995_NUM_SUPPLIES 8
35static const char *wm8995_supply_names[WM8995_NUM_SUPPLIES] = {
36 "DCVDD",
37 "DBVDD1",
38 "DBVDD2",
39 "DBVDD3",
40 "AVDD1",
41 "AVDD2",
42 "CPVDD",
43 "MICVDD"
44};
45
33static const u16 wm8995_reg_defs[WM8995_MAX_REGISTER + 1] = { 46static const u16 wm8995_reg_defs[WM8995_MAX_REGISTER + 1] = {
34 [0] = 0x8995, [5] = 0x0100, [16] = 0x000b, [17] = 0x000b, 47 [0] = 0x8995, [5] = 0x0100, [16] = 0x000b, [17] = 0x000b,
35 [24] = 0x02c0, [25] = 0x02c0, [26] = 0x02c0, [27] = 0x02c0, 48 [24] = 0x02c0, [25] = 0x02c0, [26] = 0x02c0, [27] = 0x02c0,
@@ -126,8 +139,37 @@ struct wm8995_priv {
126 int mclk[2]; 139 int mclk[2];
127 int aifclk[2]; 140 int aifclk[2];
128 struct fll_config fll[2], fll_suspend[2]; 141 struct fll_config fll[2], fll_suspend[2];
142 struct regulator_bulk_data supplies[WM8995_NUM_SUPPLIES];
143 struct notifier_block disable_nb[WM8995_NUM_SUPPLIES];
144 struct snd_soc_codec *codec;
129}; 145};
130 146
147/*
148 * We can't use the same notifier block for more than one supply and
149 * there's no way I can see to get from a callback to the caller
150 * except container_of().
151 */
152#define WM8995_REGULATOR_EVENT(n) \
153static int wm8995_regulator_event_##n(struct notifier_block *nb, \
154 unsigned long event, void *data) \
155{ \
156 struct wm8995_priv *wm8995 = container_of(nb, struct wm8995_priv, \
157 disable_nb[n]); \
158 if (event & REGULATOR_EVENT_DISABLE) { \
159 wm8995->codec->cache_sync = 1; \
160 } \
161 return 0; \
162}
163
164WM8995_REGULATOR_EVENT(0)
165WM8995_REGULATOR_EVENT(1)
166WM8995_REGULATOR_EVENT(2)
167WM8995_REGULATOR_EVENT(3)
168WM8995_REGULATOR_EVENT(4)
169WM8995_REGULATOR_EVENT(5)
170WM8995_REGULATOR_EVENT(6)
171WM8995_REGULATOR_EVENT(7)
172
131static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1); 173static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1);
132static const DECLARE_TLV_DB_SCALE(in1lr_pga_tlv, -1650, 150, 0); 174static const DECLARE_TLV_DB_SCALE(in1lr_pga_tlv, -1650, 150, 0);
133static const DECLARE_TLV_DB_SCALE(in1l_boost_tlv, 0, 600, 0); 175static const DECLARE_TLV_DB_SCALE(in1l_boost_tlv, 0, 600, 0);
@@ -909,7 +951,7 @@ static const struct snd_soc_dapm_route wm8995_intercon[] = {
909 { "SPK2R", NULL, "SPK2R Driver" } 951 { "SPK2R", NULL, "SPK2R Driver" }
910}; 952};
911 953
912static int wm8995_volatile(unsigned int reg) 954static int wm8995_volatile(struct snd_soc_codec *codec, unsigned int reg)
913{ 955{
914 /* out of bounds registers are generally considered 956 /* out of bounds registers are generally considered
915 * volatile to support register banks that are partially 957 * volatile to support register banks that are partially
@@ -1483,6 +1525,11 @@ static int wm8995_set_bias_level(struct snd_soc_codec *codec,
1483 break; 1525 break;
1484 case SND_SOC_BIAS_STANDBY: 1526 case SND_SOC_BIAS_STANDBY:
1485 if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { 1527 if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
1528 ret = regulator_bulk_enable(ARRAY_SIZE(wm8995->supplies),
1529 wm8995->supplies);
1530 if (ret)
1531 return ret;
1532
1486 ret = snd_soc_cache_sync(codec); 1533 ret = snd_soc_cache_sync(codec);
1487 if (ret) { 1534 if (ret) {
1488 dev_err(codec->dev, 1535 dev_err(codec->dev,
@@ -1492,12 +1539,13 @@ static int wm8995_set_bias_level(struct snd_soc_codec *codec,
1492 1539
1493 snd_soc_update_bits(codec, WM8995_POWER_MANAGEMENT_1, 1540 snd_soc_update_bits(codec, WM8995_POWER_MANAGEMENT_1,
1494 WM8995_BG_ENA_MASK, WM8995_BG_ENA); 1541 WM8995_BG_ENA_MASK, WM8995_BG_ENA);
1495
1496 } 1542 }
1497 break; 1543 break;
1498 case SND_SOC_BIAS_OFF: 1544 case SND_SOC_BIAS_OFF:
1499 snd_soc_update_bits(codec, WM8995_POWER_MANAGEMENT_1, 1545 snd_soc_update_bits(codec, WM8995_POWER_MANAGEMENT_1,
1500 WM8995_BG_ENA_MASK, 0); 1546 WM8995_BG_ENA_MASK, 0);
1547 regulator_bulk_disable(ARRAY_SIZE(wm8995->supplies),
1548 wm8995->supplies);
1501 break; 1549 break;
1502 } 1550 }
1503 1551
@@ -1536,10 +1584,12 @@ static int wm8995_remove(struct snd_soc_codec *codec)
1536static int wm8995_probe(struct snd_soc_codec *codec) 1584static int wm8995_probe(struct snd_soc_codec *codec)
1537{ 1585{
1538 struct wm8995_priv *wm8995; 1586 struct wm8995_priv *wm8995;
1587 int i;
1539 int ret; 1588 int ret;
1540 1589
1541 codec->dapm.idle_bias_off = 1; 1590 codec->dapm.idle_bias_off = 1;
1542 wm8995 = snd_soc_codec_get_drvdata(codec); 1591 wm8995 = snd_soc_codec_get_drvdata(codec);
1592 wm8995->codec = codec;
1543 1593
1544 ret = snd_soc_codec_set_cache_io(codec, 16, 16, wm8995->control_type); 1594 ret = snd_soc_codec_set_cache_io(codec, 16, 16, wm8995->control_type);
1545 if (ret < 0) { 1595 if (ret < 0) {
@@ -1547,21 +1597,58 @@ static int wm8995_probe(struct snd_soc_codec *codec)
1547 return ret; 1597 return ret;
1548 } 1598 }
1549 1599
1600 for (i = 0; i < ARRAY_SIZE(wm8995->supplies); i++)
1601 wm8995->supplies[i].supply = wm8995_supply_names[i];
1602
1603 ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8995->supplies),
1604 wm8995->supplies);
1605 if (ret) {
1606 dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
1607 return ret;
1608 }
1609
1610 wm8995->disable_nb[0].notifier_call = wm8995_regulator_event_0;
1611 wm8995->disable_nb[1].notifier_call = wm8995_regulator_event_1;
1612 wm8995->disable_nb[2].notifier_call = wm8995_regulator_event_2;
1613 wm8995->disable_nb[3].notifier_call = wm8995_regulator_event_3;
1614 wm8995->disable_nb[4].notifier_call = wm8995_regulator_event_4;
1615 wm8995->disable_nb[5].notifier_call = wm8995_regulator_event_5;
1616 wm8995->disable_nb[6].notifier_call = wm8995_regulator_event_6;
1617 wm8995->disable_nb[7].notifier_call = wm8995_regulator_event_7;
1618
1619 /* This should really be moved into the regulator core */
1620 for (i = 0; i < ARRAY_SIZE(wm8995->supplies); i++) {
1621 ret = regulator_register_notifier(wm8995->supplies[i].consumer,
1622 &wm8995->disable_nb[i]);
1623 if (ret) {
1624 dev_err(codec->dev,
1625 "Failed to register regulator notifier: %d\n",
1626 ret);
1627 }
1628 }
1629
1630 ret = regulator_bulk_enable(ARRAY_SIZE(wm8995->supplies),
1631 wm8995->supplies);
1632 if (ret) {
1633 dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
1634 goto err_reg_get;
1635 }
1636
1550 ret = snd_soc_read(codec, WM8995_SOFTWARE_RESET); 1637 ret = snd_soc_read(codec, WM8995_SOFTWARE_RESET);
1551 if (ret < 0) { 1638 if (ret < 0) {
1552 dev_err(codec->dev, "Failed to read device ID: %d\n", ret); 1639 dev_err(codec->dev, "Failed to read device ID: %d\n", ret);
1553 return ret; 1640 goto err_reg_enable;
1554 } 1641 }
1555 1642
1556 if (ret != 0x8995) { 1643 if (ret != 0x8995) {
1557 dev_err(codec->dev, "Invalid device ID: %#x\n", ret); 1644 dev_err(codec->dev, "Invalid device ID: %#x\n", ret);
1558 return -EINVAL; 1645 goto err_reg_enable;
1559 } 1646 }
1560 1647
1561 ret = snd_soc_write(codec, WM8995_SOFTWARE_RESET, 0); 1648 ret = snd_soc_write(codec, WM8995_SOFTWARE_RESET, 0);
1562 if (ret < 0) { 1649 if (ret < 0) {
1563 dev_err(codec->dev, "Failed to issue reset: %d\n", ret); 1650 dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
1564 return ret; 1651 goto err_reg_enable;
1565 } 1652 }
1566 1653
1567 wm8995_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1654 wm8995_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -1596,6 +1683,12 @@ static int wm8995_probe(struct snd_soc_codec *codec)
1596 ARRAY_SIZE(wm8995_intercon)); 1683 ARRAY_SIZE(wm8995_intercon));
1597 1684
1598 return 0; 1685 return 0;
1686
1687err_reg_enable:
1688 regulator_bulk_disable(ARRAY_SIZE(wm8995->supplies), wm8995->supplies);
1689err_reg_get:
1690 regulator_bulk_free(ARRAY_SIZE(wm8995->supplies), wm8995->supplies);
1691 return ret;
1599} 1692}
1600 1693
1601#define WM8995_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ 1694#define WM8995_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c
index 43825b2102a5..5c224dd917d7 100644
--- a/sound/soc/codecs/wm9081.c
+++ b/sound/soc/codecs/wm9081.c
@@ -169,7 +169,7 @@ struct wm9081_priv {
169 struct wm9081_retune_mobile_config *retune; 169 struct wm9081_retune_mobile_config *retune;
170}; 170};
171 171
172static int wm9081_volatile_register(unsigned int reg) 172static int wm9081_volatile_register(struct snd_soc_codec *codec, unsigned int reg)
173{ 173{
174 switch (reg) { 174 switch (reg) {
175 case WM9081_SOFTWARE_RESET: 175 case WM9081_SOFTWARE_RESET:
diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c
index a788c4297046..4de12203e611 100644
--- a/sound/soc/codecs/wm9090.c
+++ b/sound/soc/codecs/wm9090.c
@@ -144,7 +144,7 @@ struct wm9090_priv {
144 void *control_data; 144 void *control_data;
145}; 145};
146 146
147static int wm9090_volatile(unsigned int reg) 147static int wm9090_volatile(struct snd_soc_codec *codec, unsigned int reg)
148{ 148{
149 switch (reg) { 149 switch (reg) {
150 case WM9090_SOFTWARE_RESET: 150 case WM9090_SOFTWARE_RESET:
@@ -518,7 +518,7 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec,
518 for (i = 1; i < codec->driver->reg_cache_size; i++) { 518 for (i = 1; i < codec->driver->reg_cache_size; i++) {
519 if (reg_cache[i] == wm9090_reg_defaults[i]) 519 if (reg_cache[i] == wm9090_reg_defaults[i])
520 continue; 520 continue;
521 if (wm9090_volatile(i)) 521 if (wm9090_volatile(codec, i))
522 continue; 522 continue;
523 523
524 ret = snd_soc_write(codec, i, reg_cache[i]); 524 ret = snd_soc_write(codec, i, reg_cache[i]);
@@ -551,7 +551,6 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec,
551static int wm9090_probe(struct snd_soc_codec *codec) 551static int wm9090_probe(struct snd_soc_codec *codec)
552{ 552{
553 struct wm9090_priv *wm9090 = snd_soc_codec_get_drvdata(codec); 553 struct wm9090_priv *wm9090 = snd_soc_codec_get_drvdata(codec);
554 u16 *reg_cache = codec->reg_cache;
555 int ret; 554 int ret;
556 555
557 codec->control_data = wm9090->control_data; 556 codec->control_data = wm9090->control_data;
@@ -576,22 +575,30 @@ static int wm9090_probe(struct snd_soc_codec *codec)
576 /* Configure some defaults; they will be written out when we 575 /* Configure some defaults; they will be written out when we
577 * bring the bias up. 576 * bring the bias up.
578 */ 577 */
579 reg_cache[WM9090_IN1_LINE_INPUT_A_VOLUME] |= WM9090_IN1_VU 578 snd_soc_update_bits(codec, WM9090_IN1_LINE_INPUT_A_VOLUME,
580 | WM9090_IN1A_ZC; 579 WM9090_IN1_VU | WM9090_IN1A_ZC,
581 reg_cache[WM9090_IN1_LINE_INPUT_B_VOLUME] |= WM9090_IN1_VU 580 WM9090_IN1_VU | WM9090_IN1A_ZC);
582 | WM9090_IN1B_ZC; 581 snd_soc_update_bits(codec, WM9090_IN1_LINE_INPUT_B_VOLUME,
583 reg_cache[WM9090_IN2_LINE_INPUT_A_VOLUME] |= WM9090_IN2_VU 582 WM9090_IN1_VU | WM9090_IN1B_ZC,
584 | WM9090_IN2A_ZC; 583 WM9090_IN1_VU | WM9090_IN1B_ZC);
585 reg_cache[WM9090_IN2_LINE_INPUT_B_VOLUME] |= WM9090_IN2_VU 584 snd_soc_update_bits(codec, WM9090_IN2_LINE_INPUT_A_VOLUME,
586 | WM9090_IN2B_ZC; 585 WM9090_IN2_VU | WM9090_IN2A_ZC,
587 reg_cache[WM9090_SPEAKER_VOLUME_LEFT] |= 586 WM9090_IN2_VU | WM9090_IN2A_ZC);
588 WM9090_SPKOUT_VU | WM9090_SPKOUTL_ZC; 587 snd_soc_update_bits(codec, WM9090_IN2_LINE_INPUT_B_VOLUME,
589 reg_cache[WM9090_LEFT_OUTPUT_VOLUME] |= 588 WM9090_IN2_VU | WM9090_IN2B_ZC,
590 WM9090_HPOUT1_VU | WM9090_HPOUT1L_ZC; 589 WM9090_IN2_VU | WM9090_IN2B_ZC);
591 reg_cache[WM9090_RIGHT_OUTPUT_VOLUME] |= 590 snd_soc_update_bits(codec, WM9090_SPEAKER_VOLUME_LEFT,
592 WM9090_HPOUT1_VU | WM9090_HPOUT1R_ZC; 591 WM9090_SPKOUT_VU | WM9090_SPKOUTL_ZC,
593 592 WM9090_SPKOUT_VU | WM9090_SPKOUTL_ZC);
594 reg_cache[WM9090_CLOCKING_1] |= WM9090_TOCLK_ENA; 593 snd_soc_update_bits(codec, WM9090_LEFT_OUTPUT_VOLUME,
594 WM9090_HPOUT1_VU | WM9090_HPOUT1L_ZC,
595 WM9090_HPOUT1_VU | WM9090_HPOUT1L_ZC);
596 snd_soc_update_bits(codec, WM9090_RIGHT_OUTPUT_VOLUME,
597 WM9090_HPOUT1_VU | WM9090_HPOUT1R_ZC,
598 WM9090_HPOUT1_VU | WM9090_HPOUT1R_ZC);
599
600 snd_soc_update_bits(codec, WM9090_CLOCKING_1,
601 WM9090_TOCLK_ENA, WM9090_TOCLK_ENA);
595 602
596 wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 603 wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
597 604
diff --git a/sound/soc/ep93xx/Kconfig b/sound/soc/ep93xx/Kconfig
index 57429041189c..91a28de94109 100644
--- a/sound/soc/ep93xx/Kconfig
+++ b/sound/soc/ep93xx/Kconfig
@@ -30,3 +30,12 @@ config SND_EP93XX_SOC_SIMONE
30 help 30 help
31 Say Y or M here if you want to add support for AC97 audio on the 31 Say Y or M here if you want to add support for AC97 audio on the
32 Simplemachines Sim.One board. 32 Simplemachines Sim.One board.
33
34config SND_EP93XX_SOC_EDB93XX
35 tristate "SoC Audio support for Cirrus Logic EDB93xx boards"
36 depends on SND_EP93XX_SOC && (MACH_EDB9301 || MACH_EDB9302 || MACH_EDB9302A || MACH_EDB9307A || MACH_EDB9315A)
37 select SND_EP93XX_SOC_I2S
38 select SND_SOC_CS4271
39 help
40 Say Y or M here if you want to add support for I2S audio on the
41 Cirrus Logic EDB93xx boards.
diff --git a/sound/soc/ep93xx/Makefile b/sound/soc/ep93xx/Makefile
index 8e7977fb6b7d..5514146cbdf0 100644
--- a/sound/soc/ep93xx/Makefile
+++ b/sound/soc/ep93xx/Makefile
@@ -10,6 +10,8 @@ obj-$(CONFIG_SND_EP93XX_SOC_AC97) += snd-soc-ep93xx-ac97.o
10# EP93XX Machine Support 10# EP93XX Machine Support
11snd-soc-snappercl15-objs := snappercl15.o 11snd-soc-snappercl15-objs := snappercl15.o
12snd-soc-simone-objs := simone.o 12snd-soc-simone-objs := simone.o
13snd-soc-edb93xx-objs := edb93xx.o
13 14
14obj-$(CONFIG_SND_EP93XX_SOC_SNAPPERCL15) += snd-soc-snappercl15.o 15obj-$(CONFIG_SND_EP93XX_SOC_SNAPPERCL15) += snd-soc-snappercl15.o
15obj-$(CONFIG_SND_EP93XX_SOC_SIMONE) += snd-soc-simone.o 16obj-$(CONFIG_SND_EP93XX_SOC_SIMONE) += snd-soc-simone.o
17obj-$(CONFIG_SND_EP93XX_SOC_EDB93XX) += snd-soc-edb93xx.o
diff --git a/sound/soc/ep93xx/edb93xx.c b/sound/soc/ep93xx/edb93xx.c
new file mode 100644
index 000000000000..b270085227f3
--- /dev/null
+++ b/sound/soc/ep93xx/edb93xx.c
@@ -0,0 +1,142 @@
1/*
2 * SoC audio for EDB93xx
3 *
4 * Copyright (c) 2010 Alexander Sverdlin <subaparts@yandex.ru>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * This driver support CS4271 codec being master or slave, working
17 * in control port mode, connected either via SPI or I2C.
18 * The data format accepted is I2S or left-justified.
19 * DAPM support not implemented.
20 */
21
22#include <linux/platform_device.h>
23#include <linux/gpio.h>
24#include <sound/core.h>
25#include <sound/pcm.h>
26#include <sound/soc.h>
27#include <asm/mach-types.h>
28#include <mach/hardware.h>
29#include "ep93xx-pcm.h"
30
31#define edb93xx_has_audio() (machine_is_edb9301() || \
32 machine_is_edb9302() || \
33 machine_is_edb9302a() || \
34 machine_is_edb9307a() || \
35 machine_is_edb9315a())
36
37static int edb93xx_hw_params(struct snd_pcm_substream *substream,
38 struct snd_pcm_hw_params *params)
39{
40 struct snd_soc_pcm_runtime *rtd = substream->private_data;
41 struct snd_soc_dai *codec_dai = rtd->codec_dai;
42 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
43 int err;
44 unsigned int rate = params_rate(params);
45 /*
46 * We set LRCLK equal to `rate' and SCLK = LRCLK * 64,
47 * because our sample size is 32 bit * 2 channels.
48 * I2S standard permits us to transmit more bits than
49 * the codec uses.
50 * MCLK = SCLK * 4 is the best recommended value,
51 * but we have to fall back to ratio 2 for higher
52 * sample rates.
53 */
54 unsigned int mclk_rate = rate * 64 * ((rate <= 48000) ? 4 : 2);
55
56 err = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
57 SND_SOC_DAIFMT_NB_IF |
58 SND_SOC_DAIFMT_CBS_CFS);
59 if (err)
60 return err;
61
62 err = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
63 SND_SOC_DAIFMT_NB_IF |
64 SND_SOC_DAIFMT_CBS_CFS);
65 if (err)
66 return err;
67
68 err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk_rate,
69 SND_SOC_CLOCK_IN);
70 if (err)
71 return err;
72
73 return snd_soc_dai_set_sysclk(cpu_dai, 0, mclk_rate,
74 SND_SOC_CLOCK_OUT);
75}
76
77static struct snd_soc_ops edb93xx_ops = {
78 .hw_params = edb93xx_hw_params,
79};
80
81static struct snd_soc_dai_link edb93xx_dai = {
82 .name = "CS4271",
83 .stream_name = "CS4271 HiFi",
84 .platform_name = "ep93xx-pcm-audio",
85 .cpu_dai_name = "ep93xx-i2s",
86 .codec_name = "spi0.0",
87 .codec_dai_name = "cs4271-hifi",
88 .ops = &edb93xx_ops,
89};
90
91static struct snd_soc_card snd_soc_edb93xx = {
92 .name = "EDB93XX",
93 .dai_link = &edb93xx_dai,
94 .num_links = 1,
95};
96
97static struct platform_device *edb93xx_snd_device;
98
99static int __init edb93xx_init(void)
100{
101 int ret;
102
103 if (!edb93xx_has_audio())
104 return -ENODEV;
105
106 ret = ep93xx_i2s_acquire(EP93XX_SYSCON_DEVCFG_I2SONAC97,
107 EP93XX_SYSCON_I2SCLKDIV_ORIDE |
108 EP93XX_SYSCON_I2SCLKDIV_SPOL);
109 if (ret)
110 return ret;
111
112 edb93xx_snd_device = platform_device_alloc("soc-audio", -1);
113 if (!edb93xx_snd_device) {
114 ret = -ENOMEM;
115 goto free_i2s;
116 }
117
118 platform_set_drvdata(edb93xx_snd_device, &snd_soc_edb93xx);
119 ret = platform_device_add(edb93xx_snd_device);
120 if (ret)
121 goto device_put;
122
123 return 0;
124
125device_put:
126 platform_device_put(edb93xx_snd_device);
127free_i2s:
128 ep93xx_i2s_release();
129 return ret;
130}
131module_init(edb93xx_init);
132
133static void __exit edb93xx_exit(void)
134{
135 platform_device_unregister(edb93xx_snd_device);
136 ep93xx_i2s_release();
137}
138module_exit(edb93xx_exit);
139
140MODULE_AUTHOR("Alexander Sverdlin <subaparts@yandex.ru>");
141MODULE_DESCRIPTION("ALSA SoC EDB93xx");
142MODULE_LICENSE("GPL");
diff --git a/sound/soc/mid-x86/Kconfig b/sound/soc/mid-x86/Kconfig
new file mode 100644
index 000000000000..1ad753836356
--- /dev/null
+++ b/sound/soc/mid-x86/Kconfig
@@ -0,0 +1,14 @@
1config SND_MFLD_MACHINE
2 tristate "SOC Machine Audio driver for Intel Medfield MID platform"
3 depends on INTEL_SCU_IPC
4 select SND_SOC_SN95031
5 select SND_SST_PLATFORM
6 help
7 This adds support for ASoC machine driver for Intel(R) MID Medfield platform
8 used as alsa device in audio substem in Intel(R) MID devices
9 Say Y if you have such a device
10 If unsure select "N".
11
12config SND_SST_PLATFORM
13 tristate
14 depends on SND_INTEL_SST
diff --git a/sound/soc/mid-x86/Makefile b/sound/soc/mid-x86/Makefile
new file mode 100644
index 000000000000..639883339465
--- /dev/null
+++ b/sound/soc/mid-x86/Makefile
@@ -0,0 +1,5 @@
1snd-soc-sst-platform-objs := sst_platform.o
2snd-soc-mfld-machine-objs := mfld_machine.o
3
4obj-$(CONFIG_SND_SST_PLATFORM) += snd-soc-sst-platform.o
5obj-$(CONFIG_SND_MFLD_MACHINE) += snd-soc-mfld-machine.o
diff --git a/sound/soc/mid-x86/mfld_machine.c b/sound/soc/mid-x86/mfld_machine.c
new file mode 100644
index 000000000000..1a330be1a01e
--- /dev/null
+++ b/sound/soc/mid-x86/mfld_machine.c
@@ -0,0 +1,296 @@
1/*
2 * mfld_machine.c - ASoc Machine driver for Intel Medfield MID platform
3 *
4 * Copyright (C) 2010 Intel Corp
5 * Author: Vinod Koul <vinod.koul@intel.com>
6 * Author: Harsha Priya <priya.harsha@intel.com>
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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 as published by
11 * the Free Software Foundation; version 2 of the License.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
21 *
22 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23 */
24
25#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
26
27#include <linux/init.h>
28#include <linux/device.h>
29#include <linux/slab.h>
30#include <sound/pcm.h>
31#include <sound/pcm_params.h>
32#include <sound/soc.h>
33#include "../codecs/sn95031.h"
34
35#define MID_MONO 1
36#define MID_STEREO 2
37#define MID_MAX_CAP 5
38
39static unsigned int hs_switch;
40static unsigned int lo_dac;
41
42/* sound card controls */
43static const char *headset_switch_text[] = {"Earpiece", "Headset"};
44
45static const char *lo_text[] = {"Vibra", "Headset", "IHF", "None"};
46
47static const struct soc_enum headset_enum =
48 SOC_ENUM_SINGLE_EXT(2, headset_switch_text);
49
50static const struct soc_enum lo_enum =
51 SOC_ENUM_SINGLE_EXT(4, lo_text);
52
53static int headset_get_switch(struct snd_kcontrol *kcontrol,
54 struct snd_ctl_elem_value *ucontrol)
55{
56 ucontrol->value.integer.value[0] = hs_switch;
57 return 0;
58}
59
60static int headset_set_switch(struct snd_kcontrol *kcontrol,
61 struct snd_ctl_elem_value *ucontrol)
62{
63 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
64
65 if (ucontrol->value.integer.value[0] == hs_switch)
66 return 0;
67
68 if (ucontrol->value.integer.value[0]) {
69 pr_debug("hs_set HS path\n");
70 snd_soc_dapm_enable_pin(&codec->dapm, "HPOUTL");
71 snd_soc_dapm_enable_pin(&codec->dapm, "HPOUTR");
72 snd_soc_dapm_disable_pin(&codec->dapm, "EPOUT");
73 } else {
74 pr_debug("hs_set EP path\n");
75 snd_soc_dapm_disable_pin(&codec->dapm, "HPOUTL");
76 snd_soc_dapm_disable_pin(&codec->dapm, "HPOUTR");
77 snd_soc_dapm_enable_pin(&codec->dapm, "EPOUT");
78 }
79 snd_soc_dapm_sync(&codec->dapm);
80 hs_switch = ucontrol->value.integer.value[0];
81
82 return 0;
83}
84
85static void lo_enable_out_pins(struct snd_soc_codec *codec)
86{
87 snd_soc_dapm_enable_pin(&codec->dapm, "IHFOUTL");
88 snd_soc_dapm_enable_pin(&codec->dapm, "IHFOUTR");
89 snd_soc_dapm_enable_pin(&codec->dapm, "LINEOUTL");
90 snd_soc_dapm_enable_pin(&codec->dapm, "LINEOUTR");
91 snd_soc_dapm_enable_pin(&codec->dapm, "VIB1OUT");
92 snd_soc_dapm_enable_pin(&codec->dapm, "VIB2OUT");
93 if (hs_switch) {
94 snd_soc_dapm_enable_pin(&codec->dapm, "HPOUTL");
95 snd_soc_dapm_enable_pin(&codec->dapm, "HPOUTR");
96 snd_soc_dapm_disable_pin(&codec->dapm, "EPOUT");
97 } else {
98 snd_soc_dapm_disable_pin(&codec->dapm, "HPOUTL");
99 snd_soc_dapm_disable_pin(&codec->dapm, "HPOUTR");
100 snd_soc_dapm_enable_pin(&codec->dapm, "EPOUT");
101 }
102}
103
104static int lo_get_switch(struct snd_kcontrol *kcontrol,
105 struct snd_ctl_elem_value *ucontrol)
106{
107 ucontrol->value.integer.value[0] = lo_dac;
108 return 0;
109}
110
111static int lo_set_switch(struct snd_kcontrol *kcontrol,
112 struct snd_ctl_elem_value *ucontrol)
113{
114 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
115
116 if (ucontrol->value.integer.value[0] == lo_dac)
117 return 0;
118
119 /* we dont want to work with last state of lineout so just enable all
120 * pins and then disable pins not required
121 */
122 lo_enable_out_pins(codec);
123 switch (ucontrol->value.integer.value[0]) {
124 case 0:
125 pr_debug("set vibra path\n");
126 snd_soc_dapm_disable_pin(&codec->dapm, "VIB1OUT");
127 snd_soc_dapm_disable_pin(&codec->dapm, "VIB2OUT");
128 snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0);
129 break;
130
131 case 1:
132 pr_debug("set hs path\n");
133 snd_soc_dapm_disable_pin(&codec->dapm, "HPOUTL");
134 snd_soc_dapm_disable_pin(&codec->dapm, "HPOUTR");
135 snd_soc_dapm_disable_pin(&codec->dapm, "EPOUT");
136 snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0x22);
137 break;
138
139 case 2:
140 pr_debug("set spkr path\n");
141 snd_soc_dapm_disable_pin(&codec->dapm, "IHFOUTL");
142 snd_soc_dapm_disable_pin(&codec->dapm, "IHFOUTR");
143 snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0x44);
144 break;
145
146 case 3:
147 pr_debug("set null path\n");
148 snd_soc_dapm_disable_pin(&codec->dapm, "LINEOUTL");
149 snd_soc_dapm_disable_pin(&codec->dapm, "LINEOUTR");
150 snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0x66);
151 break;
152 }
153 snd_soc_dapm_sync(&codec->dapm);
154 lo_dac = ucontrol->value.integer.value[0];
155 return 0;
156}
157
158static const struct snd_kcontrol_new mfld_snd_controls[] = {
159 SOC_ENUM_EXT("Playback Switch", headset_enum,
160 headset_get_switch, headset_set_switch),
161 SOC_ENUM_EXT("Lineout Mux", lo_enum,
162 lo_get_switch, lo_set_switch),
163};
164
165static int mfld_init(struct snd_soc_pcm_runtime *runtime)
166{
167 struct snd_soc_codec *codec = runtime->codec;
168 struct snd_soc_dapm_context *dapm = &codec->dapm;
169 int ret_val;
170
171 ret_val = snd_soc_add_controls(codec, mfld_snd_controls,
172 ARRAY_SIZE(mfld_snd_controls));
173 if (ret_val) {
174 pr_err("soc_add_controls failed %d", ret_val);
175 return ret_val;
176 }
177 /* default is earpiece pin, userspace sets it explcitly */
178 snd_soc_dapm_disable_pin(dapm, "HPOUTL");
179 snd_soc_dapm_disable_pin(dapm, "HPOUTR");
180 /* default is lineout NC, userspace sets it explcitly */
181 snd_soc_dapm_disable_pin(dapm, "LINEOUTL");
182 snd_soc_dapm_disable_pin(dapm, "LINEOUTR");
183 lo_dac = 3;
184 hs_switch = 0;
185 return snd_soc_dapm_sync(dapm);
186}
187
188struct snd_soc_dai_link mfld_msic_dailink[] = {
189 {
190 .name = "Medfield Headset",
191 .stream_name = "Headset",
192 .cpu_dai_name = "Headset-cpu-dai",
193 .codec_dai_name = "SN95031 Headset",
194 .codec_name = "sn95031",
195 .platform_name = "sst-platform",
196 .init = mfld_init,
197 },
198 {
199 .name = "Medfield Speaker",
200 .stream_name = "Speaker",
201 .cpu_dai_name = "Speaker-cpu-dai",
202 .codec_dai_name = "SN95031 Speaker",
203 .codec_name = "sn95031",
204 .platform_name = "sst-platform",
205 .init = NULL,
206 },
207 {
208 .name = "Medfield Vibra",
209 .stream_name = "Vibra1",
210 .cpu_dai_name = "Vibra1-cpu-dai",
211 .codec_dai_name = "SN95031 Vibra1",
212 .codec_name = "sn95031",
213 .platform_name = "sst-platform",
214 .init = NULL,
215 },
216 {
217 .name = "Medfield Haptics",
218 .stream_name = "Vibra2",
219 .cpu_dai_name = "Vibra2-cpu-dai",
220 .codec_dai_name = "SN95031 Vibra2",
221 .codec_name = "sn95031",
222 .platform_name = "sst-platform",
223 .init = NULL,
224 },
225};
226
227/* SoC card */
228static struct snd_soc_card snd_soc_card_mfld = {
229 .name = "medfield_audio",
230 .dai_link = mfld_msic_dailink,
231 .num_links = ARRAY_SIZE(mfld_msic_dailink),
232};
233
234static int __devinit snd_mfld_mc_probe(struct platform_device *pdev)
235{
236 struct platform_device *socdev;
237 int ret_val = 0;
238
239 pr_debug("snd_mfld_mc_probe called\n");
240
241 socdev = platform_device_alloc("soc-audio", -1);
242 if (!socdev) {
243 pr_err("soc-audio device allocation failed\n");
244 return -ENOMEM;
245 }
246 platform_set_drvdata(socdev, &snd_soc_card_mfld);
247 ret_val = platform_device_add(socdev);
248 if (ret_val) {
249 pr_err("Unable to add soc-audio device, err %d\n", ret_val);
250 platform_device_put(socdev);
251 }
252
253 platform_set_drvdata(pdev, socdev);
254
255 pr_debug("successfully exited probe\n");
256 return ret_val;
257}
258
259static int __devexit snd_mfld_mc_remove(struct platform_device *pdev)
260{
261 struct platform_device *socdev = platform_get_drvdata(pdev);
262 pr_debug("snd_mfld_mc_remove called\n");
263
264 platform_device_unregister(socdev);
265 platform_set_drvdata(pdev, NULL);
266 return 0;
267}
268
269static struct platform_driver snd_mfld_mc_driver = {
270 .driver = {
271 .owner = THIS_MODULE,
272 .name = "msic_audio",
273 },
274 .probe = snd_mfld_mc_probe,
275 .remove = __devexit_p(snd_mfld_mc_remove),
276};
277
278static int __init snd_mfld_driver_init(void)
279{
280 pr_debug("snd_mfld_driver_init called\n");
281 return platform_driver_register(&snd_mfld_mc_driver);
282}
283module_init(snd_mfld_driver_init);
284
285static void __exit snd_mfld_driver_exit(void)
286{
287 pr_debug("snd_mfld_driver_exit called\n");
288 platform_driver_unregister(&snd_mfld_mc_driver);
289}
290module_exit(snd_mfld_driver_exit);
291
292MODULE_DESCRIPTION("ASoC Intel(R) MID Machine driver");
293MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
294MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>");
295MODULE_LICENSE("GPL v2");
296MODULE_ALIAS("platform:msic-audio");
diff --git a/sound/soc/mid-x86/sst_platform.c b/sound/soc/mid-x86/sst_platform.c
new file mode 100644
index 000000000000..1d1f5447b338
--- /dev/null
+++ b/sound/soc/mid-x86/sst_platform.c
@@ -0,0 +1,459 @@
1/*
2 * sst_platform.c - Intel MID Platform driver
3 *
4 * Copyright (C) 2010 Intel Corp
5 * Author: Vinod Koul <vinod.koul@intel.com>
6 * Author: Harsha Priya <priya.harsha@intel.com>
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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 as published by
11 * the Free Software Foundation; version 2 of the License.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
21 *
22 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23 *
24 *
25 */
26#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
27
28#include <linux/slab.h>
29#include <linux/io.h>
30#include <sound/core.h>
31#include <sound/pcm.h>
32#include <sound/pcm_params.h>
33#include <sound/soc.h>
34#include "../../../drivers/staging/intel_sst/intel_sst_ioctl.h"
35#include "../../../drivers/staging/intel_sst/intel_sst.h"
36#include "sst_platform.h"
37
38static struct snd_pcm_hardware sst_platform_pcm_hw = {
39 .info = (SNDRV_PCM_INFO_INTERLEAVED |
40 SNDRV_PCM_INFO_DOUBLE |
41 SNDRV_PCM_INFO_PAUSE |
42 SNDRV_PCM_INFO_RESUME |
43 SNDRV_PCM_INFO_MMAP|
44 SNDRV_PCM_INFO_MMAP_VALID |
45 SNDRV_PCM_INFO_BLOCK_TRANSFER |
46 SNDRV_PCM_INFO_SYNC_START),
47 .formats = (SNDRV_PCM_FMTBIT_S16 | SNDRV_PCM_FMTBIT_U16 |
48 SNDRV_PCM_FMTBIT_S24 | SNDRV_PCM_FMTBIT_U24 |
49 SNDRV_PCM_FMTBIT_S32 | SNDRV_PCM_FMTBIT_U32),
50 .rates = (SNDRV_PCM_RATE_8000|
51 SNDRV_PCM_RATE_44100 |
52 SNDRV_PCM_RATE_48000),
53 .rate_min = SST_MIN_RATE,
54 .rate_max = SST_MAX_RATE,
55 .channels_min = SST_MIN_CHANNEL,
56 .channels_max = SST_MAX_CHANNEL,
57 .buffer_bytes_max = SST_MAX_BUFFER,
58 .period_bytes_min = SST_MIN_PERIOD_BYTES,
59 .period_bytes_max = SST_MAX_PERIOD_BYTES,
60 .periods_min = SST_MIN_PERIODS,
61 .periods_max = SST_MAX_PERIODS,
62 .fifo_size = SST_FIFO_SIZE,
63};
64
65/* MFLD - MSIC */
66struct snd_soc_dai_driver sst_platform_dai[] = {
67{
68 .name = "Headset-cpu-dai",
69 .id = 0,
70 .playback = {
71 .channels_min = SST_STEREO,
72 .channels_max = SST_STEREO,
73 .rates = SNDRV_PCM_RATE_48000,
74 .formats = SNDRV_PCM_FMTBIT_S24_LE,
75 },
76},
77{
78 .name = "Speaker-cpu-dai",
79 .id = 1,
80 .playback = {
81 .channels_min = SST_MONO,
82 .channels_max = SST_STEREO,
83 .rates = SNDRV_PCM_RATE_48000,
84 .formats = SNDRV_PCM_FMTBIT_S24_LE,
85 },
86},
87{
88 .name = "Vibra1-cpu-dai",
89 .id = 2,
90 .playback = {
91 .channels_min = SST_MONO,
92 .channels_max = SST_MONO,
93 .rates = SNDRV_PCM_RATE_48000,
94 .formats = SNDRV_PCM_FMTBIT_S24_LE,
95 },
96},
97{
98 .name = "Vibra2-cpu-dai",
99 .id = 3,
100 .playback = {
101 .channels_min = SST_MONO,
102 .channels_max = SST_STEREO,
103 .rates = SNDRV_PCM_RATE_48000,
104 .formats = SNDRV_PCM_FMTBIT_S24_LE,
105 },
106},
107};
108
109/* helper functions */
110static inline void sst_set_stream_status(struct sst_runtime_stream *stream,
111 int state)
112{
113 spin_lock(&stream->status_lock);
114 stream->stream_status = state;
115 spin_unlock(&stream->status_lock);
116}
117
118static inline int sst_get_stream_status(struct sst_runtime_stream *stream)
119{
120 int state;
121
122 spin_lock(&stream->status_lock);
123 state = stream->stream_status;
124 spin_unlock(&stream->status_lock);
125 return state;
126}
127
128static void sst_fill_pcm_params(struct snd_pcm_substream *substream,
129 struct snd_sst_stream_params *param)
130{
131
132 param->uc.pcm_params.codec = SST_CODEC_TYPE_PCM;
133 param->uc.pcm_params.num_chan = (u8) substream->runtime->channels;
134 param->uc.pcm_params.pcm_wd_sz = substream->runtime->sample_bits;
135 param->uc.pcm_params.reserved = 0;
136 param->uc.pcm_params.sfreq = substream->runtime->rate;
137 param->uc.pcm_params.ring_buffer_size =
138 snd_pcm_lib_buffer_bytes(substream);
139 param->uc.pcm_params.period_count = substream->runtime->period_size;
140 param->uc.pcm_params.ring_buffer_addr =
141 virt_to_phys(substream->dma_buffer.area);
142 pr_debug("period_cnt = %d\n", param->uc.pcm_params.period_count);
143 pr_debug("sfreq= %d, wd_sz = %d\n",
144 param->uc.pcm_params.sfreq, param->uc.pcm_params.pcm_wd_sz);
145}
146
147static int sst_platform_alloc_stream(struct snd_pcm_substream *substream)
148{
149 struct sst_runtime_stream *stream =
150 substream->runtime->private_data;
151 struct snd_sst_stream_params param = {{{0,},},};
152 struct snd_sst_params str_params = {0};
153 int ret_val;
154
155 /* set codec params and inform SST driver the same */
156 sst_fill_pcm_params(substream, &param);
157 substream->runtime->dma_area = substream->dma_buffer.area;
158 str_params.sparams = param;
159 str_params.codec = param.uc.pcm_params.codec;
160 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
161 str_params.ops = STREAM_OPS_PLAYBACK;
162 str_params.device_type = substream->pcm->device + 1;
163 pr_debug("Playbck stream,Device %d\n",
164 substream->pcm->device);
165 } else {
166 str_params.ops = STREAM_OPS_CAPTURE;
167 str_params.device_type = SND_SST_DEVICE_CAPTURE;
168 pr_debug("Capture stream,Device %d\n",
169 substream->pcm->device);
170 }
171 ret_val = stream->sstdrv_ops->pcm_control->open(&str_params);
172 pr_debug("SST_SND_PLAY/CAPTURE ret_val = %x\n", ret_val);
173 if (ret_val < 0)
174 return ret_val;
175
176 stream->stream_info.str_id = ret_val;
177 pr_debug("str id : %d\n", stream->stream_info.str_id);
178 return ret_val;
179}
180
181static void sst_period_elapsed(void *mad_substream)
182{
183 struct snd_pcm_substream *substream = mad_substream;
184 struct sst_runtime_stream *stream;
185 int status;
186
187 if (!substream || !substream->runtime)
188 return;
189 stream = substream->runtime->private_data;
190 if (!stream)
191 return;
192 status = sst_get_stream_status(stream);
193 if (status != SST_PLATFORM_RUNNING)
194 return;
195 snd_pcm_period_elapsed(substream);
196}
197
198static int sst_platform_init_stream(struct snd_pcm_substream *substream)
199{
200 struct sst_runtime_stream *stream =
201 substream->runtime->private_data;
202 int ret_val;
203
204 pr_debug("setting buffer ptr param\n");
205 sst_set_stream_status(stream, SST_PLATFORM_INIT);
206 stream->stream_info.period_elapsed = sst_period_elapsed;
207 stream->stream_info.mad_substream = substream;
208 stream->stream_info.buffer_ptr = 0;
209 stream->stream_info.sfreq = substream->runtime->rate;
210 ret_val = stream->sstdrv_ops->pcm_control->device_control(
211 SST_SND_STREAM_INIT, &stream->stream_info);
212 if (ret_val)
213 pr_err("control_set ret error %d\n", ret_val);
214 return ret_val;
215
216}
217/* end -- helper functions */
218
219static int sst_platform_open(struct snd_pcm_substream *substream)
220{
221 struct snd_pcm_runtime *runtime;
222 struct sst_runtime_stream *stream;
223 int ret_val = 0;
224
225 pr_debug("sst_platform_open called\n");
226 runtime = substream->runtime;
227 runtime->hw = sst_platform_pcm_hw;
228 stream = kzalloc(sizeof(*stream), GFP_KERNEL);
229 if (!stream)
230 return -ENOMEM;
231 spin_lock_init(&stream->status_lock);
232 stream->stream_info.str_id = 0;
233 sst_set_stream_status(stream, SST_PLATFORM_INIT);
234 stream->stream_info.mad_substream = substream;
235 /* allocate memory for SST API set */
236 stream->sstdrv_ops = kzalloc(sizeof(*stream->sstdrv_ops),
237 GFP_KERNEL);
238 if (!stream->sstdrv_ops) {
239 pr_err("sst: mem allocation for ops fail\n");
240 kfree(stream);
241 return -ENOMEM;
242 }
243 stream->sstdrv_ops->vendor_id = MSIC_VENDOR_ID;
244 /* registering with SST driver to get access to SST APIs to use */
245 ret_val = register_sst_card(stream->sstdrv_ops);
246 if (ret_val) {
247 pr_err("sst: sst card registration failed\n");
248 return ret_val;
249 }
250 runtime->private_data = stream;
251 return snd_pcm_hw_constraint_integer(runtime,
252 SNDRV_PCM_HW_PARAM_PERIODS);
253}
254
255static int sst_platform_close(struct snd_pcm_substream *substream)
256{
257 struct sst_runtime_stream *stream;
258 int ret_val = 0, str_id;
259
260 pr_debug("sst_platform_close called\n");
261 stream = substream->runtime->private_data;
262 str_id = stream->stream_info.str_id;
263 if (str_id)
264 ret_val = stream->sstdrv_ops->pcm_control->close(str_id);
265 kfree(stream->sstdrv_ops);
266 kfree(stream);
267 return ret_val;
268}
269
270static int sst_platform_pcm_prepare(struct snd_pcm_substream *substream)
271{
272 struct sst_runtime_stream *stream;
273 int ret_val = 0, str_id;
274
275 pr_debug("sst_platform_pcm_prepare called\n");
276 stream = substream->runtime->private_data;
277 str_id = stream->stream_info.str_id;
278 if (stream->stream_info.str_id) {
279 ret_val = stream->sstdrv_ops->pcm_control->device_control(
280 SST_SND_DROP, &str_id);
281 return ret_val;
282 }
283
284 ret_val = sst_platform_alloc_stream(substream);
285 if (ret_val < 0)
286 return ret_val;
287 snprintf(substream->pcm->id, sizeof(substream->pcm->id),
288 "%d", stream->stream_info.str_id);
289
290 ret_val = sst_platform_init_stream(substream);
291 if (ret_val)
292 return ret_val;
293 substream->runtime->hw.info = SNDRV_PCM_INFO_BLOCK_TRANSFER;
294 return ret_val;
295}
296
297static int sst_platform_pcm_trigger(struct snd_pcm_substream *substream,
298 int cmd)
299{
300 int ret_val = 0, str_id;
301 struct sst_runtime_stream *stream;
302 int str_cmd, status;
303
304 pr_debug("sst_platform_pcm_trigger called\n");
305 stream = substream->runtime->private_data;
306 str_id = stream->stream_info.str_id;
307 switch (cmd) {
308 case SNDRV_PCM_TRIGGER_START:
309 pr_debug("sst: Trigger Start\n");
310 str_cmd = SST_SND_START;
311 status = SST_PLATFORM_RUNNING;
312 stream->stream_info.mad_substream = substream;
313 break;
314 case SNDRV_PCM_TRIGGER_STOP:
315 pr_debug("sst: in stop\n");
316 str_cmd = SST_SND_DROP;
317 status = SST_PLATFORM_DROPPED;
318 break;
319 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
320 pr_debug("sst: in pause\n");
321 str_cmd = SST_SND_PAUSE;
322 status = SST_PLATFORM_PAUSED;
323 break;
324 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
325 pr_debug("sst: in pause release\n");
326 str_cmd = SST_SND_RESUME;
327 status = SST_PLATFORM_RUNNING;
328 break;
329 default:
330 return -EINVAL;
331 }
332 ret_val = stream->sstdrv_ops->pcm_control->device_control(str_cmd,
333 &str_id);
334 if (!ret_val)
335 sst_set_stream_status(stream, status);
336
337 return ret_val;
338}
339
340
341static snd_pcm_uframes_t sst_platform_pcm_pointer
342 (struct snd_pcm_substream *substream)
343{
344 struct sst_runtime_stream *stream;
345 int ret_val, status;
346 struct pcm_stream_info *str_info;
347
348 stream = substream->runtime->private_data;
349 status = sst_get_stream_status(stream);
350 if (status == SST_PLATFORM_INIT)
351 return 0;
352 str_info = &stream->stream_info;
353 ret_val = stream->sstdrv_ops->pcm_control->device_control(
354 SST_SND_BUFFER_POINTER, str_info);
355 if (ret_val) {
356 pr_err("sst: error code = %d\n", ret_val);
357 return ret_val;
358 }
359 return stream->stream_info.buffer_ptr;
360}
361
362
363static struct snd_pcm_ops sst_platform_ops = {
364 .open = sst_platform_open,
365 .close = sst_platform_close,
366 .ioctl = snd_pcm_lib_ioctl,
367 .prepare = sst_platform_pcm_prepare,
368 .trigger = sst_platform_pcm_trigger,
369 .pointer = sst_platform_pcm_pointer,
370};
371
372static void sst_pcm_free(struct snd_pcm *pcm)
373{
374 pr_debug("sst_pcm_free called\n");
375 snd_pcm_lib_preallocate_free_for_all(pcm);
376}
377
378int sst_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
379 struct snd_pcm *pcm)
380{
381 int retval = 0;
382
383 pr_debug("sst_pcm_new called\n");
384 if (dai->driver->playback.channels_min ||
385 dai->driver->capture.channels_min) {
386 retval = snd_pcm_lib_preallocate_pages_for_all(pcm,
387 SNDRV_DMA_TYPE_CONTINUOUS,
388 snd_dma_continuous_data(GFP_KERNEL),
389 SST_MIN_BUFFER, SST_MAX_BUFFER);
390 if (retval) {
391 pr_err("dma buffer allocationf fail\n");
392 return retval;
393 }
394 }
395 return retval;
396}
397struct snd_soc_platform_driver sst_soc_platform_drv = {
398 .ops = &sst_platform_ops,
399 .pcm_new = sst_pcm_new,
400 .pcm_free = sst_pcm_free,
401};
402
403static int sst_platform_probe(struct platform_device *pdev)
404{
405 int ret;
406
407 pr_debug("sst_platform_probe called\n");
408 ret = snd_soc_register_platform(&pdev->dev, &sst_soc_platform_drv);
409 if (ret) {
410 pr_err("registering soc platform failed\n");
411 return ret;
412 }
413
414 ret = snd_soc_register_dais(&pdev->dev,
415 sst_platform_dai, ARRAY_SIZE(sst_platform_dai));
416 if (ret) {
417 pr_err("registering cpu dais failed\n");
418 snd_soc_unregister_platform(&pdev->dev);
419 }
420 return ret;
421}
422
423static int sst_platform_remove(struct platform_device *pdev)
424{
425
426 snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(sst_platform_dai));
427 snd_soc_unregister_platform(&pdev->dev);
428 pr_debug("sst_platform_remove sucess\n");
429 return 0;
430}
431
432static struct platform_driver sst_platform_driver = {
433 .driver = {
434 .name = "sst-platform",
435 .owner = THIS_MODULE,
436 },
437 .probe = sst_platform_probe,
438 .remove = sst_platform_remove,
439};
440
441static int __init sst_soc_platform_init(void)
442{
443 pr_debug("sst_soc_platform_init called\n");
444 return platform_driver_register(&sst_platform_driver);
445}
446module_init(sst_soc_platform_init);
447
448static void __exit sst_soc_platform_exit(void)
449{
450 platform_driver_unregister(&sst_platform_driver);
451 pr_debug("sst_soc_platform_exit sucess\n");
452}
453module_exit(sst_soc_platform_exit);
454
455MODULE_DESCRIPTION("ASoC Intel(R) MID Platform driver");
456MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
457MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>");
458MODULE_LICENSE("GPL v2");
459MODULE_ALIAS("platform:sst-platform");
diff --git a/sound/soc/mid-x86/sst_platform.h b/sound/soc/mid-x86/sst_platform.h
new file mode 100644
index 000000000000..df370286694f
--- /dev/null
+++ b/sound/soc/mid-x86/sst_platform.h
@@ -0,0 +1,63 @@
1/*
2 * sst_platform.h - Intel MID Platform driver header file
3 *
4 * Copyright (C) 2010 Intel Corp
5 * Author: Vinod Koul <vinod.koul@intel.com>
6 * Author: Harsha Priya <priya.harsha@intel.com>
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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 as published by
11 * the Free Software Foundation; version 2 of the License.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
21 *
22 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23 *
24 *
25 */
26
27#ifndef __SST_PLATFORMDRV_H__
28#define __SST_PLATFORMDRV_H__
29
30#define SST_MONO 1
31#define SST_STEREO 2
32#define SST_MAX_CAP 5
33
34#define SST_MIN_RATE 8000
35#define SST_MAX_RATE 48000
36#define SST_MIN_CHANNEL 1
37#define SST_MAX_CHANNEL 5
38#define SST_MAX_BUFFER (800*1024)
39#define SST_MIN_BUFFER (800*1024)
40#define SST_MIN_PERIOD_BYTES 32
41#define SST_MAX_PERIOD_BYTES SST_MAX_BUFFER
42#define SST_MIN_PERIODS 2
43#define SST_MAX_PERIODS (1024*2)
44#define SST_FIFO_SIZE 0
45#define SST_CARD_NAMES "intel_mid_card"
46#define MSIC_VENDOR_ID 3
47
48struct sst_runtime_stream {
49 int stream_status;
50 struct pcm_stream_info stream_info;
51 struct intel_sst_card_ops *sstdrv_ops;
52 spinlock_t status_lock;
53};
54
55enum sst_drv_status {
56 SST_PLATFORM_INIT = 1,
57 SST_PLATFORM_STARTED,
58 SST_PLATFORM_RUNNING,
59 SST_PLATFORM_PAUSED,
60 SST_PLATFORM_DROPPED,
61};
62
63#endif
diff --git a/sound/soc/samsung/ac97.c b/sound/soc/samsung/ac97.c
index 4770a9550341..f97110e72e85 100644
--- a/sound/soc/samsung/ac97.c
+++ b/sound/soc/samsung/ac97.c
@@ -12,24 +12,24 @@
12 * published by the Free Software Foundation. 12 * published by the Free Software Foundation.
13 */ 13 */
14 14
15#include <linux/init.h>
16#include <linux/module.h>
17#include <linux/io.h> 15#include <linux/io.h>
18#include <linux/delay.h> 16#include <linux/delay.h>
19#include <linux/clk.h> 17#include <linux/clk.h>
20 18
21#include <sound/soc.h> 19#include <sound/soc.h>
22 20
23#include <plat/regs-ac97.h>
24#include <mach/dma.h> 21#include <mach/dma.h>
22#include <plat/regs-ac97.h>
25#include <plat/audio.h> 23#include <plat/audio.h>
26 24
27#include "dma.h" 25#include "dma.h"
28#include "ac97.h"
29 26
30#define AC_CMD_ADDR(x) (x << 16) 27#define AC_CMD_ADDR(x) (x << 16)
31#define AC_CMD_DATA(x) (x & 0xffff) 28#define AC_CMD_DATA(x) (x & 0xffff)
32 29
30#define S3C_AC97_DAI_PCM 0
31#define S3C_AC97_DAI_MIC 1
32
33struct s3c_ac97_info { 33struct s3c_ac97_info {
34 struct clk *ac97_clk; 34 struct clk *ac97_clk;
35 void __iomem *regs; 35 void __iomem *regs;
diff --git a/sound/soc/samsung/ac97.h b/sound/soc/samsung/ac97.h
deleted file mode 100644
index 0d0e1b511457..000000000000
--- a/sound/soc/samsung/ac97.h
+++ /dev/null
@@ -1,21 +0,0 @@
1/* sound/soc/samsung/ac97.h
2 *
3 * ALSA SoC Audio Layer - S3C AC97 Controller driver
4 * Evolved from s3c2443-ac97.h
5 *
6 * Copyright (c) 2010 Samsung Electronics Co. Ltd
7 * Author: Jaswinder Singh <jassi.brar@samsung.com>
8 * Credits: Graeme Gregory, Sean Choi
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#ifndef __S3C_AC97_H_
16#define __S3C_AC97_H_
17
18#define S3C_AC97_DAI_PCM 0
19#define S3C_AC97_DAI_MIC 1
20
21#endif /* __S3C_AC97_H_ */
diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c
index 21240198c5d6..9bce1df1f0d1 100644
--- a/sound/soc/samsung/dma.c
+++ b/sound/soc/samsung/dma.c
@@ -14,17 +14,11 @@
14 * option) any later version. 14 * option) any later version.
15 */ 15 */
16 16
17#include <linux/module.h>
18#include <linux/init.h>
19#include <linux/io.h>
20#include <linux/platform_device.h>
21#include <linux/slab.h> 17#include <linux/slab.h>
22#include <linux/dma-mapping.h> 18#include <linux/dma-mapping.h>
23 19
24#include <sound/core.h>
25#include <sound/pcm.h>
26#include <sound/pcm_params.h>
27#include <sound/soc.h> 20#include <sound/soc.h>
21#include <sound/pcm_params.h>
28 22
29#include <asm/dma.h> 23#include <asm/dma.h>
30#include <mach/hardware.h> 24#include <mach/hardware.h>
@@ -32,6 +26,9 @@
32 26
33#include "dma.h" 27#include "dma.h"
34 28
29#define ST_RUNNING (1<<0)
30#define ST_OPENED (1<<1)
31
35static const struct snd_pcm_hardware dma_hardware = { 32static const struct snd_pcm_hardware dma_hardware = {
36 .info = SNDRV_PCM_INFO_INTERLEAVED | 33 .info = SNDRV_PCM_INFO_INTERLEAVED |
37 SNDRV_PCM_INFO_BLOCK_TRANSFER | 34 SNDRV_PCM_INFO_BLOCK_TRANSFER |
diff --git a/sound/soc/samsung/dma.h b/sound/soc/samsung/dma.h
index f8cd2b4223af..c50659269a40 100644
--- a/sound/soc/samsung/dma.h
+++ b/sound/soc/samsung/dma.h
@@ -12,9 +12,6 @@
12#ifndef _S3C_AUDIO_H 12#ifndef _S3C_AUDIO_H
13#define _S3C_AUDIO_H 13#define _S3C_AUDIO_H
14 14
15#define ST_RUNNING (1<<0)
16#define ST_OPENED (1<<1)
17
18struct s3c_dma_params { 15struct s3c_dma_params {
19 struct s3c2410_dma_client *client; /* stream identifier */ 16 struct s3c2410_dma_client *client; /* stream identifier */
20 int channel; /* Channel ID */ 17 int channel; /* Channel ID */
@@ -22,9 +19,4 @@ struct s3c_dma_params {
22 int dma_size; /* Size of the DMA transfer */ 19 int dma_size; /* Size of the DMA transfer */
23}; 20};
24 21
25#define S3C24XX_DAI_I2S 0
26
27/* platform data */
28extern struct snd_ac97_bus_ops s3c24xx_ac97_ops;
29
30#endif 22#endif
diff --git a/sound/soc/samsung/goni_wm8994.c b/sound/soc/samsung/goni_wm8994.c
index 34dd9ef1b9c0..f6b3a3ce5919 100644
--- a/sound/soc/samsung/goni_wm8994.c
+++ b/sound/soc/samsung/goni_wm8994.c
@@ -11,21 +11,13 @@
11 * 11 *
12 */ 12 */
13 13
14#include <linux/module.h>
15#include <linux/moduleparam.h>
16#include <linux/io.h>
17#include <linux/platform_device.h>
18#include <sound/soc.h> 14#include <sound/soc.h>
19#include <sound/jack.h> 15#include <sound/jack.h>
16
20#include <asm/mach-types.h> 17#include <asm/mach-types.h>
21#include <mach/gpio.h> 18#include <mach/gpio.h>
22#include <mach/regs-clock.h>
23 19
24#include <linux/mfd/wm8994/core.h>
25#include <linux/mfd/wm8994/registers.h>
26#include "../codecs/wm8994.h" 20#include "../codecs/wm8994.h"
27#include "dma.h"
28#include "i2s.h"
29 21
30#define MACHINE_NAME 0 22#define MACHINE_NAME 0
31#define CPU_VOICE_DAI 1 23#define CPU_VOICE_DAI 1
diff --git a/sound/soc/samsung/h1940_uda1380.c b/sound/soc/samsung/h1940_uda1380.c
index c45f7ce14d61..241f55d00660 100644
--- a/sound/soc/samsung/h1940_uda1380.c
+++ b/sound/soc/samsung/h1940_uda1380.c
@@ -13,25 +13,16 @@
13 * 13 *
14 */ 14 */
15 15
16#include <linux/module.h>
17#include <linux/moduleparam.h>
18#include <linux/platform_device.h>
19#include <linux/i2c.h>
20#include <linux/gpio.h> 16#include <linux/gpio.h>
21 17
22#include <sound/soc.h> 18#include <sound/soc.h>
23#include <sound/uda1380.h>
24#include <sound/jack.h> 19#include <sound/jack.h>
25 20
26#include <plat/regs-iis.h> 21#include <plat/regs-iis.h>
27
28#include <mach/h1940-latch.h> 22#include <mach/h1940-latch.h>
29
30#include <asm/mach-types.h> 23#include <asm/mach-types.h>
31 24
32#include "dma.h"
33#include "s3c24xx-i2s.h" 25#include "s3c24xx-i2s.h"
34#include "../codecs/uda1380.h"
35 26
36static unsigned int rates[] = { 27static unsigned int rates[] = {
37 11025, 28 11025,
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index d00ac3a7102c..ffa09b3b2caa 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -15,9 +15,8 @@
15#include <linux/clk.h> 15#include <linux/clk.h>
16#include <linux/io.h> 16#include <linux/io.h>
17 17
18#include <sound/pcm.h>
19#include <sound/pcm_params.h>
20#include <sound/soc.h> 18#include <sound/soc.h>
19#include <sound/pcm_params.h>
21 20
22#include <plat/audio.h> 21#include <plat/audio.h>
23 22
diff --git a/sound/soc/samsung/jive_wm8750.c b/sound/soc/samsung/jive_wm8750.c
index 08802520e014..3b53ad54bc33 100644
--- a/sound/soc/samsung/jive_wm8750.c
+++ b/sound/soc/samsung/jive_wm8750.c
@@ -11,22 +11,11 @@
11 * published by the Free Software Foundation. 11 * published by the Free Software Foundation.
12*/ 12*/
13 13
14#include <linux/module.h>
15#include <linux/moduleparam.h>
16#include <linux/timer.h>
17#include <linux/interrupt.h>
18#include <linux/platform_device.h>
19#include <linux/clk.h>
20
21#include <sound/core.h>
22#include <sound/pcm.h>
23#include <sound/soc.h> 14#include <sound/soc.h>
24 15
25#include <asm/mach-types.h> 16#include <asm/mach-types.h>
26 17
27#include "dma.h"
28#include "s3c2412-i2s.h" 18#include "s3c2412-i2s.h"
29
30#include "../codecs/wm8750.h" 19#include "../codecs/wm8750.h"
31 20
32static const struct snd_soc_dapm_route audio_map[] = { 21static const struct snd_soc_dapm_route audio_map[] = {
diff --git a/sound/soc/samsung/ln2440sbc_alc650.c b/sound/soc/samsung/ln2440sbc_alc650.c
index a2bb34def740..bd91c19a6c08 100644
--- a/sound/soc/samsung/ln2440sbc_alc650.c
+++ b/sound/soc/samsung/ln2440sbc_alc650.c
@@ -16,15 +16,8 @@
16 * 16 *
17 */ 17 */
18 18
19#include <linux/module.h>
20#include <linux/device.h>
21#include <sound/core.h>
22#include <sound/pcm.h>
23#include <sound/soc.h> 19#include <sound/soc.h>
24 20
25#include "dma.h"
26#include "ac97.h"
27
28static struct snd_soc_card ln2440sbc; 21static struct snd_soc_card ln2440sbc;
29 22
30static struct snd_soc_dai_link ln2440sbc_dai[] = { 23static struct snd_soc_dai_link ln2440sbc_dai[] = {
diff --git a/sound/soc/samsung/neo1973_gta02_wm8753.c b/sound/soc/samsung/neo1973_gta02_wm8753.c
index 0d0ae2b9eef6..95ebf812b146 100644
--- a/sound/soc/samsung/neo1973_gta02_wm8753.c
+++ b/sound/soc/samsung/neo1973_gta02_wm8753.c
@@ -13,25 +13,15 @@
13 * option) any later version. 13 * option) any later version.
14 */ 14 */
15 15
16#include <linux/module.h>
17#include <linux/moduleparam.h>
18#include <linux/timer.h>
19#include <linux/interrupt.h>
20#include <linux/platform_device.h>
21#include <linux/gpio.h> 16#include <linux/gpio.h>
22#include <sound/core.h> 17
23#include <sound/pcm.h>
24#include <sound/soc.h> 18#include <sound/soc.h>
25 19
26#include <asm/mach-types.h> 20#include <asm/mach-types.h>
27
28#include <plat/regs-iis.h> 21#include <plat/regs-iis.h>
29
30#include <mach/regs-clock.h>
31#include <asm/io.h>
32#include <mach/gta02.h> 22#include <mach/gta02.h>
23
33#include "../codecs/wm8753.h" 24#include "../codecs/wm8753.h"
34#include "dma.h"
35#include "s3c24xx-i2s.h" 25#include "s3c24xx-i2s.h"
36 26
37static struct snd_soc_card neo1973_gta02; 27static struct snd_soc_card neo1973_gta02;
diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c
index 48d0b750406b..38aac7d57a59 100644
--- a/sound/soc/samsung/pcm.c
+++ b/sound/soc/samsung/pcm.c
@@ -11,20 +11,11 @@
11 * published by the Free Software Foundation. 11 * published by the Free Software Foundation.
12 */ 12 */
13 13
14#include <linux/init.h>
15#include <linux/module.h>
16#include <linux/device.h>
17#include <linux/delay.h>
18#include <linux/clk.h> 14#include <linux/clk.h>
19#include <linux/kernel.h>
20#include <linux/gpio.h>
21#include <linux/io.h> 15#include <linux/io.h>
22 16
23#include <sound/core.h>
24#include <sound/pcm.h>
25#include <sound/pcm_params.h>
26#include <sound/initval.h>
27#include <sound/soc.h> 17#include <sound/soc.h>
18#include <sound/pcm_params.h>
28 19
29#include <plat/audio.h> 20#include <plat/audio.h>
30#include <plat/dma.h> 21#include <plat/dma.h>
@@ -32,6 +23,113 @@
32#include "dma.h" 23#include "dma.h"
33#include "pcm.h" 24#include "pcm.h"
34 25
26/*Register Offsets */
27#define S3C_PCM_CTL 0x00
28#define S3C_PCM_CLKCTL 0x04
29#define S3C_PCM_TXFIFO 0x08
30#define S3C_PCM_RXFIFO 0x0C
31#define S3C_PCM_IRQCTL 0x10
32#define S3C_PCM_IRQSTAT 0x14
33#define S3C_PCM_FIFOSTAT 0x18
34#define S3C_PCM_CLRINT 0x20
35
36/* PCM_CTL Bit-Fields */
37#define S3C_PCM_CTL_TXDIPSTICK_MASK 0x3f
38#define S3C_PCM_CTL_TXDIPSTICK_SHIFT 13
39#define S3C_PCM_CTL_RXDIPSTICK_MASK 0x3f
40#define S3C_PCM_CTL_RXDIPSTICK_SHIFT 7
41#define S3C_PCM_CTL_TXDMA_EN (0x1 << 6)
42#define S3C_PCM_CTL_RXDMA_EN (0x1 << 5)
43#define S3C_PCM_CTL_TXMSB_AFTER_FSYNC (0x1 << 4)
44#define S3C_PCM_CTL_RXMSB_AFTER_FSYNC (0x1 << 3)
45#define S3C_PCM_CTL_TXFIFO_EN (0x1 << 2)
46#define S3C_PCM_CTL_RXFIFO_EN (0x1 << 1)
47#define S3C_PCM_CTL_ENABLE (0x1 << 0)
48
49/* PCM_CLKCTL Bit-Fields */
50#define S3C_PCM_CLKCTL_SERCLK_EN (0x1 << 19)
51#define S3C_PCM_CLKCTL_SERCLKSEL_PCLK (0x1 << 18)
52#define S3C_PCM_CLKCTL_SCLKDIV_MASK 0x1ff
53#define S3C_PCM_CLKCTL_SYNCDIV_MASK 0x1ff
54#define S3C_PCM_CLKCTL_SCLKDIV_SHIFT 9
55#define S3C_PCM_CLKCTL_SYNCDIV_SHIFT 0
56
57/* PCM_TXFIFO Bit-Fields */
58#define S3C_PCM_TXFIFO_DVALID (0x1 << 16)
59#define S3C_PCM_TXFIFO_DATA_MSK (0xffff << 0)
60
61/* PCM_RXFIFO Bit-Fields */
62#define S3C_PCM_RXFIFO_DVALID (0x1 << 16)
63#define S3C_PCM_RXFIFO_DATA_MSK (0xffff << 0)
64
65/* PCM_IRQCTL Bit-Fields */
66#define S3C_PCM_IRQCTL_IRQEN (0x1 << 14)
67#define S3C_PCM_IRQCTL_WRDEN (0x1 << 12)
68#define S3C_PCM_IRQCTL_TXEMPTYEN (0x1 << 11)
69#define S3C_PCM_IRQCTL_TXALMSTEMPTYEN (0x1 << 10)
70#define S3C_PCM_IRQCTL_TXFULLEN (0x1 << 9)
71#define S3C_PCM_IRQCTL_TXALMSTFULLEN (0x1 << 8)
72#define S3C_PCM_IRQCTL_TXSTARVEN (0x1 << 7)
73#define S3C_PCM_IRQCTL_TXERROVRFLEN (0x1 << 6)
74#define S3C_PCM_IRQCTL_RXEMPTEN (0x1 << 5)
75#define S3C_PCM_IRQCTL_RXALMSTEMPTEN (0x1 << 4)
76#define S3C_PCM_IRQCTL_RXFULLEN (0x1 << 3)
77#define S3C_PCM_IRQCTL_RXALMSTFULLEN (0x1 << 2)
78#define S3C_PCM_IRQCTL_RXSTARVEN (0x1 << 1)
79#define S3C_PCM_IRQCTL_RXERROVRFLEN (0x1 << 0)
80
81/* PCM_IRQSTAT Bit-Fields */
82#define S3C_PCM_IRQSTAT_IRQPND (0x1 << 13)
83#define S3C_PCM_IRQSTAT_WRD_XFER (0x1 << 12)
84#define S3C_PCM_IRQSTAT_TXEMPTY (0x1 << 11)
85#define S3C_PCM_IRQSTAT_TXALMSTEMPTY (0x1 << 10)
86#define S3C_PCM_IRQSTAT_TXFULL (0x1 << 9)
87#define S3C_PCM_IRQSTAT_TXALMSTFULL (0x1 << 8)
88#define S3C_PCM_IRQSTAT_TXSTARV (0x1 << 7)
89#define S3C_PCM_IRQSTAT_TXERROVRFL (0x1 << 6)
90#define S3C_PCM_IRQSTAT_RXEMPT (0x1 << 5)
91#define S3C_PCM_IRQSTAT_RXALMSTEMPT (0x1 << 4)
92#define S3C_PCM_IRQSTAT_RXFULL (0x1 << 3)
93#define S3C_PCM_IRQSTAT_RXALMSTFULL (0x1 << 2)
94#define S3C_PCM_IRQSTAT_RXSTARV (0x1 << 1)
95#define S3C_PCM_IRQSTAT_RXERROVRFL (0x1 << 0)
96
97/* PCM_FIFOSTAT Bit-Fields */
98#define S3C_PCM_FIFOSTAT_TXCNT_MSK (0x3f << 14)
99#define S3C_PCM_FIFOSTAT_TXFIFOEMPTY (0x1 << 13)
100#define S3C_PCM_FIFOSTAT_TXFIFOALMSTEMPTY (0x1 << 12)
101#define S3C_PCM_FIFOSTAT_TXFIFOFULL (0x1 << 11)
102#define S3C_PCM_FIFOSTAT_TXFIFOALMSTFULL (0x1 << 10)
103#define S3C_PCM_FIFOSTAT_RXCNT_MSK (0x3f << 4)
104#define S3C_PCM_FIFOSTAT_RXFIFOEMPTY (0x1 << 3)
105#define S3C_PCM_FIFOSTAT_RXFIFOALMSTEMPTY (0x1 << 2)
106#define S3C_PCM_FIFOSTAT_RXFIFOFULL (0x1 << 1)
107#define S3C_PCM_FIFOSTAT_RXFIFOALMSTFULL (0x1 << 0)
108
109/**
110 * struct s3c_pcm_info - S3C PCM Controller information
111 * @dev: The parent device passed to use from the probe.
112 * @regs: The pointer to the device register block.
113 * @dma_playback: DMA information for playback channel.
114 * @dma_capture: DMA information for capture channel.
115 */
116struct s3c_pcm_info {
117 spinlock_t lock;
118 struct device *dev;
119 void __iomem *regs;
120
121 unsigned int sclk_per_fs;
122
123 /* Whether to keep PCMSCLK enabled even when idle(no active xfer) */
124 unsigned int idleclk;
125
126 struct clk *pclk;
127 struct clk *cclk;
128
129 struct s3c_dma_params *dma_playback;
130 struct s3c_dma_params *dma_capture;
131};
132
35static struct s3c2410_dma_client s3c_pcm_dma_client_out = { 133static struct s3c2410_dma_client s3c_pcm_dma_client_out = {
36 .name = "PCM Stereo out" 134 .name = "PCM Stereo out"
37}; 135};
diff --git a/sound/soc/samsung/pcm.h b/sound/soc/samsung/pcm.h
index 03393dcf852d..726baf814613 100644
--- a/sound/soc/samsung/pcm.h
+++ b/sound/soc/samsung/pcm.h
@@ -9,116 +9,9 @@
9#ifndef __S3C_PCM_H 9#ifndef __S3C_PCM_H
10#define __S3C_PCM_H __FILE__ 10#define __S3C_PCM_H __FILE__
11 11
12/*Register Offsets */
13#define S3C_PCM_CTL (0x00)
14#define S3C_PCM_CLKCTL (0x04)
15#define S3C_PCM_TXFIFO (0x08)
16#define S3C_PCM_RXFIFO (0x0C)
17#define S3C_PCM_IRQCTL (0x10)
18#define S3C_PCM_IRQSTAT (0x14)
19#define S3C_PCM_FIFOSTAT (0x18)
20#define S3C_PCM_CLRINT (0x20)
21
22/* PCM_CTL Bit-Fields */
23#define S3C_PCM_CTL_TXDIPSTICK_MASK (0x3f)
24#define S3C_PCM_CTL_TXDIPSTICK_SHIFT (13)
25#define S3C_PCM_CTL_RXDIPSTICK_MASK (0x3f)
26#define S3C_PCM_CTL_RXDIPSTICK_SHIFT (7)
27#define S3C_PCM_CTL_TXDMA_EN (0x1<<6)
28#define S3C_PCM_CTL_RXDMA_EN (0x1<<5)
29#define S3C_PCM_CTL_TXMSB_AFTER_FSYNC (0x1<<4)
30#define S3C_PCM_CTL_RXMSB_AFTER_FSYNC (0x1<<3)
31#define S3C_PCM_CTL_TXFIFO_EN (0x1<<2)
32#define S3C_PCM_CTL_RXFIFO_EN (0x1<<1)
33#define S3C_PCM_CTL_ENABLE (0x1<<0)
34
35/* PCM_CLKCTL Bit-Fields */
36#define S3C_PCM_CLKCTL_SERCLK_EN (0x1<<19)
37#define S3C_PCM_CLKCTL_SERCLKSEL_PCLK (0x1<<18)
38#define S3C_PCM_CLKCTL_SCLKDIV_MASK (0x1ff)
39#define S3C_PCM_CLKCTL_SYNCDIV_MASK (0x1ff)
40#define S3C_PCM_CLKCTL_SCLKDIV_SHIFT (9)
41#define S3C_PCM_CLKCTL_SYNCDIV_SHIFT (0)
42
43/* PCM_TXFIFO Bit-Fields */
44#define S3C_PCM_TXFIFO_DVALID (0x1<<16)
45#define S3C_PCM_TXFIFO_DATA_MSK (0xffff<<0)
46
47/* PCM_RXFIFO Bit-Fields */
48#define S3C_PCM_RXFIFO_DVALID (0x1<<16)
49#define S3C_PCM_RXFIFO_DATA_MSK (0xffff<<0)
50
51/* PCM_IRQCTL Bit-Fields */
52#define S3C_PCM_IRQCTL_IRQEN (0x1<<14)
53#define S3C_PCM_IRQCTL_WRDEN (0x1<<12)
54#define S3C_PCM_IRQCTL_TXEMPTYEN (0x1<<11)
55#define S3C_PCM_IRQCTL_TXALMSTEMPTYEN (0x1<<10)
56#define S3C_PCM_IRQCTL_TXFULLEN (0x1<<9)
57#define S3C_PCM_IRQCTL_TXALMSTFULLEN (0x1<<8)
58#define S3C_PCM_IRQCTL_TXSTARVEN (0x1<<7)
59#define S3C_PCM_IRQCTL_TXERROVRFLEN (0x1<<6)
60#define S3C_PCM_IRQCTL_RXEMPTEN (0x1<<5)
61#define S3C_PCM_IRQCTL_RXALMSTEMPTEN (0x1<<4)
62#define S3C_PCM_IRQCTL_RXFULLEN (0x1<<3)
63#define S3C_PCM_IRQCTL_RXALMSTFULLEN (0x1<<2)
64#define S3C_PCM_IRQCTL_RXSTARVEN (0x1<<1)
65#define S3C_PCM_IRQCTL_RXERROVRFLEN (0x1<<0)
66
67/* PCM_IRQSTAT Bit-Fields */
68#define S3C_PCM_IRQSTAT_IRQPND (0x1<<13)
69#define S3C_PCM_IRQSTAT_WRD_XFER (0x1<<12)
70#define S3C_PCM_IRQSTAT_TXEMPTY (0x1<<11)
71#define S3C_PCM_IRQSTAT_TXALMSTEMPTY (0x1<<10)
72#define S3C_PCM_IRQSTAT_TXFULL (0x1<<9)
73#define S3C_PCM_IRQSTAT_TXALMSTFULL (0x1<<8)
74#define S3C_PCM_IRQSTAT_TXSTARV (0x1<<7)
75#define S3C_PCM_IRQSTAT_TXERROVRFL (0x1<<6)
76#define S3C_PCM_IRQSTAT_RXEMPT (0x1<<5)
77#define S3C_PCM_IRQSTAT_RXALMSTEMPT (0x1<<4)
78#define S3C_PCM_IRQSTAT_RXFULL (0x1<<3)
79#define S3C_PCM_IRQSTAT_RXALMSTFULL (0x1<<2)
80#define S3C_PCM_IRQSTAT_RXSTARV (0x1<<1)
81#define S3C_PCM_IRQSTAT_RXERROVRFL (0x1<<0)
82
83/* PCM_FIFOSTAT Bit-Fields */
84#define S3C_PCM_FIFOSTAT_TXCNT_MSK (0x3f<<14)
85#define S3C_PCM_FIFOSTAT_TXFIFOEMPTY (0x1<<13)
86#define S3C_PCM_FIFOSTAT_TXFIFOALMSTEMPTY (0x1<<12)
87#define S3C_PCM_FIFOSTAT_TXFIFOFULL (0x1<<11)
88#define S3C_PCM_FIFOSTAT_TXFIFOALMSTFULL (0x1<<10)
89#define S3C_PCM_FIFOSTAT_RXCNT_MSK (0x3f<<4)
90#define S3C_PCM_FIFOSTAT_RXFIFOEMPTY (0x1<<3)
91#define S3C_PCM_FIFOSTAT_RXFIFOALMSTEMPTY (0x1<<2)
92#define S3C_PCM_FIFOSTAT_RXFIFOFULL (0x1<<1)
93#define S3C_PCM_FIFOSTAT_RXFIFOALMSTFULL (0x1<<0)
94
95#define S3C_PCM_CLKSRC_PCLK 0 12#define S3C_PCM_CLKSRC_PCLK 0
96#define S3C_PCM_CLKSRC_MUX 1 13#define S3C_PCM_CLKSRC_MUX 1
97 14
98#define S3C_PCM_SCLK_PER_FS 0 15#define S3C_PCM_SCLK_PER_FS 0
99 16
100/**
101 * struct s3c_pcm_info - S3C PCM Controller information
102 * @dev: The parent device passed to use from the probe.
103 * @regs: The pointer to the device register block.
104 * @dma_playback: DMA information for playback channel.
105 * @dma_capture: DMA information for capture channel.
106 */
107struct s3c_pcm_info {
108 spinlock_t lock;
109 struct device *dev;
110 void __iomem *regs;
111
112 unsigned int sclk_per_fs;
113
114 /* Whether to keep PCMSCLK enabled even when idle(no active xfer) */
115 unsigned int idleclk;
116
117 struct clk *pclk;
118 struct clk *cclk;
119
120 struct s3c_dma_params *dma_playback;
121 struct s3c_dma_params *dma_capture;
122};
123
124#endif /* __S3C_PCM_H */ 17#endif /* __S3C_PCM_H */
diff --git a/sound/soc/samsung/rx1950_uda1380.c b/sound/soc/samsung/rx1950_uda1380.c
index f40027445dda..1e574a5d440d 100644
--- a/sound/soc/samsung/rx1950_uda1380.c
+++ b/sound/soc/samsung/rx1950_uda1380.c
@@ -17,26 +17,15 @@
17 * 17 *
18 */ 18 */
19 19
20#include <linux/module.h>
21#include <linux/moduleparam.h>
22#include <linux/platform_device.h>
23#include <linux/i2c.h>
24#include <linux/gpio.h> 20#include <linux/gpio.h>
25#include <linux/clk.h>
26 21
27#include <sound/soc.h> 22#include <sound/soc.h>
28#include <sound/uda1380.h>
29#include <sound/jack.h> 23#include <sound/jack.h>
30 24
31#include <plat/regs-iis.h> 25#include <plat/regs-iis.h>
32
33#include <mach/regs-clock.h>
34
35#include <asm/mach-types.h> 26#include <asm/mach-types.h>
36 27
37#include "dma.h"
38#include "s3c24xx-i2s.h" 28#include "s3c24xx-i2s.h"
39#include "../codecs/uda1380.h"
40 29
41static int rx1950_uda1380_init(struct snd_soc_pcm_runtime *rtd); 30static int rx1950_uda1380_init(struct snd_soc_pcm_runtime *rtd);
42static int rx1950_startup(struct snd_pcm_substream *substream); 31static int rx1950_startup(struct snd_pcm_substream *substream);
diff --git a/sound/soc/samsung/s3c-i2s-v2.c b/sound/soc/samsung/s3c-i2s-v2.c
index 094f36e41e83..52074a2b0696 100644
--- a/sound/soc/samsung/s3c-i2s-v2.c
+++ b/sound/soc/samsung/s3c-i2s-v2.c
@@ -20,9 +20,8 @@
20#include <linux/clk.h> 20#include <linux/clk.h>
21#include <linux/io.h> 21#include <linux/io.h>
22 22
23#include <sound/pcm.h>
24#include <sound/pcm_params.h>
25#include <sound/soc.h> 23#include <sound/soc.h>
24#include <sound/pcm_params.h>
26 25
27#include <mach/dma.h> 26#include <mach/dma.h>
28 27
diff --git a/sound/soc/samsung/s3c2412-i2s.c b/sound/soc/samsung/s3c2412-i2s.c
index 7ea837867124..841ab14c1100 100644
--- a/sound/soc/samsung/s3c2412-i2s.c
+++ b/sound/soc/samsung/s3c2412-i2s.c
@@ -16,21 +16,13 @@
16 * option) any later version. 16 * option) any later version.
17 */ 17 */
18 18
19#include <linux/init.h>
20#include <linux/module.h>
21#include <linux/device.h>
22#include <linux/delay.h> 19#include <linux/delay.h>
23#include <linux/gpio.h> 20#include <linux/gpio.h>
24#include <linux/clk.h> 21#include <linux/clk.h>
25#include <linux/kernel.h>
26#include <linux/io.h> 22#include <linux/io.h>
27 23
28#include <sound/core.h>
29#include <sound/pcm.h>
30#include <sound/pcm_params.h>
31#include <sound/initval.h>
32#include <sound/soc.h> 24#include <sound/soc.h>
33#include <mach/hardware.h> 25#include <sound/pcm_params.h>
34 26
35#include <mach/regs-gpio.h> 27#include <mach/regs-gpio.h>
36#include <mach/dma.h> 28#include <mach/dma.h>
@@ -39,8 +31,6 @@
39#include "regs-i2s-v2.h" 31#include "regs-i2s-v2.h"
40#include "s3c2412-i2s.h" 32#include "s3c2412-i2s.h"
41 33
42#define S3C2412_I2S_DEBUG 0
43
44static struct s3c2410_dma_client s3c2412_dma_client_out = { 34static struct s3c2410_dma_client s3c2412_dma_client_out = {
45 .name = "I2S PCM Stereo out" 35 .name = "I2S PCM Stereo out"
46}; 36};
diff --git a/sound/soc/samsung/s3c24xx-i2s.c b/sound/soc/samsung/s3c24xx-i2s.c
index 13e41ed8e22b..63d8849d80bd 100644
--- a/sound/soc/samsung/s3c24xx-i2s.c
+++ b/sound/soc/samsung/s3c24xx-i2s.c
@@ -14,28 +14,16 @@
14 * option) any later version. 14 * option) any later version.
15 */ 15 */
16 16
17#include <linux/init.h>
18#include <linux/module.h>
19#include <linux/device.h>
20#include <linux/delay.h> 17#include <linux/delay.h>
21#include <linux/clk.h> 18#include <linux/clk.h>
22#include <linux/jiffies.h>
23#include <linux/io.h> 19#include <linux/io.h>
24#include <linux/gpio.h> 20#include <linux/gpio.h>
25 21
26#include <sound/core.h>
27#include <sound/pcm.h>
28#include <sound/pcm_params.h>
29#include <sound/initval.h>
30#include <sound/soc.h> 22#include <sound/soc.h>
23#include <sound/pcm_params.h>
31 24
32#include <mach/hardware.h>
33#include <mach/regs-gpio.h> 25#include <mach/regs-gpio.h>
34#include <mach/regs-clock.h>
35
36#include <asm/dma.h>
37#include <mach/dma.h> 26#include <mach/dma.h>
38
39#include <plat/regs-iis.h> 27#include <plat/regs-iis.h>
40 28
41#include "dma.h" 29#include "dma.h"
diff --git a/sound/soc/samsung/s3c24xx_simtec.c b/sound/soc/samsung/s3c24xx_simtec.c
index a434032d1832..349566f0686b 100644
--- a/sound/soc/samsung/s3c24xx_simtec.c
+++ b/sound/soc/samsung/s3c24xx_simtec.c
@@ -7,20 +7,13 @@
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
8*/ 8*/
9 9
10#include <linux/module.h>
11#include <linux/moduleparam.h>
12#include <linux/platform_device.h>
13#include <linux/gpio.h> 10#include <linux/gpio.h>
14#include <linux/clk.h> 11#include <linux/clk.h>
15#include <linux/i2c.h>
16 12
17#include <sound/core.h>
18#include <sound/pcm.h>
19#include <sound/soc.h> 13#include <sound/soc.h>
20 14
21#include <plat/audio-simtec.h> 15#include <plat/audio-simtec.h>
22 16
23#include "dma.h"
24#include "s3c24xx-i2s.h" 17#include "s3c24xx-i2s.h"
25#include "s3c24xx_simtec.h" 18#include "s3c24xx_simtec.h"
26 19
diff --git a/sound/soc/samsung/s3c24xx_simtec_hermes.c b/sound/soc/samsung/s3c24xx_simtec_hermes.c
index 08fcaaa66907..ce6aef604179 100644
--- a/sound/soc/samsung/s3c24xx_simtec_hermes.c
+++ b/sound/soc/samsung/s3c24xx_simtec_hermes.c
@@ -7,18 +7,8 @@
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
8*/ 8*/
9 9
10#include <linux/module.h>
11#include <linux/clk.h>
12#include <linux/platform_device.h>
13
14#include <sound/core.h>
15#include <sound/pcm.h>
16#include <sound/soc.h> 10#include <sound/soc.h>
17 11
18#include <plat/audio-simtec.h>
19
20#include "dma.h"
21#include "s3c24xx-i2s.h"
22#include "s3c24xx_simtec.h" 12#include "s3c24xx_simtec.h"
23 13
24static const struct snd_soc_dapm_widget dapm_widgets[] = { 14static const struct snd_soc_dapm_widget dapm_widgets[] = {
diff --git a/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c b/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c
index 116e3e670167..a7ef7db54687 100644
--- a/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c
+++ b/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c
@@ -7,22 +7,10 @@
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
8*/ 8*/
9 9
10#include <linux/module.h>
11#include <linux/clk.h>
12#include <linux/platform_device.h>
13
14#include <sound/core.h>
15#include <sound/pcm.h>
16#include <sound/soc.h> 10#include <sound/soc.h>
17 11
18#include <plat/audio-simtec.h>
19
20#include "dma.h"
21#include "s3c24xx-i2s.h"
22#include "s3c24xx_simtec.h" 12#include "s3c24xx_simtec.h"
23 13
24#include "../codecs/tlv320aic23.h"
25
26/* supported machines: 14/* supported machines:
27 * 15 *
28 * Machine Connections AMP 16 * Machine Connections AMP
diff --git a/sound/soc/samsung/s3c24xx_uda134x.c b/sound/soc/samsung/s3c24xx_uda134x.c
index 2c09e93dd566..3cb700751078 100644
--- a/sound/soc/samsung/s3c24xx_uda134x.c
+++ b/sound/soc/samsung/s3c24xx_uda134x.c
@@ -11,22 +11,15 @@
11 * published by the Free Software Foundation. 11 * published by the Free Software Foundation.
12 */ 12 */
13 13
14#include <linux/module.h>
15#include <linux/clk.h> 14#include <linux/clk.h>
16#include <linux/mutex.h>
17#include <linux/gpio.h> 15#include <linux/gpio.h>
18#include <sound/pcm.h> 16
19#include <sound/pcm_params.h>
20#include <sound/soc.h> 17#include <sound/soc.h>
21#include <sound/s3c24xx_uda134x.h> 18#include <sound/s3c24xx_uda134x.h>
22#include <sound/uda134x.h>
23 19
24#include <plat/regs-iis.h> 20#include <plat/regs-iis.h>
25 21
26#include "dma.h"
27#include "s3c24xx-i2s.h" 22#include "s3c24xx-i2s.h"
28#include "../codecs/uda134x.h"
29
30 23
31/* #define ENFORCE_RATES 1 */ 24/* #define ENFORCE_RATES 1 */
32/* 25/*
diff --git a/sound/soc/samsung/smartq_wm8987.c b/sound/soc/samsung/smartq_wm8987.c
index 61e2b5219d42..0a2c4f223038 100644
--- a/sound/soc/samsung/smartq_wm8987.c
+++ b/sound/soc/samsung/smartq_wm8987.c
@@ -13,20 +13,14 @@
13 * 13 *
14 */ 14 */
15 15
16#include <linux/module.h>
17#include <linux/platform_device.h>
18#include <linux/gpio.h> 16#include <linux/gpio.h>
19 17
20#include <sound/pcm.h>
21#include <sound/pcm_params.h>
22#include <sound/soc.h> 18#include <sound/soc.h>
23#include <sound/jack.h> 19#include <sound/jack.h>
24 20
25#include <asm/mach-types.h> 21#include <asm/mach-types.h>
26 22
27#include "dma.h"
28#include "i2s.h" 23#include "i2s.h"
29
30#include "../codecs/wm8750.h" 24#include "../codecs/wm8750.h"
31 25
32/* 26/*
diff --git a/sound/soc/samsung/smdk2443_wm9710.c b/sound/soc/samsung/smdk2443_wm9710.c
index 3be7e7e92d6e..3a0dbfc793f0 100644
--- a/sound/soc/samsung/smdk2443_wm9710.c
+++ b/sound/soc/samsung/smdk2443_wm9710.c
@@ -12,15 +12,8 @@
12 * 12 *
13 */ 13 */
14 14
15#include <linux/module.h>
16#include <linux/device.h>
17#include <sound/core.h>
18#include <sound/pcm.h>
19#include <sound/soc.h> 15#include <sound/soc.h>
20 16
21#include "dma.h"
22#include "ac97.h"
23
24static struct snd_soc_card smdk2443; 17static struct snd_soc_card smdk2443;
25 18
26static struct snd_soc_dai_link smdk2443_dai[] = { 19static struct snd_soc_dai_link smdk2443_dai[] = {
diff --git a/sound/soc/samsung/smdk_spdif.c b/sound/soc/samsung/smdk_spdif.c
index b5c3fad01bb8..e8ac961c6ba1 100644
--- a/sound/soc/samsung/smdk_spdif.c
+++ b/sound/soc/samsung/smdk_spdif.c
@@ -10,15 +10,10 @@
10 * 10 *
11 */ 11 */
12 12
13#include <linux/module.h>
14#include <linux/device.h>
15#include <linux/clk.h> 13#include <linux/clk.h>
16 14
17#include <plat/devs.h>
18
19#include <sound/soc.h> 15#include <sound/soc.h>
20 16
21#include "dma.h"
22#include "spdif.h" 17#include "spdif.h"
23 18
24/* Audio clock settings are belonged to board specific part. Every 19/* Audio clock settings are belonged to board specific part. Every
diff --git a/sound/soc/samsung/smdk_wm8580.c b/sound/soc/samsung/smdk_wm8580.c
index b2cff1a44aed..8aacf23d6f3a 100644
--- a/sound/soc/samsung/smdk_wm8580.c
+++ b/sound/soc/samsung/smdk_wm8580.c
@@ -10,17 +10,12 @@
10 * option) any later version. 10 * option) any later version.
11 */ 11 */
12 12
13#include <linux/platform_device.h>
14#include <linux/clk.h>
15#include <sound/core.h>
16#include <sound/pcm.h>
17#include <sound/pcm_params.h>
18#include <sound/soc.h> 13#include <sound/soc.h>
14#include <sound/pcm_params.h>
19 15
20#include <asm/mach-types.h> 16#include <asm/mach-types.h>
21 17
22#include "../codecs/wm8580.h" 18#include "../codecs/wm8580.h"
23#include "dma.h"
24#include "i2s.h" 19#include "i2s.h"
25 20
26/* 21/*
diff --git a/sound/soc/samsung/smdk_wm9713.c b/sound/soc/samsung/smdk_wm9713.c
index ae5fed6f772f..fffe3c1dd1bd 100644
--- a/sound/soc/samsung/smdk_wm9713.c
+++ b/sound/soc/samsung/smdk_wm9713.c
@@ -11,13 +11,8 @@
11 * 11 *
12 */ 12 */
13 13
14#include <linux/module.h>
15#include <linux/device.h>
16#include <sound/soc.h> 14#include <sound/soc.h>
17 15
18#include "dma.h"
19#include "ac97.h"
20
21static struct snd_soc_card smdk; 16static struct snd_soc_card smdk;
22 17
23/* 18/*
diff --git a/sound/soc/samsung/spdif.c b/sound/soc/samsung/spdif.c
index f0816404ea3e..28c491dacf7a 100644
--- a/sound/soc/samsung/spdif.c
+++ b/sound/soc/samsung/spdif.c
@@ -13,9 +13,8 @@
13#include <linux/clk.h> 13#include <linux/clk.h>
14#include <linux/io.h> 14#include <linux/io.h>
15 15
16#include <sound/pcm.h>
17#include <sound/pcm_params.h>
18#include <sound/soc.h> 16#include <sound/soc.h>
17#include <sound/pcm_params.h>
19 18
20#include <plat/audio.h> 19#include <plat/audio.h>
21#include <mach/dma.h> 20#include <mach/dma.h>
diff --git a/sound/soc/sh/fsi-ak4642.c b/sound/soc/sh/fsi-ak4642.c
index a14820ac9665..ce058c749e6a 100644
--- a/sound/soc/sh/fsi-ak4642.c
+++ b/sound/soc/sh/fsi-ak4642.c
@@ -18,18 +18,25 @@ struct fsi_ak4642_data {
18 const char *cpu_dai; 18 const char *cpu_dai;
19 const char *codec; 19 const char *codec;
20 const char *platform; 20 const char *platform;
21 int id;
21}; 22};
22 23
23static int fsi_ak4642_dai_init(struct snd_soc_pcm_runtime *rtd) 24static int fsi_ak4642_dai_init(struct snd_soc_pcm_runtime *rtd)
24{ 25{
25 struct snd_soc_dai *dai = rtd->codec_dai; 26 struct snd_soc_dai *codec = rtd->codec_dai;
27 struct snd_soc_dai *cpu = rtd->cpu_dai;
26 int ret; 28 int ret;
27 29
28 ret = snd_soc_dai_set_fmt(dai, SND_SOC_DAIFMT_CBM_CFM); 30 ret = snd_soc_dai_set_fmt(codec, SND_SOC_DAIFMT_LEFT_J |
31 SND_SOC_DAIFMT_CBM_CFM);
29 if (ret < 0) 32 if (ret < 0)
30 return ret; 33 return ret;
31 34
32 ret = snd_soc_dai_set_sysclk(dai, 0, 11289600, 0); 35 ret = snd_soc_dai_set_sysclk(codec, 0, 11289600, 0);
36 if (ret < 0)
37 return ret;
38
39 ret = snd_soc_dai_set_fmt(cpu, SND_SOC_DAIFMT_CBS_CFS);
33 40
34 return ret; 41 return ret;
35} 42}
@@ -60,7 +67,7 @@ static int fsi_ak4642_probe(struct platform_device *pdev)
60 67
61 pdata = (struct fsi_ak4642_data *)id_entry->driver_data; 68 pdata = (struct fsi_ak4642_data *)id_entry->driver_data;
62 69
63 fsi_snd_device = platform_device_alloc("soc-audio", FSI_PORT_A); 70 fsi_snd_device = platform_device_alloc("soc-audio", pdata->id);
64 if (!fsi_snd_device) 71 if (!fsi_snd_device)
65 goto out; 72 goto out;
66 73
@@ -93,6 +100,7 @@ static struct fsi_ak4642_data fsi_a_ak4642 = {
93 .cpu_dai = "fsia-dai", 100 .cpu_dai = "fsia-dai",
94 .codec = "ak4642-codec.0-0012", 101 .codec = "ak4642-codec.0-0012",
95 .platform = "sh_fsi.0", 102 .platform = "sh_fsi.0",
103 .id = FSI_PORT_A,
96}; 104};
97 105
98static struct fsi_ak4642_data fsi_b_ak4642 = { 106static struct fsi_ak4642_data fsi_b_ak4642 = {
@@ -101,6 +109,7 @@ static struct fsi_ak4642_data fsi_b_ak4642 = {
101 .cpu_dai = "fsib-dai", 109 .cpu_dai = "fsib-dai",
102 .codec = "ak4642-codec.0-0012", 110 .codec = "ak4642-codec.0-0012",
103 .platform = "sh_fsi.0", 111 .platform = "sh_fsi.0",
112 .id = FSI_PORT_B,
104}; 113};
105 114
106static struct fsi_ak4642_data fsi_a_ak4643 = { 115static struct fsi_ak4642_data fsi_a_ak4643 = {
@@ -109,6 +118,7 @@ static struct fsi_ak4642_data fsi_a_ak4643 = {
109 .cpu_dai = "fsia-dai", 118 .cpu_dai = "fsia-dai",
110 .codec = "ak4642-codec.0-0013", 119 .codec = "ak4642-codec.0-0013",
111 .platform = "sh_fsi.0", 120 .platform = "sh_fsi.0",
121 .id = FSI_PORT_A,
112}; 122};
113 123
114static struct fsi_ak4642_data fsi_b_ak4643 = { 124static struct fsi_ak4642_data fsi_b_ak4643 = {
@@ -117,6 +127,7 @@ static struct fsi_ak4642_data fsi_b_ak4643 = {
117 .cpu_dai = "fsib-dai", 127 .cpu_dai = "fsib-dai",
118 .codec = "ak4642-codec.0-0013", 128 .codec = "ak4642-codec.0-0013",
119 .platform = "sh_fsi.0", 129 .platform = "sh_fsi.0",
130 .id = FSI_PORT_B,
120}; 131};
121 132
122static struct fsi_ak4642_data fsi2_a_ak4642 = { 133static struct fsi_ak4642_data fsi2_a_ak4642 = {
@@ -125,6 +136,7 @@ static struct fsi_ak4642_data fsi2_a_ak4642 = {
125 .cpu_dai = "fsia-dai", 136 .cpu_dai = "fsia-dai",
126 .codec = "ak4642-codec.0-0012", 137 .codec = "ak4642-codec.0-0012",
127 .platform = "sh_fsi2", 138 .platform = "sh_fsi2",
139 .id = FSI_PORT_A,
128}; 140};
129 141
130static struct fsi_ak4642_data fsi2_b_ak4642 = { 142static struct fsi_ak4642_data fsi2_b_ak4642 = {
@@ -133,6 +145,7 @@ static struct fsi_ak4642_data fsi2_b_ak4642 = {
133 .cpu_dai = "fsib-dai", 145 .cpu_dai = "fsib-dai",
134 .codec = "ak4642-codec.0-0012", 146 .codec = "ak4642-codec.0-0012",
135 .platform = "sh_fsi2", 147 .platform = "sh_fsi2",
148 .id = FSI_PORT_B,
136}; 149};
137 150
138static struct fsi_ak4642_data fsi2_a_ak4643 = { 151static struct fsi_ak4642_data fsi2_a_ak4643 = {
@@ -141,6 +154,7 @@ static struct fsi_ak4642_data fsi2_a_ak4643 = {
141 .cpu_dai = "fsia-dai", 154 .cpu_dai = "fsia-dai",
142 .codec = "ak4642-codec.0-0013", 155 .codec = "ak4642-codec.0-0013",
143 .platform = "sh_fsi2", 156 .platform = "sh_fsi2",
157 .id = FSI_PORT_A,
144}; 158};
145 159
146static struct fsi_ak4642_data fsi2_b_ak4643 = { 160static struct fsi_ak4642_data fsi2_b_ak4643 = {
@@ -149,6 +163,7 @@ static struct fsi_ak4642_data fsi2_b_ak4643 = {
149 .cpu_dai = "fsib-dai", 163 .cpu_dai = "fsib-dai",
150 .codec = "ak4642-codec.0-0013", 164 .codec = "ak4642-codec.0-0013",
151 .platform = "sh_fsi2", 165 .platform = "sh_fsi2",
166 .id = FSI_PORT_B,
152}; 167};
153 168
154static struct platform_device_id fsi_id_table[] = { 169static struct platform_device_id fsi_id_table[] = {
diff --git a/sound/soc/sh/fsi-da7210.c b/sound/soc/sh/fsi-da7210.c
index e8df9da92f71..9b24ed466ab1 100644
--- a/sound/soc/sh/fsi-da7210.c
+++ b/sound/soc/sh/fsi-da7210.c
@@ -15,11 +15,19 @@
15 15
16static int fsi_da7210_init(struct snd_soc_pcm_runtime *rtd) 16static int fsi_da7210_init(struct snd_soc_pcm_runtime *rtd)
17{ 17{
18 struct snd_soc_dai *dai = rtd->codec_dai; 18 struct snd_soc_dai *codec = rtd->codec_dai;
19 struct snd_soc_dai *cpu = rtd->cpu_dai;
20 int ret;
19 21
20 return snd_soc_dai_set_fmt(dai, 22 ret = snd_soc_dai_set_fmt(codec,
21 SND_SOC_DAIFMT_I2S | 23 SND_SOC_DAIFMT_I2S |
22 SND_SOC_DAIFMT_CBM_CFM); 24 SND_SOC_DAIFMT_CBM_CFM);
25 if (ret < 0)
26 return ret;
27
28 ret = snd_soc_dai_set_fmt(cpu, SND_SOC_DAIFMT_CBS_CFS);
29
30 return ret;
23} 31}
24 32
25static struct snd_soc_dai_link fsi_da7210_dai = { 33static struct snd_soc_dai_link fsi_da7210_dai = {
diff --git a/sound/soc/sh/fsi-hdmi.c b/sound/soc/sh/fsi-hdmi.c
index a52dd8ec71d3..9719985eb82d 100644
--- a/sound/soc/sh/fsi-hdmi.c
+++ b/sound/soc/sh/fsi-hdmi.c
@@ -12,31 +12,59 @@
12#include <linux/platform_device.h> 12#include <linux/platform_device.h>
13#include <sound/sh_fsi.h> 13#include <sound/sh_fsi.h>
14 14
15struct fsi_hdmi_data {
16 const char *cpu_dai;
17 const char *card;
18 int id;
19};
20
21static int fsi_hdmi_dai_init(struct snd_soc_pcm_runtime *rtd)
22{
23 struct snd_soc_dai *cpu = rtd->cpu_dai;
24 int ret;
25
26 ret = snd_soc_dai_set_fmt(cpu, SND_SOC_DAIFMT_CBM_CFM);
27
28 return ret;
29}
30
15static struct snd_soc_dai_link fsi_dai_link = { 31static struct snd_soc_dai_link fsi_dai_link = {
16 .name = "HDMI", 32 .name = "HDMI",
17 .stream_name = "HDMI", 33 .stream_name = "HDMI",
18 .cpu_dai_name = "fsib-dai", /* fsi B */
19 .codec_dai_name = "sh_mobile_hdmi-hifi", 34 .codec_dai_name = "sh_mobile_hdmi-hifi",
20 .platform_name = "sh_fsi2", 35 .platform_name = "sh_fsi2",
21 .codec_name = "sh-mobile-hdmi", 36 .codec_name = "sh-mobile-hdmi",
37 .init = fsi_hdmi_dai_init,
22}; 38};
23 39
24static struct snd_soc_card fsi_soc_card = { 40static struct snd_soc_card fsi_soc_card = {
25 .name = "FSI (SH MOBILE HDMI)",
26 .dai_link = &fsi_dai_link, 41 .dai_link = &fsi_dai_link,
27 .num_links = 1, 42 .num_links = 1,
28}; 43};
29 44
30static struct platform_device *fsi_snd_device; 45static struct platform_device *fsi_snd_device;
31 46
32static int __init fsi_hdmi_init(void) 47static int fsi_hdmi_probe(struct platform_device *pdev)
33{ 48{
34 int ret = -ENOMEM; 49 int ret = -ENOMEM;
50 const struct platform_device_id *id_entry;
51 struct fsi_hdmi_data *pdata;
52
53 id_entry = pdev->id_entry;
54 if (!id_entry) {
55 dev_err(&pdev->dev, "unknown fsi hdmi\n");
56 return -ENODEV;
57 }
35 58
36 fsi_snd_device = platform_device_alloc("soc-audio", FSI_PORT_B); 59 pdata = (struct fsi_hdmi_data *)id_entry->driver_data;
60
61 fsi_snd_device = platform_device_alloc("soc-audio", pdata->id);
37 if (!fsi_snd_device) 62 if (!fsi_snd_device)
38 goto out; 63 goto out;
39 64
65 fsi_dai_link.cpu_dai_name = pdata->cpu_dai;
66 fsi_soc_card.name = pdata->card;
67
40 platform_set_drvdata(fsi_snd_device, &fsi_soc_card); 68 platform_set_drvdata(fsi_snd_device, &fsi_soc_card);
41 ret = platform_device_add(fsi_snd_device); 69 ret = platform_device_add(fsi_snd_device);
42 70
@@ -47,9 +75,48 @@ out:
47 return ret; 75 return ret;
48} 76}
49 77
50static void __exit fsi_hdmi_exit(void) 78static int fsi_hdmi_remove(struct platform_device *pdev)
51{ 79{
52 platform_device_unregister(fsi_snd_device); 80 platform_device_unregister(fsi_snd_device);
81 return 0;
82}
83
84static struct fsi_hdmi_data fsi2_a_hdmi = {
85 .cpu_dai = "fsia-dai",
86 .card = "FSI2A (SH MOBILE HDMI)",
87 .id = FSI_PORT_A,
88};
89
90static struct fsi_hdmi_data fsi2_b_hdmi = {
91 .cpu_dai = "fsib-dai",
92 .card = "FSI2B (SH MOBILE HDMI)",
93 .id = FSI_PORT_B,
94};
95
96static struct platform_device_id fsi_id_table[] = {
97 /* FSI 2 */
98 { "sh_fsi2_a_hdmi", (kernel_ulong_t)&fsi2_a_hdmi },
99 { "sh_fsi2_b_hdmi", (kernel_ulong_t)&fsi2_b_hdmi },
100 {},
101};
102
103static struct platform_driver fsi_hdmi = {
104 .driver = {
105 .name = "fsi-hdmi-audio",
106 },
107 .probe = fsi_hdmi_probe,
108 .remove = fsi_hdmi_remove,
109 .id_table = fsi_id_table,
110};
111
112static int __init fsi_hdmi_init(void)
113{
114 return platform_driver_register(&fsi_hdmi);
115}
116
117static void __exit fsi_hdmi_exit(void)
118{
119 platform_driver_unregister(&fsi_hdmi);
53} 120}
54 121
55module_init(fsi_hdmi_init); 122module_init(fsi_hdmi_init);
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
index 2b06402801ef..5f39f364effd 100644
--- a/sound/soc/sh/fsi.c
+++ b/sound/soc/sh/fsi.c
@@ -78,6 +78,8 @@
78/* CKG1 */ 78/* CKG1 */
79#define ACKMD_MASK 0x00007000 79#define ACKMD_MASK 0x00007000
80#define BPFMD_MASK 0x00000700 80#define BPFMD_MASK 0x00000700
81#define DIMD (1 << 4)
82#define DOMD (1 << 0)
81 83
82/* A/B MST_CTLR */ 84/* A/B MST_CTLR */
83#define BP (1 << 4) /* Fix the signal of Biphase output */ 85#define BP (1 << 4) /* Fix the signal of Biphase output */
@@ -252,9 +254,8 @@ static struct snd_soc_dai *fsi_get_dai(struct snd_pcm_substream *substream)
252 return rtd->cpu_dai; 254 return rtd->cpu_dai;
253} 255}
254 256
255static struct fsi_priv *fsi_get_priv(struct snd_pcm_substream *substream) 257static struct fsi_priv *fsi_get_priv_frm_dai(struct snd_soc_dai *dai)
256{ 258{
257 struct snd_soc_dai *dai = fsi_get_dai(substream);
258 struct fsi_master *master = snd_soc_dai_get_drvdata(dai); 259 struct fsi_master *master = snd_soc_dai_get_drvdata(dai);
259 260
260 if (dai->id == 0) 261 if (dai->id == 0)
@@ -263,6 +264,11 @@ static struct fsi_priv *fsi_get_priv(struct snd_pcm_substream *substream)
263 return &master->fsib; 264 return &master->fsib;
264} 265}
265 266
267static struct fsi_priv *fsi_get_priv(struct snd_pcm_substream *substream)
268{
269 return fsi_get_priv_frm_dai(fsi_get_dai(substream));
270}
271
266static u32 fsi_get_info_flags(struct fsi_priv *fsi) 272static u32 fsi_get_info_flags(struct fsi_priv *fsi)
267{ 273{
268 int is_porta = fsi_is_port_a(fsi); 274 int is_porta = fsi_is_port_a(fsi);
@@ -288,21 +294,6 @@ static inline struct fsi_stream *fsi_get_stream(struct fsi_priv *fsi,
288 return is_play ? &fsi->playback : &fsi->capture; 294 return is_play ? &fsi->playback : &fsi->capture;
289} 295}
290 296
291static int fsi_is_master_mode(struct fsi_priv *fsi, int is_play)
292{
293 u32 mode;
294 u32 flags = fsi_get_info_flags(fsi);
295
296 mode = is_play ? SH_FSI_OUT_SLAVE_MODE : SH_FSI_IN_SLAVE_MODE;
297
298 /* return
299 * 1 : master mode
300 * 0 : slave mode
301 */
302
303 return (mode & flags) != mode;
304}
305
306static u32 fsi_get_port_shift(struct fsi_priv *fsi, int is_play) 297static u32 fsi_get_port_shift(struct fsi_priv *fsi, int is_play)
307{ 298{
308 int is_porta = fsi_is_port_a(fsi); 299 int is_porta = fsi_is_port_a(fsi);
@@ -760,19 +751,11 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
760 u32 fmt; 751 u32 fmt;
761 u32 data; 752 u32 data;
762 int is_play = fsi_is_play(substream); 753 int is_play = fsi_is_play(substream);
763 int is_master;
764 754
765 io = fsi_get_stream(fsi, is_play); 755 io = fsi_get_stream(fsi, is_play);
766 756
767 pm_runtime_get_sync(dai->dev); 757 pm_runtime_get_sync(dai->dev);
768 758
769 /* CKG1 */
770 data = is_play ? (1 << 0) : (1 << 4);
771 is_master = fsi_is_master_mode(fsi, is_play);
772 if (is_master)
773 fsi_reg_mask_set(fsi, CKG1, data, data);
774 else
775 fsi_reg_mask_set(fsi, CKG1, data, 0);
776 759
777 /* clock inversion (CKG2) */ 760 /* clock inversion (CKG2) */
778 data = 0; 761 data = 0;
@@ -889,6 +872,34 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
889 return ret; 872 return ret;
890} 873}
891 874
875static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
876{
877 struct fsi_priv *fsi = fsi_get_priv_frm_dai(dai);
878 u32 data = 0;
879 int ret;
880
881 pm_runtime_get_sync(dai->dev);
882
883 /* set master/slave audio interface */
884 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
885 case SND_SOC_DAIFMT_CBM_CFM:
886 data = DIMD | DOMD;
887 break;
888 case SND_SOC_DAIFMT_CBS_CFS:
889 break;
890 default:
891 ret = -EINVAL;
892 goto set_fmt_exit;
893 }
894 fsi_reg_mask_set(fsi, CKG1, (DIMD | DOMD), data);
895 ret = 0;
896
897set_fmt_exit:
898 pm_runtime_put_sync(dai->dev);
899
900 return ret;
901}
902
892static int fsi_dai_hw_params(struct snd_pcm_substream *substream, 903static int fsi_dai_hw_params(struct snd_pcm_substream *substream,
893 struct snd_pcm_hw_params *params, 904 struct snd_pcm_hw_params *params,
894 struct snd_soc_dai *dai) 905 struct snd_soc_dai *dai)
@@ -975,6 +986,7 @@ static struct snd_soc_dai_ops fsi_dai_ops = {
975 .startup = fsi_dai_startup, 986 .startup = fsi_dai_startup,
976 .shutdown = fsi_dai_shutdown, 987 .shutdown = fsi_dai_shutdown,
977 .trigger = fsi_dai_trigger, 988 .trigger = fsi_dai_trigger,
989 .set_fmt = fsi_dai_set_fmt,
978 .hw_params = fsi_dai_hw_params, 990 .hw_params = fsi_dai_hw_params,
979}; 991};
980 992
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c
index 8c2a21a978ac..db66dc44add2 100644
--- a/sound/soc/soc-cache.c
+++ b/sound/soc/soc-cache.c
@@ -18,6 +18,8 @@
18#include <linux/bitmap.h> 18#include <linux/bitmap.h>
19#include <linux/rbtree.h> 19#include <linux/rbtree.h>
20 20
21#include <trace/events/asoc.h>
22
21static unsigned int snd_soc_4_12_read(struct snd_soc_codec *codec, 23static unsigned int snd_soc_4_12_read(struct snd_soc_codec *codec,
22 unsigned int reg) 24 unsigned int reg)
23{ 25{
@@ -25,7 +27,8 @@ static unsigned int snd_soc_4_12_read(struct snd_soc_codec *codec,
25 unsigned int val; 27 unsigned int val;
26 28
27 if (reg >= codec->driver->reg_cache_size || 29 if (reg >= codec->driver->reg_cache_size ||
28 snd_soc_codec_volatile_register(codec, reg)) { 30 snd_soc_codec_volatile_register(codec, reg) ||
31 codec->cache_bypass) {
29 if (codec->cache_only) 32 if (codec->cache_only)
30 return -1; 33 return -1;
31 34
@@ -49,7 +52,8 @@ static int snd_soc_4_12_write(struct snd_soc_codec *codec, unsigned int reg,
49 data[1] = value & 0x00ff; 52 data[1] = value & 0x00ff;
50 53
51 if (!snd_soc_codec_volatile_register(codec, reg) && 54 if (!snd_soc_codec_volatile_register(codec, reg) &&
52 reg < codec->driver->reg_cache_size) { 55 reg < codec->driver->reg_cache_size &&
56 !codec->cache_bypass) {
53 ret = snd_soc_cache_write(codec, reg, value); 57 ret = snd_soc_cache_write(codec, reg, value);
54 if (ret < 0) 58 if (ret < 0)
55 return -1; 59 return -1;
@@ -106,7 +110,8 @@ static unsigned int snd_soc_7_9_read(struct snd_soc_codec *codec,
106 unsigned int val; 110 unsigned int val;
107 111
108 if (reg >= codec->driver->reg_cache_size || 112 if (reg >= codec->driver->reg_cache_size ||
109 snd_soc_codec_volatile_register(codec, reg)) { 113 snd_soc_codec_volatile_register(codec, reg) ||
114 codec->cache_bypass) {
110 if (codec->cache_only) 115 if (codec->cache_only)
111 return -1; 116 return -1;
112 117
@@ -130,7 +135,8 @@ static int snd_soc_7_9_write(struct snd_soc_codec *codec, unsigned int reg,
130 data[1] = value & 0x00ff; 135 data[1] = value & 0x00ff;
131 136
132 if (!snd_soc_codec_volatile_register(codec, reg) && 137 if (!snd_soc_codec_volatile_register(codec, reg) &&
133 reg < codec->driver->reg_cache_size) { 138 reg < codec->driver->reg_cache_size &&
139 !codec->cache_bypass) {
134 ret = snd_soc_cache_write(codec, reg, value); 140 ret = snd_soc_cache_write(codec, reg, value);
135 if (ret < 0) 141 if (ret < 0)
136 return -1; 142 return -1;
@@ -191,7 +197,8 @@ static int snd_soc_8_8_write(struct snd_soc_codec *codec, unsigned int reg,
191 data[1] = value & 0xff; 197 data[1] = value & 0xff;
192 198
193 if (!snd_soc_codec_volatile_register(codec, reg) && 199 if (!snd_soc_codec_volatile_register(codec, reg) &&
194 reg < codec->driver->reg_cache_size) { 200 reg < codec->driver->reg_cache_size &&
201 !codec->cache_bypass) {
195 ret = snd_soc_cache_write(codec, reg, value); 202 ret = snd_soc_cache_write(codec, reg, value);
196 if (ret < 0) 203 if (ret < 0)
197 return -1; 204 return -1;
@@ -216,7 +223,8 @@ static unsigned int snd_soc_8_8_read(struct snd_soc_codec *codec,
216 223
217 reg &= 0xff; 224 reg &= 0xff;
218 if (reg >= codec->driver->reg_cache_size || 225 if (reg >= codec->driver->reg_cache_size ||
219 snd_soc_codec_volatile_register(codec, reg)) { 226 snd_soc_codec_volatile_register(codec, reg) ||
227 codec->cache_bypass) {
220 if (codec->cache_only) 228 if (codec->cache_only)
221 return -1; 229 return -1;
222 230
@@ -271,7 +279,8 @@ static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg,
271 data[2] = value & 0xff; 279 data[2] = value & 0xff;
272 280
273 if (!snd_soc_codec_volatile_register(codec, reg) && 281 if (!snd_soc_codec_volatile_register(codec, reg) &&
274 reg < codec->driver->reg_cache_size) { 282 reg < codec->driver->reg_cache_size &&
283 !codec->cache_bypass) {
275 ret = snd_soc_cache_write(codec, reg, value); 284 ret = snd_soc_cache_write(codec, reg, value);
276 if (ret < 0) 285 if (ret < 0)
277 return -1; 286 return -1;
@@ -295,7 +304,8 @@ static unsigned int snd_soc_8_16_read(struct snd_soc_codec *codec,
295 unsigned int val; 304 unsigned int val;
296 305
297 if (reg >= codec->driver->reg_cache_size || 306 if (reg >= codec->driver->reg_cache_size ||
298 snd_soc_codec_volatile_register(codec, reg)) { 307 snd_soc_codec_volatile_register(codec, reg) ||
308 codec->cache_bypass) {
299 if (codec->cache_only) 309 if (codec->cache_only)
300 return -1; 310 return -1;
301 311
@@ -450,7 +460,8 @@ static unsigned int snd_soc_16_8_read(struct snd_soc_codec *codec,
450 460
451 reg &= 0xff; 461 reg &= 0xff;
452 if (reg >= codec->driver->reg_cache_size || 462 if (reg >= codec->driver->reg_cache_size ||
453 snd_soc_codec_volatile_register(codec, reg)) { 463 snd_soc_codec_volatile_register(codec, reg) ||
464 codec->cache_bypass) {
454 if (codec->cache_only) 465 if (codec->cache_only)
455 return -1; 466 return -1;
456 467
@@ -476,7 +487,8 @@ static int snd_soc_16_8_write(struct snd_soc_codec *codec, unsigned int reg,
476 487
477 reg &= 0xff; 488 reg &= 0xff;
478 if (!snd_soc_codec_volatile_register(codec, reg) && 489 if (!snd_soc_codec_volatile_register(codec, reg) &&
479 reg < codec->driver->reg_cache_size) { 490 reg < codec->driver->reg_cache_size &&
491 !codec->cache_bypass) {
480 ret = snd_soc_cache_write(codec, reg, value); 492 ret = snd_soc_cache_write(codec, reg, value);
481 if (ret < 0) 493 if (ret < 0)
482 return -1; 494 return -1;
@@ -568,7 +580,8 @@ static unsigned int snd_soc_16_16_read(struct snd_soc_codec *codec,
568 unsigned int val; 580 unsigned int val;
569 581
570 if (reg >= codec->driver->reg_cache_size || 582 if (reg >= codec->driver->reg_cache_size ||
571 snd_soc_codec_volatile_register(codec, reg)) { 583 snd_soc_codec_volatile_register(codec, reg) ||
584 codec->cache_bypass) {
572 if (codec->cache_only) 585 if (codec->cache_only)
573 return -1; 586 return -1;
574 587
@@ -595,7 +608,8 @@ static int snd_soc_16_16_write(struct snd_soc_codec *codec, unsigned int reg,
595 data[3] = value & 0xff; 608 data[3] = value & 0xff;
596 609
597 if (!snd_soc_codec_volatile_register(codec, reg) && 610 if (!snd_soc_codec_volatile_register(codec, reg) &&
598 reg < codec->driver->reg_cache_size) { 611 reg < codec->driver->reg_cache_size &&
612 !codec->cache_bypass) {
599 ret = snd_soc_cache_write(codec, reg, value); 613 ret = snd_soc_cache_write(codec, reg, value);
600 if (ret < 0) 614 if (ret < 0)
601 return -1; 615 return -1;
@@ -761,6 +775,49 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
761} 775}
762EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io); 776EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io);
763 777
778static bool snd_soc_set_cache_val(void *base, unsigned int idx,
779 unsigned int val, unsigned int word_size)
780{
781 switch (word_size) {
782 case 1: {
783 u8 *cache = base;
784 if (cache[idx] == val)
785 return true;
786 cache[idx] = val;
787 break;
788 }
789 case 2: {
790 u16 *cache = base;
791 if (cache[idx] == val)
792 return true;
793 cache[idx] = val;
794 break;
795 }
796 default:
797 BUG();
798 }
799 return false;
800}
801
802static unsigned int snd_soc_get_cache_val(const void *base, unsigned int idx,
803 unsigned int word_size)
804{
805 switch (word_size) {
806 case 1: {
807 const u8 *cache = base;
808 return cache[idx];
809 }
810 case 2: {
811 const u16 *cache = base;
812 return cache[idx];
813 }
814 default:
815 BUG();
816 }
817 /* unreachable */
818 return -1;
819}
820
764struct snd_soc_rbtree_node { 821struct snd_soc_rbtree_node {
765 struct rb_node node; 822 struct rb_node node;
766 unsigned int reg; 823 unsigned int reg;
@@ -835,7 +892,9 @@ static int snd_soc_rbtree_cache_sync(struct snd_soc_codec *codec)
835 ret = snd_soc_cache_read(codec, rbnode->reg, &val); 892 ret = snd_soc_cache_read(codec, rbnode->reg, &val);
836 if (ret) 893 if (ret)
837 return ret; 894 return ret;
895 codec->cache_bypass = 1;
838 ret = snd_soc_write(codec, rbnode->reg, val); 896 ret = snd_soc_write(codec, rbnode->reg, val);
897 codec->cache_bypass = 0;
839 if (ret) 898 if (ret)
840 return ret; 899 return ret;
841 dev_dbg(codec->dev, "Synced register %#x, value = %#x\n", 900 dev_dbg(codec->dev, "Synced register %#x, value = %#x\n",
@@ -924,7 +983,12 @@ static int snd_soc_rbtree_cache_exit(struct snd_soc_codec *codec)
924 983
925static int snd_soc_rbtree_cache_init(struct snd_soc_codec *codec) 984static int snd_soc_rbtree_cache_init(struct snd_soc_codec *codec)
926{ 985{
986 struct snd_soc_rbtree_node *rbtree_node;
927 struct snd_soc_rbtree_ctx *rbtree_ctx; 987 struct snd_soc_rbtree_ctx *rbtree_ctx;
988 unsigned int val;
989 unsigned int word_size;
990 int i;
991 int ret;
928 992
929 codec->reg_cache = kmalloc(sizeof *rbtree_ctx, GFP_KERNEL); 993 codec->reg_cache = kmalloc(sizeof *rbtree_ctx, GFP_KERNEL);
930 if (!codec->reg_cache) 994 if (!codec->reg_cache)
@@ -936,53 +1000,25 @@ static int snd_soc_rbtree_cache_init(struct snd_soc_codec *codec)
936 if (!codec->reg_def_copy) 1000 if (!codec->reg_def_copy)
937 return 0; 1001 return 0;
938 1002
939/* 1003 /*
940 * populate the rbtree with the initialized registers. All other 1004 * populate the rbtree with the initialized registers. All other
941 * registers will be inserted into the tree when they are first written. 1005 * registers will be inserted when they are first modified.
942 * 1006 */
943 * The reasoning behind this, is that we need to step through and 1007 word_size = codec->driver->reg_word_size;
944 * dereference the cache in u8/u16 increments without sacrificing 1008 for (i = 0; i < codec->driver->reg_cache_size; ++i) {
945 * portability. This could also be done using memcpy() but that would 1009 val = snd_soc_get_cache_val(codec->reg_def_copy, i, word_size);
946 * be slightly more cryptic. 1010 if (!val)
947 */ 1011 continue;
948#define snd_soc_rbtree_populate(cache) \ 1012 rbtree_node = kzalloc(sizeof *rbtree_node, GFP_KERNEL);
949({ \ 1013 if (!rbtree_node) {
950 int ret, i; \ 1014 ret = -ENOMEM;
951 struct snd_soc_rbtree_node *rbtree_node; \ 1015 snd_soc_cache_exit(codec);
952 \ 1016 break;
953 ret = 0; \ 1017 }
954 cache = codec->reg_def_copy; \ 1018 rbtree_node->reg = i;
955 for (i = 0; i < codec->driver->reg_cache_size; ++i) { \ 1019 rbtree_node->value = val;
956 if (!cache[i]) \ 1020 rbtree_node->defval = val;
957 continue; \ 1021 snd_soc_rbtree_insert(&rbtree_ctx->root, rbtree_node);
958 rbtree_node = kzalloc(sizeof *rbtree_node, GFP_KERNEL); \
959 if (!rbtree_node) { \
960 ret = -ENOMEM; \
961 snd_soc_cache_exit(codec); \
962 break; \
963 } \
964 rbtree_node->reg = i; \
965 rbtree_node->value = cache[i]; \
966 rbtree_node->defval = cache[i]; \
967 snd_soc_rbtree_insert(&rbtree_ctx->root, \
968 rbtree_node); \
969 } \
970 ret; \
971})
972
973 switch (codec->driver->reg_word_size) {
974 case 1: {
975 const u8 *cache;
976
977 return snd_soc_rbtree_populate(cache);
978 }
979 case 2: {
980 const u16 *cache;
981
982 return snd_soc_rbtree_populate(cache);
983 }
984 default:
985 BUG();
986 } 1022 }
987 1023
988 return 0; 1024 return 0;
@@ -1080,34 +1116,28 @@ static inline int snd_soc_lzo_get_blkindex(struct snd_soc_codec *codec,
1080 unsigned int reg) 1116 unsigned int reg)
1081{ 1117{
1082 const struct snd_soc_codec_driver *codec_drv; 1118 const struct snd_soc_codec_driver *codec_drv;
1083 size_t reg_size;
1084 1119
1085 codec_drv = codec->driver; 1120 codec_drv = codec->driver;
1086 reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size;
1087 return (reg * codec_drv->reg_word_size) / 1121 return (reg * codec_drv->reg_word_size) /
1088 DIV_ROUND_UP(reg_size, snd_soc_lzo_block_count()); 1122 DIV_ROUND_UP(codec->reg_size, snd_soc_lzo_block_count());
1089} 1123}
1090 1124
1091static inline int snd_soc_lzo_get_blkpos(struct snd_soc_codec *codec, 1125static inline int snd_soc_lzo_get_blkpos(struct snd_soc_codec *codec,
1092 unsigned int reg) 1126 unsigned int reg)
1093{ 1127{
1094 const struct snd_soc_codec_driver *codec_drv; 1128 const struct snd_soc_codec_driver *codec_drv;
1095 size_t reg_size;
1096 1129
1097 codec_drv = codec->driver; 1130 codec_drv = codec->driver;
1098 reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size; 1131 return reg % (DIV_ROUND_UP(codec->reg_size, snd_soc_lzo_block_count()) /
1099 return reg % (DIV_ROUND_UP(reg_size, snd_soc_lzo_block_count()) /
1100 codec_drv->reg_word_size); 1132 codec_drv->reg_word_size);
1101} 1133}
1102 1134
1103static inline int snd_soc_lzo_get_blksize(struct snd_soc_codec *codec) 1135static inline int snd_soc_lzo_get_blksize(struct snd_soc_codec *codec)
1104{ 1136{
1105 const struct snd_soc_codec_driver *codec_drv; 1137 const struct snd_soc_codec_driver *codec_drv;
1106 size_t reg_size;
1107 1138
1108 codec_drv = codec->driver; 1139 codec_drv = codec->driver;
1109 reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size; 1140 return DIV_ROUND_UP(codec->reg_size, snd_soc_lzo_block_count());
1110 return DIV_ROUND_UP(reg_size, snd_soc_lzo_block_count());
1111} 1141}
1112 1142
1113static int snd_soc_lzo_cache_sync(struct snd_soc_codec *codec) 1143static int snd_soc_lzo_cache_sync(struct snd_soc_codec *codec)
@@ -1122,7 +1152,9 @@ static int snd_soc_lzo_cache_sync(struct snd_soc_codec *codec)
1122 ret = snd_soc_cache_read(codec, i, &val); 1152 ret = snd_soc_cache_read(codec, i, &val);
1123 if (ret) 1153 if (ret)
1124 return ret; 1154 return ret;
1155 codec->cache_bypass = 1;
1125 ret = snd_soc_write(codec, i, val); 1156 ret = snd_soc_write(codec, i, val);
1157 codec->cache_bypass = 0;
1126 if (ret) 1158 if (ret)
1127 return ret; 1159 return ret;
1128 dev_dbg(codec->dev, "Synced register %#x, value = %#x\n", 1160 dev_dbg(codec->dev, "Synced register %#x, value = %#x\n",
@@ -1165,29 +1197,10 @@ static int snd_soc_lzo_cache_write(struct snd_soc_codec *codec,
1165 } 1197 }
1166 1198
1167 /* write the new value to the cache */ 1199 /* write the new value to the cache */
1168 switch (codec->driver->reg_word_size) { 1200 if (snd_soc_set_cache_val(lzo_block->dst, blkpos, value,
1169 case 1: { 1201 codec->driver->reg_word_size)) {
1170 u8 *cache; 1202 kfree(lzo_block->dst);
1171 cache = lzo_block->dst; 1203 goto out;
1172 if (cache[blkpos] == value) {
1173 kfree(lzo_block->dst);
1174 goto out;
1175 }
1176 cache[blkpos] = value;
1177 }
1178 break;
1179 case 2: {
1180 u16 *cache;
1181 cache = lzo_block->dst;
1182 if (cache[blkpos] == value) {
1183 kfree(lzo_block->dst);
1184 goto out;
1185 }
1186 cache[blkpos] = value;
1187 }
1188 break;
1189 default:
1190 BUG();
1191 } 1204 }
1192 1205
1193 /* prepare the source to be the decompressed block */ 1206 /* prepare the source to be the decompressed block */
@@ -1241,25 +1254,10 @@ static int snd_soc_lzo_cache_read(struct snd_soc_codec *codec,
1241 1254
1242 /* decompress the block */ 1255 /* decompress the block */
1243 ret = snd_soc_lzo_decompress_cache_block(codec, lzo_block); 1256 ret = snd_soc_lzo_decompress_cache_block(codec, lzo_block);
1244 if (ret >= 0) { 1257 if (ret >= 0)
1245 /* fetch the value from the cache */ 1258 /* fetch the value from the cache */
1246 switch (codec->driver->reg_word_size) { 1259 *value = snd_soc_get_cache_val(lzo_block->dst, blkpos,
1247 case 1: { 1260 codec->driver->reg_word_size);
1248 u8 *cache;
1249 cache = lzo_block->dst;
1250 *value = cache[blkpos];
1251 }
1252 break;
1253 case 2: {
1254 u16 *cache;
1255 cache = lzo_block->dst;
1256 *value = cache[blkpos];
1257 }
1258 break;
1259 default:
1260 BUG();
1261 }
1262 }
1263 1261
1264 kfree(lzo_block->dst); 1262 kfree(lzo_block->dst);
1265 /* restore the pointer and length of the compressed block */ 1263 /* restore the pointer and length of the compressed block */
@@ -1301,7 +1299,7 @@ static int snd_soc_lzo_cache_exit(struct snd_soc_codec *codec)
1301static int snd_soc_lzo_cache_init(struct snd_soc_codec *codec) 1299static int snd_soc_lzo_cache_init(struct snd_soc_codec *codec)
1302{ 1300{
1303 struct snd_soc_lzo_ctx **lzo_blocks; 1301 struct snd_soc_lzo_ctx **lzo_blocks;
1304 size_t reg_size, bmp_size; 1302 size_t bmp_size;
1305 const struct snd_soc_codec_driver *codec_drv; 1303 const struct snd_soc_codec_driver *codec_drv;
1306 int ret, tofree, i, blksize, blkcount; 1304 int ret, tofree, i, blksize, blkcount;
1307 const char *p, *end; 1305 const char *p, *end;
@@ -1309,7 +1307,6 @@ static int snd_soc_lzo_cache_init(struct snd_soc_codec *codec)
1309 1307
1310 ret = 0; 1308 ret = 0;
1311 codec_drv = codec->driver; 1309 codec_drv = codec->driver;
1312 reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size;
1313 1310
1314 /* 1311 /*
1315 * If we have not been given a default register cache 1312 * If we have not been given a default register cache
@@ -1321,8 +1318,7 @@ static int snd_soc_lzo_cache_init(struct snd_soc_codec *codec)
1321 tofree = 1; 1318 tofree = 1;
1322 1319
1323 if (!codec->reg_def_copy) { 1320 if (!codec->reg_def_copy) {
1324 codec->reg_def_copy = kzalloc(reg_size, 1321 codec->reg_def_copy = kzalloc(codec->reg_size, GFP_KERNEL);
1325 GFP_KERNEL);
1326 if (!codec->reg_def_copy) 1322 if (!codec->reg_def_copy)
1327 return -ENOMEM; 1323 return -ENOMEM;
1328 } 1324 }
@@ -1370,7 +1366,7 @@ static int snd_soc_lzo_cache_init(struct snd_soc_codec *codec)
1370 1366
1371 blksize = snd_soc_lzo_get_blksize(codec); 1367 blksize = snd_soc_lzo_get_blksize(codec);
1372 p = codec->reg_def_copy; 1368 p = codec->reg_def_copy;
1373 end = codec->reg_def_copy + reg_size; 1369 end = codec->reg_def_copy + codec->reg_size;
1374 /* compress the register map and fill the lzo blocks */ 1370 /* compress the register map and fill the lzo blocks */
1375 for (i = 0; i < blkcount; ++i, p += blksize) { 1371 for (i = 0; i < blkcount; ++i, p += blksize) {
1376 lzo_blocks[i]->src = p; 1372 lzo_blocks[i]->src = p;
@@ -1414,28 +1410,10 @@ static int snd_soc_flat_cache_sync(struct snd_soc_codec *codec)
1414 ret = snd_soc_cache_read(codec, i, &val); 1410 ret = snd_soc_cache_read(codec, i, &val);
1415 if (ret) 1411 if (ret)
1416 return ret; 1412 return ret;
1417 if (codec_drv->reg_cache_default) { 1413 if (codec->reg_def_copy)
1418 switch (codec_drv->reg_word_size) { 1414 if (snd_soc_get_cache_val(codec->reg_def_copy,
1419 case 1: { 1415 i, codec_drv->reg_word_size) == val)
1420 const u8 *cache; 1416 continue;
1421
1422 cache = codec_drv->reg_cache_default;
1423 if (cache[i] == val)
1424 continue;
1425 }
1426 break;
1427 case 2: {
1428 const u16 *cache;
1429
1430 cache = codec_drv->reg_cache_default;
1431 if (cache[i] == val)
1432 continue;
1433 }
1434 break;
1435 default:
1436 BUG();
1437 }
1438 }
1439 ret = snd_soc_write(codec, i, val); 1417 ret = snd_soc_write(codec, i, val);
1440 if (ret) 1418 if (ret)
1441 return ret; 1419 return ret;
@@ -1448,50 +1426,16 @@ static int snd_soc_flat_cache_sync(struct snd_soc_codec *codec)
1448static int snd_soc_flat_cache_write(struct snd_soc_codec *codec, 1426static int snd_soc_flat_cache_write(struct snd_soc_codec *codec,
1449 unsigned int reg, unsigned int value) 1427 unsigned int reg, unsigned int value)
1450{ 1428{
1451 switch (codec->driver->reg_word_size) { 1429 snd_soc_set_cache_val(codec->reg_cache, reg, value,
1452 case 1: { 1430 codec->driver->reg_word_size);
1453 u8 *cache;
1454
1455 cache = codec->reg_cache;
1456 cache[reg] = value;
1457 }
1458 break;
1459 case 2: {
1460 u16 *cache;
1461
1462 cache = codec->reg_cache;
1463 cache[reg] = value;
1464 }
1465 break;
1466 default:
1467 BUG();
1468 }
1469
1470 return 0; 1431 return 0;
1471} 1432}
1472 1433
1473static int snd_soc_flat_cache_read(struct snd_soc_codec *codec, 1434static int snd_soc_flat_cache_read(struct snd_soc_codec *codec,
1474 unsigned int reg, unsigned int *value) 1435 unsigned int reg, unsigned int *value)
1475{ 1436{
1476 switch (codec->driver->reg_word_size) { 1437 *value = snd_soc_get_cache_val(codec->reg_cache, reg,
1477 case 1: { 1438 codec->driver->reg_word_size);
1478 u8 *cache;
1479
1480 cache = codec->reg_cache;
1481 *value = cache[reg];
1482 }
1483 break;
1484 case 2: {
1485 u16 *cache;
1486
1487 cache = codec->reg_cache;
1488 *value = cache[reg];
1489 }
1490 break;
1491 default:
1492 BUG();
1493 }
1494
1495 return 0; 1439 return 0;
1496} 1440}
1497 1441
@@ -1507,24 +1451,14 @@ static int snd_soc_flat_cache_exit(struct snd_soc_codec *codec)
1507static int snd_soc_flat_cache_init(struct snd_soc_codec *codec) 1451static int snd_soc_flat_cache_init(struct snd_soc_codec *codec)
1508{ 1452{
1509 const struct snd_soc_codec_driver *codec_drv; 1453 const struct snd_soc_codec_driver *codec_drv;
1510 size_t reg_size;
1511 1454
1512 codec_drv = codec->driver; 1455 codec_drv = codec->driver;
1513 reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size;
1514 1456
1515 /* 1457 if (codec->reg_def_copy)
1516 * for flat compression, we don't need to keep a copy of the 1458 codec->reg_cache = kmemdup(codec->reg_def_copy,
1517 * original defaults register cache as it will definitely not 1459 codec->reg_size, GFP_KERNEL);
1518 * be marked as __devinitconst
1519 */
1520 kfree(codec->reg_def_copy);
1521 codec->reg_def_copy = NULL;
1522
1523 if (codec_drv->reg_cache_default)
1524 codec->reg_cache = kmemdup(codec_drv->reg_cache_default,
1525 reg_size, GFP_KERNEL);
1526 else 1460 else
1527 codec->reg_cache = kzalloc(reg_size, GFP_KERNEL); 1461 codec->reg_cache = kzalloc(codec->reg_size, GFP_KERNEL);
1528 if (!codec->reg_cache) 1462 if (!codec->reg_cache)
1529 return -ENOMEM; 1463 return -ENOMEM;
1530 1464
@@ -1669,21 +1603,78 @@ EXPORT_SYMBOL_GPL(snd_soc_cache_write);
1669int snd_soc_cache_sync(struct snd_soc_codec *codec) 1603int snd_soc_cache_sync(struct snd_soc_codec *codec)
1670{ 1604{
1671 int ret; 1605 int ret;
1606 const char *name;
1672 1607
1673 if (!codec->cache_sync) { 1608 if (!codec->cache_sync) {
1674 return 0; 1609 return 0;
1675 } 1610 }
1676 1611
1612 if (codec->cache_ops->name)
1613 name = codec->cache_ops->name;
1614 else
1615 name = "unknown";
1616
1677 if (codec->cache_ops && codec->cache_ops->sync) { 1617 if (codec->cache_ops && codec->cache_ops->sync) {
1678 if (codec->cache_ops->name) 1618 if (codec->cache_ops->name)
1679 dev_dbg(codec->dev, "Syncing %s cache for %s codec\n", 1619 dev_dbg(codec->dev, "Syncing %s cache for %s codec\n",
1680 codec->cache_ops->name, codec->name); 1620 codec->cache_ops->name, codec->name);
1621 trace_snd_soc_cache_sync(codec, name, "start");
1681 ret = codec->cache_ops->sync(codec); 1622 ret = codec->cache_ops->sync(codec);
1682 if (!ret) 1623 if (!ret)
1683 codec->cache_sync = 0; 1624 codec->cache_sync = 0;
1625 trace_snd_soc_cache_sync(codec, name, "end");
1684 return ret; 1626 return ret;
1685 } 1627 }
1686 1628
1687 return -EINVAL; 1629 return -EINVAL;
1688} 1630}
1689EXPORT_SYMBOL_GPL(snd_soc_cache_sync); 1631EXPORT_SYMBOL_GPL(snd_soc_cache_sync);
1632
1633static int snd_soc_get_reg_access_index(struct snd_soc_codec *codec,
1634 unsigned int reg)
1635{
1636 const struct snd_soc_codec_driver *codec_drv;
1637 unsigned int min, max, index;
1638
1639 codec_drv = codec->driver;
1640 min = 0;
1641 max = codec_drv->reg_access_size - 1;
1642 do {
1643 index = (min + max) / 2;
1644 if (codec_drv->reg_access_default[index].reg == reg)
1645 return index;
1646 if (codec_drv->reg_access_default[index].reg < reg)
1647 min = index + 1;
1648 else
1649 max = index;
1650 } while (min <= max);
1651 return -1;
1652}
1653
1654int snd_soc_default_volatile_register(struct snd_soc_codec *codec,
1655 unsigned int reg)
1656{
1657 int index;
1658
1659 if (reg >= codec->driver->reg_cache_size)
1660 return 1;
1661 index = snd_soc_get_reg_access_index(codec, reg);
1662 if (index < 0)
1663 return 0;
1664 return codec->driver->reg_access_default[index].vol;
1665}
1666EXPORT_SYMBOL_GPL(snd_soc_default_volatile_register);
1667
1668int snd_soc_default_readable_register(struct snd_soc_codec *codec,
1669 unsigned int reg)
1670{
1671 int index;
1672
1673 if (reg >= codec->driver->reg_cache_size)
1674 return 1;
1675 index = snd_soc_get_reg_access_index(codec, reg);
1676 if (index < 0)
1677 return 0;
1678 return codec->driver->reg_access_default[index].read;
1679}
1680EXPORT_SYMBOL_GPL(snd_soc_default_readable_register);
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index bac7291b6ff6..14861f95f629 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -48,7 +48,8 @@ static DEFINE_MUTEX(pcm_mutex);
48static DECLARE_WAIT_QUEUE_HEAD(soc_pm_waitq); 48static DECLARE_WAIT_QUEUE_HEAD(soc_pm_waitq);
49 49
50#ifdef CONFIG_DEBUG_FS 50#ifdef CONFIG_DEBUG_FS
51static struct dentry *debugfs_root; 51struct dentry *snd_soc_debugfs_root;
52EXPORT_SYMBOL_GPL(snd_soc_debugfs_root);
52#endif 53#endif
53 54
54static DEFINE_MUTEX(client_mutex); 55static DEFINE_MUTEX(client_mutex);
@@ -57,8 +58,6 @@ static LIST_HEAD(dai_list);
57static LIST_HEAD(platform_list); 58static LIST_HEAD(platform_list);
58static LIST_HEAD(codec_list); 59static LIST_HEAD(codec_list);
59 60
60static int snd_soc_register_card(struct snd_soc_card *card);
61static int snd_soc_unregister_card(struct snd_soc_card *card);
62static int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num); 61static int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num);
63 62
64/* 63/*
@@ -83,7 +82,7 @@ static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf)
83 82
84 count += sprintf(buf, "%s registers\n", codec->name); 83 count += sprintf(buf, "%s registers\n", codec->name);
85 for (i = 0; i < codec->driver->reg_cache_size; i += step) { 84 for (i = 0; i < codec->driver->reg_cache_size; i += step) {
86 if (codec->driver->readable_register && !codec->driver->readable_register(i)) 85 if (codec->readable_register && !codec->readable_register(codec, i))
87 continue; 86 continue;
88 87
89 count += sprintf(buf + count, "%2x: ", i); 88 count += sprintf(buf + count, "%2x: ", i);
@@ -209,6 +208,10 @@ static ssize_t codec_reg_write_file(struct file *file,
209 start++; 208 start++;
210 if (strict_strtoul(start, 16, &value)) 209 if (strict_strtoul(start, 16, &value))
211 return -EINVAL; 210 return -EINVAL;
211
212 /* Userspace has been fiddling around behind the kernel's back */
213 add_taint(TAINT_USER);
214
212 snd_soc_write(codec, reg, value); 215 snd_soc_write(codec, reg, value);
213 return buf_size; 216 return buf_size;
214} 217}
@@ -356,7 +359,7 @@ static const struct file_operations platform_list_fops = {
356static void soc_init_card_debugfs(struct snd_soc_card *card) 359static void soc_init_card_debugfs(struct snd_soc_card *card)
357{ 360{
358 card->debugfs_card_root = debugfs_create_dir(card->name, 361 card->debugfs_card_root = debugfs_create_dir(card->name,
359 debugfs_root); 362 snd_soc_debugfs_root);
360 if (!card->debugfs_card_root) { 363 if (!card->debugfs_card_root) {
361 dev_warn(card->dev, 364 dev_warn(card->dev,
362 "ASoC: Failed to create codec debugfs directory\n"); 365 "ASoC: Failed to create codec debugfs directory\n");
@@ -1467,7 +1470,6 @@ static int soc_post_component_init(struct snd_soc_card *card,
1467 1470
1468 /* Make sure all DAPM widgets are instantiated */ 1471 /* Make sure all DAPM widgets are instantiated */
1469 snd_soc_dapm_new_widgets(&codec->dapm); 1472 snd_soc_dapm_new_widgets(&codec->dapm);
1470 snd_soc_dapm_sync(&codec->dapm);
1471 1473
1472 /* register the rtd device */ 1474 /* register the rtd device */
1473 rtd->codec = codec; 1475 rtd->codec = codec;
@@ -1743,6 +1745,8 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
1743 list_for_each_entry(codec, &codec_list, list) { 1745 list_for_each_entry(codec, &codec_list, list) {
1744 if (codec->cache_init) 1746 if (codec->cache_init)
1745 continue; 1747 continue;
1748 /* by default we don't override the compress_type */
1749 compress_type = 0;
1746 /* check to see if we need to override the compress_type */ 1750 /* check to see if we need to override the compress_type */
1747 for (i = 0; i < card->num_configs; ++i) { 1751 for (i = 0; i < card->num_configs; ++i) {
1748 codec_conf = &card->codec_conf[i]; 1752 codec_conf = &card->codec_conf[i];
@@ -1753,18 +1757,6 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
1753 break; 1757 break;
1754 } 1758 }
1755 } 1759 }
1756 if (i == card->num_configs) {
1757 /* no need to override the compress_type so
1758 * go ahead and do the standard thing */
1759 ret = snd_soc_init_codec_cache(codec, 0);
1760 if (ret < 0) {
1761 mutex_unlock(&card->mutex);
1762 return;
1763 }
1764 continue;
1765 }
1766 /* override the compress_type with the one supplied in
1767 * the machine driver */
1768 ret = snd_soc_init_codec_cache(codec, compress_type); 1760 ret = snd_soc_init_codec_cache(codec, compress_type);
1769 if (ret < 0) { 1761 if (ret < 0) {
1770 mutex_unlock(&card->mutex); 1762 mutex_unlock(&card->mutex);
@@ -1875,16 +1867,16 @@ static int soc_probe(struct platform_device *pdev)
1875 struct snd_soc_card *card = platform_get_drvdata(pdev); 1867 struct snd_soc_card *card = platform_get_drvdata(pdev);
1876 int ret = 0; 1868 int ret = 0;
1877 1869
1870 /*
1871 * no card, so machine driver should be registering card
1872 * we should not be here in that case so ret error
1873 */
1874 if (!card)
1875 return -EINVAL;
1876
1878 /* Bodge while we unpick instantiation */ 1877 /* Bodge while we unpick instantiation */
1879 card->dev = &pdev->dev; 1878 card->dev = &pdev->dev;
1880 INIT_LIST_HEAD(&card->dai_dev_list); 1879 snd_soc_initialize_card_lists(card);
1881 INIT_LIST_HEAD(&card->codec_dev_list);
1882 INIT_LIST_HEAD(&card->platform_dev_list);
1883 INIT_LIST_HEAD(&card->widgets);
1884 INIT_LIST_HEAD(&card->paths);
1885 INIT_LIST_HEAD(&card->dapm_list);
1886
1887 soc_init_card_debugfs(card);
1888 1880
1889 ret = snd_soc_register_card(card); 1881 ret = snd_soc_register_card(card);
1890 if (ret != 0) { 1882 if (ret != 0) {
@@ -1895,37 +1887,42 @@ static int soc_probe(struct platform_device *pdev)
1895 return 0; 1887 return 0;
1896} 1888}
1897 1889
1898/* removes a socdev */ 1890static int soc_cleanup_card_resources(struct snd_soc_card *card)
1899static int soc_remove(struct platform_device *pdev)
1900{ 1891{
1901 struct snd_soc_card *card = platform_get_drvdata(pdev); 1892 struct platform_device *pdev = to_platform_device(card->dev);
1902 int i; 1893 int i;
1903 1894
1904 if (card->instantiated) { 1895 /* make sure any delayed work runs */
1896 for (i = 0; i < card->num_rtd; i++) {
1897 struct snd_soc_pcm_runtime *rtd = &card->rtd[i];
1898 flush_delayed_work_sync(&rtd->delayed_work);
1899 }
1905 1900
1906 /* make sure any delayed work runs */ 1901 /* remove auxiliary devices */
1907 for (i = 0; i < card->num_rtd; i++) { 1902 for (i = 0; i < card->num_aux_devs; i++)
1908 struct snd_soc_pcm_runtime *rtd = &card->rtd[i]; 1903 soc_remove_aux_dev(card, i);
1909 flush_delayed_work_sync(&rtd->delayed_work); 1904
1910 } 1905 /* remove and free each DAI */
1906 for (i = 0; i < card->num_rtd; i++)
1907 soc_remove_dai_link(card, i);
1908
1909 soc_cleanup_card_debugfs(card);
1911 1910
1912 /* remove auxiliary devices */ 1911 /* remove the card */
1913 for (i = 0; i < card->num_aux_devs; i++) 1912 if (card->remove)
1914 soc_remove_aux_dev(card, i); 1913 card->remove(pdev);
1915 1914
1916 /* remove and free each DAI */ 1915 kfree(card->rtd);
1917 for (i = 0; i < card->num_rtd; i++) 1916 snd_card_free(card->snd_card);
1918 soc_remove_dai_link(card, i); 1917 return 0;
1919 1918
1920 soc_cleanup_card_debugfs(card); 1919}
1921 1920
1922 /* remove the card */ 1921/* removes a socdev */
1923 if (card->remove) 1922static int soc_remove(struct platform_device *pdev)
1924 card->remove(pdev); 1923{
1924 struct snd_soc_card *card = platform_get_drvdata(pdev);
1925 1925
1926 kfree(card->rtd);
1927 snd_card_free(card->snd_card);
1928 }
1929 snd_soc_unregister_card(card); 1926 snd_soc_unregister_card(card);
1930 return 0; 1927 return 0;
1931} 1928}
@@ -2032,10 +2029,11 @@ static int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
2032 * 2029 *
2033 * Boolean function indiciating if a CODEC register is volatile. 2030 * Boolean function indiciating if a CODEC register is volatile.
2034 */ 2031 */
2035int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, int reg) 2032int snd_soc_codec_volatile_register(struct snd_soc_codec *codec,
2033 unsigned int reg)
2036{ 2034{
2037 if (codec->driver->volatile_register) 2035 if (codec->volatile_register)
2038 return codec->driver->volatile_register(reg); 2036 return codec->volatile_register(codec, reg);
2039 else 2037 else
2040 return 0; 2038 return 0;
2041} 2039}
@@ -2132,19 +2130,27 @@ EXPORT_SYMBOL_GPL(snd_soc_write);
2132 * 2130 *
2133 * Writes new register value. 2131 * Writes new register value.
2134 * 2132 *
2135 * Returns 1 for change else 0. 2133 * Returns 1 for change, 0 for no change, or negative error code.
2136 */ 2134 */
2137int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg, 2135int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg,
2138 unsigned int mask, unsigned int value) 2136 unsigned int mask, unsigned int value)
2139{ 2137{
2140 int change; 2138 int change;
2141 unsigned int old, new; 2139 unsigned int old, new;
2140 int ret;
2142 2141
2143 old = snd_soc_read(codec, reg); 2142 ret = snd_soc_read(codec, reg);
2143 if (ret < 0)
2144 return ret;
2145
2146 old = ret;
2144 new = (old & ~mask) | value; 2147 new = (old & ~mask) | value;
2145 change = old != new; 2148 change = old != new;
2146 if (change) 2149 if (change) {
2147 snd_soc_write(codec, reg, new); 2150 ret = snd_soc_write(codec, reg, new);
2151 if (ret < 0)
2152 return ret;
2153 }
2148 2154
2149 return change; 2155 return change;
2150} 2156}
@@ -3104,17 +3110,16 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute);
3104 * 3110 *
3105 * @card: Card to register 3111 * @card: Card to register
3106 * 3112 *
3107 * Note that currently this is an internal only function: it will be
3108 * exposed to machine drivers after further backporting of ASoC v2
3109 * registration APIs.
3110 */ 3113 */
3111static int snd_soc_register_card(struct snd_soc_card *card) 3114int snd_soc_register_card(struct snd_soc_card *card)
3112{ 3115{
3113 int i; 3116 int i;
3114 3117
3115 if (!card->name || !card->dev) 3118 if (!card->name || !card->dev)
3116 return -EINVAL; 3119 return -EINVAL;
3117 3120
3121 soc_init_card_debugfs(card);
3122
3118 card->rtd = kzalloc(sizeof(struct snd_soc_pcm_runtime) * 3123 card->rtd = kzalloc(sizeof(struct snd_soc_pcm_runtime) *
3119 (card->num_links + card->num_aux_devs), 3124 (card->num_links + card->num_aux_devs),
3120 GFP_KERNEL); 3125 GFP_KERNEL);
@@ -3138,18 +3143,18 @@ static int snd_soc_register_card(struct snd_soc_card *card)
3138 3143
3139 return 0; 3144 return 0;
3140} 3145}
3146EXPORT_SYMBOL_GPL(snd_soc_register_card);
3141 3147
3142/** 3148/**
3143 * snd_soc_unregister_card - Unregister a card with the ASoC core 3149 * snd_soc_unregister_card - Unregister a card with the ASoC core
3144 * 3150 *
3145 * @card: Card to unregister 3151 * @card: Card to unregister
3146 * 3152 *
3147 * Note that currently this is an internal only function: it will be
3148 * exposed to machine drivers after further backporting of ASoC v2
3149 * registration APIs.
3150 */ 3153 */
3151static int snd_soc_unregister_card(struct snd_soc_card *card) 3154int snd_soc_unregister_card(struct snd_soc_card *card)
3152{ 3155{
3156 if (card->instantiated)
3157 soc_cleanup_card_resources(card);
3153 mutex_lock(&client_mutex); 3158 mutex_lock(&client_mutex);
3154 list_del(&card->list); 3159 list_del(&card->list);
3155 mutex_unlock(&client_mutex); 3160 mutex_unlock(&client_mutex);
@@ -3157,6 +3162,7 @@ static int snd_soc_unregister_card(struct snd_soc_card *card)
3157 3162
3158 return 0; 3163 return 0;
3159} 3164}
3165EXPORT_SYMBOL_GPL(snd_soc_unregister_card);
3160 3166
3161/* 3167/*
3162 * Simplify DAI link configuration by removing ".-1" from device names 3168 * Simplify DAI link configuration by removing ".-1" from device names
@@ -3486,9 +3492,12 @@ int snd_soc_register_codec(struct device *dev,
3486 3492
3487 codec->write = codec_drv->write; 3493 codec->write = codec_drv->write;
3488 codec->read = codec_drv->read; 3494 codec->read = codec_drv->read;
3495 codec->volatile_register = codec_drv->volatile_register;
3496 codec->readable_register = codec_drv->readable_register;
3489 codec->dapm.bias_level = SND_SOC_BIAS_OFF; 3497 codec->dapm.bias_level = SND_SOC_BIAS_OFF;
3490 codec->dapm.dev = dev; 3498 codec->dapm.dev = dev;
3491 codec->dapm.codec = codec; 3499 codec->dapm.codec = codec;
3500 codec->dapm.seq_notifier = codec_drv->seq_notifier;
3492 codec->dev = dev; 3501 codec->dev = dev;
3493 codec->driver = codec_drv; 3502 codec->driver = codec_drv;
3494 codec->num_dai = num_dai; 3503 codec->num_dai = num_dai;
@@ -3497,20 +3506,30 @@ int snd_soc_register_codec(struct device *dev,
3497 /* allocate CODEC register cache */ 3506 /* allocate CODEC register cache */
3498 if (codec_drv->reg_cache_size && codec_drv->reg_word_size) { 3507 if (codec_drv->reg_cache_size && codec_drv->reg_word_size) {
3499 reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size; 3508 reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size;
3509 codec->reg_size = reg_size;
3500 /* it is necessary to make a copy of the default register cache 3510 /* it is necessary to make a copy of the default register cache
3501 * because in the case of using a compression type that requires 3511 * because in the case of using a compression type that requires
3502 * the default register cache to be marked as __devinitconst the 3512 * the default register cache to be marked as __devinitconst the
3503 * kernel might have freed the array by the time we initialize 3513 * kernel might have freed the array by the time we initialize
3504 * the cache. 3514 * the cache.
3505 */ 3515 */
3506 codec->reg_def_copy = kmemdup(codec_drv->reg_cache_default, 3516 if (codec_drv->reg_cache_default) {
3507 reg_size, GFP_KERNEL); 3517 codec->reg_def_copy = kmemdup(codec_drv->reg_cache_default,
3508 if (!codec->reg_def_copy) { 3518 reg_size, GFP_KERNEL);
3509 ret = -ENOMEM; 3519 if (!codec->reg_def_copy) {
3510 goto fail; 3520 ret = -ENOMEM;
3521 goto fail;
3522 }
3511 } 3523 }
3512 } 3524 }
3513 3525
3526 if (codec_drv->reg_access_size && codec_drv->reg_access_default) {
3527 if (!codec->volatile_register)
3528 codec->volatile_register = snd_soc_default_volatile_register;
3529 if (!codec->readable_register)
3530 codec->readable_register = snd_soc_default_readable_register;
3531 }
3532
3514 for (i = 0; i < num_dai; i++) { 3533 for (i = 0; i < num_dai; i++) {
3515 fixup_codec_formats(&dai_drv[i].playback); 3534 fixup_codec_formats(&dai_drv[i].playback);
3516 fixup_codec_formats(&dai_drv[i].capture); 3535 fixup_codec_formats(&dai_drv[i].capture);
@@ -3577,22 +3596,22 @@ EXPORT_SYMBOL_GPL(snd_soc_unregister_codec);
3577static int __init snd_soc_init(void) 3596static int __init snd_soc_init(void)
3578{ 3597{
3579#ifdef CONFIG_DEBUG_FS 3598#ifdef CONFIG_DEBUG_FS
3580 debugfs_root = debugfs_create_dir("asoc", NULL); 3599 snd_soc_debugfs_root = debugfs_create_dir("asoc", NULL);
3581 if (IS_ERR(debugfs_root) || !debugfs_root) { 3600 if (IS_ERR(snd_soc_debugfs_root) || !snd_soc_debugfs_root) {
3582 printk(KERN_WARNING 3601 printk(KERN_WARNING
3583 "ASoC: Failed to create debugfs directory\n"); 3602 "ASoC: Failed to create debugfs directory\n");
3584 debugfs_root = NULL; 3603 snd_soc_debugfs_root = NULL;
3585 } 3604 }
3586 3605
3587 if (!debugfs_create_file("codecs", 0444, debugfs_root, NULL, 3606 if (!debugfs_create_file("codecs", 0444, snd_soc_debugfs_root, NULL,
3588 &codec_list_fops)) 3607 &codec_list_fops))
3589 pr_warn("ASoC: Failed to create CODEC list debugfs file\n"); 3608 pr_warn("ASoC: Failed to create CODEC list debugfs file\n");
3590 3609
3591 if (!debugfs_create_file("dais", 0444, debugfs_root, NULL, 3610 if (!debugfs_create_file("dais", 0444, snd_soc_debugfs_root, NULL,
3592 &dai_list_fops)) 3611 &dai_list_fops))
3593 pr_warn("ASoC: Failed to create DAI list debugfs file\n"); 3612 pr_warn("ASoC: Failed to create DAI list debugfs file\n");
3594 3613
3595 if (!debugfs_create_file("platforms", 0444, debugfs_root, NULL, 3614 if (!debugfs_create_file("platforms", 0444, snd_soc_debugfs_root, NULL,
3596 &platform_list_fops)) 3615 &platform_list_fops))
3597 pr_warn("ASoC: Failed to create platform list debugfs file\n"); 3616 pr_warn("ASoC: Failed to create platform list debugfs file\n");
3598#endif 3617#endif
@@ -3604,7 +3623,7 @@ module_init(snd_soc_init);
3604static void __exit snd_soc_exit(void) 3623static void __exit snd_soc_exit(void)
3605{ 3624{
3606#ifdef CONFIG_DEBUG_FS 3625#ifdef CONFIG_DEBUG_FS
3607 debugfs_remove_recursive(debugfs_root); 3626 debugfs_remove_recursive(snd_soc_debugfs_root);
3608#endif 3627#endif
3609 platform_driver_unregister(&soc_driver); 3628 platform_driver_unregister(&soc_driver);
3610} 3629}
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 499730ab5638..37b376f4c75d 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -726,10 +726,23 @@ static int dapm_supply_check_power(struct snd_soc_dapm_widget *w)
726 726
727static int dapm_seq_compare(struct snd_soc_dapm_widget *a, 727static int dapm_seq_compare(struct snd_soc_dapm_widget *a,
728 struct snd_soc_dapm_widget *b, 728 struct snd_soc_dapm_widget *b,
729 int sort[]) 729 bool power_up)
730{ 730{
731 int *sort;
732
733 if (power_up)
734 sort = dapm_up_seq;
735 else
736 sort = dapm_down_seq;
737
731 if (sort[a->id] != sort[b->id]) 738 if (sort[a->id] != sort[b->id])
732 return sort[a->id] - sort[b->id]; 739 return sort[a->id] - sort[b->id];
740 if (a->subseq != b->subseq) {
741 if (power_up)
742 return a->subseq - b->subseq;
743 else
744 return b->subseq - a->subseq;
745 }
733 if (a->reg != b->reg) 746 if (a->reg != b->reg)
734 return a->reg - b->reg; 747 return a->reg - b->reg;
735 if (a->dapm != b->dapm) 748 if (a->dapm != b->dapm)
@@ -741,12 +754,12 @@ static int dapm_seq_compare(struct snd_soc_dapm_widget *a,
741/* Insert a widget in order into a DAPM power sequence. */ 754/* Insert a widget in order into a DAPM power sequence. */
742static void dapm_seq_insert(struct snd_soc_dapm_widget *new_widget, 755static void dapm_seq_insert(struct snd_soc_dapm_widget *new_widget,
743 struct list_head *list, 756 struct list_head *list,
744 int sort[]) 757 bool power_up)
745{ 758{
746 struct snd_soc_dapm_widget *w; 759 struct snd_soc_dapm_widget *w;
747 760
748 list_for_each_entry(w, list, power_list) 761 list_for_each_entry(w, list, power_list)
749 if (dapm_seq_compare(new_widget, w, sort) < 0) { 762 if (dapm_seq_compare(new_widget, w, power_up) < 0) {
750 list_add_tail(&new_widget->power_list, &w->power_list); 763 list_add_tail(&new_widget->power_list, &w->power_list);
751 return; 764 return;
752 } 765 }
@@ -857,26 +870,41 @@ static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm,
857 * handled. 870 * handled.
858 */ 871 */
859static void dapm_seq_run(struct snd_soc_dapm_context *dapm, 872static void dapm_seq_run(struct snd_soc_dapm_context *dapm,
860 struct list_head *list, int event, int sort[]) 873 struct list_head *list, int event, bool power_up)
861{ 874{
862 struct snd_soc_dapm_widget *w, *n; 875 struct snd_soc_dapm_widget *w, *n;
863 LIST_HEAD(pending); 876 LIST_HEAD(pending);
864 int cur_sort = -1; 877 int cur_sort = -1;
878 int cur_subseq = -1;
865 int cur_reg = SND_SOC_NOPM; 879 int cur_reg = SND_SOC_NOPM;
866 struct snd_soc_dapm_context *cur_dapm = NULL; 880 struct snd_soc_dapm_context *cur_dapm = NULL;
867 int ret; 881 int ret, i;
882 int *sort;
883
884 if (power_up)
885 sort = dapm_up_seq;
886 else
887 sort = dapm_down_seq;
868 888
869 list_for_each_entry_safe(w, n, list, power_list) { 889 list_for_each_entry_safe(w, n, list, power_list) {
870 ret = 0; 890 ret = 0;
871 891
872 /* Do we need to apply any queued changes? */ 892 /* Do we need to apply any queued changes? */
873 if (sort[w->id] != cur_sort || w->reg != cur_reg || 893 if (sort[w->id] != cur_sort || w->reg != cur_reg ||
874 w->dapm != cur_dapm) { 894 w->dapm != cur_dapm || w->subseq != cur_subseq) {
875 if (!list_empty(&pending)) 895 if (!list_empty(&pending))
876 dapm_seq_run_coalesced(cur_dapm, &pending); 896 dapm_seq_run_coalesced(cur_dapm, &pending);
877 897
898 if (cur_dapm && cur_dapm->seq_notifier) {
899 for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++)
900 if (sort[i] == cur_sort)
901 cur_dapm->seq_notifier(cur_dapm,
902 i);
903 }
904
878 INIT_LIST_HEAD(&pending); 905 INIT_LIST_HEAD(&pending);
879 cur_sort = -1; 906 cur_sort = -1;
907 cur_subseq = -1;
880 cur_reg = SND_SOC_NOPM; 908 cur_reg = SND_SOC_NOPM;
881 cur_dapm = NULL; 909 cur_dapm = NULL;
882 } 910 }
@@ -921,6 +949,7 @@ static void dapm_seq_run(struct snd_soc_dapm_context *dapm,
921 default: 949 default:
922 /* Queue it up for application */ 950 /* Queue it up for application */
923 cur_sort = sort[w->id]; 951 cur_sort = sort[w->id];
952 cur_subseq = w->subseq;
924 cur_reg = w->reg; 953 cur_reg = w->reg;
925 cur_dapm = w->dapm; 954 cur_dapm = w->dapm;
926 list_move(&w->power_list, &pending); 955 list_move(&w->power_list, &pending);
@@ -934,6 +963,13 @@ static void dapm_seq_run(struct snd_soc_dapm_context *dapm,
934 963
935 if (!list_empty(&pending)) 964 if (!list_empty(&pending))
936 dapm_seq_run_coalesced(dapm, &pending); 965 dapm_seq_run_coalesced(dapm, &pending);
966
967 if (cur_dapm && cur_dapm->seq_notifier) {
968 for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++)
969 if (sort[i] == cur_sort)
970 cur_dapm->seq_notifier(cur_dapm,
971 i);
972 }
937} 973}
938 974
939static void dapm_widget_update(struct snd_soc_dapm_context *dapm) 975static void dapm_widget_update(struct snd_soc_dapm_context *dapm)
@@ -1002,10 +1038,10 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
1002 list_for_each_entry(w, &card->widgets, list) { 1038 list_for_each_entry(w, &card->widgets, list) {
1003 switch (w->id) { 1039 switch (w->id) {
1004 case snd_soc_dapm_pre: 1040 case snd_soc_dapm_pre:
1005 dapm_seq_insert(w, &down_list, dapm_down_seq); 1041 dapm_seq_insert(w, &down_list, false);
1006 break; 1042 break;
1007 case snd_soc_dapm_post: 1043 case snd_soc_dapm_post:
1008 dapm_seq_insert(w, &up_list, dapm_up_seq); 1044 dapm_seq_insert(w, &up_list, true);
1009 break; 1045 break;
1010 1046
1011 default: 1047 default:
@@ -1025,9 +1061,9 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
1025 trace_snd_soc_dapm_widget_power(w, power); 1061 trace_snd_soc_dapm_widget_power(w, power);
1026 1062
1027 if (power) 1063 if (power)
1028 dapm_seq_insert(w, &up_list, dapm_up_seq); 1064 dapm_seq_insert(w, &up_list, true);
1029 else 1065 else
1030 dapm_seq_insert(w, &down_list, dapm_down_seq); 1066 dapm_seq_insert(w, &down_list, false);
1031 1067
1032 w->power = power; 1068 w->power = power;
1033 break; 1069 break;
@@ -1086,12 +1122,12 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
1086 } 1122 }
1087 1123
1088 /* Power down widgets first; try to avoid amplifying pops. */ 1124 /* Power down widgets first; try to avoid amplifying pops. */
1089 dapm_seq_run(dapm, &down_list, event, dapm_down_seq); 1125 dapm_seq_run(dapm, &down_list, event, false);
1090 1126
1091 dapm_widget_update(dapm); 1127 dapm_widget_update(dapm);
1092 1128
1093 /* Now power up. */ 1129 /* Now power up. */
1094 dapm_seq_run(dapm, &up_list, event, dapm_up_seq); 1130 dapm_seq_run(dapm, &up_list, event, true);
1095 1131
1096 list_for_each_entry(d, &dapm->card->dapm_list, list) { 1132 list_for_each_entry(d, &dapm->card->dapm_list, list) {
1097 /* If we just powered the last thing off drop to standby bias */ 1133 /* If we just powered the last thing off drop to standby bias */
@@ -2372,7 +2408,7 @@ static void soc_dapm_shutdown_codec(struct snd_soc_dapm_context *dapm)
2372 if (w->dapm != dapm) 2408 if (w->dapm != dapm)
2373 continue; 2409 continue;
2374 if (w->power) { 2410 if (w->power) {
2375 dapm_seq_insert(w, &down_list, dapm_down_seq); 2411 dapm_seq_insert(w, &down_list, false);
2376 w->power = 0; 2412 w->power = 0;
2377 powerdown = 1; 2413 powerdown = 1;
2378 } 2414 }
@@ -2383,7 +2419,7 @@ static void soc_dapm_shutdown_codec(struct snd_soc_dapm_context *dapm)
2383 */ 2419 */
2384 if (powerdown) { 2420 if (powerdown) {
2385 snd_soc_dapm_set_bias_level(NULL, dapm, SND_SOC_BIAS_PREPARE); 2421 snd_soc_dapm_set_bias_level(NULL, dapm, SND_SOC_BIAS_PREPARE);
2386 dapm_seq_run(dapm, &down_list, 0, dapm_down_seq); 2422 dapm_seq_run(dapm, &down_list, 0, false);
2387 snd_soc_dapm_set_bias_level(NULL, dapm, SND_SOC_BIAS_STANDBY); 2423 snd_soc_dapm_set_bias_level(NULL, dapm, SND_SOC_BIAS_STANDBY);
2388 } 2424 }
2389} 2425}
diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig
new file mode 100644
index 000000000000..66b504f06c23
--- /dev/null
+++ b/sound/soc/tegra/Kconfig
@@ -0,0 +1,26 @@
1config SND_TEGRA_SOC
2 tristate "SoC Audio for the Tegra System-on-Chip"
3 depends on ARCH_TEGRA && TEGRA_SYSTEM_DMA
4 default m
5 help
6 Say Y or M here if you want support for SoC audio on Tegra.
7
8config SND_TEGRA_SOC_I2S
9 tristate
10 depends on SND_TEGRA_SOC
11 default m
12 help
13 Say Y or M if you want to add support for codecs attached to the
14 Tegra I2S interface. You will also need to select the individual
15 machine drivers to support below.
16
17config SND_TEGRA_SOC_HARMONY
18 tristate "SoC Audio support for Tegra Harmony reference board"
19 depends on SND_TEGRA_SOC && MACH_HARMONY && I2C
20 default m
21 select SND_TEGRA_SOC_I2S
22 select SND_SOC_WM8903
23 help
24 Say Y or M here if you want to add support for SoC audio on the
25 Tegra Harmony reference board.
26
diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile
new file mode 100644
index 000000000000..dfd2ab9d975c
--- /dev/null
+++ b/sound/soc/tegra/Makefile
@@ -0,0 +1,14 @@
1# Tegra platform Support
2snd-soc-tegra-das-objs := tegra_das.o
3snd-soc-tegra-pcm-objs := tegra_pcm.o
4snd-soc-tegra-i2s-objs := tegra_i2s.o
5
6obj-$(CONFIG_SND_TEGRA_SOC) += snd-soc-tegra-das.o
7obj-$(CONFIG_SND_TEGRA_SOC) += snd-soc-tegra-pcm.o
8obj-$(CONFIG_SND_TEGRA_SOC_I2S) += snd-soc-tegra-i2s.o
9
10# Tegra machine Support
11snd-soc-tegra-harmony-objs := harmony.o
12snd-soc-tegra-harmony-objs += tegra_asoc_utils.o
13
14obj-$(CONFIG_SND_TEGRA_SOC_HARMONY) += snd-soc-tegra-harmony.o
diff --git a/sound/soc/tegra/harmony.c b/sound/soc/tegra/harmony.c
new file mode 100644
index 000000000000..b160b7113f45
--- /dev/null
+++ b/sound/soc/tegra/harmony.c
@@ -0,0 +1,210 @@
1/*
2 * harmony.c - Harmony machine ASoC driver
3 *
4 * Author: Stephen Warren <swarren@nvidia.com>
5 * Copyright (C) 2010 - NVIDIA, Inc.
6 *
7 * Based on code copyright/by:
8 *
9 * (c) 2009, 2010 Nvidia Graphics Pvt. Ltd.
10 *
11 * Copyright 2007 Wolfson Microelectronics PLC.
12 * Author: Graeme Gregory
13 * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * version 2 as published by the Free Software Foundation.
18 *
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * 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, write to the Free Software
26 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
27 * 02110-1301 USA
28 *
29 */
30
31#include <asm/mach-types.h>
32#include <linux/module.h>
33#include <sound/core.h>
34#include <sound/pcm.h>
35#include <sound/pcm_params.h>
36#include <sound/soc.h>
37
38#include "tegra_das.h"
39#include "tegra_i2s.h"
40#include "tegra_pcm.h"
41#include "tegra_asoc_utils.h"
42
43#define PREFIX "ASoC Harmony: "
44
45static struct platform_device *harmony_snd_device;
46
47static int harmony_asoc_hw_params(struct snd_pcm_substream *substream,
48 struct snd_pcm_hw_params *params)
49{
50 struct snd_soc_pcm_runtime *rtd = substream->private_data;
51 struct snd_soc_dai *codec_dai = rtd->codec_dai;
52 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
53 int srate, mclk, mclk_change;
54 int err;
55
56 srate = params_rate(params);
57 switch (srate) {
58 case 64000:
59 case 88200:
60 case 96000:
61 mclk = 128 * srate;
62 break;
63 default:
64 mclk = 256 * srate;
65 break;
66 }
67 /* FIXME: Codec only requires >= 3MHz if OSR==0 */
68 while (mclk < 6000000)
69 mclk *= 2;
70
71 err = tegra_asoc_utils_set_rate(srate, mclk, &mclk_change);
72 if (err < 0) {
73 pr_err(PREFIX "Can't configure clocks\n");
74 return err;
75 }
76
77 err = snd_soc_dai_set_fmt(codec_dai,
78 SND_SOC_DAIFMT_I2S |
79 SND_SOC_DAIFMT_NB_NF |
80 SND_SOC_DAIFMT_CBS_CFS);
81 if (err < 0) {
82 pr_err(PREFIX "codec_dai fmt not set\n");
83 return err;
84 }
85
86 err = snd_soc_dai_set_fmt(cpu_dai,
87 SND_SOC_DAIFMT_I2S |
88 SND_SOC_DAIFMT_NB_NF |
89 SND_SOC_DAIFMT_CBS_CFS);
90 if (err < 0) {
91 pr_err(PREFIX "cpu_dai fmt not set\n");
92 return err;
93 }
94
95 if (mclk_change) {
96 err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, SND_SOC_CLOCK_IN);
97 if (err < 0) {
98 pr_err(PREFIX "codec_dai clock not set\n");
99 return err;
100 }
101 }
102
103 return 0;
104}
105
106static struct snd_soc_ops harmony_asoc_ops = {
107 .hw_params = harmony_asoc_hw_params,
108};
109
110static const struct snd_soc_dapm_widget harmony_dapm_widgets[] = {
111 SND_SOC_DAPM_HP("Headphone Jack", NULL),
112 SND_SOC_DAPM_MIC("Mic Jack", NULL),
113};
114
115static const struct snd_soc_dapm_route harmony_audio_map[] = {
116 {"Headphone Jack", NULL, "HPOUTR"},
117 {"Headphone Jack", NULL, "HPOUTL"},
118 {"Mic Bias", NULL, "Mic Jack"},
119 {"IN1L", NULL, "Mic Bias"},
120};
121
122static int harmony_asoc_init(struct snd_soc_pcm_runtime *rtd)
123{
124 struct snd_soc_codec *codec = rtd->codec;
125 struct snd_soc_dapm_context *dapm = &codec->dapm;
126
127 snd_soc_dapm_new_controls(dapm, harmony_dapm_widgets,
128 ARRAY_SIZE(harmony_dapm_widgets));
129
130 snd_soc_dapm_add_routes(dapm, harmony_audio_map,
131 ARRAY_SIZE(harmony_audio_map));
132
133 snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
134 snd_soc_dapm_enable_pin(dapm, "Mic Jack");
135 snd_soc_dapm_sync(dapm);
136
137 return 0;
138}
139
140static struct snd_soc_dai_link harmony_wm8903_dai = {
141 .name = "WM8903",
142 .stream_name = "WM8903 PCM",
143 .codec_name = "wm8903-codec.0-001a",
144 .platform_name = "tegra-pcm-audio",
145 .cpu_dai_name = "tegra-i2s.0",
146 .codec_dai_name = "wm8903-hifi",
147 .init = harmony_asoc_init,
148 .ops = &harmony_asoc_ops,
149};
150
151static struct snd_soc_card snd_soc_harmony = {
152 .name = "tegra-harmony",
153 .dai_link = &harmony_wm8903_dai,
154 .num_links = 1,
155};
156
157static int __init harmony_soc_modinit(void)
158{
159 int ret;
160
161 if (!machine_is_harmony()) {
162 pr_err(PREFIX "Not running on Tegra Harmony!\n");
163 return -ENODEV;
164 }
165
166 ret = tegra_asoc_utils_init();
167 if (ret) {
168 return ret;
169 }
170
171 /*
172 * Create and register platform device
173 */
174 harmony_snd_device = platform_device_alloc("soc-audio", -1);
175 if (harmony_snd_device == NULL) {
176 pr_err(PREFIX "platform_device_alloc failed\n");
177 ret = -ENOMEM;
178 goto err_clock_utils;
179 }
180
181 platform_set_drvdata(harmony_snd_device, &snd_soc_harmony);
182
183 ret = platform_device_add(harmony_snd_device);
184 if (ret) {
185 pr_err(PREFIX "platform_device_add failed (%d)\n",
186 ret);
187 goto err_device_put;
188 }
189
190 return 0;
191
192err_device_put:
193 platform_device_put(harmony_snd_device);
194err_clock_utils:
195 tegra_asoc_utils_fini();
196 return ret;
197}
198module_init(harmony_soc_modinit);
199
200static void __exit harmony_soc_modexit(void)
201{
202 platform_device_unregister(harmony_snd_device);
203
204 tegra_asoc_utils_fini();
205}
206module_exit(harmony_soc_modexit);
207
208MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
209MODULE_DESCRIPTION("Harmony machine ASoC driver");
210MODULE_LICENSE("GPL");
diff --git a/sound/soc/tegra/tegra_asoc_utils.c b/sound/soc/tegra/tegra_asoc_utils.c
new file mode 100644
index 000000000000..cfe2ea890dc0
--- /dev/null
+++ b/sound/soc/tegra/tegra_asoc_utils.c
@@ -0,0 +1,152 @@
1/*
2 * tegra_asoc_utils.c - Harmony machine ASoC driver
3 *
4 * Author: Stephen Warren <swarren@nvidia.com>
5 * Copyright (C) 2010 - NVIDIA, Inc.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * version 2 as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
19 * 02110-1301 USA
20 *
21 */
22
23#include <linux/clk.h>
24#include <linux/err.h>
25#include <linux/kernel.h>
26
27#include "tegra_asoc_utils.h"
28
29#define PREFIX "ASoC Tegra: "
30
31static struct clk *clk_pll_a;
32static struct clk *clk_pll_a_out0;
33static struct clk *clk_cdev1;
34
35static int set_baseclock, set_mclk;
36
37int tegra_asoc_utils_set_rate(int srate, int mclk, int *mclk_change)
38{
39 int new_baseclock;
40 int err;
41
42 switch (srate) {
43 case 11025:
44 case 22050:
45 case 44100:
46 case 88200:
47 new_baseclock = 56448000;
48 break;
49 case 8000:
50 case 16000:
51 case 32000:
52 case 48000:
53 case 64000:
54 case 96000:
55 new_baseclock = 73728000;
56 break;
57 default:
58 return -EINVAL;
59 }
60
61 *mclk_change = ((new_baseclock != set_baseclock) ||
62 (mclk != set_mclk));
63 if (!*mclk_change)
64 return 0;
65
66 set_baseclock = 0;
67 set_mclk = 0;
68
69 clk_disable(clk_cdev1);
70 clk_disable(clk_pll_a_out0);
71 clk_disable(clk_pll_a);
72
73 err = clk_set_rate(clk_pll_a, new_baseclock);
74 if (err) {
75 pr_err(PREFIX "Can't set pll_a rate: %d\n", err);
76 return err;
77 }
78
79 err = clk_set_rate(clk_pll_a_out0, mclk);
80 if (err) {
81 pr_err(PREFIX "Can't set pll_a_out0 rate: %d\n", err);
82 return err;
83 }
84
85 /* Don't set cdev1 rate; its locked to pll_a_out0 */
86
87 err = clk_enable(clk_pll_a);
88 if (err) {
89 pr_err(PREFIX "Can't enable pll_a: %d\n", err);
90 return err;
91 }
92
93 err = clk_enable(clk_pll_a_out0);
94 if (err) {
95 pr_err(PREFIX "Can't enable pll_a_out0: %d\n", err);
96 return err;
97 }
98
99 err = clk_enable(clk_cdev1);
100 if (err) {
101 pr_err(PREFIX "Can't enable cdev1: %d\n", err);
102 return err;
103 }
104
105 set_baseclock = new_baseclock;
106 set_mclk = mclk;
107
108 return 0;
109}
110
111int tegra_asoc_utils_init(void)
112{
113 int ret;
114
115 clk_pll_a = clk_get_sys(NULL, "pll_a");
116 if (IS_ERR(clk_pll_a)) {
117 pr_err(PREFIX "Can't retrieve clk pll_a\n");
118 ret = PTR_ERR(clk_pll_a);
119 goto err;
120 }
121
122 clk_pll_a_out0 = clk_get_sys(NULL, "pll_a_out0");
123 if (IS_ERR(clk_pll_a_out0)) {
124 pr_err(PREFIX "Can't retrieve clk pll_a_out0\n");
125 ret = PTR_ERR(clk_pll_a_out0);
126 goto err_put_pll_a;
127 }
128
129 clk_cdev1 = clk_get_sys(NULL, "cdev1");
130 if (IS_ERR(clk_cdev1)) {
131 pr_err(PREFIX "Can't retrieve clk cdev1\n");
132 ret = PTR_ERR(clk_cdev1);
133 goto err_put_pll_a_out0;
134 }
135
136 return 0;
137
138err_put_pll_a_out0:
139 clk_put(clk_pll_a_out0);
140err_put_pll_a:
141 clk_put(clk_pll_a);
142err:
143 return ret;
144}
145
146void tegra_asoc_utils_fini(void)
147{
148 clk_put(clk_cdev1);
149 clk_put(clk_pll_a_out0);
150 clk_put(clk_pll_a);
151}
152
diff --git a/sound/soc/tegra/tegra_asoc_utils.h b/sound/soc/tegra/tegra_asoc_utils.h
new file mode 100644
index 000000000000..855f8f6e44ca
--- /dev/null
+++ b/sound/soc/tegra/tegra_asoc_utils.h
@@ -0,0 +1,31 @@
1/*
2 * tegra_asoc_utils.h - Definitions for Tegra DAS driver
3 *
4 * Author: Stephen Warren <swarren@nvidia.com>
5 * Copyright (C) 2010 - NVIDIA, Inc.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * version 2 as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
19 * 02110-1301 USA
20 *
21 */
22
23#ifndef __TEGRA_ASOC_UTILS_H__
24#define __TEGRA_ASOC_UTILS_H_
25
26int tegra_asoc_utils_set_rate(int srate, int mclk_rate, int *mclk_change);
27int tegra_asoc_utils_init(void);
28void tegra_asoc_utils_fini(void);
29
30#endif
31
diff --git a/sound/soc/tegra/tegra_das.c b/sound/soc/tegra/tegra_das.c
new file mode 100644
index 000000000000..01eb9c9301de
--- /dev/null
+++ b/sound/soc/tegra/tegra_das.c
@@ -0,0 +1,264 @@
1/*
2 * tegra_das.c - Tegra DAS driver
3 *
4 * Author: Stephen Warren <swarren@nvidia.com>
5 * Copyright (C) 2010 - NVIDIA, Inc.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * version 2 as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
19 * 02110-1301 USA
20 *
21 */
22
23#include <linux/module.h>
24#include <linux/debugfs.h>
25#include <linux/device.h>
26#include <linux/platform_device.h>
27#include <linux/seq_file.h>
28#include <linux/slab.h>
29#include <linux/io.h>
30#include <mach/iomap.h>
31#include <sound/soc.h>
32#include "tegra_das.h"
33
34#define DRV_NAME "tegra-das"
35
36static struct tegra_das *das;
37
38static inline void tegra_das_write(u32 reg, u32 val)
39{
40 __raw_writel(val, das->regs + reg);
41}
42
43static inline u32 tegra_das_read(u32 reg)
44{
45 return __raw_readl(das->regs + reg);
46}
47
48int tegra_das_connect_dap_to_dac(int dap, int dac)
49{
50 u32 addr;
51 u32 reg;
52
53 if (!das)
54 return -ENODEV;
55
56 addr = TEGRA_DAS_DAP_CTRL_SEL +
57 (dap * TEGRA_DAS_DAP_CTRL_SEL_STRIDE);
58 reg = dac << TEGRA_DAS_DAP_CTRL_SEL_DAP_CTRL_SEL_P;
59
60 tegra_das_write(addr, reg);
61
62 return 0;
63}
64EXPORT_SYMBOL_GPL(tegra_das_connect_dap_to_dac);
65
66int tegra_das_connect_dap_to_dap(int dap, int otherdap, int master,
67 int sdata1rx, int sdata2rx)
68{
69 u32 addr;
70 u32 reg;
71
72 if (!das)
73 return -ENODEV;
74
75 addr = TEGRA_DAS_DAP_CTRL_SEL +
76 (dap * TEGRA_DAS_DAP_CTRL_SEL_STRIDE);
77 reg = otherdap << TEGRA_DAS_DAP_CTRL_SEL_DAP_CTRL_SEL_P |
78 !!sdata2rx << TEGRA_DAS_DAP_CTRL_SEL_DAP_SDATA2_TX_RX_P |
79 !!sdata1rx << TEGRA_DAS_DAP_CTRL_SEL_DAP_SDATA1_TX_RX_P |
80 !!master << TEGRA_DAS_DAP_CTRL_SEL_DAP_MS_SEL_P;
81
82 tegra_das_write(addr, reg);
83
84 return 0;
85}
86EXPORT_SYMBOL_GPL(tegra_das_connect_dap_to_dap);
87
88int tegra_das_connect_dac_to_dap(int dac, int dap)
89{
90 u32 addr;
91 u32 reg;
92
93 if (!das)
94 return -ENODEV;
95
96 addr = TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL +
97 (dac * TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_STRIDE);
98 reg = dap << TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_CLK_SEL_P |
99 dap << TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA1_SEL_P |
100 dap << TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA2_SEL_P;
101
102 tegra_das_write(addr, reg);
103
104 return 0;
105}
106EXPORT_SYMBOL_GPL(tegra_das_connect_dac_to_dap);
107
108#ifdef CONFIG_DEBUG_FS
109static int tegra_das_show(struct seq_file *s, void *unused)
110{
111 int i;
112 u32 addr;
113 u32 reg;
114
115 for (i = 0; i < TEGRA_DAS_DAP_CTRL_SEL_COUNT; i++) {
116 addr = TEGRA_DAS_DAP_CTRL_SEL +
117 (i * TEGRA_DAS_DAP_CTRL_SEL_STRIDE);
118 reg = tegra_das_read(addr);
119 seq_printf(s, "TEGRA_DAS_DAP_CTRL_SEL[%d] = %08x\n", i, reg);
120 }
121
122 for (i = 0; i < TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_COUNT; i++) {
123 addr = TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL +
124 (i * TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_STRIDE);
125 reg = tegra_das_read(addr);
126 seq_printf(s, "TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL[%d] = %08x\n",
127 i, reg);
128 }
129
130 return 0;
131}
132
133static int tegra_das_debug_open(struct inode *inode, struct file *file)
134{
135 return single_open(file, tegra_das_show, inode->i_private);
136}
137
138static const struct file_operations tegra_das_debug_fops = {
139 .open = tegra_das_debug_open,
140 .read = seq_read,
141 .llseek = seq_lseek,
142 .release = single_release,
143};
144
145static void tegra_das_debug_add(struct tegra_das *das)
146{
147 das->debug = debugfs_create_file(DRV_NAME, S_IRUGO,
148 snd_soc_debugfs_root, das,
149 &tegra_das_debug_fops);
150}
151
152static void tegra_das_debug_remove(struct tegra_das *das)
153{
154 if (das->debug)
155 debugfs_remove(das->debug);
156}
157#else
158static inline void tegra_das_debug_add(struct tegra_das *das)
159{
160}
161
162static inline void tegra_das_debug_remove(struct tegra_das *das)
163{
164}
165#endif
166
167static int __devinit tegra_das_probe(struct platform_device *pdev)
168{
169 struct resource *res, *region;
170 int ret = 0;
171
172 if (das)
173 return -ENODEV;
174
175 das = kzalloc(sizeof(struct tegra_das), GFP_KERNEL);
176 if (!das) {
177 dev_err(&pdev->dev, "Can't allocate tegra_das\n");
178 ret = -ENOMEM;
179 goto exit;
180 }
181 das->dev = &pdev->dev;
182
183 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
184 if (!res) {
185 dev_err(&pdev->dev, "No memory resource\n");
186 ret = -ENODEV;
187 goto err_free;
188 }
189
190 region = request_mem_region(res->start, resource_size(res),
191 pdev->name);
192 if (!region) {
193 dev_err(&pdev->dev, "Memory region already claimed\n");
194 ret = -EBUSY;
195 goto err_free;
196 }
197
198 das->regs = ioremap(res->start, resource_size(res));
199 if (!das->regs) {
200 dev_err(&pdev->dev, "ioremap failed\n");
201 ret = -ENOMEM;
202 goto err_release;
203 }
204
205 tegra_das_debug_add(das);
206
207 platform_set_drvdata(pdev, das);
208
209 return 0;
210
211err_release:
212 release_mem_region(res->start, resource_size(res));
213err_free:
214 kfree(das);
215 das = 0;
216exit:
217 return ret;
218}
219
220static int __devexit tegra_das_remove(struct platform_device *pdev)
221{
222 struct resource *res;
223
224 if (!das)
225 return -ENODEV;
226
227 platform_set_drvdata(pdev, NULL);
228
229 tegra_das_debug_remove(das);
230
231 iounmap(das->regs);
232
233 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
234 release_mem_region(res->start, resource_size(res));
235
236 kfree(das);
237 das = 0;
238
239 return 0;
240}
241
242static struct platform_driver tegra_das_driver = {
243 .probe = tegra_das_probe,
244 .remove = __devexit_p(tegra_das_remove),
245 .driver = {
246 .name = DRV_NAME,
247 },
248};
249
250static int __init tegra_das_modinit(void)
251{
252 return platform_driver_register(&tegra_das_driver);
253}
254module_init(tegra_das_modinit);
255
256static void __exit tegra_das_modexit(void)
257{
258 platform_driver_unregister(&tegra_das_driver);
259}
260module_exit(tegra_das_modexit);
261
262MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
263MODULE_DESCRIPTION("Tegra DAS driver");
264MODULE_LICENSE("GPL");
diff --git a/sound/soc/tegra/tegra_das.h b/sound/soc/tegra/tegra_das.h
new file mode 100644
index 000000000000..2c96c7b3c459
--- /dev/null
+++ b/sound/soc/tegra/tegra_das.h
@@ -0,0 +1,135 @@
1/*
2 * tegra_das.h - Definitions for Tegra DAS driver
3 *
4 * Author: Stephen Warren <swarren@nvidia.com>
5 * Copyright (C) 2010 - NVIDIA, Inc.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * version 2 as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
19 * 02110-1301 USA
20 *
21 */
22
23#ifndef __TEGRA_DAS_H__
24#define __TEGRA_DAS_H__
25
26/* Register TEGRA_DAS_DAP_CTRL_SEL */
27#define TEGRA_DAS_DAP_CTRL_SEL 0x00
28#define TEGRA_DAS_DAP_CTRL_SEL_COUNT 5
29#define TEGRA_DAS_DAP_CTRL_SEL_STRIDE 4
30#define TEGRA_DAS_DAP_CTRL_SEL_DAP_MS_SEL_P 31
31#define TEGRA_DAS_DAP_CTRL_SEL_DAP_MS_SEL_S 1
32#define TEGRA_DAS_DAP_CTRL_SEL_DAP_SDATA1_TX_RX_P 30
33#define TEGRA_DAS_DAP_CTRL_SEL_DAP_SDATA1_TX_RX_S 1
34#define TEGRA_DAS_DAP_CTRL_SEL_DAP_SDATA2_TX_RX_P 29
35#define TEGRA_DAS_DAP_CTRL_SEL_DAP_SDATA2_TX_RX_S 1
36#define TEGRA_DAS_DAP_CTRL_SEL_DAP_CTRL_SEL_P 0
37#define TEGRA_DAS_DAP_CTRL_SEL_DAP_CTRL_SEL_S 5
38
39/* Values for field TEGRA_DAS_DAP_CTRL_SEL_DAP_CTRL_SEL */
40#define TEGRA_DAS_DAP_SEL_DAC1 0
41#define TEGRA_DAS_DAP_SEL_DAC2 1
42#define TEGRA_DAS_DAP_SEL_DAC3 2
43#define TEGRA_DAS_DAP_SEL_DAP1 16
44#define TEGRA_DAS_DAP_SEL_DAP2 17
45#define TEGRA_DAS_DAP_SEL_DAP3 18
46#define TEGRA_DAS_DAP_SEL_DAP4 19
47#define TEGRA_DAS_DAP_SEL_DAP5 20
48
49/* Register TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL */
50#define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL 0x40
51#define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_COUNT 3
52#define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_STRIDE 4
53#define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA2_SEL_P 28
54#define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA2_SEL_S 4
55#define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA1_SEL_P 24
56#define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA1_SEL_S 4
57#define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_CLK_SEL_P 0
58#define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_CLK_SEL_S 4
59
60/*
61 * Values for:
62 * TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA2_SEL
63 * TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA1_SEL
64 * TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_CLK_SEL
65 */
66#define TEGRA_DAS_DAC_SEL_DAP1 0
67#define TEGRA_DAS_DAC_SEL_DAP2 1
68#define TEGRA_DAS_DAC_SEL_DAP3 2
69#define TEGRA_DAS_DAC_SEL_DAP4 3
70#define TEGRA_DAS_DAC_SEL_DAP5 4
71
72/*
73 * Names/IDs of the DACs/DAPs.
74 */
75
76#define TEGRA_DAS_DAP_ID_1 0
77#define TEGRA_DAS_DAP_ID_2 1
78#define TEGRA_DAS_DAP_ID_3 2
79#define TEGRA_DAS_DAP_ID_4 3
80#define TEGRA_DAS_DAP_ID_5 4
81
82#define TEGRA_DAS_DAC_ID_1 0
83#define TEGRA_DAS_DAC_ID_2 1
84#define TEGRA_DAS_DAC_ID_3 2
85
86struct tegra_das {
87 struct device *dev;
88 void __iomem *regs;
89 struct dentry *debug;
90};
91
92/*
93 * Terminology:
94 * DAS: Digital audio switch (HW module controlled by this driver)
95 * DAP: Digital audio port (port/pins on Tegra device)
96 * DAC: Digital audio controller (e.g. I2S or AC97 controller elsewhere)
97 *
98 * The Tegra DAS is a mux/cross-bar which can connect each DAP to a specific
99 * DAC, or another DAP. When DAPs are connected, one must be the master and
100 * one the slave. Each DAC allows selection of a specific DAP for input, to
101 * cater for the case where N DAPs are connected to 1 DAC for broadcast
102 * output.
103 *
104 * This driver is dumb; no attempt is made to ensure that a valid routing
105 * configuration is programmed.
106 */
107
108/*
109 * Connect a DAP to to a DAC
110 * dap_id: DAP to connect: TEGRA_DAS_DAP_ID_*
111 * dac_sel: DAC to connect to: TEGRA_DAS_DAP_SEL_DAC*
112 */
113extern int tegra_das_connect_dap_to_dac(int dap_id, int dac_sel);
114
115/*
116 * Connect a DAP to to another DAP
117 * dap_id: DAP to connect: TEGRA_DAS_DAP_ID_*
118 * other_dap_sel: DAP to connect to: TEGRA_DAS_DAP_SEL_DAP*
119 * master: Is this DAP the master (1) or slave (0)
120 * sdata1rx: Is this DAP's SDATA1 pin RX (1) or TX (0)
121 * sdata2rx: Is this DAP's SDATA2 pin RX (1) or TX (0)
122 */
123extern int tegra_das_connect_dap_to_dap(int dap_id, int other_dap_sel,
124 int master, int sdata1rx,
125 int sdata2rx);
126
127/*
128 * Connect a DAC's input to a DAP
129 * (DAC outputs are selected by the DAP)
130 * dac_id: DAC ID to connect: TEGRA_DAS_DAC_ID_*
131 * dap_sel: DAP to receive input from: TEGRA_DAS_DAC_SEL_DAP*
132 */
133extern int tegra_das_connect_dac_to_dap(int dac_id, int dap_sel);
134
135#endif
diff --git a/sound/soc/tegra/tegra_i2s.c b/sound/soc/tegra/tegra_i2s.c
new file mode 100644
index 000000000000..6d668785e9af
--- /dev/null
+++ b/sound/soc/tegra/tegra_i2s.c
@@ -0,0 +1,502 @@
1/*
2 * tegra_i2s.c - Tegra I2S driver
3 *
4 * Author: Stephen Warren <swarren@nvidia.com>
5 * Copyright (C) 2010 - NVIDIA, Inc.
6 *
7 * Based on code copyright/by:
8 *
9 * Copyright (c) 2009-2010, NVIDIA Corporation.
10 * Scott Peterson <speterson@nvidia.com>
11 *
12 * Copyright (C) 2010 Google, Inc.
13 * Iliyan Malchev <malchev@google.com>
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * version 2 as published by the Free Software Foundation.
18 *
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * 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, write to the Free Software
26 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
27 * 02110-1301 USA
28 *
29 */
30
31#include <linux/clk.h>
32#include <linux/module.h>
33#include <linux/debugfs.h>
34#include <linux/device.h>
35#include <linux/platform_device.h>
36#include <linux/seq_file.h>
37#include <linux/slab.h>
38#include <linux/io.h>
39#include <mach/iomap.h>
40#include <sound/core.h>
41#include <sound/pcm.h>
42#include <sound/pcm_params.h>
43#include <sound/soc.h>
44
45#include "tegra_das.h"
46#include "tegra_i2s.h"
47
48#define DRV_NAME "tegra-i2s"
49
50static inline void tegra_i2s_write(struct tegra_i2s *i2s, u32 reg, u32 val)
51{
52 __raw_writel(val, i2s->regs + reg);
53}
54
55static inline u32 tegra_i2s_read(struct tegra_i2s *i2s, u32 reg)
56{
57 return __raw_readl(i2s->regs + reg);
58}
59
60#ifdef CONFIG_DEBUG_FS
61static int tegra_i2s_show(struct seq_file *s, void *unused)
62{
63#define REG(r) { r, #r }
64 static const struct {
65 int offset;
66 const char *name;
67 } regs[] = {
68 REG(TEGRA_I2S_CTRL),
69 REG(TEGRA_I2S_STATUS),
70 REG(TEGRA_I2S_TIMING),
71 REG(TEGRA_I2S_FIFO_SCR),
72 REG(TEGRA_I2S_PCM_CTRL),
73 REG(TEGRA_I2S_NW_CTRL),
74 REG(TEGRA_I2S_TDM_CTRL),
75 REG(TEGRA_I2S_TDM_TX_RX_CTRL),
76 };
77#undef REG
78
79 struct tegra_i2s *i2s = s->private;
80 int i;
81
82 for (i = 0; i < ARRAY_SIZE(regs); i++) {
83 u32 val = tegra_i2s_read(i2s, regs[i].offset);
84 seq_printf(s, "%s = %08x\n", regs[i].name, val);
85 }
86
87 return 0;
88}
89
90static int tegra_i2s_debug_open(struct inode *inode, struct file *file)
91{
92 return single_open(file, tegra_i2s_show, inode->i_private);
93}
94
95static const struct file_operations tegra_i2s_debug_fops = {
96 .open = tegra_i2s_debug_open,
97 .read = seq_read,
98 .llseek = seq_lseek,
99 .release = single_release,
100};
101
102static void tegra_i2s_debug_add(struct tegra_i2s *i2s, int id)
103{
104 char name[] = DRV_NAME ".0";
105
106 snprintf(name, sizeof(name), DRV_NAME".%1d", id);
107 i2s->debug = debugfs_create_file(name, S_IRUGO, snd_soc_debugfs_root,
108 i2s, &tegra_i2s_debug_fops);
109}
110
111static void tegra_i2s_debug_remove(struct tegra_i2s *i2s)
112{
113 if (i2s->debug)
114 debugfs_remove(i2s->debug);
115}
116#else
117static inline void tegra_i2s_debug_add(struct tegra_i2s *i2s)
118{
119}
120
121static inline void tegra_i2s_debug_remove(struct tegra_i2s *i2s)
122{
123}
124#endif
125
126static int tegra_i2s_set_fmt(struct snd_soc_dai *dai,
127 unsigned int fmt)
128{
129 struct tegra_i2s *i2s = snd_soc_dai_get_drvdata(dai);
130
131 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
132 case SND_SOC_DAIFMT_NB_NF:
133 break;
134 default:
135 return -EINVAL;
136 }
137
138 i2s->reg_ctrl &= ~TEGRA_I2S_CTRL_MASTER_ENABLE;
139 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
140 case SND_SOC_DAIFMT_CBS_CFS:
141 i2s->reg_ctrl |= TEGRA_I2S_CTRL_MASTER_ENABLE;
142 break;
143 case SND_SOC_DAIFMT_CBM_CFM:
144 break;
145 default:
146 return -EINVAL;
147 }
148
149 i2s->reg_ctrl &= ~(TEGRA_I2S_CTRL_BIT_FORMAT_MASK |
150 TEGRA_I2S_CTRL_LRCK_MASK);
151 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
152 case SND_SOC_DAIFMT_DSP_A:
153 i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_FORMAT_DSP;
154 i2s->reg_ctrl |= TEGRA_I2S_CTRL_LRCK_L_LOW;
155 break;
156 case SND_SOC_DAIFMT_DSP_B:
157 i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_FORMAT_DSP;
158 i2s->reg_ctrl |= TEGRA_I2S_CTRL_LRCK_R_LOW;
159 break;
160 case SND_SOC_DAIFMT_I2S:
161 i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_FORMAT_I2S;
162 i2s->reg_ctrl |= TEGRA_I2S_CTRL_LRCK_L_LOW;
163 break;
164 case SND_SOC_DAIFMT_RIGHT_J:
165 i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_FORMAT_RJM;
166 i2s->reg_ctrl |= TEGRA_I2S_CTRL_LRCK_L_LOW;
167 break;
168 case SND_SOC_DAIFMT_LEFT_J:
169 i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_FORMAT_LJM;
170 i2s->reg_ctrl |= TEGRA_I2S_CTRL_LRCK_L_LOW;
171 break;
172 default:
173 return -EINVAL;
174 }
175
176 return 0;
177}
178
179static int tegra_i2s_hw_params(struct snd_pcm_substream *substream,
180 struct snd_pcm_hw_params *params,
181 struct snd_soc_dai *dai)
182{
183 struct device *dev = substream->pcm->card->dev;
184 struct tegra_i2s *i2s = snd_soc_dai_get_drvdata(dai);
185 u32 reg;
186 int ret, sample_size, srate, i2sclock, bitcnt;
187
188 i2s->reg_ctrl &= ~TEGRA_I2S_CTRL_BIT_SIZE_MASK;
189 switch (params_format(params)) {
190 case SNDRV_PCM_FORMAT_S16_LE:
191 i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_SIZE_16;
192 sample_size = 16;
193 break;
194 case SNDRV_PCM_FORMAT_S24_LE:
195 i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_SIZE_24;
196 sample_size = 24;
197 break;
198 case SNDRV_PCM_FORMAT_S32_LE:
199 i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_SIZE_32;
200 sample_size = 32;
201 break;
202 default:
203 return -EINVAL;
204 }
205
206 srate = params_rate(params);
207
208 /* Final "* 2" required by Tegra hardware */
209 i2sclock = srate * params_channels(params) * sample_size * 2;
210
211 ret = clk_set_rate(i2s->clk_i2s, i2sclock);
212 if (ret) {
213 dev_err(dev, "Can't set I2S clock rate: %d\n", ret);
214 return ret;
215 }
216
217 bitcnt = (i2sclock / (2 * srate)) - 1;
218 if (bitcnt < 0 || bitcnt > TEGRA_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US)
219 return -EINVAL;
220 reg = bitcnt << TEGRA_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT;
221
222 if (i2sclock % (2 * srate))
223 reg |= TEGRA_I2S_TIMING_NON_SYM_ENABLE;
224
225 tegra_i2s_write(i2s, TEGRA_I2S_TIMING, reg);
226
227 tegra_i2s_write(i2s, TEGRA_I2S_FIFO_SCR,
228 TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_FOUR_SLOTS |
229 TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_FOUR_SLOTS);
230
231 return 0;
232}
233
234static void tegra_i2s_start_playback(struct tegra_i2s *i2s)
235{
236 i2s->reg_ctrl |= TEGRA_I2S_CTRL_FIFO1_ENABLE;
237 tegra_i2s_write(i2s, TEGRA_I2S_CTRL, i2s->reg_ctrl);
238}
239
240static void tegra_i2s_stop_playback(struct tegra_i2s *i2s)
241{
242 i2s->reg_ctrl &= ~TEGRA_I2S_CTRL_FIFO1_ENABLE;
243 tegra_i2s_write(i2s, TEGRA_I2S_CTRL, i2s->reg_ctrl);
244}
245
246static void tegra_i2s_start_capture(struct tegra_i2s *i2s)
247{
248 i2s->reg_ctrl |= TEGRA_I2S_CTRL_FIFO2_ENABLE;
249 tegra_i2s_write(i2s, TEGRA_I2S_CTRL, i2s->reg_ctrl);
250}
251
252static void tegra_i2s_stop_capture(struct tegra_i2s *i2s)
253{
254 i2s->reg_ctrl &= ~TEGRA_I2S_CTRL_FIFO2_ENABLE;
255 tegra_i2s_write(i2s, TEGRA_I2S_CTRL, i2s->reg_ctrl);
256}
257
258static int tegra_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
259 struct snd_soc_dai *dai)
260{
261 struct tegra_i2s *i2s = snd_soc_dai_get_drvdata(dai);
262
263 switch (cmd) {
264 case SNDRV_PCM_TRIGGER_START:
265 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
266 case SNDRV_PCM_TRIGGER_RESUME:
267 if (!i2s->clk_refs)
268 clk_enable(i2s->clk_i2s);
269 i2s->clk_refs++;
270 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
271 tegra_i2s_start_playback(i2s);
272 else
273 tegra_i2s_start_capture(i2s);
274 break;
275 case SNDRV_PCM_TRIGGER_STOP:
276 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
277 case SNDRV_PCM_TRIGGER_SUSPEND:
278 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
279 tegra_i2s_stop_playback(i2s);
280 else
281 tegra_i2s_stop_capture(i2s);
282 i2s->clk_refs--;
283 if (!i2s->clk_refs)
284 clk_disable(i2s->clk_i2s);
285 break;
286 default:
287 return -EINVAL;
288 }
289
290 return 0;
291}
292
293static int tegra_i2s_probe(struct snd_soc_dai *dai)
294{
295 struct tegra_i2s * i2s = snd_soc_dai_get_drvdata(dai);
296
297 dai->capture_dma_data = &i2s->capture_dma_data;
298 dai->playback_dma_data = &i2s->playback_dma_data;
299
300 return 0;
301}
302
303static struct snd_soc_dai_ops tegra_i2s_dai_ops = {
304 .set_fmt = tegra_i2s_set_fmt,
305 .hw_params = tegra_i2s_hw_params,
306 .trigger = tegra_i2s_trigger,
307};
308
309struct snd_soc_dai_driver tegra_i2s_dai[] = {
310 {
311 .name = DRV_NAME ".0",
312 .probe = tegra_i2s_probe,
313 .playback = {
314 .channels_min = 2,
315 .channels_max = 2,
316 .rates = SNDRV_PCM_RATE_8000_96000,
317 .formats = SNDRV_PCM_FMTBIT_S16_LE,
318 },
319 .capture = {
320 .channels_min = 2,
321 .channels_max = 2,
322 .rates = SNDRV_PCM_RATE_8000_96000,
323 .formats = SNDRV_PCM_FMTBIT_S16_LE,
324 },
325 .ops = &tegra_i2s_dai_ops,
326 .symmetric_rates = 1,
327 },
328 {
329 .name = DRV_NAME ".1",
330 .probe = tegra_i2s_probe,
331 .playback = {
332 .channels_min = 2,
333 .channels_max = 2,
334 .rates = SNDRV_PCM_RATE_8000_96000,
335 .formats = SNDRV_PCM_FMTBIT_S16_LE,
336 },
337 .capture = {
338 .channels_min = 2,
339 .channels_max = 2,
340 .rates = SNDRV_PCM_RATE_8000_96000,
341 .formats = SNDRV_PCM_FMTBIT_S16_LE,
342 },
343 .ops = &tegra_i2s_dai_ops,
344 .symmetric_rates = 1,
345 },
346};
347
348static __devinit int tegra_i2s_platform_probe(struct platform_device *pdev)
349{
350 struct tegra_i2s * i2s;
351 char clk_name[12]; /* tegra-i2s.0 */
352 struct resource *mem, *memregion, *dmareq;
353 int ret;
354
355 if ((pdev->id < 0) ||
356 (pdev->id >= ARRAY_SIZE(tegra_i2s_dai))) {
357 dev_err(&pdev->dev, "ID %d out of range\n", pdev->id);
358 return -EINVAL;
359 }
360
361 /*
362 * FIXME: Until a codec driver exists for the tegra DAS, hard-code a
363 * 1:1 mapping between audio controllers and audio ports.
364 */
365 ret = tegra_das_connect_dap_to_dac(TEGRA_DAS_DAP_ID_1 + pdev->id,
366 TEGRA_DAS_DAP_SEL_DAC1 + pdev->id);
367 if (ret) {
368 dev_err(&pdev->dev, "Can't set up DAP connection\n");
369 return ret;
370 }
371 ret = tegra_das_connect_dac_to_dap(TEGRA_DAS_DAC_ID_1 + pdev->id,
372 TEGRA_DAS_DAC_SEL_DAP1 + pdev->id);
373 if (ret) {
374 dev_err(&pdev->dev, "Can't set up DAC connection\n");
375 return ret;
376 }
377
378 i2s = kzalloc(sizeof(struct tegra_i2s), GFP_KERNEL);
379 if (!i2s) {
380 dev_err(&pdev->dev, "Can't allocate tegra_i2s\n");
381 ret = -ENOMEM;
382 goto exit;
383 }
384 dev_set_drvdata(&pdev->dev, i2s);
385
386 snprintf(clk_name, sizeof(clk_name), DRV_NAME ".%d", pdev->id);
387 i2s->clk_i2s = clk_get_sys(clk_name, NULL);
388 if (IS_ERR(i2s->clk_i2s)) {
389 pr_err("Can't retrieve i2s clock\n");
390 ret = PTR_ERR(i2s->clk_i2s);
391 goto err_free;
392 }
393
394 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
395 if (!mem) {
396 dev_err(&pdev->dev, "No memory resource\n");
397 ret = -ENODEV;
398 goto err_clk_put;
399 }
400
401 dmareq = platform_get_resource(pdev, IORESOURCE_DMA, 0);
402 if (!dmareq) {
403 dev_err(&pdev->dev, "No DMA resource\n");
404 ret = -ENODEV;
405 goto err_clk_put;
406 }
407
408 memregion = request_mem_region(mem->start, resource_size(mem),
409 DRV_NAME);
410 if (!memregion) {
411 dev_err(&pdev->dev, "Memory region already claimed\n");
412 ret = -EBUSY;
413 goto err_clk_put;
414 }
415
416 i2s->regs = ioremap(mem->start, resource_size(mem));
417 if (!i2s->regs) {
418 dev_err(&pdev->dev, "ioremap failed\n");
419 ret = -ENOMEM;
420 goto err_release;
421 }
422
423 i2s->capture_dma_data.addr = mem->start + TEGRA_I2S_FIFO2;
424 i2s->capture_dma_data.wrap = 4;
425 i2s->capture_dma_data.width = 32;
426 i2s->capture_dma_data.req_sel = dmareq->start;
427
428 i2s->playback_dma_data.addr = mem->start + TEGRA_I2S_FIFO1;
429 i2s->playback_dma_data.wrap = 4;
430 i2s->playback_dma_data.width = 32;
431 i2s->playback_dma_data.req_sel = dmareq->start;
432
433 i2s->reg_ctrl = TEGRA_I2S_CTRL_FIFO_FORMAT_PACKED;
434
435 ret = snd_soc_register_dai(&pdev->dev, &tegra_i2s_dai[pdev->id]);
436 if (ret) {
437 dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
438 ret = -ENOMEM;
439 goto err_unmap;
440 }
441
442 tegra_i2s_debug_add(i2s, pdev->id);
443
444 return 0;
445
446err_unmap:
447 iounmap(i2s->regs);
448err_release:
449 release_mem_region(mem->start, resource_size(mem));
450err_clk_put:
451 clk_put(i2s->clk_i2s);
452err_free:
453 kfree(i2s);
454exit:
455 return ret;
456}
457
458static int __devexit tegra_i2s_platform_remove(struct platform_device *pdev)
459{
460 struct tegra_i2s *i2s = dev_get_drvdata(&pdev->dev);
461 struct resource *res;
462
463 snd_soc_unregister_dai(&pdev->dev);
464
465 tegra_i2s_debug_remove(i2s);
466
467 iounmap(i2s->regs);
468
469 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
470 release_mem_region(res->start, resource_size(res));
471
472 clk_put(i2s->clk_i2s);
473
474 kfree(i2s);
475
476 return 0;
477}
478
479static struct platform_driver tegra_i2s_driver = {
480 .driver = {
481 .name = DRV_NAME,
482 .owner = THIS_MODULE,
483 },
484 .probe = tegra_i2s_platform_probe,
485 .remove = __devexit_p(tegra_i2s_platform_remove),
486};
487
488static int __init snd_tegra_i2s_init(void)
489{
490 return platform_driver_register(&tegra_i2s_driver);
491}
492module_init(snd_tegra_i2s_init);
493
494static void __exit snd_tegra_i2s_exit(void)
495{
496 platform_driver_unregister(&tegra_i2s_driver);
497}
498module_exit(snd_tegra_i2s_exit);
499
500MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
501MODULE_DESCRIPTION("Tegra I2S ASoC driver");
502MODULE_LICENSE("GPL");
diff --git a/sound/soc/tegra/tegra_i2s.h b/sound/soc/tegra/tegra_i2s.h
new file mode 100644
index 000000000000..2b38a096f46c
--- /dev/null
+++ b/sound/soc/tegra/tegra_i2s.h
@@ -0,0 +1,165 @@
1/*
2 * tegra_i2s.h - Definitions for Tegra I2S driver
3 *
4 * Author: Stephen Warren <swarren@nvidia.com>
5 * Copyright (C) 2010 - NVIDIA, Inc.
6 *
7 * Based on code copyright/by:
8 *
9 * Copyright (c) 2009-2010, NVIDIA Corporation.
10 * Scott Peterson <speterson@nvidia.com>
11 *
12 * Copyright (C) 2010 Google, Inc.
13 * Iliyan Malchev <malchev@google.com>
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * version 2 as published by the Free Software Foundation.
18 *
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * 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, write to the Free Software
26 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
27 * 02110-1301 USA
28 *
29 */
30
31#ifndef __TEGRA_I2S_H__
32#define __TEGRA_I2S_H__
33
34#include "tegra_pcm.h"
35
36/* Register offsets from TEGRA_I2S1_BASE and TEGRA_I2S2_BASE */
37
38#define TEGRA_I2S_CTRL 0x00
39#define TEGRA_I2S_STATUS 0x04
40#define TEGRA_I2S_TIMING 0x08
41#define TEGRA_I2S_FIFO_SCR 0x0c
42#define TEGRA_I2S_PCM_CTRL 0x10
43#define TEGRA_I2S_NW_CTRL 0x14
44#define TEGRA_I2S_TDM_CTRL 0x20
45#define TEGRA_I2S_TDM_TX_RX_CTRL 0x24
46#define TEGRA_I2S_FIFO1 0x40
47#define TEGRA_I2S_FIFO2 0x80
48
49/* Fields in TEGRA_I2S_CTRL */
50
51#define TEGRA_I2S_CTRL_FIFO2_TX_ENABLE (1 << 30)
52#define TEGRA_I2S_CTRL_FIFO1_ENABLE (1 << 29)
53#define TEGRA_I2S_CTRL_FIFO2_ENABLE (1 << 28)
54#define TEGRA_I2S_CTRL_FIFO1_RX_ENABLE (1 << 27)
55#define TEGRA_I2S_CTRL_FIFO_LPBK_ENABLE (1 << 26)
56#define TEGRA_I2S_CTRL_MASTER_ENABLE (1 << 25)
57
58#define TEGRA_I2S_LRCK_LEFT_LOW 0
59#define TEGRA_I2S_LRCK_RIGHT_LOW 1
60
61#define TEGRA_I2S_CTRL_LRCK_SHIFT 24
62#define TEGRA_I2S_CTRL_LRCK_MASK (1 << TEGRA_I2S_CTRL_LRCK_SHIFT)
63#define TEGRA_I2S_CTRL_LRCK_L_LOW (TEGRA_I2S_LRCK_LEFT_LOW << TEGRA_I2S_CTRL_LRCK_SHIFT)
64#define TEGRA_I2S_CTRL_LRCK_R_LOW (TEGRA_I2S_LRCK_RIGHT_LOW << TEGRA_I2S_CTRL_LRCK_SHIFT)
65
66#define TEGRA_I2S_BIT_FORMAT_I2S 0
67#define TEGRA_I2S_BIT_FORMAT_RJM 1
68#define TEGRA_I2S_BIT_FORMAT_LJM 2
69#define TEGRA_I2S_BIT_FORMAT_DSP 3
70
71#define TEGRA_I2S_CTRL_BIT_FORMAT_SHIFT 10
72#define TEGRA_I2S_CTRL_BIT_FORMAT_MASK (3 << TEGRA_I2S_CTRL_BIT_FORMAT_SHIFT)
73#define TEGRA_I2S_CTRL_BIT_FORMAT_I2S (TEGRA_I2S_BIT_FORMAT_I2S << TEGRA_I2S_CTRL_BIT_FORMAT_SHIFT)
74#define TEGRA_I2S_CTRL_BIT_FORMAT_RJM (TEGRA_I2S_BIT_FORMAT_RJM << TEGRA_I2S_CTRL_BIT_FORMAT_SHIFT)
75#define TEGRA_I2S_CTRL_BIT_FORMAT_LJM (TEGRA_I2S_BIT_FORMAT_LJM << TEGRA_I2S_CTRL_BIT_FORMAT_SHIFT)
76#define TEGRA_I2S_CTRL_BIT_FORMAT_DSP (TEGRA_I2S_BIT_FORMAT_DSP << TEGRA_I2S_CTRL_BIT_FORMAT_SHIFT)
77
78#define TEGRA_I2S_BIT_SIZE_16 0
79#define TEGRA_I2S_BIT_SIZE_20 1
80#define TEGRA_I2S_BIT_SIZE_24 2
81#define TEGRA_I2S_BIT_SIZE_32 3
82
83#define TEGRA_I2S_CTRL_BIT_SIZE_SHIFT 8
84#define TEGRA_I2S_CTRL_BIT_SIZE_MASK (3 << TEGRA_I2S_CTRL_BIT_SIZE_SHIFT)
85#define TEGRA_I2S_CTRL_BIT_SIZE_16 (TEGRA_I2S_BIT_SIZE_16 << TEGRA_I2S_CTRL_BIT_SIZE_SHIFT)
86#define TEGRA_I2S_CTRL_BIT_SIZE_20 (TEGRA_I2S_BIT_SIZE_20 << TEGRA_I2S_CTRL_BIT_SIZE_SHIFT)
87#define TEGRA_I2S_CTRL_BIT_SIZE_24 (TEGRA_I2S_BIT_SIZE_24 << TEGRA_I2S_CTRL_BIT_SIZE_SHIFT)
88#define TEGRA_I2S_CTRL_BIT_SIZE_32 (TEGRA_I2S_BIT_SIZE_32 << TEGRA_I2S_CTRL_BIT_SIZE_SHIFT)
89
90#define TEGRA_I2S_FIFO_16_LSB 0
91#define TEGRA_I2S_FIFO_20_LSB 1
92#define TEGRA_I2S_FIFO_24_LSB 2
93#define TEGRA_I2S_FIFO_32 3
94#define TEGRA_I2S_FIFO_PACKED 7
95
96#define TEGRA_I2S_CTRL_FIFO_FORMAT_SHIFT 4
97#define TEGRA_I2S_CTRL_FIFO_FORMAT_MASK (7 << TEGRA_I2S_CTRL_FIFO_FORMAT_SHIFT)
98#define TEGRA_I2S_CTRL_FIFO_FORMAT_16_LSB (TEGRA_I2S_FIFO_16_LSB << TEGRA_I2S_CTRL_FIFO_FORMAT_SHIFT)
99#define TEGRA_I2S_CTRL_FIFO_FORMAT_20_LSB (TEGRA_I2S_FIFO_20_LSB << TEGRA_I2S_CTRL_FIFO_FORMAT_SHIFT)
100#define TEGRA_I2S_CTRL_FIFO_FORMAT_24_LSB (TEGRA_I2S_FIFO_24_LSB << TEGRA_I2S_CTRL_FIFO_FORMAT_SHIFT)
101#define TEGRA_I2S_CTRL_FIFO_FORMAT_32 (TEGRA_I2S_FIFO_32 << TEGRA_I2S_CTRL_FIFO_FORMAT_SHIFT)
102#define TEGRA_I2S_CTRL_FIFO_FORMAT_PACKED (TEGRA_I2S_FIFO_PACKED << TEGRA_I2S_CTRL_FIFO_FORMAT_SHIFT)
103
104#define TEGRA_I2S_CTRL_IE_FIFO1_ERR (1 << 3)
105#define TEGRA_I2S_CTRL_IE_FIFO2_ERR (1 << 2)
106#define TEGRA_I2S_CTRL_QE_FIFO1 (1 << 1)
107#define TEGRA_I2S_CTRL_QE_FIFO2 (1 << 0)
108
109/* Fields in TEGRA_I2S_STATUS */
110
111#define TEGRA_I2S_STATUS_FIFO1_RDY (1 << 31)
112#define TEGRA_I2S_STATUS_FIFO2_RDY (1 << 30)
113#define TEGRA_I2S_STATUS_FIFO1_BSY (1 << 29)
114#define TEGRA_I2S_STATUS_FIFO2_BSY (1 << 28)
115#define TEGRA_I2S_STATUS_FIFO1_ERR (1 << 3)
116#define TEGRA_I2S_STATUS_FIFO2_ERR (1 << 2)
117#define TEGRA_I2S_STATUS_QS_FIFO1 (1 << 1)
118#define TEGRA_I2S_STATUS_QS_FIFO2 (1 << 0)
119
120/* Fields in TEGRA_I2S_TIMING */
121
122#define TEGRA_I2S_TIMING_NON_SYM_ENABLE (1 << 12)
123#define TEGRA_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT 0
124#define TEGRA_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US 0x7fff
125#define TEGRA_I2S_TIMING_CHANNEL_BIT_COUNT_MASK (TEGRA_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US << TEGRA_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT)
126
127/* Fields in TEGRA_I2S_FIFO_SCR */
128
129#define TEGRA_I2S_FIFO_SCR_FIFO2_FULL_EMPTY_COUNT_SHIFT 24
130#define TEGRA_I2S_FIFO_SCR_FIFO1_FULL_EMPTY_COUNT_SHIFT 16
131#define TEGRA_I2S_FIFO_SCR_FIFO_FULL_EMPTY_COUNT_MASK 0x3f
132
133#define TEGRA_I2S_FIFO_SCR_FIFO2_CLR (1 << 12)
134#define TEGRA_I2S_FIFO_SCR_FIFO1_CLR (1 << 8)
135
136#define TEGRA_I2S_FIFO_ATN_LVL_ONE_SLOT 0
137#define TEGRA_I2S_FIFO_ATN_LVL_FOUR_SLOTS 1
138#define TEGRA_I2S_FIFO_ATN_LVL_EIGHT_SLOTS 2
139#define TEGRA_I2S_FIFO_ATN_LVL_TWELVE_SLOTS 3
140
141#define TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_SHIFT 4
142#define TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_MASK (3 << TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_SHIFT)
143#define TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_ONE_SLOT (TEGRA_I2S_FIFO_ATN_LVL_ONE_SLOT << TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_SHIFT)
144#define TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_FOUR_SLOTS (TEGRA_I2S_FIFO_ATN_LVL_FOUR_SLOTS << TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_SHIFT)
145#define TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_EIGHT_SLOTS (TEGRA_I2S_FIFO_ATN_LVL_EIGHT_SLOTS << TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_SHIFT)
146#define TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_TWELVE_SLOTS (TEGRA_I2S_FIFO_ATN_LVL_TWELVE_SLOTS << TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_SHIFT)
147
148#define TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT 0
149#define TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_MASK (3 << TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT)
150#define TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_ONE_SLOT (TEGRA_I2S_FIFO_ATN_LVL_ONE_SLOT << TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT)
151#define TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_FOUR_SLOTS (TEGRA_I2S_FIFO_ATN_LVL_FOUR_SLOTS << TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT)
152#define TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_EIGHT_SLOTS (TEGRA_I2S_FIFO_ATN_LVL_EIGHT_SLOTS << TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT)
153#define TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_TWELVE_SLOTS (TEGRA_I2S_FIFO_ATN_LVL_TWELVE_SLOTS << TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT)
154
155struct tegra_i2s {
156 struct clk *clk_i2s;
157 int clk_refs;
158 struct tegra_pcm_dma_params capture_dma_data;
159 struct tegra_pcm_dma_params playback_dma_data;
160 void __iomem *regs;
161 struct dentry *debug;
162 u32 reg_ctrl;
163};
164
165#endif
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c
new file mode 100644
index 000000000000..663ea9fa0ca3
--- /dev/null
+++ b/sound/soc/tegra/tegra_pcm.c
@@ -0,0 +1,401 @@
1/*
2 * tegra_pcm.c - Tegra PCM driver
3 *
4 * Author: Stephen Warren <swarren@nvidia.com>
5 * Copyright (C) 2010 - NVIDIA, Inc.
6 *
7 * Based on code copyright/by:
8 *
9 * Copyright (c) 2009-2010, NVIDIA Corporation.
10 * Scott Peterson <speterson@nvidia.com>
11 * Vijay Mali <vmali@nvidia.com>
12 *
13 * Copyright (C) 2010 Google, Inc.
14 * Iliyan Malchev <malchev@google.com>
15 *
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * version 2 as published by the Free Software Foundation.
19 *
20 * This program is distributed in the hope that it will be useful, but
21 * WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 * 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, write to the Free Software
27 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
28 * 02110-1301 USA
29 *
30 */
31
32#include <linux/module.h>
33#include <linux/dma-mapping.h>
34#include <linux/slab.h>
35#include <sound/core.h>
36#include <sound/pcm.h>
37#include <sound/pcm_params.h>
38#include <sound/soc.h>
39
40#include "tegra_pcm.h"
41
42static const struct snd_pcm_hardware tegra_pcm_hardware = {
43 .info = SNDRV_PCM_INFO_MMAP |
44 SNDRV_PCM_INFO_MMAP_VALID |
45 SNDRV_PCM_INFO_PAUSE |
46 SNDRV_PCM_INFO_RESUME |
47 SNDRV_PCM_INFO_INTERLEAVED,
48 .formats = SNDRV_PCM_FMTBIT_S16_LE,
49 .channels_min = 2,
50 .channels_max = 2,
51 .period_bytes_min = 1024,
52 .period_bytes_max = PAGE_SIZE,
53 .periods_min = 2,
54 .periods_max = 8,
55 .buffer_bytes_max = PAGE_SIZE * 8,
56 .fifo_size = 4,
57};
58
59static void tegra_pcm_queue_dma(struct tegra_runtime_data *prtd)
60{
61 struct snd_pcm_substream *substream = prtd->substream;
62 struct snd_dma_buffer *buf = &substream->dma_buffer;
63 struct tegra_dma_req *dma_req;
64 unsigned long addr;
65
66 dma_req = &prtd->dma_req[prtd->dma_req_idx];
67 prtd->dma_req_idx = 1 - prtd->dma_req_idx;
68
69 addr = buf->addr + prtd->dma_pos;
70 prtd->dma_pos += dma_req->size;
71 if (prtd->dma_pos >= prtd->dma_pos_end)
72 prtd->dma_pos = 0;
73
74 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
75 dma_req->source_addr = addr;
76 else
77 dma_req->dest_addr = addr;
78
79 tegra_dma_enqueue_req(prtd->dma_chan, dma_req);
80}
81
82static void dma_complete_callback(struct tegra_dma_req *req)
83{
84 struct tegra_runtime_data *prtd = (struct tegra_runtime_data *)req->dev;
85 struct snd_pcm_substream *substream = prtd->substream;
86 struct snd_pcm_runtime *runtime = substream->runtime;
87
88 spin_lock(&prtd->lock);
89
90 if (!prtd->running) {
91 spin_unlock(&prtd->lock);
92 return;
93 }
94
95 if (++prtd->period_index >= runtime->periods)
96 prtd->period_index = 0;
97
98 tegra_pcm_queue_dma(prtd);
99
100 spin_unlock(&prtd->lock);
101
102 snd_pcm_period_elapsed(substream);
103}
104
105static void setup_dma_tx_request(struct tegra_dma_req *req,
106 struct tegra_pcm_dma_params * dmap)
107{
108 req->complete = dma_complete_callback;
109 req->to_memory = false;
110 req->dest_addr = dmap->addr;
111 req->dest_wrap = dmap->wrap;
112 req->source_bus_width = 32;
113 req->source_wrap = 0;
114 req->dest_bus_width = dmap->width;
115 req->req_sel = dmap->req_sel;
116}
117
118static void setup_dma_rx_request(struct tegra_dma_req *req,
119 struct tegra_pcm_dma_params * dmap)
120{
121 req->complete = dma_complete_callback;
122 req->to_memory = true;
123 req->source_addr = dmap->addr;
124 req->dest_wrap = 0;
125 req->source_bus_width = dmap->width;
126 req->source_wrap = dmap->wrap;
127 req->dest_bus_width = 32;
128 req->req_sel = dmap->req_sel;
129}
130
131static int tegra_pcm_open(struct snd_pcm_substream *substream)
132{
133 struct snd_pcm_runtime *runtime = substream->runtime;
134 struct tegra_runtime_data *prtd;
135 struct snd_soc_pcm_runtime *rtd = substream->private_data;
136 struct tegra_pcm_dma_params * dmap;
137 int ret = 0;
138
139 prtd = kzalloc(sizeof(struct tegra_runtime_data), GFP_KERNEL);
140 if (prtd == NULL)
141 return -ENOMEM;
142
143 runtime->private_data = prtd;
144 prtd->substream = substream;
145
146 spin_lock_init(&prtd->lock);
147
148 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
149 dmap = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
150 setup_dma_tx_request(&prtd->dma_req[0], dmap);
151 setup_dma_tx_request(&prtd->dma_req[1], dmap);
152 } else {
153 dmap = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
154 setup_dma_rx_request(&prtd->dma_req[0], dmap);
155 setup_dma_rx_request(&prtd->dma_req[1], dmap);
156 }
157
158 prtd->dma_req[0].dev = prtd;
159 prtd->dma_req[1].dev = prtd;
160
161 prtd->dma_chan = tegra_dma_allocate_channel(TEGRA_DMA_MODE_ONESHOT);
162 if (IS_ERR(prtd->dma_chan)) {
163 ret = PTR_ERR(prtd->dma_chan);
164 goto err;
165 }
166
167 /* Set HW params now that initialization is complete */
168 snd_soc_set_runtime_hwparams(substream, &tegra_pcm_hardware);
169
170 /* Ensure that buffer size is a multiple of period size */
171 ret = snd_pcm_hw_constraint_integer(runtime,
172 SNDRV_PCM_HW_PARAM_PERIODS);
173 if (ret < 0)
174 goto err;
175
176 return 0;
177
178err:
179 if (prtd->dma_chan) {
180 tegra_dma_free_channel(prtd->dma_chan);
181 }
182
183 kfree(prtd);
184
185 return ret;
186}
187
188static int tegra_pcm_close(struct snd_pcm_substream *substream)
189{
190 struct snd_pcm_runtime *runtime = substream->runtime;
191 struct tegra_runtime_data *prtd = runtime->private_data;
192
193 tegra_dma_free_channel(prtd->dma_chan);
194
195 kfree(prtd);
196
197 return 0;
198}
199
200static int tegra_pcm_hw_params(struct snd_pcm_substream *substream,
201 struct snd_pcm_hw_params *params)
202{
203 struct snd_pcm_runtime *runtime = substream->runtime;
204 struct tegra_runtime_data *prtd = runtime->private_data;
205
206 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
207
208 prtd->dma_req[0].size = params_period_bytes(params);
209 prtd->dma_req[1].size = prtd->dma_req[0].size;
210
211 return 0;
212}
213
214static int tegra_pcm_hw_free(struct snd_pcm_substream *substream)
215{
216 snd_pcm_set_runtime_buffer(substream, NULL);
217
218 return 0;
219}
220
221static int tegra_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
222{
223 struct snd_pcm_runtime *runtime = substream->runtime;
224 struct tegra_runtime_data *prtd = runtime->private_data;
225 unsigned long flags;
226
227 switch (cmd) {
228 case SNDRV_PCM_TRIGGER_START:
229 prtd->dma_pos = 0;
230 prtd->dma_pos_end = frames_to_bytes(runtime, runtime->periods * runtime->period_size);
231 prtd->period_index = 0;
232 prtd->dma_req_idx = 0;
233 /* Fall-through */
234 case SNDRV_PCM_TRIGGER_RESUME:
235 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
236 spin_lock_irqsave(&prtd->lock, flags);
237 prtd->running = 1;
238 spin_unlock_irqrestore(&prtd->lock, flags);
239 tegra_pcm_queue_dma(prtd);
240 tegra_pcm_queue_dma(prtd);
241 break;
242 case SNDRV_PCM_TRIGGER_STOP:
243 case SNDRV_PCM_TRIGGER_SUSPEND:
244 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
245 spin_lock_irqsave(&prtd->lock, flags);
246 prtd->running = 0;
247 spin_unlock_irqrestore(&prtd->lock, flags);
248 tegra_dma_dequeue_req(prtd->dma_chan, &prtd->dma_req[0]);
249 tegra_dma_dequeue_req(prtd->dma_chan, &prtd->dma_req[1]);
250 break;
251 default:
252 return -EINVAL;
253 }
254
255 return 0;
256}
257
258static snd_pcm_uframes_t tegra_pcm_pointer(struct snd_pcm_substream *substream)
259{
260 struct snd_pcm_runtime *runtime = substream->runtime;
261 struct tegra_runtime_data *prtd = runtime->private_data;
262
263 return prtd->period_index * runtime->period_size;
264}
265
266
267static int tegra_pcm_mmap(struct snd_pcm_substream *substream,
268 struct vm_area_struct *vma)
269{
270 struct snd_pcm_runtime *runtime = substream->runtime;
271
272 return dma_mmap_writecombine(substream->pcm->card->dev, vma,
273 runtime->dma_area,
274 runtime->dma_addr,
275 runtime->dma_bytes);
276}
277
278static struct snd_pcm_ops tegra_pcm_ops = {
279 .open = tegra_pcm_open,
280 .close = tegra_pcm_close,
281 .ioctl = snd_pcm_lib_ioctl,
282 .hw_params = tegra_pcm_hw_params,
283 .hw_free = tegra_pcm_hw_free,
284 .trigger = tegra_pcm_trigger,
285 .pointer = tegra_pcm_pointer,
286 .mmap = tegra_pcm_mmap,
287};
288
289static int tegra_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
290{
291 struct snd_pcm_substream *substream = pcm->streams[stream].substream;
292 struct snd_dma_buffer *buf = &substream->dma_buffer;
293 size_t size = tegra_pcm_hardware.buffer_bytes_max;
294
295 buf->area = dma_alloc_writecombine(pcm->card->dev, size,
296 &buf->addr, GFP_KERNEL);
297 if (!buf->area)
298 return -ENOMEM;
299
300 buf->dev.type = SNDRV_DMA_TYPE_DEV;
301 buf->dev.dev = pcm->card->dev;
302 buf->private_data = NULL;
303 buf->bytes = size;
304
305 return 0;
306}
307
308static void tegra_pcm_deallocate_dma_buffer(struct snd_pcm *pcm, int stream)
309{
310 struct snd_pcm_substream *substream = pcm->streams[stream].substream;
311 struct snd_dma_buffer *buf = &substream->dma_buffer;
312
313 if (!buf->area)
314 return;
315
316 dma_free_writecombine(pcm->card->dev, buf->bytes,
317 buf->area, buf->addr);
318 buf->area = NULL;
319}
320
321static u64 tegra_dma_mask = DMA_BIT_MASK(32);
322
323static int tegra_pcm_new(struct snd_card *card,
324 struct snd_soc_dai *dai, struct snd_pcm *pcm)
325{
326 int ret = 0;
327
328 if (!card->dev->dma_mask)
329 card->dev->dma_mask = &tegra_dma_mask;
330 if (!card->dev->coherent_dma_mask)
331 card->dev->coherent_dma_mask = 0xffffffff;
332
333 if (dai->driver->playback.channels_min) {
334 ret = tegra_pcm_preallocate_dma_buffer(pcm,
335 SNDRV_PCM_STREAM_PLAYBACK);
336 if (ret)
337 goto err;
338 }
339
340 if (dai->driver->capture.channels_min) {
341 ret = tegra_pcm_preallocate_dma_buffer(pcm,
342 SNDRV_PCM_STREAM_CAPTURE);
343 if (ret)
344 goto err_free_play;
345 }
346
347 return 0;
348
349err_free_play:
350 tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK);
351err:
352 return ret;
353}
354
355static void tegra_pcm_free(struct snd_pcm *pcm)
356{
357 tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_CAPTURE);
358 tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK);
359}
360
361struct snd_soc_platform_driver tegra_pcm_platform = {
362 .ops = &tegra_pcm_ops,
363 .pcm_new = tegra_pcm_new,
364 .pcm_free = tegra_pcm_free,
365};
366
367static int __devinit tegra_pcm_platform_probe(struct platform_device *pdev)
368{
369 return snd_soc_register_platform(&pdev->dev, &tegra_pcm_platform);
370}
371
372static int __devexit tegra_pcm_platform_remove(struct platform_device *pdev)
373{
374 snd_soc_unregister_platform(&pdev->dev);
375 return 0;
376}
377
378static struct platform_driver tegra_pcm_driver = {
379 .driver = {
380 .name = "tegra-pcm-audio",
381 .owner = THIS_MODULE,
382 },
383 .probe = tegra_pcm_platform_probe,
384 .remove = __devexit_p(tegra_pcm_platform_remove),
385};
386
387static int __init snd_tegra_pcm_init(void)
388{
389 return platform_driver_register(&tegra_pcm_driver);
390}
391module_init(snd_tegra_pcm_init);
392
393static void __exit snd_tegra_pcm_exit(void)
394{
395 platform_driver_unregister(&tegra_pcm_driver);
396}
397module_exit(snd_tegra_pcm_exit);
398
399MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
400MODULE_DESCRIPTION("Tegra PCM ASoC driver");
401MODULE_LICENSE("GPL");
diff --git a/sound/soc/tegra/tegra_pcm.h b/sound/soc/tegra/tegra_pcm.h
new file mode 100644
index 000000000000..dbb90339fe0d
--- /dev/null
+++ b/sound/soc/tegra/tegra_pcm.h
@@ -0,0 +1,55 @@
1/*
2 * tegra_pcm.h - Definitions for Tegra PCM driver
3 *
4 * Author: Stephen Warren <swarren@nvidia.com>
5 * Copyright (C) 2010 - NVIDIA, Inc.
6 *
7 * Based on code copyright/by:
8 *
9 * Copyright (c) 2009-2010, NVIDIA Corporation.
10 * Scott Peterson <speterson@nvidia.com>
11 *
12 * Copyright (C) 2010 Google, Inc.
13 * Iliyan Malchev <malchev@google.com>
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * version 2 as published by the Free Software Foundation.
18 *
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * 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, write to the Free Software
26 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
27 * 02110-1301 USA
28 *
29 */
30
31#ifndef __TEGRA_PCM_H__
32#define __TEGRA_PCM_H__
33
34#include <mach/dma.h>
35
36struct tegra_pcm_dma_params {
37 unsigned long addr;
38 unsigned long wrap;
39 unsigned long width;
40 unsigned long req_sel;
41};
42
43struct tegra_runtime_data {
44 struct snd_pcm_substream *substream;
45 spinlock_t lock;
46 int running;
47 int dma_pos;
48 int dma_pos_end;
49 int period_index;
50 int dma_req_idx;
51 struct tegra_dma_req dma_req[2];
52 struct tegra_dma_channel *dma_chan;
53};
54
55#endif