diff options
Diffstat (limited to 'sound')
46 files changed, 1870 insertions, 332 deletions
diff --git a/sound/soc/atmel/snd-soc-afeb9260.c b/sound/soc/atmel/snd-soc-afeb9260.c index da2208e06b0d..5e4d499d8434 100644 --- a/sound/soc/atmel/snd-soc-afeb9260.c +++ b/sound/soc/atmel/snd-soc-afeb9260.c | |||
@@ -129,7 +129,7 @@ static struct snd_soc_dai_link afeb9260_dai = { | |||
129 | .cpu_dai_name = "atmel-ssc-dai.0", | 129 | .cpu_dai_name = "atmel-ssc-dai.0", |
130 | .codec_dai_name = "tlv320aic23-hifi", | 130 | .codec_dai_name = "tlv320aic23-hifi", |
131 | .platform_name = "atmel_pcm-audio", | 131 | .platform_name = "atmel_pcm-audio", |
132 | .codec_name = "tlv320aic23-codec.0-0x1a", | 132 | .codec_name = "tlv320aic23-codec.0-001a", |
133 | .init = afeb9260_tlv320aic23_init, | 133 | .init = afeb9260_tlv320aic23_init, |
134 | .ops = &afeb9260_ops, | 134 | .ops = &afeb9260_ops, |
135 | }; | 135 | }; |
diff --git a/sound/soc/blackfin/bf5xx-ssm2602.c b/sound/soc/blackfin/bf5xx-ssm2602.c index e902b24c1856..ad28663f5bbd 100644 --- a/sound/soc/blackfin/bf5xx-ssm2602.c +++ b/sound/soc/blackfin/bf5xx-ssm2602.c | |||
@@ -119,7 +119,7 @@ static struct snd_soc_dai_link bf5xx_ssm2602_dai = { | |||
119 | .cpu_dai_name = "bf5xx-i2s", | 119 | .cpu_dai_name = "bf5xx-i2s", |
120 | .codec_dai_name = "ssm2602-hifi", | 120 | .codec_dai_name = "ssm2602-hifi", |
121 | .platform_name = "bf5xx-pcm-audio", | 121 | .platform_name = "bf5xx-pcm-audio", |
122 | .codec_name = "ssm2602-codec.0-0x1b", | 122 | .codec_name = "ssm2602-codec.0-001b", |
123 | .ops = &bf5xx_ssm2602_ops, | 123 | .ops = &bf5xx_ssm2602_ops, |
124 | }; | 124 | }; |
125 | 125 | ||
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index a9cb2a04ad56..e239345a4d5d 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -26,6 +26,7 @@ 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 |
@@ -157,6 +158,9 @@ config SND_SOC_CS4270_VD33_ERRATA | |||
157 | bool | 158 | bool |
158 | depends on SND_SOC_CS4270 | 159 | depends on SND_SOC_CS4270 |
159 | 160 | ||
161 | config SND_SOC_CS4271 | ||
162 | tristate | ||
163 | |||
160 | config SND_SOC_CX20442 | 164 | config SND_SOC_CX20442 |
161 | tristate | 165 | tristate |
162 | 166 | ||
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 68e76af894b9..83b7accd7037 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
@@ -12,6 +12,7 @@ snd-soc-ak4671-objs := ak4671.o | |||
12 | snd-soc-cq93vc-objs := cq93vc.o | 12 | snd-soc-cq93vc-objs := cq93vc.o |
13 | snd-soc-cs42l51-objs := cs42l51.o | 13 | snd-soc-cs42l51-objs := cs42l51.o |
14 | snd-soc-cs4270-objs := cs4270.o | 14 | snd-soc-cs4270-objs := cs4270.o |
15 | snd-soc-cs4271-objs := cs4271.o | ||
15 | snd-soc-cx20442-objs := cx20442.o | 16 | snd-soc-cx20442-objs := cx20442.o |
16 | snd-soc-da7210-objs := da7210.o | 17 | snd-soc-da7210-objs := da7210.o |
17 | snd-soc-dmic-objs := dmic.o | 18 | snd-soc-dmic-objs := dmic.o |
@@ -93,6 +94,7 @@ obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o | |||
93 | obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.o | 94 | obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.o |
94 | obj-$(CONFIG_SND_SOC_CS42L51) += snd-soc-cs42l51.o | 95 | obj-$(CONFIG_SND_SOC_CS42L51) += snd-soc-cs42l51.o |
95 | obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o | 96 | obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o |
97 | obj-$(CONFIG_SND_SOC_CS4271) += snd-soc-cs4271.o | ||
96 | obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o | 98 | obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o |
97 | obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o | 99 | obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o |
98 | obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o | 100 | obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.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/cq93vc.c b/sound/soc/codecs/cq93vc.c index 46dbfd067f79..347a567b01e1 100644 --- a/sound/soc/codecs/cq93vc.c +++ b/sound/soc/codecs/cq93vc.c | |||
@@ -153,7 +153,7 @@ static int cq93vc_resume(struct snd_soc_codec *codec) | |||
153 | 153 | ||
154 | static int cq93vc_probe(struct snd_soc_codec *codec) | 154 | static int cq93vc_probe(struct snd_soc_codec *codec) |
155 | { | 155 | { |
156 | struct davinci_vc *davinci_vc = codec->dev->platform_data; | 156 | struct davinci_vc *davinci_vc = snd_soc_codec_get_drvdata(codec); |
157 | 157 | ||
158 | davinci_vc->cq93vc.codec = codec; | 158 | davinci_vc->cq93vc.codec = codec; |
159 | codec->control_data = davinci_vc; | 159 | codec->control_data = davinci_vc; |
diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c new file mode 100644 index 000000000000..9c5b7db0ce6a --- /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 | */ | ||
144 | static 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 | |||
155 | struct 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 | |||
170 | struct 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 | |||
177 | static 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 | */ | ||
196 | static 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 | |||
206 | static 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 | |||
254 | static int cs4271_deemph[] = {0, 44100, 48000, 32000}; | ||
255 | |||
256 | static 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 | |||
279 | static 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 | |||
289 | static 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 | |||
299 | static 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 | |||
336 | static 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 */ | ||
359 | static DECLARE_TLV_DB_SCALE(cs4271_dac_tlv, -12700, 100, 0); | ||
360 | |||
361 | static 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 | |||
382 | static 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 | |||
389 | static struct 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 | ||
410 | static 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 | |||
420 | static 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 | |||
438 | static 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 | |||
509 | static 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 | |||
529 | static struct 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) | ||
541 | static 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 | |||
557 | static int __devexit cs4271_spi_remove(struct spi_device *spi) | ||
558 | { | ||
559 | snd_soc_unregister_codec(&spi->dev); | ||
560 | return 0; | ||
561 | } | ||
562 | |||
563 | static 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) | ||
574 | static struct i2c_device_id cs4271_i2c_id[] = { | ||
575 | {"cs4271", 0}, | ||
576 | {} | ||
577 | }; | ||
578 | MODULE_DEVICE_TABLE(i2c, cs4271_i2c_id); | ||
579 | |||
580 | static 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 | |||
597 | static int __devexit cs4271_i2c_remove(struct i2c_client *client) | ||
598 | { | ||
599 | snd_soc_unregister_codec(&client->dev); | ||
600 | return 0; | ||
601 | } | ||
602 | |||
603 | static 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 | */ | ||
621 | static 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 | } | ||
643 | module_init(cs4271_modinit); | ||
644 | |||
645 | static 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 | } | ||
655 | module_exit(cs4271_modexit); | ||
656 | |||
657 | MODULE_AUTHOR("Alexander Sverdlin <subaparts@yandex.ru>"); | ||
658 | MODULE_DESCRIPTION("Cirrus Logic CS4271 ALSA SoC Codec Driver"); | ||
659 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/cx20442.c b/sound/soc/codecs/cx20442.c index 03d1e860d229..bb4bf65b9e7e 100644 --- a/sound/soc/codecs/cx20442.c +++ b/sound/soc/codecs/cx20442.c | |||
@@ -367,9 +367,12 @@ static int cx20442_codec_remove(struct snd_soc_codec *codec) | |||
367 | return 0; | 367 | return 0; |
368 | } | 368 | } |
369 | 369 | ||
370 | static const u8 cx20442_reg = CX20442_TELOUT | CX20442_MIC; | ||
371 | |||
370 | static struct snd_soc_codec_driver cx20442_codec_dev = { | 372 | static struct snd_soc_codec_driver cx20442_codec_dev = { |
371 | .probe = cx20442_codec_probe, | 373 | .probe = cx20442_codec_probe, |
372 | .remove = cx20442_codec_remove, | 374 | .remove = cx20442_codec_remove, |
375 | .reg_cache_default = &cx20442_reg, | ||
373 | .reg_cache_size = 1, | 376 | .reg_cache_size = 1, |
374 | .reg_word_size = sizeof(u8), | 377 | .reg_word_size = sizeof(u8), |
375 | .read = cx20442_read_reg_cache, | 378 | .read = cx20442_read_reg_cache, |
diff --git a/sound/soc/codecs/sn95031.c b/sound/soc/codecs/sn95031.c index 593632cf791d..40e285df9ae5 100644 --- a/sound/soc/codecs/sn95031.c +++ b/sound/soc/codecs/sn95031.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <sound/soc.h> | 33 | #include <sound/soc.h> |
34 | #include <sound/soc-dapm.h> | 34 | #include <sound/soc-dapm.h> |
35 | #include <sound/initval.h> | 35 | #include <sound/initval.h> |
36 | #include <sound/tlv.h> | ||
36 | #include "sn95031.h" | 37 | #include "sn95031.h" |
37 | 38 | ||
38 | #define SN95031_RATES (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100) | 39 | #define SN95031_RATES (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100) |
@@ -145,6 +146,129 @@ static int sn95031_vihf_event(struct snd_soc_dapm_widget *w, | |||
145 | return 0; | 146 | return 0; |
146 | } | 147 | } |
147 | 148 | ||
149 | static int sn95031_dmic12_event(struct snd_soc_dapm_widget *w, | ||
150 | struct snd_kcontrol *k, int event) | ||
151 | { | ||
152 | unsigned int ldo = 0, clk_dir = 0, data_dir = 0; | ||
153 | |||
154 | if (SND_SOC_DAPM_EVENT_ON(event)) { | ||
155 | ldo = BIT(5)|BIT(4); | ||
156 | clk_dir = BIT(0); | ||
157 | data_dir = BIT(7); | ||
158 | } | ||
159 | /* program DMIC LDO, clock and set clock */ | ||
160 | snd_soc_update_bits(w->codec, SN95031_MICBIAS, BIT(5)|BIT(4), ldo); | ||
161 | snd_soc_update_bits(w->codec, SN95031_DMICBUF0123, BIT(0), clk_dir); | ||
162 | snd_soc_update_bits(w->codec, SN95031_DMICBUF0123, BIT(7), data_dir); | ||
163 | return 0; | ||
164 | } | ||
165 | |||
166 | static int sn95031_dmic34_event(struct snd_soc_dapm_widget *w, | ||
167 | struct snd_kcontrol *k, int event) | ||
168 | { | ||
169 | unsigned int ldo = 0, clk_dir = 0, data_dir = 0; | ||
170 | |||
171 | if (SND_SOC_DAPM_EVENT_ON(event)) { | ||
172 | ldo = BIT(5)|BIT(4); | ||
173 | clk_dir = BIT(2); | ||
174 | data_dir = BIT(1); | ||
175 | } | ||
176 | /* program DMIC LDO, clock and set clock */ | ||
177 | snd_soc_update_bits(w->codec, SN95031_MICBIAS, BIT(5)|BIT(4), ldo); | ||
178 | snd_soc_update_bits(w->codec, SN95031_DMICBUF0123, BIT(2), clk_dir); | ||
179 | snd_soc_update_bits(w->codec, SN95031_DMICBUF45, BIT(1), data_dir); | ||
180 | return 0; | ||
181 | } | ||
182 | |||
183 | static int sn95031_dmic56_event(struct snd_soc_dapm_widget *w, | ||
184 | struct snd_kcontrol *k, int event) | ||
185 | { | ||
186 | unsigned int ldo = 0; | ||
187 | |||
188 | if (SND_SOC_DAPM_EVENT_ON(event)) | ||
189 | ldo = BIT(7)|BIT(6); | ||
190 | |||
191 | /* program DMIC LDO */ | ||
192 | snd_soc_update_bits(w->codec, SN95031_MICBIAS, BIT(7)|BIT(6), ldo); | ||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | /* mux controls */ | ||
197 | static const char *sn95031_mic_texts[] = { "AMIC", "LineIn" }; | ||
198 | |||
199 | static const struct soc_enum sn95031_micl_enum = | ||
200 | SOC_ENUM_SINGLE(SN95031_ADCCONFIG, 1, 2, sn95031_mic_texts); | ||
201 | |||
202 | static const struct snd_kcontrol_new sn95031_micl_mux_control = | ||
203 | SOC_DAPM_ENUM("Route", sn95031_micl_enum); | ||
204 | |||
205 | static const struct soc_enum sn95031_micr_enum = | ||
206 | SOC_ENUM_SINGLE(SN95031_ADCCONFIG, 3, 2, sn95031_mic_texts); | ||
207 | |||
208 | static const struct snd_kcontrol_new sn95031_micr_mux_control = | ||
209 | SOC_DAPM_ENUM("Route", sn95031_micr_enum); | ||
210 | |||
211 | static const char *sn95031_input_texts[] = { "DMIC1", "DMIC2", "DMIC3", | ||
212 | "DMIC4", "DMIC5", "DMIC6", | ||
213 | "ADC Left", "ADC Right" }; | ||
214 | |||
215 | static const struct soc_enum sn95031_input1_enum = | ||
216 | SOC_ENUM_SINGLE(SN95031_AUDIOMUX12, 0, 8, sn95031_input_texts); | ||
217 | |||
218 | static const struct snd_kcontrol_new sn95031_input1_mux_control = | ||
219 | SOC_DAPM_ENUM("Route", sn95031_input1_enum); | ||
220 | |||
221 | static const struct soc_enum sn95031_input2_enum = | ||
222 | SOC_ENUM_SINGLE(SN95031_AUDIOMUX12, 4, 8, sn95031_input_texts); | ||
223 | |||
224 | static const struct snd_kcontrol_new sn95031_input2_mux_control = | ||
225 | SOC_DAPM_ENUM("Route", sn95031_input2_enum); | ||
226 | |||
227 | static const struct soc_enum sn95031_input3_enum = | ||
228 | SOC_ENUM_SINGLE(SN95031_AUDIOMUX34, 0, 8, sn95031_input_texts); | ||
229 | |||
230 | static const struct snd_kcontrol_new sn95031_input3_mux_control = | ||
231 | SOC_DAPM_ENUM("Route", sn95031_input3_enum); | ||
232 | |||
233 | static const struct soc_enum sn95031_input4_enum = | ||
234 | SOC_ENUM_SINGLE(SN95031_AUDIOMUX34, 4, 8, sn95031_input_texts); | ||
235 | |||
236 | static const struct snd_kcontrol_new sn95031_input4_mux_control = | ||
237 | SOC_DAPM_ENUM("Route", sn95031_input4_enum); | ||
238 | |||
239 | /* capture path controls */ | ||
240 | |||
241 | static const char *sn95031_micmode_text[] = {"Single Ended", "Differential"}; | ||
242 | |||
243 | /* 0dB to 30dB in 10dB steps */ | ||
244 | static const DECLARE_TLV_DB_SCALE(mic_tlv, 0, 10, 30); | ||
245 | |||
246 | static const struct soc_enum sn95031_micmode1_enum = | ||
247 | SOC_ENUM_SINGLE(SN95031_MICAMP1, 1, 2, sn95031_micmode_text); | ||
248 | static const struct soc_enum sn95031_micmode2_enum = | ||
249 | SOC_ENUM_SINGLE(SN95031_MICAMP2, 1, 2, sn95031_micmode_text); | ||
250 | |||
251 | static const char *sn95031_dmic_cfg_text[] = {"GPO", "DMIC"}; | ||
252 | |||
253 | static const struct soc_enum sn95031_dmic12_cfg_enum = | ||
254 | SOC_ENUM_SINGLE(SN95031_DMICMUX, 0, 2, sn95031_dmic_cfg_text); | ||
255 | static const struct soc_enum sn95031_dmic34_cfg_enum = | ||
256 | SOC_ENUM_SINGLE(SN95031_DMICMUX, 1, 2, sn95031_dmic_cfg_text); | ||
257 | static const struct soc_enum sn95031_dmic56_cfg_enum = | ||
258 | SOC_ENUM_SINGLE(SN95031_DMICMUX, 2, 2, sn95031_dmic_cfg_text); | ||
259 | |||
260 | static const struct snd_kcontrol_new sn95031_snd_controls[] = { | ||
261 | SOC_ENUM("Mic1Mode Capture Route", sn95031_micmode1_enum), | ||
262 | SOC_ENUM("Mic2Mode Capture Route", sn95031_micmode2_enum), | ||
263 | SOC_ENUM("DMIC12 Capture Route", sn95031_dmic12_cfg_enum), | ||
264 | SOC_ENUM("DMIC34 Capture Route", sn95031_dmic34_cfg_enum), | ||
265 | SOC_ENUM("DMIC56 Capture Route", sn95031_dmic56_cfg_enum), | ||
266 | SOC_SINGLE_TLV("Mic1 Capture Volume", SN95031_MICAMP1, | ||
267 | 2, 4, 0, mic_tlv), | ||
268 | SOC_SINGLE_TLV("Mic2 Capture Volume", SN95031_MICAMP2, | ||
269 | 2, 4, 0, mic_tlv), | ||
270 | }; | ||
271 | |||
148 | /* DAPM widgets */ | 272 | /* DAPM widgets */ |
149 | static const struct snd_soc_dapm_widget sn95031_dapm_widgets[] = { | 273 | static const struct snd_soc_dapm_widget sn95031_dapm_widgets[] = { |
150 | 274 | ||
@@ -159,6 +283,36 @@ static const struct snd_soc_dapm_widget sn95031_dapm_widgets[] = { | |||
159 | SND_SOC_DAPM_OUTPUT("VIB1OUT"), | 283 | SND_SOC_DAPM_OUTPUT("VIB1OUT"), |
160 | SND_SOC_DAPM_OUTPUT("VIB2OUT"), | 284 | SND_SOC_DAPM_OUTPUT("VIB2OUT"), |
161 | 285 | ||
286 | SND_SOC_DAPM_INPUT("AMIC1"), /* headset mic */ | ||
287 | SND_SOC_DAPM_INPUT("AMIC2"), | ||
288 | SND_SOC_DAPM_INPUT("DMIC1"), | ||
289 | SND_SOC_DAPM_INPUT("DMIC2"), | ||
290 | SND_SOC_DAPM_INPUT("DMIC3"), | ||
291 | SND_SOC_DAPM_INPUT("DMIC4"), | ||
292 | SND_SOC_DAPM_INPUT("DMIC5"), | ||
293 | SND_SOC_DAPM_INPUT("DMIC6"), | ||
294 | SND_SOC_DAPM_INPUT("LINEINL"), | ||
295 | SND_SOC_DAPM_INPUT("LINEINR"), | ||
296 | |||
297 | SND_SOC_DAPM_MICBIAS("AMIC1Bias", SN95031_MICBIAS, 2, 0), | ||
298 | SND_SOC_DAPM_MICBIAS("AMIC2Bias", SN95031_MICBIAS, 3, 0), | ||
299 | SND_SOC_DAPM_MICBIAS("DMIC12Bias", SN95031_DMICMUX, 3, 0), | ||
300 | SND_SOC_DAPM_MICBIAS("DMIC34Bias", SN95031_DMICMUX, 4, 0), | ||
301 | SND_SOC_DAPM_MICBIAS("DMIC56Bias", SN95031_DMICMUX, 5, 0), | ||
302 | |||
303 | SND_SOC_DAPM_SUPPLY("DMIC12supply", SN95031_DMICLK, 0, 0, | ||
304 | sn95031_dmic12_event, | ||
305 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
306 | SND_SOC_DAPM_SUPPLY("DMIC34supply", SN95031_DMICLK, 1, 0, | ||
307 | sn95031_dmic34_event, | ||
308 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
309 | SND_SOC_DAPM_SUPPLY("DMIC56supply", SN95031_DMICLK, 2, 0, | ||
310 | sn95031_dmic56_event, | ||
311 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
312 | |||
313 | SND_SOC_DAPM_AIF_OUT("PCM_Out", "Capture", 0, | ||
314 | SND_SOC_NOPM, 0, 0), | ||
315 | |||
162 | SND_SOC_DAPM_SUPPLY("Headset Rail", SND_SOC_NOPM, 0, 0, | 316 | SND_SOC_DAPM_SUPPLY("Headset Rail", SND_SOC_NOPM, 0, 0, |
163 | sn95031_vhs_event, | 317 | sn95031_vhs_event, |
164 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | 318 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), |
@@ -209,6 +363,40 @@ static const struct snd_soc_dapm_widget sn95031_dapm_widgets[] = { | |||
209 | SN95031_VIB1C5, 1, 0), | 363 | SN95031_VIB1C5, 1, 0), |
210 | SND_SOC_DAPM_DAC("Vibra2 DAC", "Vibra2", | 364 | SND_SOC_DAPM_DAC("Vibra2 DAC", "Vibra2", |
211 | SN95031_VIB2C5, 1, 0), | 365 | SN95031_VIB2C5, 1, 0), |
366 | |||
367 | /* capture widgets */ | ||
368 | SND_SOC_DAPM_PGA("LineIn Enable Left", SN95031_MICAMP1, | ||
369 | 7, 0, NULL, 0), | ||
370 | SND_SOC_DAPM_PGA("LineIn Enable Right", SN95031_MICAMP2, | ||
371 | 7, 0, NULL, 0), | ||
372 | |||
373 | SND_SOC_DAPM_PGA("MIC1 Enable", SN95031_MICAMP1, 0, 0, NULL, 0), | ||
374 | SND_SOC_DAPM_PGA("MIC2 Enable", SN95031_MICAMP2, 0, 0, NULL, 0), | ||
375 | SND_SOC_DAPM_PGA("TX1 Enable", SN95031_AUDIOTXEN, 2, 0, NULL, 0), | ||
376 | SND_SOC_DAPM_PGA("TX2 Enable", SN95031_AUDIOTXEN, 3, 0, NULL, 0), | ||
377 | SND_SOC_DAPM_PGA("TX3 Enable", SN95031_AUDIOTXEN, 4, 0, NULL, 0), | ||
378 | SND_SOC_DAPM_PGA("TX4 Enable", SN95031_AUDIOTXEN, 5, 0, NULL, 0), | ||
379 | |||
380 | /* ADC have null stream as they will be turned ON by TX path */ | ||
381 | SND_SOC_DAPM_ADC("ADC Left", NULL, | ||
382 | SN95031_ADCCONFIG, 0, 0), | ||
383 | SND_SOC_DAPM_ADC("ADC Right", NULL, | ||
384 | SN95031_ADCCONFIG, 2, 0), | ||
385 | |||
386 | SND_SOC_DAPM_MUX("Mic_InputL Capture Route", | ||
387 | SND_SOC_NOPM, 0, 0, &sn95031_micl_mux_control), | ||
388 | SND_SOC_DAPM_MUX("Mic_InputR Capture Route", | ||
389 | SND_SOC_NOPM, 0, 0, &sn95031_micr_mux_control), | ||
390 | |||
391 | SND_SOC_DAPM_MUX("Txpath1 Capture Route", | ||
392 | SND_SOC_NOPM, 0, 0, &sn95031_input1_mux_control), | ||
393 | SND_SOC_DAPM_MUX("Txpath2 Capture Route", | ||
394 | SND_SOC_NOPM, 0, 0, &sn95031_input2_mux_control), | ||
395 | SND_SOC_DAPM_MUX("Txpath3 Capture Route", | ||
396 | SND_SOC_NOPM, 0, 0, &sn95031_input3_mux_control), | ||
397 | SND_SOC_DAPM_MUX("Txpath4 Capture Route", | ||
398 | SND_SOC_NOPM, 0, 0, &sn95031_input4_mux_control), | ||
399 | |||
212 | }; | 400 | }; |
213 | 401 | ||
214 | static const struct snd_soc_dapm_route sn95031_audio_map[] = { | 402 | static const struct snd_soc_dapm_route sn95031_audio_map[] = { |
@@ -250,6 +438,87 @@ static const struct snd_soc_dapm_route sn95031_audio_map[] = { | |||
250 | { "Lineout Right Playback", NULL, "Headset Right Filter"}, | 438 | { "Lineout Right Playback", NULL, "Headset Right Filter"}, |
251 | { "Lineout Right Playback", NULL, "Speaker Right Filter"}, | 439 | { "Lineout Right Playback", NULL, "Speaker Right Filter"}, |
252 | { "Lineout Right Playback", NULL, "Vibra2 DAC"}, | 440 | { "Lineout Right Playback", NULL, "Vibra2 DAC"}, |
441 | |||
442 | /* Headset (AMIC1) mic */ | ||
443 | { "AMIC1Bias", NULL, "AMIC1"}, | ||
444 | { "MIC1 Enable", NULL, "AMIC1Bias"}, | ||
445 | { "Mic_InputL Capture Route", "AMIC", "MIC1 Enable"}, | ||
446 | |||
447 | /* AMIC2 */ | ||
448 | { "AMIC2Bias", NULL, "AMIC2"}, | ||
449 | { "MIC2 Enable", NULL, "AMIC2Bias"}, | ||
450 | { "Mic_InputR Capture Route", "AMIC", "MIC2 Enable"}, | ||
451 | |||
452 | |||
453 | /* Linein */ | ||
454 | { "LineIn Enable Left", NULL, "LINEINL"}, | ||
455 | { "LineIn Enable Right", NULL, "LINEINR"}, | ||
456 | { "Mic_InputL Capture Route", "LineIn", "LineIn Enable Left"}, | ||
457 | { "Mic_InputR Capture Route", "LineIn", "LineIn Enable Right"}, | ||
458 | |||
459 | /* ADC connection */ | ||
460 | { "ADC Left", NULL, "Mic_InputL Capture Route"}, | ||
461 | { "ADC Right", NULL, "Mic_InputR Capture Route"}, | ||
462 | |||
463 | /*DMIC connections */ | ||
464 | { "DMIC1", NULL, "DMIC12supply"}, | ||
465 | { "DMIC2", NULL, "DMIC12supply"}, | ||
466 | { "DMIC3", NULL, "DMIC34supply"}, | ||
467 | { "DMIC4", NULL, "DMIC34supply"}, | ||
468 | { "DMIC5", NULL, "DMIC56supply"}, | ||
469 | { "DMIC6", NULL, "DMIC56supply"}, | ||
470 | |||
471 | { "DMIC12Bias", NULL, "DMIC1"}, | ||
472 | { "DMIC12Bias", NULL, "DMIC2"}, | ||
473 | { "DMIC34Bias", NULL, "DMIC3"}, | ||
474 | { "DMIC34Bias", NULL, "DMIC4"}, | ||
475 | { "DMIC56Bias", NULL, "DMIC5"}, | ||
476 | { "DMIC56Bias", NULL, "DMIC6"}, | ||
477 | |||
478 | /*TX path inputs*/ | ||
479 | { "Txpath1 Capture Route", "ADC Left", "ADC Left"}, | ||
480 | { "Txpath2 Capture Route", "ADC Left", "ADC Left"}, | ||
481 | { "Txpath3 Capture Route", "ADC Left", "ADC Left"}, | ||
482 | { "Txpath4 Capture Route", "ADC Left", "ADC Left"}, | ||
483 | { "Txpath1 Capture Route", "ADC Right", "ADC Right"}, | ||
484 | { "Txpath2 Capture Route", "ADC Right", "ADC Right"}, | ||
485 | { "Txpath3 Capture Route", "ADC Right", "ADC Right"}, | ||
486 | { "Txpath4 Capture Route", "ADC Right", "ADC Right"}, | ||
487 | { "Txpath1 Capture Route", NULL, "DMIC1"}, | ||
488 | { "Txpath2 Capture Route", NULL, "DMIC1"}, | ||
489 | { "Txpath3 Capture Route", NULL, "DMIC1"}, | ||
490 | { "Txpath4 Capture Route", NULL, "DMIC1"}, | ||
491 | { "Txpath1 Capture Route", NULL, "DMIC2"}, | ||
492 | { "Txpath2 Capture Route", NULL, "DMIC2"}, | ||
493 | { "Txpath3 Capture Route", NULL, "DMIC2"}, | ||
494 | { "Txpath4 Capture Route", NULL, "DMIC2"}, | ||
495 | { "Txpath1 Capture Route", NULL, "DMIC3"}, | ||
496 | { "Txpath2 Capture Route", NULL, "DMIC3"}, | ||
497 | { "Txpath3 Capture Route", NULL, "DMIC3"}, | ||
498 | { "Txpath4 Capture Route", NULL, "DMIC3"}, | ||
499 | { "Txpath1 Capture Route", NULL, "DMIC4"}, | ||
500 | { "Txpath2 Capture Route", NULL, "DMIC4"}, | ||
501 | { "Txpath3 Capture Route", NULL, "DMIC4"}, | ||
502 | { "Txpath4 Capture Route", NULL, "DMIC4"}, | ||
503 | { "Txpath1 Capture Route", NULL, "DMIC5"}, | ||
504 | { "Txpath2 Capture Route", NULL, "DMIC5"}, | ||
505 | { "Txpath3 Capture Route", NULL, "DMIC5"}, | ||
506 | { "Txpath4 Capture Route", NULL, "DMIC5"}, | ||
507 | { "Txpath1 Capture Route", NULL, "DMIC6"}, | ||
508 | { "Txpath2 Capture Route", NULL, "DMIC6"}, | ||
509 | { "Txpath3 Capture Route", NULL, "DMIC6"}, | ||
510 | { "Txpath4 Capture Route", NULL, "DMIC6"}, | ||
511 | |||
512 | /* tx path */ | ||
513 | { "TX1 Enable", NULL, "Txpath1 Capture Route"}, | ||
514 | { "TX2 Enable", NULL, "Txpath2 Capture Route"}, | ||
515 | { "TX3 Enable", NULL, "Txpath3 Capture Route"}, | ||
516 | { "TX4 Enable", NULL, "Txpath4 Capture Route"}, | ||
517 | { "PCM_Out", NULL, "TX1 Enable"}, | ||
518 | { "PCM_Out", NULL, "TX2 Enable"}, | ||
519 | { "PCM_Out", NULL, "TX3 Enable"}, | ||
520 | { "PCM_Out", NULL, "TX4 Enable"}, | ||
521 | |||
253 | }; | 522 | }; |
254 | 523 | ||
255 | /* speaker and headset mutes, for audio pops and clicks */ | 524 | /* speaker and headset mutes, for audio pops and clicks */ |
@@ -339,6 +608,13 @@ struct snd_soc_dai_driver sn95031_dais[] = { | |||
339 | .rates = SN95031_RATES, | 608 | .rates = SN95031_RATES, |
340 | .formats = SN95031_FORMATS, | 609 | .formats = SN95031_FORMATS, |
341 | }, | 610 | }, |
611 | .capture = { | ||
612 | .stream_name = "Capture", | ||
613 | .channels_min = 1, | ||
614 | .channels_max = 5, | ||
615 | .rates = SN95031_RATES, | ||
616 | .formats = SN95031_FORMATS, | ||
617 | }, | ||
342 | .ops = &sn95031_headset_dai_ops, | 618 | .ops = &sn95031_headset_dai_ops, |
343 | }, | 619 | }, |
344 | { .name = "SN95031 Speaker", | 620 | { .name = "SN95031 Speaker", |
@@ -390,6 +666,8 @@ static int sn95031_codec_probe(struct snd_soc_codec *codec) | |||
390 | snd_soc_write(codec, SN95031_PCM2RXSLOT01, 0x10); | 666 | snd_soc_write(codec, SN95031_PCM2RXSLOT01, 0x10); |
391 | snd_soc_write(codec, SN95031_PCM2RXSLOT23, 0x32); | 667 | snd_soc_write(codec, SN95031_PCM2RXSLOT23, 0x32); |
392 | snd_soc_write(codec, SN95031_PCM2RXSLOT45, 0x54); | 668 | snd_soc_write(codec, SN95031_PCM2RXSLOT45, 0x54); |
669 | snd_soc_write(codec, SN95031_PCM2TXSLOT01, 0x10); | ||
670 | snd_soc_write(codec, SN95031_PCM2TXSLOT23, 0x32); | ||
393 | /* pcm port setting | 671 | /* pcm port setting |
394 | * This sets the pcm port to slave and clock at 19.2Mhz which | 672 | * 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 | 673 | * can support 6slots, sampling rate set per stream in hw-params |
@@ -423,6 +701,9 @@ static int sn95031_codec_probe(struct snd_soc_codec *codec) | |||
423 | snd_soc_write(codec, SN95031_SSR2, 0x10); | 701 | snd_soc_write(codec, SN95031_SSR2, 0x10); |
424 | snd_soc_write(codec, SN95031_SSR3, 0x40); | 702 | snd_soc_write(codec, SN95031_SSR3, 0x40); |
425 | 703 | ||
704 | snd_soc_add_controls(codec, sn95031_snd_controls, | ||
705 | ARRAY_SIZE(sn95031_snd_controls)); | ||
706 | |||
426 | ret = snd_soc_dapm_new_controls(&codec->dapm, sn95031_dapm_widgets, | 707 | ret = snd_soc_dapm_new_controls(&codec->dapm, sn95031_dapm_widgets, |
427 | ARRAY_SIZE(sn95031_dapm_widgets)); | 708 | ARRAY_SIZE(sn95031_dapm_widgets)); |
428 | if (ret) | 709 | if (ret) |
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index a2a446cb1807..3d4c55f3c7b5 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 | ||
215 | struct wm8903_priv { | 217 | struct wm8903_priv { |
218 | struct snd_soc_codec *codec; | ||
216 | 219 | ||
217 | int sysclk; | 220 | int sysclk; |
218 | int irq; | 221 | int irq; |
@@ -230,6 +233,10 @@ 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 | ||
235 | static int wm8903_volatile_register(struct snd_soc_codec *codec, unsigned int reg) | 242 | static int wm8903_volatile_register(struct snd_soc_codec *codec, unsigned int reg) |
@@ -1635,6 +1642,120 @@ static int wm8903_resume(struct snd_soc_codec *codec) | |||
1635 | return 0; | 1642 | return 0; |
1636 | } | 1643 | } |
1637 | 1644 | ||
1645 | #ifdef CONFIG_GPIOLIB | ||
1646 | static inline struct wm8903_priv *gpio_to_wm8903(struct gpio_chip *chip) | ||
1647 | { | ||
1648 | return container_of(chip, struct wm8903_priv, gpio_chip); | ||
1649 | } | ||
1650 | |||
1651 | static 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 | |||
1659 | static 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 | |||
1673 | static 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 | |||
1684 | static 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 | |||
1699 | static 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, | ||
1706 | !!value << WM8903_GP1_LVL_SHIFT); | ||
1707 | } | ||
1708 | |||
1709 | static struct gpio_chip wm8903_template_chip = { | ||
1710 | .label = "wm8903", | ||
1711 | .owner = THIS_MODULE, | ||
1712 | .request = wm8903_gpio_request, | ||
1713 | .direction_input = wm8903_gpio_direction_in, | ||
1714 | .get = wm8903_gpio_get, | ||
1715 | .direction_output = wm8903_gpio_direction_out, | ||
1716 | .set = wm8903_gpio_set, | ||
1717 | .can_sleep = 1, | ||
1718 | }; | ||
1719 | |||
1720 | static void wm8903_init_gpio(struct snd_soc_codec *codec) | ||
1721 | { | ||
1722 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); | ||
1723 | struct wm8903_platform_data *pdata = dev_get_platdata(codec->dev); | ||
1724 | int ret; | ||
1725 | |||
1726 | wm8903->gpio_chip = wm8903_template_chip; | ||
1727 | wm8903->gpio_chip.ngpio = WM8903_NUM_GPIO; | ||
1728 | wm8903->gpio_chip.dev = codec->dev; | ||
1729 | |||
1730 | if (pdata && pdata->gpio_base) | ||
1731 | wm8903->gpio_chip.base = pdata->gpio_base; | ||
1732 | else | ||
1733 | wm8903->gpio_chip.base = -1; | ||
1734 | |||
1735 | ret = gpiochip_add(&wm8903->gpio_chip); | ||
1736 | if (ret != 0) | ||
1737 | dev_err(codec->dev, "Failed to add GPIOs: %d\n", ret); | ||
1738 | } | ||
1739 | |||
1740 | static void wm8903_free_gpio(struct snd_soc_codec *codec) | ||
1741 | { | ||
1742 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); | ||
1743 | int ret; | ||
1744 | |||
1745 | ret = gpiochip_remove(&wm8903->gpio_chip); | ||
1746 | if (ret != 0) | ||
1747 | dev_err(codec->dev, "Failed to remove GPIOs: %d\n", ret); | ||
1748 | } | ||
1749 | #else | ||
1750 | static void wm8903_init_gpio(struct snd_soc_codec *codec) | ||
1751 | { | ||
1752 | } | ||
1753 | |||
1754 | static void wm8903_free_gpio(struct snd_soc_codec *codec) | ||
1755 | { | ||
1756 | } | ||
1757 | #endif | ||
1758 | |||
1638 | static int wm8903_probe(struct snd_soc_codec *codec) | 1759 | static int wm8903_probe(struct snd_soc_codec *codec) |
1639 | { | 1760 | { |
1640 | struct wm8903_platform_data *pdata = dev_get_platdata(codec->dev); | 1761 | struct wm8903_platform_data *pdata = dev_get_platdata(codec->dev); |
@@ -1643,6 +1764,7 @@ static int wm8903_probe(struct snd_soc_codec *codec) | |||
1643 | int trigger, irq_pol; | 1764 | int trigger, irq_pol; |
1644 | u16 val; | 1765 | u16 val; |
1645 | 1766 | ||
1767 | wm8903->codec = codec; | ||
1646 | init_completion(&wm8903->wseq); | 1768 | init_completion(&wm8903->wseq); |
1647 | 1769 | ||
1648 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); | 1770 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); |
@@ -1667,7 +1789,7 @@ static int wm8903_probe(struct snd_soc_codec *codec) | |||
1667 | /* Set up GPIOs and microphone detection */ | 1789 | /* Set up GPIOs and microphone detection */ |
1668 | if (pdata) { | 1790 | if (pdata) { |
1669 | for (i = 0; i < ARRAY_SIZE(pdata->gpio_cfg); i++) { | 1791 | for (i = 0; i < ARRAY_SIZE(pdata->gpio_cfg); i++) { |
1670 | if (!pdata->gpio_cfg[i]) | 1792 | if (pdata->gpio_cfg[i] == WM8903_GPIO_NO_CONFIG) |
1671 | continue; | 1793 | continue; |
1672 | 1794 | ||
1673 | snd_soc_write(codec, WM8903_GPIO_CONTROL_1 + i, | 1795 | snd_soc_write(codec, WM8903_GPIO_CONTROL_1 + i, |
@@ -1749,12 +1871,15 @@ static int wm8903_probe(struct snd_soc_codec *codec) | |||
1749 | ARRAY_SIZE(wm8903_snd_controls)); | 1871 | ARRAY_SIZE(wm8903_snd_controls)); |
1750 | wm8903_add_widgets(codec); | 1872 | wm8903_add_widgets(codec); |
1751 | 1873 | ||
1874 | wm8903_init_gpio(codec); | ||
1875 | |||
1752 | return ret; | 1876 | return ret; |
1753 | } | 1877 | } |
1754 | 1878 | ||
1755 | /* power down chip */ | 1879 | /* power down chip */ |
1756 | static int wm8903_remove(struct snd_soc_codec *codec) | 1880 | static int wm8903_remove(struct snd_soc_codec *codec) |
1757 | { | 1881 | { |
1882 | wm8903_free_gpio(codec); | ||
1758 | wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1883 | wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1759 | return 0; | 1884 | return 0; |
1760 | } | 1885 | } |
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 5c7b730a864f..3b71dd65c966 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c | |||
@@ -3635,7 +3635,7 @@ static void wm8962_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | |||
3635 | struct snd_soc_codec *codec = wm8962->codec; | 3635 | struct snd_soc_codec *codec = wm8962->codec; |
3636 | 3636 | ||
3637 | snd_soc_update_bits(codec, WM8962_GPIO_BASE + offset, | 3637 | snd_soc_update_bits(codec, WM8962_GPIO_BASE + offset, |
3638 | WM8962_GP2_LVL, value << WM8962_GP2_LVL_SHIFT); | 3638 | WM8962_GP2_LVL, !!value << WM8962_GP2_LVL_SHIFT); |
3639 | } | 3639 | } |
3640 | 3640 | ||
3641 | static int wm8962_gpio_direction_out(struct gpio_chip *chip, | 3641 | static int wm8962_gpio_direction_out(struct gpio_chip *chip, |
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 0bb0bb40b842..0ca81d3c64e8 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c | |||
@@ -2386,7 +2386,7 @@ static int wm8994_set_tristate(struct snd_soc_dai *codec_dai, int tristate) | |||
2386 | else | 2386 | else |
2387 | val = 0; | 2387 | val = 0; |
2388 | 2388 | ||
2389 | return snd_soc_update_bits(codec, reg, mask, reg); | 2389 | return snd_soc_update_bits(codec, reg, mask, val); |
2390 | } | 2390 | } |
2391 | 2391 | ||
2392 | #define WM8994_RATES SNDRV_PCM_RATE_8000_96000 | 2392 | #define WM8994_RATES SNDRV_PCM_RATE_8000_96000 |
diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c index 7d563413df3e..67eaaecbb42e 100644 --- a/sound/soc/codecs/wm8995.c +++ b/sound/soc/codecs/wm8995.c | |||
@@ -1265,7 +1265,7 @@ static int wm8995_set_tristate(struct snd_soc_dai *codec_dai, int tristate) | |||
1265 | else | 1265 | else |
1266 | val = 0; | 1266 | val = 0; |
1267 | 1267 | ||
1268 | return snd_soc_update_bits(codec, reg, mask, reg); | 1268 | return snd_soc_update_bits(codec, reg, mask, val); |
1269 | } | 1269 | } |
1270 | 1270 | ||
1271 | /* The size in bits of the FLL divide multiplied by 10 | 1271 | /* The size in bits of the FLL divide multiplied by 10 |
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index c466982eed23..613df5db0b32 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c | |||
@@ -91,6 +91,7 @@ static void wait_for_dc_servo(struct snd_soc_codec *codec, unsigned int op) | |||
91 | static void calibrate_dc_servo(struct snd_soc_codec *codec) | 91 | static void calibrate_dc_servo(struct snd_soc_codec *codec) |
92 | { | 92 | { |
93 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); | 93 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); |
94 | s8 offset; | ||
94 | u16 reg, reg_l, reg_r, dcs_cfg; | 95 | u16 reg, reg_l, reg_r, dcs_cfg; |
95 | 96 | ||
96 | /* If we're using a digital only path and have a previously | 97 | /* If we're using a digital only path and have a previously |
@@ -149,16 +150,14 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec) | |||
149 | hubs->dcs_codes); | 150 | hubs->dcs_codes); |
150 | 151 | ||
151 | /* HPOUT1L */ | 152 | /* HPOUT1L */ |
152 | if (reg_l + hubs->dcs_codes > 0 && | 153 | offset = reg_l; |
153 | reg_l + hubs->dcs_codes < 0xff) | 154 | offset += hubs->dcs_codes; |
154 | reg_l += hubs->dcs_codes; | 155 | dcs_cfg = (u8)offset << WM8993_DCS_DAC_WR_VAL_1_SHIFT; |
155 | dcs_cfg = reg_l << WM8993_DCS_DAC_WR_VAL_1_SHIFT; | ||
156 | 156 | ||
157 | /* HPOUT1R */ | 157 | /* HPOUT1R */ |
158 | if (reg_r + hubs->dcs_codes > 0 && | 158 | offset = reg_r; |
159 | reg_r + hubs->dcs_codes < 0xff) | 159 | offset += hubs->dcs_codes; |
160 | reg_r += hubs->dcs_codes; | 160 | dcs_cfg |= (u8)offset; |
161 | dcs_cfg |= reg_r; | ||
162 | 161 | ||
163 | dev_dbg(codec->dev, "DCS result: %x\n", dcs_cfg); | 162 | dev_dbg(codec->dev, "DCS result: %x\n", dcs_cfg); |
164 | 163 | ||
diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c index 0c2d6bacc681..b36f0b39b090 100644 --- a/sound/soc/davinci/davinci-evm.c +++ b/sound/soc/davinci/davinci-evm.c | |||
@@ -223,7 +223,7 @@ static struct snd_soc_dai_link da8xx_evm_dai = { | |||
223 | .stream_name = "AIC3X", | 223 | .stream_name = "AIC3X", |
224 | .cpu_dai_name= "davinci-mcasp.0", | 224 | .cpu_dai_name= "davinci-mcasp.0", |
225 | .codec_dai_name = "tlv320aic3x-hifi", | 225 | .codec_dai_name = "tlv320aic3x-hifi", |
226 | .codec_name = "tlv320aic3x-codec.0-001a", | 226 | .codec_name = "tlv320aic3x-codec.1-0018", |
227 | .platform_name = "davinci-pcm-audio", | 227 | .platform_name = "davinci-pcm-audio", |
228 | .init = evm_aic3x_init, | 228 | .init = evm_aic3x_init, |
229 | .ops = &evm_ops, | 229 | .ops = &evm_ops, |
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 | |||
34 | config 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 |
11 | snd-soc-snappercl15-objs := snappercl15.o | 11 | snd-soc-snappercl15-objs := snappercl15.o |
12 | snd-soc-simone-objs := simone.o | 12 | snd-soc-simone-objs := simone.o |
13 | snd-soc-edb93xx-objs := edb93xx.o | ||
13 | 14 | ||
14 | obj-$(CONFIG_SND_EP93XX_SOC_SNAPPERCL15) += snd-soc-snappercl15.o | 15 | obj-$(CONFIG_SND_EP93XX_SOC_SNAPPERCL15) += snd-soc-snappercl15.o |
15 | obj-$(CONFIG_SND_EP93XX_SOC_SIMONE) += snd-soc-simone.o | 16 | obj-$(CONFIG_SND_EP93XX_SOC_SIMONE) += snd-soc-simone.o |
17 | obj-$(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 | |||
37 | static 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 | |||
77 | static struct snd_soc_ops edb93xx_ops = { | ||
78 | .hw_params = edb93xx_hw_params, | ||
79 | }; | ||
80 | |||
81 | static 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 | |||
91 | static struct snd_soc_card snd_soc_edb93xx = { | ||
92 | .name = "EDB93XX", | ||
93 | .dai_link = &edb93xx_dai, | ||
94 | .num_links = 1, | ||
95 | }; | ||
96 | |||
97 | static struct platform_device *edb93xx_snd_device; | ||
98 | |||
99 | static 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 | |||
125 | device_put: | ||
126 | platform_device_put(edb93xx_snd_device); | ||
127 | free_i2s: | ||
128 | ep93xx_i2s_release(); | ||
129 | return ret; | ||
130 | } | ||
131 | module_init(edb93xx_init); | ||
132 | |||
133 | static void __exit edb93xx_exit(void) | ||
134 | { | ||
135 | platform_device_unregister(edb93xx_snd_device); | ||
136 | ep93xx_i2s_release(); | ||
137 | } | ||
138 | module_exit(edb93xx_exit); | ||
139 | |||
140 | MODULE_AUTHOR("Alexander Sverdlin <subaparts@yandex.ru>"); | ||
141 | MODULE_DESCRIPTION("ALSA SoC EDB93xx"); | ||
142 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c index 7d7847a1e66b..c16c6b2eff95 100644 --- a/sound/soc/fsl/mpc8610_hpcd.c +++ b/sound/soc/fsl/mpc8610_hpcd.c | |||
@@ -53,9 +53,8 @@ struct mpc8610_hpcd_data { | |||
53 | * | 53 | * |
54 | * Here we program the DMACR and PMUXCR registers. | 54 | * Here we program the DMACR and PMUXCR registers. |
55 | */ | 55 | */ |
56 | static int mpc8610_hpcd_machine_probe(struct platform_device *sound_device) | 56 | static int mpc8610_hpcd_machine_probe(struct snd_soc_card *card) |
57 | { | 57 | { |
58 | struct snd_soc_card *card = platform_get_drvdata(sound_device); | ||
59 | struct mpc8610_hpcd_data *machine_data = | 58 | struct mpc8610_hpcd_data *machine_data = |
60 | container_of(card, struct mpc8610_hpcd_data, card); | 59 | container_of(card, struct mpc8610_hpcd_data, card); |
61 | struct ccsr_guts_86xx __iomem *guts; | 60 | struct ccsr_guts_86xx __iomem *guts; |
@@ -138,9 +137,8 @@ static int mpc8610_hpcd_startup(struct snd_pcm_substream *substream) | |||
138 | * This function is called to remove the sound device for one SSI. We | 137 | * This function is called to remove the sound device for one SSI. We |
139 | * de-program the DMACR and PMUXCR register. | 138 | * de-program the DMACR and PMUXCR register. |
140 | */ | 139 | */ |
141 | static int mpc8610_hpcd_machine_remove(struct platform_device *sound_device) | 140 | static int mpc8610_hpcd_machine_remove(struct snd_soc_card *card) |
142 | { | 141 | { |
143 | struct snd_soc_card *card = platform_get_drvdata(sound_device); | ||
144 | struct mpc8610_hpcd_data *machine_data = | 142 | struct mpc8610_hpcd_data *machine_data = |
145 | container_of(card, struct mpc8610_hpcd_data, card); | 143 | container_of(card, struct mpc8610_hpcd_data, card); |
146 | struct ccsr_guts_86xx __iomem *guts; | 144 | struct ccsr_guts_86xx __iomem *guts; |
diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c index 026b756961e0..66e0b68af147 100644 --- a/sound/soc/fsl/p1022_ds.c +++ b/sound/soc/fsl/p1022_ds.c | |||
@@ -85,9 +85,8 @@ struct machine_data { | |||
85 | * | 85 | * |
86 | * Here we program the DMACR and PMUXCR registers. | 86 | * Here we program the DMACR and PMUXCR registers. |
87 | */ | 87 | */ |
88 | static int p1022_ds_machine_probe(struct platform_device *sound_device) | 88 | static int p1022_ds_machine_probe(struct snd_soc_card *card) |
89 | { | 89 | { |
90 | struct snd_soc_card *card = platform_get_drvdata(sound_device); | ||
91 | struct machine_data *mdata = | 90 | struct machine_data *mdata = |
92 | container_of(card, struct machine_data, card); | 91 | container_of(card, struct machine_data, card); |
93 | struct ccsr_guts_85xx __iomem *guts; | 92 | struct ccsr_guts_85xx __iomem *guts; |
@@ -160,9 +159,8 @@ static int p1022_ds_startup(struct snd_pcm_substream *substream) | |||
160 | * This function is called to remove the sound device for one SSI. We | 159 | * This function is called to remove the sound device for one SSI. We |
161 | * de-program the DMACR and PMUXCR register. | 160 | * de-program the DMACR and PMUXCR register. |
162 | */ | 161 | */ |
163 | static int p1022_ds_machine_remove(struct platform_device *sound_device) | 162 | static int p1022_ds_machine_remove(struct snd_soc_card *card) |
164 | { | 163 | { |
165 | struct snd_soc_card *card = platform_get_drvdata(sound_device); | ||
166 | struct machine_data *mdata = | 164 | struct machine_data *mdata = |
167 | container_of(card, struct machine_data, card); | 165 | container_of(card, struct machine_data, card); |
168 | struct ccsr_guts_85xx __iomem *guts; | 166 | struct ccsr_guts_85xx __iomem *guts; |
diff --git a/sound/soc/mid-x86/mfld_machine.c b/sound/soc/mid-x86/mfld_machine.c index 1a330be1a01e..7925851a5de1 100644 --- a/sound/soc/mid-x86/mfld_machine.c +++ b/sound/soc/mid-x86/mfld_machine.c | |||
@@ -182,6 +182,9 @@ static int mfld_init(struct snd_soc_pcm_runtime *runtime) | |||
182 | snd_soc_dapm_disable_pin(dapm, "LINEOUTR"); | 182 | snd_soc_dapm_disable_pin(dapm, "LINEOUTR"); |
183 | lo_dac = 3; | 183 | lo_dac = 3; |
184 | hs_switch = 0; | 184 | hs_switch = 0; |
185 | /* we dont use linein in this so set to NC */ | ||
186 | snd_soc_dapm_disable_pin(dapm, "LINEINL"); | ||
187 | snd_soc_dapm_disable_pin(dapm, "LINEINR"); | ||
185 | return snd_soc_dapm_sync(dapm); | 188 | return snd_soc_dapm_sync(dapm); |
186 | } | 189 | } |
187 | 190 | ||
diff --git a/sound/soc/mid-x86/sst_platform.c b/sound/soc/mid-x86/sst_platform.c index 1d1f5447b338..96e6e9c9c5f4 100644 --- a/sound/soc/mid-x86/sst_platform.c +++ b/sound/soc/mid-x86/sst_platform.c | |||
@@ -73,6 +73,12 @@ struct snd_soc_dai_driver sst_platform_dai[] = { | |||
73 | .rates = SNDRV_PCM_RATE_48000, | 73 | .rates = SNDRV_PCM_RATE_48000, |
74 | .formats = SNDRV_PCM_FMTBIT_S24_LE, | 74 | .formats = SNDRV_PCM_FMTBIT_S24_LE, |
75 | }, | 75 | }, |
76 | .capture = { | ||
77 | .channels_min = 1, | ||
78 | .channels_max = 5, | ||
79 | .rates = SNDRV_PCM_RATE_48000, | ||
80 | .formats = SNDRV_PCM_FMTBIT_S24_LE, | ||
81 | }, | ||
76 | }, | 82 | }, |
77 | { | 83 | { |
78 | .name = "Speaker-cpu-dai", | 84 | .name = "Speaker-cpu-dai", |
diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c index 2101bdcee21f..3167be689621 100644 --- a/sound/soc/omap/ams-delta.c +++ b/sound/soc/omap/ams-delta.c | |||
@@ -507,8 +507,6 @@ static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd) | |||
507 | /* Set up digital mute if not provided by the codec */ | 507 | /* Set up digital mute if not provided by the codec */ |
508 | if (!codec_dai->driver->ops) { | 508 | if (!codec_dai->driver->ops) { |
509 | codec_dai->driver->ops = &ams_delta_dai_ops; | 509 | codec_dai->driver->ops = &ams_delta_dai_ops; |
510 | } else if (!codec_dai->driver->ops->digital_mute) { | ||
511 | codec_dai->driver->ops->digital_mute = ams_delta_digital_mute; | ||
512 | } else { | 510 | } else { |
513 | ams_delta_ops.startup = ams_delta_startup; | 511 | ams_delta_ops.startup = ams_delta_startup; |
514 | ams_delta_ops.shutdown = ams_delta_shutdown; | 512 | ams_delta_ops.shutdown = ams_delta_shutdown; |
diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c index fc592f0d5fc7..784cff5f67e8 100644 --- a/sound/soc/pxa/corgi.c +++ b/sound/soc/pxa/corgi.c | |||
@@ -307,10 +307,10 @@ static int corgi_wm8731_init(struct snd_soc_pcm_runtime *rtd) | |||
307 | static struct snd_soc_dai_link corgi_dai = { | 307 | static struct snd_soc_dai_link corgi_dai = { |
308 | .name = "WM8731", | 308 | .name = "WM8731", |
309 | .stream_name = "WM8731", | 309 | .stream_name = "WM8731", |
310 | .cpu_dai_name = "pxa-is2-dai", | 310 | .cpu_dai_name = "pxa2xx-i2s", |
311 | .codec_dai_name = "wm8731-hifi", | 311 | .codec_dai_name = "wm8731-hifi", |
312 | .platform_name = "pxa-pcm-audio", | 312 | .platform_name = "pxa-pcm-audio", |
313 | .codec_name = "wm8731-codec-0.001a", | 313 | .codec_name = "wm8731-codec-0.001b", |
314 | .init = corgi_wm8731_init, | 314 | .init = corgi_wm8731_init, |
315 | .ops = &corgi_ops, | 315 | .ops = &corgi_ops, |
316 | }; | 316 | }; |
diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c index 6298ee115e27..a7d4999f9b24 100644 --- a/sound/soc/pxa/poodle.c +++ b/sound/soc/pxa/poodle.c | |||
@@ -276,7 +276,7 @@ static struct snd_soc_dai_link poodle_dai = { | |||
276 | .cpu_dai_name = "pxa2xx-i2s", | 276 | .cpu_dai_name = "pxa2xx-i2s", |
277 | .codec_dai_name = "wm8731-hifi", | 277 | .codec_dai_name = "wm8731-hifi", |
278 | .platform_name = "pxa-pcm-audio", | 278 | .platform_name = "pxa-pcm-audio", |
279 | .codec_name = "wm8731-codec.0-001a", | 279 | .codec_name = "wm8731-codec.0-001b", |
280 | .init = poodle_wm8731_init, | 280 | .init = poodle_wm8731_init, |
281 | .ops = &poodle_ops, | 281 | .ops = &poodle_ops, |
282 | }; | 282 | }; |
diff --git a/sound/soc/pxa/raumfeld.c b/sound/soc/pxa/raumfeld.c index 0fd60f423036..db1dd560a585 100644 --- a/sound/soc/pxa/raumfeld.c +++ b/sound/soc/pxa/raumfeld.c | |||
@@ -151,13 +151,13 @@ static struct snd_soc_ops raumfeld_cs4270_ops = { | |||
151 | .hw_params = raumfeld_cs4270_hw_params, | 151 | .hw_params = raumfeld_cs4270_hw_params, |
152 | }; | 152 | }; |
153 | 153 | ||
154 | static int raumfeld_line_suspend(struct platform_device *pdev, pm_message_t state) | 154 | static int raumfeld_line_suspend(struct snd_soc_card *card) |
155 | { | 155 | { |
156 | raumfeld_enable_audio(false); | 156 | raumfeld_enable_audio(false); |
157 | return 0; | 157 | return 0; |
158 | } | 158 | } |
159 | 159 | ||
160 | static int raumfeld_line_resume(struct platform_device *pdev) | 160 | static int raumfeld_line_resume(struct snd_soc_card *card) |
161 | { | 161 | { |
162 | raumfeld_enable_audio(true); | 162 | raumfeld_enable_audio(true); |
163 | return 0; | 163 | return 0; |
diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c index c2acb69b957a..8e1571350630 100644 --- a/sound/soc/pxa/spitz.c +++ b/sound/soc/pxa/spitz.c | |||
@@ -315,10 +315,10 @@ static int spitz_wm8750_init(struct snd_soc_pcm_runtime *rtd) | |||
315 | static struct snd_soc_dai_link spitz_dai = { | 315 | static struct snd_soc_dai_link spitz_dai = { |
316 | .name = "wm8750", | 316 | .name = "wm8750", |
317 | .stream_name = "WM8750", | 317 | .stream_name = "WM8750", |
318 | .cpu_dai_name = "pxa-is2", | 318 | .cpu_dai_name = "pxa2xx-i2s", |
319 | .codec_dai_name = "wm8750-hifi", | 319 | .codec_dai_name = "wm8750-hifi", |
320 | .platform_name = "pxa-pcm-audio", | 320 | .platform_name = "pxa-pcm-audio", |
321 | .codec_name = "wm8750-codec.0-001a", | 321 | .codec_name = "wm8750-codec.0-001b", |
322 | .init = spitz_wm8750_init, | 322 | .init = spitz_wm8750_init, |
323 | .ops = &spitz_ops, | 323 | .ops = &spitz_ops, |
324 | }; | 324 | }; |
diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c index f75804ef0897..489139a31cf9 100644 --- a/sound/soc/pxa/tosa.c +++ b/sound/soc/pxa/tosa.c | |||
@@ -237,7 +237,7 @@ static struct snd_soc_dai_link tosa_dai[] = { | |||
237 | }, | 237 | }, |
238 | }; | 238 | }; |
239 | 239 | ||
240 | static int tosa_probe(struct platform_device *dev) | 240 | static int tosa_probe(struct snd_soc_card *card) |
241 | { | 241 | { |
242 | int ret; | 242 | int ret; |
243 | 243 | ||
@@ -251,7 +251,7 @@ static int tosa_probe(struct platform_device *dev) | |||
251 | return ret; | 251 | return ret; |
252 | } | 252 | } |
253 | 253 | ||
254 | static int tosa_remove(struct platform_device *dev) | 254 | static int tosa_remove(struct snd_soc_card *card) |
255 | { | 255 | { |
256 | gpio_free(TOSA_GPIO_L_MUTE); | 256 | gpio_free(TOSA_GPIO_L_MUTE); |
257 | return 0; | 257 | return 0; |
diff --git a/sound/soc/pxa/zylonite.c b/sound/soc/pxa/zylonite.c index b222a7d72027..c5858296b48a 100644 --- a/sound/soc/pxa/zylonite.c +++ b/sound/soc/pxa/zylonite.c | |||
@@ -189,7 +189,7 @@ static struct snd_soc_dai_link zylonite_dai[] = { | |||
189 | }, | 189 | }, |
190 | }; | 190 | }; |
191 | 191 | ||
192 | static int zylonite_probe(struct platform_device *pdev) | 192 | static int zylonite_probe(struct snd_soc_card *card) |
193 | { | 193 | { |
194 | int ret; | 194 | int ret; |
195 | 195 | ||
@@ -216,7 +216,7 @@ static int zylonite_probe(struct platform_device *pdev) | |||
216 | return 0; | 216 | return 0; |
217 | } | 217 | } |
218 | 218 | ||
219 | static int zylonite_remove(struct platform_device *pdev) | 219 | static int zylonite_remove(struct snd_soc_card *card) |
220 | { | 220 | { |
221 | if (clk_pout) { | 221 | if (clk_pout) { |
222 | clk_disable(pout); | 222 | clk_disable(pout); |
@@ -226,8 +226,7 @@ static int zylonite_remove(struct platform_device *pdev) | |||
226 | return 0; | 226 | return 0; |
227 | } | 227 | } |
228 | 228 | ||
229 | static int zylonite_suspend_post(struct platform_device *pdev, | 229 | static int zylonite_suspend_post(struct snd_soc_card *card) |
230 | pm_message_t state) | ||
231 | { | 230 | { |
232 | if (clk_pout) | 231 | if (clk_pout) |
233 | clk_disable(pout); | 232 | clk_disable(pout); |
@@ -235,7 +234,7 @@ static int zylonite_suspend_post(struct platform_device *pdev, | |||
235 | return 0; | 234 | return 0; |
236 | } | 235 | } |
237 | 236 | ||
238 | static int zylonite_resume_pre(struct platform_device *pdev) | 237 | static int zylonite_resume_pre(struct snd_soc_card *card) |
239 | { | 238 | { |
240 | int ret = 0; | 239 | int ret = 0; |
241 | 240 | ||
diff --git a/sound/soc/samsung/neo1973_gta02_wm8753.c b/sound/soc/samsung/neo1973_gta02_wm8753.c index 69e08fd1ff00..95ebf812b146 100644 --- a/sound/soc/samsung/neo1973_gta02_wm8753.c +++ b/sound/soc/samsung/neo1973_gta02_wm8753.c | |||
@@ -387,11 +387,11 @@ static struct snd_soc_dai_link neo1973_gta02_dai[] = { | |||
387 | { /* Hifi Playback - for similatious use with voice below */ | 387 | { /* Hifi Playback - for similatious use with voice below */ |
388 | .name = "WM8753", | 388 | .name = "WM8753", |
389 | .stream_name = "WM8753 HiFi", | 389 | .stream_name = "WM8753 HiFi", |
390 | .cpu_dai_name = "s3c24xx-i2s", | 390 | .cpu_dai_name = "s3c24xx-iis", |
391 | .codec_dai_name = "wm8753-hifi", | 391 | .codec_dai_name = "wm8753-hifi", |
392 | .init = neo1973_gta02_wm8753_init, | 392 | .init = neo1973_gta02_wm8753_init, |
393 | .platform_name = "samsung-audio", | 393 | .platform_name = "samsung-audio", |
394 | .codec_name = "wm8753-codec.0-0x1a", | 394 | .codec_name = "wm8753-codec.0-001a", |
395 | .ops = &neo1973_gta02_hifi_ops, | 395 | .ops = &neo1973_gta02_hifi_ops, |
396 | }, | 396 | }, |
397 | { /* Voice via BT */ | 397 | { /* Voice via BT */ |
@@ -400,7 +400,7 @@ static struct snd_soc_dai_link neo1973_gta02_dai[] = { | |||
400 | .cpu_dai_name = "bluetooth-dai", | 400 | .cpu_dai_name = "bluetooth-dai", |
401 | .codec_dai_name = "wm8753-voice", | 401 | .codec_dai_name = "wm8753-voice", |
402 | .ops = &neo1973_gta02_voice_ops, | 402 | .ops = &neo1973_gta02_voice_ops, |
403 | .codec_name = "wm8753-codec.0-0x1a", | 403 | .codec_name = "wm8753-codec.0-001a", |
404 | .platform_name = "samsung-audio", | 404 | .platform_name = "samsung-audio", |
405 | }, | 405 | }, |
406 | }; | 406 | }; |
diff --git a/sound/soc/samsung/neo1973_wm8753.c b/sound/soc/samsung/neo1973_wm8753.c index c7a24514beb5..d3cd6888a810 100644 --- a/sound/soc/samsung/neo1973_wm8753.c +++ b/sound/soc/samsung/neo1973_wm8753.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include <sound/tlv.h> | 24 | #include <sound/tlv.h> |
25 | 25 | ||
26 | #include <asm/mach-types.h> | 26 | #include <asm/mach-types.h> |
27 | #include <asm/hardware/scoop.h> | ||
28 | #include <mach/regs-clock.h> | 27 | #include <mach/regs-clock.h> |
29 | #include <mach/regs-gpio.h> | 28 | #include <mach/regs-gpio.h> |
30 | #include <mach/hardware.h> | 29 | #include <mach/hardware.h> |
@@ -559,9 +558,9 @@ static struct snd_soc_dai_link neo1973_dai[] = { | |||
559 | .name = "WM8753", | 558 | .name = "WM8753", |
560 | .stream_name = "WM8753 HiFi", | 559 | .stream_name = "WM8753 HiFi", |
561 | .platform_name = "samsung-audio", | 560 | .platform_name = "samsung-audio", |
562 | .cpu_dai_name = "s3c24xx-i2s", | 561 | .cpu_dai_name = "s3c24xx-iis", |
563 | .codec_dai_name = "wm8753-hifi", | 562 | .codec_dai_name = "wm8753-hifi", |
564 | .codec_name = "wm8753-codec.0-0x1a", | 563 | .codec_name = "wm8753-codec.0-001a", |
565 | .init = neo1973_wm8753_init, | 564 | .init = neo1973_wm8753_init, |
566 | .ops = &neo1973_hifi_ops, | 565 | .ops = &neo1973_hifi_ops, |
567 | }, | 566 | }, |
@@ -571,7 +570,7 @@ static struct snd_soc_dai_link neo1973_dai[] = { | |||
571 | .platform_name = "samsung-audio", | 570 | .platform_name = "samsung-audio", |
572 | .cpu_dai_name = "bluetooth-dai", | 571 | .cpu_dai_name = "bluetooth-dai", |
573 | .codec_dai_name = "wm8753-voice", | 572 | .codec_dai_name = "wm8753-voice", |
574 | .codec_name = "wm8753-codec.0-0x1a", | 573 | .codec_name = "wm8753-codec.0-001a", |
575 | .ops = &neo1973_voice_ops, | 574 | .ops = &neo1973_voice_ops, |
576 | }, | 575 | }, |
577 | }; | 576 | }; |
diff --git a/sound/soc/samsung/s3c24xx_simtec_hermes.c b/sound/soc/samsung/s3c24xx_simtec_hermes.c index d7b3e6e9d783..ce6aef604179 100644 --- a/sound/soc/samsung/s3c24xx_simtec_hermes.c +++ b/sound/soc/samsung/s3c24xx_simtec_hermes.c | |||
@@ -84,8 +84,8 @@ static int simtec_hermes_init(struct snd_soc_pcm_runtime *rtd) | |||
84 | static struct snd_soc_dai_link simtec_dai_aic33 = { | 84 | static struct snd_soc_dai_link simtec_dai_aic33 = { |
85 | .name = "tlv320aic33", | 85 | .name = "tlv320aic33", |
86 | .stream_name = "TLV320AIC33", | 86 | .stream_name = "TLV320AIC33", |
87 | .codec_name = "tlv320aic3x-codec.0-0x1a", | 87 | .codec_name = "tlv320aic3x-codec.0-001a", |
88 | .cpu_dai_name = "s3c24xx-i2s", | 88 | .cpu_dai_name = "s3c24xx-iis", |
89 | .codec_dai_name = "tlv320aic3x-hifi", | 89 | .codec_dai_name = "tlv320aic3x-hifi", |
90 | .platform_name = "samsung-audio", | 90 | .platform_name = "samsung-audio", |
91 | .init = simtec_hermes_init, | 91 | .init = simtec_hermes_init, |
diff --git a/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c b/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c index ff6168f5f2e0..a7ef7db54687 100644 --- a/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c +++ b/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c | |||
@@ -73,8 +73,8 @@ static int simtec_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd) | |||
73 | static struct snd_soc_dai_link simtec_dai_aic23 = { | 73 | static struct snd_soc_dai_link simtec_dai_aic23 = { |
74 | .name = "tlv320aic23", | 74 | .name = "tlv320aic23", |
75 | .stream_name = "TLV320AIC23", | 75 | .stream_name = "TLV320AIC23", |
76 | .codec_name = "tlv320aic3x-codec.0-0x1a", | 76 | .codec_name = "tlv320aic3x-codec.0-001a", |
77 | .cpu_dai_name = "s3c24xx-i2s", | 77 | .cpu_dai_name = "s3c24xx-iis", |
78 | .codec_dai_name = "tlv320aic3x-hifi", | 78 | .codec_dai_name = "tlv320aic3x-hifi", |
79 | .platform_name = "samsung-audio", | 79 | .platform_name = "samsung-audio", |
80 | .init = simtec_tlv320aic23_init, | 80 | .init = simtec_tlv320aic23_init, |
diff --git a/sound/soc/samsung/s3c24xx_uda134x.c b/sound/soc/samsung/s3c24xx_uda134x.c index ce749a10ec07..3cb700751078 100644 --- a/sound/soc/samsung/s3c24xx_uda134x.c +++ b/sound/soc/samsung/s3c24xx_uda134x.c | |||
@@ -221,7 +221,7 @@ static struct snd_soc_dai_link s3c24xx_uda134x_dai_link = { | |||
221 | .stream_name = "UDA134X", | 221 | .stream_name = "UDA134X", |
222 | .codec_name = "uda134x-hifi", | 222 | .codec_name = "uda134x-hifi", |
223 | .codec_dai_name = "uda134x-hifi", | 223 | .codec_dai_name = "uda134x-hifi", |
224 | .cpu_dai_name = "s3c24xx-i2s", | 224 | .cpu_dai_name = "s3c24xx-iis", |
225 | .ops = &s3c24xx_uda134x_ops, | 225 | .ops = &s3c24xx_uda134x_ops, |
226 | .platform_name = "samsung-audio", | 226 | .platform_name = "samsung-audio", |
227 | }; | 227 | }; |
diff --git a/sound/soc/sh/fsi-ak4642.c b/sound/soc/sh/fsi-ak4642.c index 56cd34223100..d6f4703b3c07 100644 --- a/sound/soc/sh/fsi-ak4642.c +++ b/sound/soc/sh/fsi-ak4642.c | |||
@@ -23,14 +23,21 @@ struct fsi_ak4642_data { | |||
23 | 23 | ||
24 | static int fsi_ak4642_dai_init(struct snd_soc_pcm_runtime *rtd) | 24 | static int fsi_ak4642_dai_init(struct snd_soc_pcm_runtime *rtd) |
25 | { | 25 | { |
26 | 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; | ||
27 | int ret; | 28 | int ret; |
28 | 29 | ||
29 | 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); | ||
30 | if (ret < 0) | 32 | if (ret < 0) |
31 | return ret; | 33 | return ret; |
32 | 34 | ||
33 | 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_LEFT_J | | ||
40 | SND_SOC_DAIFMT_CBS_CFS); | ||
34 | 41 | ||
35 | return ret; | 42 | return ret; |
36 | } | 43 | } |
diff --git a/sound/soc/sh/fsi-da7210.c b/sound/soc/sh/fsi-da7210.c index e8df9da92f71..dbafd7ac5590 100644 --- a/sound/soc/sh/fsi-da7210.c +++ b/sound/soc/sh/fsi-da7210.c | |||
@@ -15,11 +15,20 @@ | |||
15 | 15 | ||
16 | static int fsi_da7210_init(struct snd_soc_pcm_runtime *rtd) | 16 | static 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_I2S | | ||
29 | SND_SOC_DAIFMT_CBS_CFS); | ||
30 | |||
31 | return ret; | ||
23 | } | 32 | } |
24 | 33 | ||
25 | static struct snd_soc_dai_link fsi_da7210_dai = { | 34 | static 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 | ||
15 | struct fsi_hdmi_data { | ||
16 | const char *cpu_dai; | ||
17 | const char *card; | ||
18 | int id; | ||
19 | }; | ||
20 | |||
21 | static 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 | |||
15 | static struct snd_soc_dai_link fsi_dai_link = { | 31 | static 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 | ||
24 | static struct snd_soc_card fsi_soc_card = { | 40 | static 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 | ||
30 | static struct platform_device *fsi_snd_device; | 45 | static struct platform_device *fsi_snd_device; |
31 | 46 | ||
32 | static int __init fsi_hdmi_init(void) | 47 | static 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 | ||
50 | static void __exit fsi_hdmi_exit(void) | 78 | static 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 | |||
84 | static 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 | |||
90 | static 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 | |||
96 | static 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 | |||
103 | static 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 | |||
112 | static int __init fsi_hdmi_init(void) | ||
113 | { | ||
114 | return platform_driver_register(&fsi_hdmi); | ||
115 | } | ||
116 | |||
117 | static void __exit fsi_hdmi_exit(void) | ||
118 | { | ||
119 | platform_driver_unregister(&fsi_hdmi); | ||
53 | } | 120 | } |
54 | 121 | ||
55 | module_init(fsi_hdmi_init); | 122 | module_init(fsi_hdmi_init); |
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 2b06402801ef..0c9997e2d8c0 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 */ |
@@ -111,6 +113,8 @@ | |||
111 | 113 | ||
112 | #define FSI_FMTS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE) | 114 | #define FSI_FMTS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE) |
113 | 115 | ||
116 | typedef int (*set_rate_func)(struct device *dev, int is_porta, int rate, int enable); | ||
117 | |||
114 | /* | 118 | /* |
115 | * FSI driver use below type name for variable | 119 | * FSI driver use below type name for variable |
116 | * | 120 | * |
@@ -128,7 +132,6 @@ struct fsi_stream { | |||
128 | struct snd_pcm_substream *substream; | 132 | struct snd_pcm_substream *substream; |
129 | 133 | ||
130 | int fifo_max_num; | 134 | int fifo_max_num; |
131 | int chan_num; | ||
132 | 135 | ||
133 | int buff_offset; | 136 | int buff_offset; |
134 | int buff_len; | 137 | int buff_len; |
@@ -143,6 +146,7 @@ struct fsi_priv { | |||
143 | void __iomem *base; | 146 | void __iomem *base; |
144 | struct fsi_master *master; | 147 | struct fsi_master *master; |
145 | 148 | ||
149 | int chan_num; | ||
146 | struct fsi_stream playback; | 150 | struct fsi_stream playback; |
147 | struct fsi_stream capture; | 151 | struct fsi_stream capture; |
148 | 152 | ||
@@ -252,9 +256,8 @@ static struct snd_soc_dai *fsi_get_dai(struct snd_pcm_substream *substream) | |||
252 | return rtd->cpu_dai; | 256 | return rtd->cpu_dai; |
253 | } | 257 | } |
254 | 258 | ||
255 | static struct fsi_priv *fsi_get_priv(struct snd_pcm_substream *substream) | 259 | static struct fsi_priv *fsi_get_priv_frm_dai(struct snd_soc_dai *dai) |
256 | { | 260 | { |
257 | struct snd_soc_dai *dai = fsi_get_dai(substream); | ||
258 | struct fsi_master *master = snd_soc_dai_get_drvdata(dai); | 261 | struct fsi_master *master = snd_soc_dai_get_drvdata(dai); |
259 | 262 | ||
260 | if (dai->id == 0) | 263 | if (dai->id == 0) |
@@ -263,11 +266,27 @@ static struct fsi_priv *fsi_get_priv(struct snd_pcm_substream *substream) | |||
263 | return &master->fsib; | 266 | return &master->fsib; |
264 | } | 267 | } |
265 | 268 | ||
269 | static struct fsi_priv *fsi_get_priv(struct snd_pcm_substream *substream) | ||
270 | { | ||
271 | return fsi_get_priv_frm_dai(fsi_get_dai(substream)); | ||
272 | } | ||
273 | |||
274 | static set_rate_func fsi_get_info_set_rate(struct fsi_master *master) | ||
275 | { | ||
276 | if (!master->info) | ||
277 | return NULL; | ||
278 | |||
279 | return master->info->set_rate; | ||
280 | } | ||
281 | |||
266 | static u32 fsi_get_info_flags(struct fsi_priv *fsi) | 282 | static u32 fsi_get_info_flags(struct fsi_priv *fsi) |
267 | { | 283 | { |
268 | int is_porta = fsi_is_port_a(fsi); | 284 | int is_porta = fsi_is_port_a(fsi); |
269 | struct fsi_master *master = fsi_get_master(fsi); | 285 | struct fsi_master *master = fsi_get_master(fsi); |
270 | 286 | ||
287 | if (!master->info) | ||
288 | return 0; | ||
289 | |||
271 | return is_porta ? master->info->porta_flags : | 290 | return is_porta ? master->info->porta_flags : |
272 | master->info->portb_flags; | 291 | master->info->portb_flags; |
273 | } | 292 | } |
@@ -288,21 +307,6 @@ static inline struct fsi_stream *fsi_get_stream(struct fsi_priv *fsi, | |||
288 | return is_play ? &fsi->playback : &fsi->capture; | 307 | return is_play ? &fsi->playback : &fsi->capture; |
289 | } | 308 | } |
290 | 309 | ||
291 | static 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 | |||
306 | static u32 fsi_get_port_shift(struct fsi_priv *fsi, int is_play) | 310 | static u32 fsi_get_port_shift(struct fsi_priv *fsi, int is_play) |
307 | { | 311 | { |
308 | int is_porta = fsi_is_port_a(fsi); | 312 | int is_porta = fsi_is_port_a(fsi); |
@@ -357,7 +361,6 @@ static void fsi_stream_pop(struct fsi_priv *fsi, int is_play) | |||
357 | static int fsi_get_fifo_data_num(struct fsi_priv *fsi, int is_play) | 361 | static int fsi_get_fifo_data_num(struct fsi_priv *fsi, int is_play) |
358 | { | 362 | { |
359 | u32 status; | 363 | u32 status; |
360 | struct fsi_stream *io = fsi_get_stream(fsi, is_play); | ||
361 | int data_num; | 364 | int data_num; |
362 | 365 | ||
363 | status = is_play ? | 366 | status = is_play ? |
@@ -365,7 +368,7 @@ static int fsi_get_fifo_data_num(struct fsi_priv *fsi, int is_play) | |||
365 | fsi_reg_read(fsi, DIFF_ST); | 368 | fsi_reg_read(fsi, DIFF_ST); |
366 | 369 | ||
367 | data_num = 0x1ff & (status >> 8); | 370 | data_num = 0x1ff & (status >> 8); |
368 | data_num *= io->chan_num; | 371 | data_num *= fsi->chan_num; |
369 | 372 | ||
370 | return data_num; | 373 | return data_num; |
371 | } | 374 | } |
@@ -387,7 +390,7 @@ static int fsi_get_frame_width(struct fsi_priv *fsi, int is_play) | |||
387 | struct snd_pcm_substream *substream = io->substream; | 390 | struct snd_pcm_substream *substream = io->substream; |
388 | struct snd_pcm_runtime *runtime = substream->runtime; | 391 | struct snd_pcm_runtime *runtime = substream->runtime; |
389 | 392 | ||
390 | return frames_to_bytes(runtime, 1) / io->chan_num; | 393 | return frames_to_bytes(runtime, 1) / fsi->chan_num; |
391 | } | 394 | } |
392 | 395 | ||
393 | static void fsi_count_fifo_err(struct fsi_priv *fsi) | 396 | static void fsi_count_fifo_err(struct fsi_priv *fsi) |
@@ -580,10 +583,10 @@ static void fsi_fifo_init(struct fsi_priv *fsi, | |||
580 | * 7 channels: 32 ( 32 x 7 = 224) | 583 | * 7 channels: 32 ( 32 x 7 = 224) |
581 | * 8 channels: 32 ( 32 x 8 = 256) | 584 | * 8 channels: 32 ( 32 x 8 = 256) |
582 | */ | 585 | */ |
583 | for (i = 1; i < io->chan_num; i <<= 1) | 586 | for (i = 1; i < fsi->chan_num; i <<= 1) |
584 | io->fifo_max_num >>= 1; | 587 | io->fifo_max_num >>= 1; |
585 | dev_dbg(dai->dev, "%d channel %d store\n", | 588 | dev_dbg(dai->dev, "%d channel %d store\n", |
586 | io->chan_num, io->fifo_max_num); | 589 | fsi->chan_num, io->fifo_max_num); |
587 | 590 | ||
588 | /* | 591 | /* |
589 | * set interrupt generation factor | 592 | * set interrupt generation factor |
@@ -659,7 +662,7 @@ static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream) | |||
659 | * data_num_max : number of FSI fifo free space | 662 | * data_num_max : number of FSI fifo free space |
660 | * data_num : number of ALSA residue data | 663 | * data_num : number of ALSA residue data |
661 | */ | 664 | */ |
662 | data_num_max = io->fifo_max_num * io->chan_num; | 665 | data_num_max = io->fifo_max_num * fsi->chan_num; |
663 | data_num_max -= fsi_get_fifo_data_num(fsi, is_play); | 666 | data_num_max -= fsi_get_fifo_data_num(fsi, is_play); |
664 | 667 | ||
665 | data_num = data_residue_num; | 668 | data_num = data_residue_num; |
@@ -754,25 +757,12 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream, | |||
754 | struct snd_soc_dai *dai) | 757 | struct snd_soc_dai *dai) |
755 | { | 758 | { |
756 | struct fsi_priv *fsi = fsi_get_priv(substream); | 759 | struct fsi_priv *fsi = fsi_get_priv(substream); |
757 | struct fsi_master *master = fsi_get_master(fsi); | ||
758 | struct fsi_stream *io; | ||
759 | u32 flags = fsi_get_info_flags(fsi); | 760 | u32 flags = fsi_get_info_flags(fsi); |
760 | u32 fmt; | ||
761 | u32 data; | 761 | u32 data; |
762 | int is_play = fsi_is_play(substream); | 762 | int is_play = fsi_is_play(substream); |
763 | int is_master; | ||
764 | |||
765 | io = fsi_get_stream(fsi, is_play); | ||
766 | 763 | ||
767 | pm_runtime_get_sync(dai->dev); | 764 | pm_runtime_get_sync(dai->dev); |
768 | 765 | ||
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 | 766 | ||
777 | /* clock inversion (CKG2) */ | 767 | /* clock inversion (CKG2) */ |
778 | data = 0; | 768 | data = 0; |
@@ -787,54 +777,6 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream, | |||
787 | 777 | ||
788 | fsi_reg_write(fsi, CKG2, data); | 778 | fsi_reg_write(fsi, CKG2, data); |
789 | 779 | ||
790 | /* do fmt, di fmt */ | ||
791 | data = 0; | ||
792 | fmt = is_play ? SH_FSI_GET_OFMT(flags) : SH_FSI_GET_IFMT(flags); | ||
793 | switch (fmt) { | ||
794 | case SH_FSI_FMT_MONO: | ||
795 | data = CR_MONO; | ||
796 | io->chan_num = 1; | ||
797 | break; | ||
798 | case SH_FSI_FMT_MONO_DELAY: | ||
799 | data = CR_MONO_D; | ||
800 | io->chan_num = 1; | ||
801 | break; | ||
802 | case SH_FSI_FMT_PCM: | ||
803 | data = CR_PCM; | ||
804 | io->chan_num = 2; | ||
805 | break; | ||
806 | case SH_FSI_FMT_I2S: | ||
807 | data = CR_I2S; | ||
808 | io->chan_num = 2; | ||
809 | break; | ||
810 | case SH_FSI_FMT_TDM: | ||
811 | io->chan_num = is_play ? | ||
812 | SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags); | ||
813 | data = CR_TDM | (io->chan_num - 1); | ||
814 | break; | ||
815 | case SH_FSI_FMT_TDM_DELAY: | ||
816 | io->chan_num = is_play ? | ||
817 | SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags); | ||
818 | data = CR_TDM_D | (io->chan_num - 1); | ||
819 | break; | ||
820 | case SH_FSI_FMT_SPDIF: | ||
821 | if (master->core->ver < 2) { | ||
822 | dev_err(dai->dev, "This FSI can not use SPDIF\n"); | ||
823 | return -EINVAL; | ||
824 | } | ||
825 | data = CR_BWS_16 | CR_DTMD_SPDIF_PCM | CR_PCM; | ||
826 | io->chan_num = 2; | ||
827 | fsi_spdif_clk_ctrl(fsi, 1); | ||
828 | fsi_reg_mask_set(fsi, OUT_SEL, DMMD, DMMD); | ||
829 | break; | ||
830 | default: | ||
831 | dev_err(dai->dev, "unknown format.\n"); | ||
832 | return -EINVAL; | ||
833 | } | ||
834 | is_play ? | ||
835 | fsi_reg_write(fsi, DO_FMT, data) : | ||
836 | fsi_reg_write(fsi, DI_FMT, data); | ||
837 | |||
838 | /* irq clear */ | 780 | /* irq clear */ |
839 | fsi_irq_disable(fsi, is_play); | 781 | fsi_irq_disable(fsi, is_play); |
840 | fsi_irq_clear_status(fsi); | 782 | fsi_irq_clear_status(fsi); |
@@ -851,12 +793,12 @@ static void fsi_dai_shutdown(struct snd_pcm_substream *substream, | |||
851 | struct fsi_priv *fsi = fsi_get_priv(substream); | 793 | struct fsi_priv *fsi = fsi_get_priv(substream); |
852 | int is_play = fsi_is_play(substream); | 794 | int is_play = fsi_is_play(substream); |
853 | struct fsi_master *master = fsi_get_master(fsi); | 795 | struct fsi_master *master = fsi_get_master(fsi); |
854 | int (*set_rate)(struct device *dev, int is_porta, int rate, int enable); | 796 | set_rate_func set_rate; |
855 | 797 | ||
856 | fsi_irq_disable(fsi, is_play); | 798 | fsi_irq_disable(fsi, is_play); |
857 | fsi_clk_ctrl(fsi, 0); | 799 | fsi_clk_ctrl(fsi, 0); |
858 | 800 | ||
859 | set_rate = master->info->set_rate; | 801 | set_rate = fsi_get_info_set_rate(master); |
860 | if (set_rate && fsi->rate) | 802 | if (set_rate && fsi->rate) |
861 | set_rate(dai->dev, fsi_is_port_a(fsi), fsi->rate, 0); | 803 | set_rate(dai->dev, fsi_is_port_a(fsi), fsi->rate, 0); |
862 | fsi->rate = 0; | 804 | fsi->rate = 0; |
@@ -889,18 +831,100 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd, | |||
889 | return ret; | 831 | return ret; |
890 | } | 832 | } |
891 | 833 | ||
834 | static int fsi_set_fmt_dai(struct fsi_priv *fsi, unsigned int fmt) | ||
835 | { | ||
836 | u32 data = 0; | ||
837 | |||
838 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
839 | case SND_SOC_DAIFMT_I2S: | ||
840 | data = CR_I2S; | ||
841 | fsi->chan_num = 2; | ||
842 | break; | ||
843 | case SND_SOC_DAIFMT_LEFT_J: | ||
844 | data = CR_PCM; | ||
845 | fsi->chan_num = 2; | ||
846 | break; | ||
847 | default: | ||
848 | return -EINVAL; | ||
849 | } | ||
850 | |||
851 | fsi_reg_write(fsi, DO_FMT, data); | ||
852 | fsi_reg_write(fsi, DI_FMT, data); | ||
853 | |||
854 | return 0; | ||
855 | } | ||
856 | |||
857 | static int fsi_set_fmt_spdif(struct fsi_priv *fsi) | ||
858 | { | ||
859 | struct fsi_master *master = fsi_get_master(fsi); | ||
860 | u32 data = 0; | ||
861 | |||
862 | if (master->core->ver < 2) | ||
863 | return -EINVAL; | ||
864 | |||
865 | data = CR_BWS_16 | CR_DTMD_SPDIF_PCM | CR_PCM; | ||
866 | fsi->chan_num = 2; | ||
867 | fsi_spdif_clk_ctrl(fsi, 1); | ||
868 | fsi_reg_mask_set(fsi, OUT_SEL, DMMD, DMMD); | ||
869 | |||
870 | fsi_reg_write(fsi, DO_FMT, data); | ||
871 | fsi_reg_write(fsi, DI_FMT, data); | ||
872 | |||
873 | return 0; | ||
874 | } | ||
875 | |||
876 | static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
877 | { | ||
878 | struct fsi_priv *fsi = fsi_get_priv_frm_dai(dai); | ||
879 | u32 flags = fsi_get_info_flags(fsi); | ||
880 | u32 data = 0; | ||
881 | int ret; | ||
882 | |||
883 | pm_runtime_get_sync(dai->dev); | ||
884 | |||
885 | /* set master/slave audio interface */ | ||
886 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
887 | case SND_SOC_DAIFMT_CBM_CFM: | ||
888 | data = DIMD | DOMD; | ||
889 | break; | ||
890 | case SND_SOC_DAIFMT_CBS_CFS: | ||
891 | break; | ||
892 | default: | ||
893 | ret = -EINVAL; | ||
894 | goto set_fmt_exit; | ||
895 | } | ||
896 | fsi_reg_mask_set(fsi, CKG1, (DIMD | DOMD), data); | ||
897 | |||
898 | /* set format */ | ||
899 | switch (flags & SH_FSI_FMT_MASK) { | ||
900 | case SH_FSI_FMT_DAI: | ||
901 | ret = fsi_set_fmt_dai(fsi, fmt & SND_SOC_DAIFMT_FORMAT_MASK); | ||
902 | break; | ||
903 | case SH_FSI_FMT_SPDIF: | ||
904 | ret = fsi_set_fmt_spdif(fsi); | ||
905 | break; | ||
906 | default: | ||
907 | ret = -EINVAL; | ||
908 | } | ||
909 | |||
910 | set_fmt_exit: | ||
911 | pm_runtime_put_sync(dai->dev); | ||
912 | |||
913 | return ret; | ||
914 | } | ||
915 | |||
892 | static int fsi_dai_hw_params(struct snd_pcm_substream *substream, | 916 | static int fsi_dai_hw_params(struct snd_pcm_substream *substream, |
893 | struct snd_pcm_hw_params *params, | 917 | struct snd_pcm_hw_params *params, |
894 | struct snd_soc_dai *dai) | 918 | struct snd_soc_dai *dai) |
895 | { | 919 | { |
896 | struct fsi_priv *fsi = fsi_get_priv(substream); | 920 | struct fsi_priv *fsi = fsi_get_priv(substream); |
897 | struct fsi_master *master = fsi_get_master(fsi); | 921 | struct fsi_master *master = fsi_get_master(fsi); |
898 | int (*set_rate)(struct device *dev, int is_porta, int rate, int enable); | 922 | set_rate_func set_rate; |
899 | int fsi_ver = master->core->ver; | 923 | int fsi_ver = master->core->ver; |
900 | long rate = params_rate(params); | 924 | long rate = params_rate(params); |
901 | int ret; | 925 | int ret; |
902 | 926 | ||
903 | set_rate = master->info->set_rate; | 927 | set_rate = fsi_get_info_set_rate(master); |
904 | if (!set_rate) | 928 | if (!set_rate) |
905 | return 0; | 929 | return 0; |
906 | 930 | ||
@@ -975,6 +999,7 @@ static struct snd_soc_dai_ops fsi_dai_ops = { | |||
975 | .startup = fsi_dai_startup, | 999 | .startup = fsi_dai_startup, |
976 | .shutdown = fsi_dai_shutdown, | 1000 | .shutdown = fsi_dai_shutdown, |
977 | .trigger = fsi_dai_trigger, | 1001 | .trigger = fsi_dai_trigger, |
1002 | .set_fmt = fsi_dai_set_fmt, | ||
978 | .hw_params = fsi_dai_hw_params, | 1003 | .hw_params = fsi_dai_hw_params, |
979 | }; | 1004 | }; |
980 | 1005 | ||
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index d97a59f6a249..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 | |||
21 | static unsigned int snd_soc_4_12_read(struct snd_soc_codec *codec, | 23 | static 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; |
@@ -878,7 +892,9 @@ static int snd_soc_rbtree_cache_sync(struct snd_soc_codec *codec) | |||
878 | ret = snd_soc_cache_read(codec, rbnode->reg, &val); | 892 | ret = snd_soc_cache_read(codec, rbnode->reg, &val); |
879 | if (ret) | 893 | if (ret) |
880 | return ret; | 894 | return ret; |
895 | codec->cache_bypass = 1; | ||
881 | ret = snd_soc_write(codec, rbnode->reg, val); | 896 | ret = snd_soc_write(codec, rbnode->reg, val); |
897 | codec->cache_bypass = 0; | ||
882 | if (ret) | 898 | if (ret) |
883 | return ret; | 899 | return ret; |
884 | dev_dbg(codec->dev, "Synced register %#x, value = %#x\n", | 900 | dev_dbg(codec->dev, "Synced register %#x, value = %#x\n", |
@@ -1136,7 +1152,9 @@ static int snd_soc_lzo_cache_sync(struct snd_soc_codec *codec) | |||
1136 | ret = snd_soc_cache_read(codec, i, &val); | 1152 | ret = snd_soc_cache_read(codec, i, &val); |
1137 | if (ret) | 1153 | if (ret) |
1138 | return ret; | 1154 | return ret; |
1155 | codec->cache_bypass = 1; | ||
1139 | ret = snd_soc_write(codec, i, val); | 1156 | ret = snd_soc_write(codec, i, val); |
1157 | codec->cache_bypass = 0; | ||
1140 | if (ret) | 1158 | if (ret) |
1141 | return ret; | 1159 | return ret; |
1142 | dev_dbg(codec->dev, "Synced register %#x, value = %#x\n", | 1160 | dev_dbg(codec->dev, "Synced register %#x, value = %#x\n", |
@@ -1585,18 +1603,26 @@ EXPORT_SYMBOL_GPL(snd_soc_cache_write); | |||
1585 | int snd_soc_cache_sync(struct snd_soc_codec *codec) | 1603 | int snd_soc_cache_sync(struct snd_soc_codec *codec) |
1586 | { | 1604 | { |
1587 | int ret; | 1605 | int ret; |
1606 | const char *name; | ||
1588 | 1607 | ||
1589 | if (!codec->cache_sync) { | 1608 | if (!codec->cache_sync) { |
1590 | return 0; | 1609 | return 0; |
1591 | } | 1610 | } |
1592 | 1611 | ||
1612 | if (codec->cache_ops->name) | ||
1613 | name = codec->cache_ops->name; | ||
1614 | else | ||
1615 | name = "unknown"; | ||
1616 | |||
1593 | if (codec->cache_ops && codec->cache_ops->sync) { | 1617 | if (codec->cache_ops && codec->cache_ops->sync) { |
1594 | if (codec->cache_ops->name) | 1618 | if (codec->cache_ops->name) |
1595 | dev_dbg(codec->dev, "Syncing %s cache for %s codec\n", | 1619 | dev_dbg(codec->dev, "Syncing %s cache for %s codec\n", |
1596 | codec->cache_ops->name, codec->name); | 1620 | codec->cache_ops->name, codec->name); |
1621 | trace_snd_soc_cache_sync(codec, name, "start"); | ||
1597 | ret = codec->cache_ops->sync(codec); | 1622 | ret = codec->cache_ops->sync(codec); |
1598 | if (!ret) | 1623 | if (!ret) |
1599 | codec->cache_sync = 0; | 1624 | codec->cache_sync = 0; |
1625 | trace_snd_soc_cache_sync(codec, name, "end"); | ||
1600 | return ret; | 1626 | return ret; |
1601 | } | 1627 | } |
1602 | 1628 | ||
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 9e68984423b2..205cbd7b149f 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -69,10 +69,32 @@ static int pmdown_time = 5000; | |||
69 | module_param(pmdown_time, int, 0); | 69 | module_param(pmdown_time, int, 0); |
70 | MODULE_PARM_DESC(pmdown_time, "DAPM stream powerdown time (msecs)"); | 70 | MODULE_PARM_DESC(pmdown_time, "DAPM stream powerdown time (msecs)"); |
71 | 71 | ||
72 | /* returns the minimum number of bytes needed to represent | ||
73 | * a particular given value */ | ||
74 | static int min_bytes_needed(unsigned long val) | ||
75 | { | ||
76 | int c = 0; | ||
77 | int i; | ||
78 | |||
79 | for (i = (sizeof val * 8) - 1; i >= 0; --i, ++c) | ||
80 | if (val & (1UL << i)) | ||
81 | break; | ||
82 | c = (sizeof val * 8) - c; | ||
83 | if (!c || (c % 8)) | ||
84 | c = (c + 8) / 8; | ||
85 | else | ||
86 | c /= 8; | ||
87 | return c; | ||
88 | } | ||
89 | |||
72 | /* codec register dump */ | 90 | /* codec register dump */ |
73 | static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf) | 91 | static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf) |
74 | { | 92 | { |
75 | int ret, i, step = 1, count = 0; | 93 | int ret, i, step = 1, count = 0; |
94 | int wordsize, regsize; | ||
95 | |||
96 | wordsize = codec->driver->reg_word_size * 2; | ||
97 | regsize = min_bytes_needed(codec->driver->reg_cache_size) * 2; | ||
76 | 98 | ||
77 | if (!codec->driver->reg_cache_size) | 99 | if (!codec->driver->reg_cache_size) |
78 | return 0; | 100 | return 0; |
@@ -80,12 +102,11 @@ static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf) | |||
80 | if (codec->driver->reg_cache_step) | 102 | if (codec->driver->reg_cache_step) |
81 | step = codec->driver->reg_cache_step; | 103 | step = codec->driver->reg_cache_step; |
82 | 104 | ||
83 | count += sprintf(buf, "%s registers\n", codec->name); | ||
84 | for (i = 0; i < codec->driver->reg_cache_size; i += step) { | 105 | for (i = 0; i < codec->driver->reg_cache_size; i += step) { |
85 | if (codec->readable_register && !codec->readable_register(codec, i)) | 106 | if (codec->readable_register && !codec->readable_register(codec, i)) |
86 | continue; | 107 | continue; |
87 | 108 | ||
88 | count += sprintf(buf + count, "%2x: ", i); | 109 | count += sprintf(buf + count, "%.*x: ", regsize, i); |
89 | if (count >= PAGE_SIZE - 1) | 110 | if (count >= PAGE_SIZE - 1) |
90 | break; | 111 | break; |
91 | 112 | ||
@@ -101,7 +122,7 @@ static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf) | |||
101 | if (ret >= 0) | 122 | if (ret >= 0) |
102 | count += snprintf(buf + count, | 123 | count += snprintf(buf + count, |
103 | PAGE_SIZE - count, | 124 | PAGE_SIZE - count, |
104 | "%4x", ret); | 125 | "%.*x", wordsize, ret); |
105 | else | 126 | else |
106 | count += snprintf(buf + count, | 127 | count += snprintf(buf + count, |
107 | PAGE_SIZE - count, | 128 | PAGE_SIZE - count, |
@@ -235,6 +256,11 @@ static void soc_init_codec_debugfs(struct snd_soc_codec *codec) | |||
235 | return; | 256 | return; |
236 | } | 257 | } |
237 | 258 | ||
259 | debugfs_create_bool("cache_sync", 0444, codec->debugfs_codec_root, | ||
260 | &codec->cache_sync); | ||
261 | debugfs_create_bool("cache_only", 0444, codec->debugfs_codec_root, | ||
262 | &codec->cache_only); | ||
263 | |||
238 | codec->debugfs_reg = debugfs_create_file("codec_reg", 0644, | 264 | codec->debugfs_reg = debugfs_create_file("codec_reg", 0644, |
239 | codec->debugfs_codec_root, | 265 | codec->debugfs_codec_root, |
240 | codec, &codec_reg_fops); | 266 | codec, &codec_reg_fops); |
@@ -965,12 +991,11 @@ static struct snd_pcm_ops soc_pcm_ops = { | |||
965 | .pointer = soc_pcm_pointer, | 991 | .pointer = soc_pcm_pointer, |
966 | }; | 992 | }; |
967 | 993 | ||
968 | #ifdef CONFIG_PM | 994 | #ifdef CONFIG_PM_SLEEP |
969 | /* powers down audio subsystem for suspend */ | 995 | /* powers down audio subsystem for suspend */ |
970 | static int soc_suspend(struct device *dev) | 996 | int snd_soc_suspend(struct device *dev) |
971 | { | 997 | { |
972 | struct platform_device *pdev = to_platform_device(dev); | 998 | struct snd_soc_card *card = dev_get_drvdata(dev); |
973 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
974 | struct snd_soc_codec *codec; | 999 | struct snd_soc_codec *codec; |
975 | int i; | 1000 | int i; |
976 | 1001 | ||
@@ -1011,7 +1036,7 @@ static int soc_suspend(struct device *dev) | |||
1011 | } | 1036 | } |
1012 | 1037 | ||
1013 | if (card->suspend_pre) | 1038 | if (card->suspend_pre) |
1014 | card->suspend_pre(pdev, PMSG_SUSPEND); | 1039 | card->suspend_pre(card); |
1015 | 1040 | ||
1016 | for (i = 0; i < card->num_rtd; i++) { | 1041 | for (i = 0; i < card->num_rtd; i++) { |
1017 | struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; | 1042 | struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; |
@@ -1078,10 +1103,11 @@ static int soc_suspend(struct device *dev) | |||
1078 | } | 1103 | } |
1079 | 1104 | ||
1080 | if (card->suspend_post) | 1105 | if (card->suspend_post) |
1081 | card->suspend_post(pdev, PMSG_SUSPEND); | 1106 | card->suspend_post(card); |
1082 | 1107 | ||
1083 | return 0; | 1108 | return 0; |
1084 | } | 1109 | } |
1110 | EXPORT_SYMBOL_GPL(snd_soc_suspend); | ||
1085 | 1111 | ||
1086 | /* deferred resume work, so resume can complete before we finished | 1112 | /* deferred resume work, so resume can complete before we finished |
1087 | * setting our codec back up, which can be very slow on I2C | 1113 | * setting our codec back up, which can be very slow on I2C |
@@ -1090,7 +1116,6 @@ static void soc_resume_deferred(struct work_struct *work) | |||
1090 | { | 1116 | { |
1091 | struct snd_soc_card *card = | 1117 | struct snd_soc_card *card = |
1092 | container_of(work, struct snd_soc_card, deferred_resume_work); | 1118 | container_of(work, struct snd_soc_card, deferred_resume_work); |
1093 | struct platform_device *pdev = to_platform_device(card->dev); | ||
1094 | struct snd_soc_codec *codec; | 1119 | struct snd_soc_codec *codec; |
1095 | int i; | 1120 | int i; |
1096 | 1121 | ||
@@ -1104,7 +1129,7 @@ static void soc_resume_deferred(struct work_struct *work) | |||
1104 | snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D2); | 1129 | snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D2); |
1105 | 1130 | ||
1106 | if (card->resume_pre) | 1131 | if (card->resume_pre) |
1107 | card->resume_pre(pdev); | 1132 | card->resume_pre(card); |
1108 | 1133 | ||
1109 | /* resume AC97 DAIs */ | 1134 | /* resume AC97 DAIs */ |
1110 | for (i = 0; i < card->num_rtd; i++) { | 1135 | for (i = 0; i < card->num_rtd; i++) { |
@@ -1179,7 +1204,7 @@ static void soc_resume_deferred(struct work_struct *work) | |||
1179 | } | 1204 | } |
1180 | 1205 | ||
1181 | if (card->resume_post) | 1206 | if (card->resume_post) |
1182 | card->resume_post(pdev); | 1207 | card->resume_post(card); |
1183 | 1208 | ||
1184 | dev_dbg(card->dev, "resume work completed\n"); | 1209 | dev_dbg(card->dev, "resume work completed\n"); |
1185 | 1210 | ||
@@ -1188,10 +1213,9 @@ static void soc_resume_deferred(struct work_struct *work) | |||
1188 | } | 1213 | } |
1189 | 1214 | ||
1190 | /* powers up audio subsystem after a suspend */ | 1215 | /* powers up audio subsystem after a suspend */ |
1191 | static int soc_resume(struct device *dev) | 1216 | int snd_soc_resume(struct device *dev) |
1192 | { | 1217 | { |
1193 | struct platform_device *pdev = to_platform_device(dev); | 1218 | struct snd_soc_card *card = dev_get_drvdata(dev); |
1194 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
1195 | int i; | 1219 | int i; |
1196 | 1220 | ||
1197 | /* AC97 devices might have other drivers hanging off them so | 1221 | /* AC97 devices might have other drivers hanging off them so |
@@ -1213,9 +1237,10 @@ static int soc_resume(struct device *dev) | |||
1213 | 1237 | ||
1214 | return 0; | 1238 | return 0; |
1215 | } | 1239 | } |
1240 | EXPORT_SYMBOL_GPL(snd_soc_resume); | ||
1216 | #else | 1241 | #else |
1217 | #define soc_suspend NULL | 1242 | #define snd_soc_suspend NULL |
1218 | #define soc_resume NULL | 1243 | #define snd_soc_resume NULL |
1219 | #endif | 1244 | #endif |
1220 | 1245 | ||
1221 | static struct snd_soc_dai_ops null_dai_ops = { | 1246 | static struct snd_soc_dai_ops null_dai_ops = { |
@@ -1408,26 +1433,31 @@ static int soc_probe_codec(struct snd_soc_card *card, | |||
1408 | codec->dapm.card = card; | 1433 | codec->dapm.card = card; |
1409 | soc_set_name_prefix(card, codec); | 1434 | soc_set_name_prefix(card, codec); |
1410 | 1435 | ||
1436 | if (!try_module_get(codec->dev->driver->owner)) | ||
1437 | return -ENODEV; | ||
1438 | |||
1411 | if (codec->driver->probe) { | 1439 | if (codec->driver->probe) { |
1412 | ret = codec->driver->probe(codec); | 1440 | ret = codec->driver->probe(codec); |
1413 | if (ret < 0) { | 1441 | if (ret < 0) { |
1414 | dev_err(codec->dev, | 1442 | dev_err(codec->dev, |
1415 | "asoc: failed to probe CODEC %s: %d\n", | 1443 | "asoc: failed to probe CODEC %s: %d\n", |
1416 | codec->name, ret); | 1444 | codec->name, ret); |
1417 | return ret; | 1445 | goto err_probe; |
1418 | } | 1446 | } |
1419 | } | 1447 | } |
1420 | 1448 | ||
1421 | soc_init_codec_debugfs(codec); | 1449 | soc_init_codec_debugfs(codec); |
1422 | 1450 | ||
1423 | /* mark codec as probed and add to card codec list */ | 1451 | /* mark codec as probed and add to card codec list */ |
1424 | if (!try_module_get(codec->dev->driver->owner)) | ||
1425 | return -ENODEV; | ||
1426 | |||
1427 | codec->probed = 1; | 1452 | codec->probed = 1; |
1428 | list_add(&codec->card_list, &card->codec_dev_list); | 1453 | list_add(&codec->card_list, &card->codec_dev_list); |
1429 | list_add(&codec->dapm.list, &card->dapm_list); | 1454 | list_add(&codec->dapm.list, &card->dapm_list); |
1430 | 1455 | ||
1456 | return 0; | ||
1457 | |||
1458 | err_probe: | ||
1459 | module_put(codec->dev->driver->owner); | ||
1460 | |||
1431 | return ret; | 1461 | return ret; |
1432 | } | 1462 | } |
1433 | 1463 | ||
@@ -1545,19 +1575,19 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num) | |||
1545 | 1575 | ||
1546 | /* probe the platform */ | 1576 | /* probe the platform */ |
1547 | if (!platform->probed) { | 1577 | if (!platform->probed) { |
1578 | if (!try_module_get(platform->dev->driver->owner)) | ||
1579 | return -ENODEV; | ||
1580 | |||
1548 | if (platform->driver->probe) { | 1581 | if (platform->driver->probe) { |
1549 | ret = platform->driver->probe(platform); | 1582 | ret = platform->driver->probe(platform); |
1550 | if (ret < 0) { | 1583 | if (ret < 0) { |
1551 | printk(KERN_ERR "asoc: failed to probe platform %s\n", | 1584 | printk(KERN_ERR "asoc: failed to probe platform %s\n", |
1552 | platform->name); | 1585 | platform->name); |
1586 | module_put(platform->dev->driver->owner); | ||
1553 | return ret; | 1587 | return ret; |
1554 | } | 1588 | } |
1555 | } | 1589 | } |
1556 | /* mark platform as probed and add to card platform list */ | 1590 | /* mark platform as probed and add to card platform list */ |
1557 | |||
1558 | if (!try_module_get(platform->dev->driver->owner)) | ||
1559 | return -ENODEV; | ||
1560 | |||
1561 | platform->probed = 1; | 1591 | platform->probed = 1; |
1562 | list_add(&platform->card_list, &card->platform_dev_list); | 1592 | list_add(&platform->card_list, &card->platform_dev_list); |
1563 | } | 1593 | } |
@@ -1666,9 +1696,6 @@ static int soc_probe_aux_dev(struct snd_soc_card *card, int num) | |||
1666 | goto out; | 1696 | goto out; |
1667 | 1697 | ||
1668 | found: | 1698 | found: |
1669 | if (!try_module_get(codec->dev->driver->owner)) | ||
1670 | return -ENODEV; | ||
1671 | |||
1672 | ret = soc_probe_codec(card, codec); | 1699 | ret = soc_probe_codec(card, codec); |
1673 | if (ret < 0) | 1700 | if (ret < 0) |
1674 | return ret; | 1701 | return ret; |
@@ -1718,7 +1745,6 @@ static int snd_soc_init_codec_cache(struct snd_soc_codec *codec, | |||
1718 | 1745 | ||
1719 | static void snd_soc_instantiate_card(struct snd_soc_card *card) | 1746 | static void snd_soc_instantiate_card(struct snd_soc_card *card) |
1720 | { | 1747 | { |
1721 | struct platform_device *pdev = to_platform_device(card->dev); | ||
1722 | struct snd_soc_codec *codec; | 1748 | struct snd_soc_codec *codec; |
1723 | struct snd_soc_codec_conf *codec_conf; | 1749 | struct snd_soc_codec_conf *codec_conf; |
1724 | enum snd_soc_compress_type compress_type; | 1750 | enum snd_soc_compress_type compress_type; |
@@ -1782,7 +1808,7 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card) | |||
1782 | 1808 | ||
1783 | /* initialise the sound card only once */ | 1809 | /* initialise the sound card only once */ |
1784 | if (card->probe) { | 1810 | if (card->probe) { |
1785 | ret = card->probe(pdev); | 1811 | ret = card->probe(card); |
1786 | if (ret < 0) | 1812 | if (ret < 0) |
1787 | goto card_probe_error; | 1813 | goto card_probe_error; |
1788 | } | 1814 | } |
@@ -1843,7 +1869,7 @@ probe_dai_err: | |||
1843 | 1869 | ||
1844 | card_probe_error: | 1870 | card_probe_error: |
1845 | if (card->remove) | 1871 | if (card->remove) |
1846 | card->remove(pdev); | 1872 | card->remove(card); |
1847 | 1873 | ||
1848 | snd_card_free(card->snd_card); | 1874 | snd_card_free(card->snd_card); |
1849 | 1875 | ||
@@ -1876,7 +1902,6 @@ static int soc_probe(struct platform_device *pdev) | |||
1876 | 1902 | ||
1877 | /* Bodge while we unpick instantiation */ | 1903 | /* Bodge while we unpick instantiation */ |
1878 | card->dev = &pdev->dev; | 1904 | card->dev = &pdev->dev; |
1879 | snd_soc_initialize_card_lists(card); | ||
1880 | 1905 | ||
1881 | ret = snd_soc_register_card(card); | 1906 | ret = snd_soc_register_card(card); |
1882 | if (ret != 0) { | 1907 | if (ret != 0) { |
@@ -1889,7 +1914,6 @@ static int soc_probe(struct platform_device *pdev) | |||
1889 | 1914 | ||
1890 | static int soc_cleanup_card_resources(struct snd_soc_card *card) | 1915 | static int soc_cleanup_card_resources(struct snd_soc_card *card) |
1891 | { | 1916 | { |
1892 | struct platform_device *pdev = to_platform_device(card->dev); | ||
1893 | int i; | 1917 | int i; |
1894 | 1918 | ||
1895 | /* make sure any delayed work runs */ | 1919 | /* make sure any delayed work runs */ |
@@ -1910,7 +1934,7 @@ static int soc_cleanup_card_resources(struct snd_soc_card *card) | |||
1910 | 1934 | ||
1911 | /* remove the card */ | 1935 | /* remove the card */ |
1912 | if (card->remove) | 1936 | if (card->remove) |
1913 | card->remove(pdev); | 1937 | card->remove(card); |
1914 | 1938 | ||
1915 | kfree(card->rtd); | 1939 | kfree(card->rtd); |
1916 | snd_card_free(card->snd_card); | 1940 | snd_card_free(card->snd_card); |
@@ -1927,10 +1951,9 @@ static int soc_remove(struct platform_device *pdev) | |||
1927 | return 0; | 1951 | return 0; |
1928 | } | 1952 | } |
1929 | 1953 | ||
1930 | static int soc_poweroff(struct device *dev) | 1954 | int snd_soc_poweroff(struct device *dev) |
1931 | { | 1955 | { |
1932 | struct platform_device *pdev = to_platform_device(dev); | 1956 | struct snd_soc_card *card = dev_get_drvdata(dev); |
1933 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
1934 | int i; | 1957 | int i; |
1935 | 1958 | ||
1936 | if (!card->instantiated) | 1959 | if (!card->instantiated) |
@@ -1947,11 +1970,12 @@ static int soc_poweroff(struct device *dev) | |||
1947 | 1970 | ||
1948 | return 0; | 1971 | return 0; |
1949 | } | 1972 | } |
1973 | EXPORT_SYMBOL_GPL(snd_soc_poweroff); | ||
1950 | 1974 | ||
1951 | static const struct dev_pm_ops soc_pm_ops = { | 1975 | const struct dev_pm_ops snd_soc_pm_ops = { |
1952 | .suspend = soc_suspend, | 1976 | .suspend = snd_soc_suspend, |
1953 | .resume = soc_resume, | 1977 | .resume = snd_soc_resume, |
1954 | .poweroff = soc_poweroff, | 1978 | .poweroff = snd_soc_poweroff, |
1955 | }; | 1979 | }; |
1956 | 1980 | ||
1957 | /* ASoC platform driver */ | 1981 | /* ASoC platform driver */ |
@@ -1959,7 +1983,7 @@ static struct platform_driver soc_driver = { | |||
1959 | .driver = { | 1983 | .driver = { |
1960 | .name = "soc-audio", | 1984 | .name = "soc-audio", |
1961 | .owner = THIS_MODULE, | 1985 | .owner = THIS_MODULE, |
1962 | .pm = &soc_pm_ops, | 1986 | .pm = &snd_soc_pm_ops, |
1963 | }, | 1987 | }, |
1964 | .probe = soc_probe, | 1988 | .probe = soc_probe, |
1965 | .remove = soc_remove, | 1989 | .remove = soc_remove, |
@@ -2029,7 +2053,8 @@ static int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) | |||
2029 | * | 2053 | * |
2030 | * Boolean function indiciating if a CODEC register is volatile. | 2054 | * Boolean function indiciating if a CODEC register is volatile. |
2031 | */ | 2055 | */ |
2032 | int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, int reg) | 2056 | int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, |
2057 | unsigned int reg) | ||
2033 | { | 2058 | { |
2034 | if (codec->volatile_register) | 2059 | if (codec->volatile_register) |
2035 | return codec->volatile_register(codec, reg); | 2060 | return codec->volatile_register(codec, reg); |
@@ -3117,6 +3142,8 @@ int snd_soc_register_card(struct snd_soc_card *card) | |||
3117 | if (!card->name || !card->dev) | 3142 | if (!card->name || !card->dev) |
3118 | return -EINVAL; | 3143 | return -EINVAL; |
3119 | 3144 | ||
3145 | snd_soc_initialize_card_lists(card); | ||
3146 | |||
3120 | soc_init_card_debugfs(card); | 3147 | soc_init_card_debugfs(card); |
3121 | 3148 | ||
3122 | card->rtd = kzalloc(sizeof(struct snd_soc_pcm_runtime) * | 3149 | card->rtd = kzalloc(sizeof(struct snd_soc_pcm_runtime) * |
@@ -3496,6 +3523,7 @@ int snd_soc_register_codec(struct device *dev, | |||
3496 | codec->dapm.bias_level = SND_SOC_BIAS_OFF; | 3523 | codec->dapm.bias_level = SND_SOC_BIAS_OFF; |
3497 | codec->dapm.dev = dev; | 3524 | codec->dapm.dev = dev; |
3498 | codec->dapm.codec = codec; | 3525 | codec->dapm.codec = codec; |
3526 | codec->dapm.seq_notifier = codec_drv->seq_notifier; | ||
3499 | codec->dev = dev; | 3527 | codec->dev = dev; |
3500 | codec->driver = codec_drv; | 3528 | codec->driver = codec_drv; |
3501 | codec->num_dai = num_dai; | 3529 | codec->num_dai = num_dai; |
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 499730ab5638..d0342aab2c15 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 | ||
727 | static int dapm_seq_compare(struct snd_soc_dapm_widget *a, | 727 | static 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. */ |
742 | static void dapm_seq_insert(struct snd_soc_dapm_widget *new_widget, | 755 | static 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,42 @@ static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm, | |||
857 | * handled. | 870 | * handled. |
858 | */ | 871 | */ |
859 | static void dapm_seq_run(struct snd_soc_dapm_context *dapm, | 872 | static 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 | cur_subseq); | ||
904 | } | ||
905 | |||
878 | INIT_LIST_HEAD(&pending); | 906 | INIT_LIST_HEAD(&pending); |
879 | cur_sort = -1; | 907 | cur_sort = -1; |
908 | cur_subseq = -1; | ||
880 | cur_reg = SND_SOC_NOPM; | 909 | cur_reg = SND_SOC_NOPM; |
881 | cur_dapm = NULL; | 910 | cur_dapm = NULL; |
882 | } | 911 | } |
@@ -921,6 +950,7 @@ static void dapm_seq_run(struct snd_soc_dapm_context *dapm, | |||
921 | default: | 950 | default: |
922 | /* Queue it up for application */ | 951 | /* Queue it up for application */ |
923 | cur_sort = sort[w->id]; | 952 | cur_sort = sort[w->id]; |
953 | cur_subseq = w->subseq; | ||
924 | cur_reg = w->reg; | 954 | cur_reg = w->reg; |
925 | cur_dapm = w->dapm; | 955 | cur_dapm = w->dapm; |
926 | list_move(&w->power_list, &pending); | 956 | list_move(&w->power_list, &pending); |
@@ -934,6 +964,13 @@ static void dapm_seq_run(struct snd_soc_dapm_context *dapm, | |||
934 | 964 | ||
935 | if (!list_empty(&pending)) | 965 | if (!list_empty(&pending)) |
936 | dapm_seq_run_coalesced(dapm, &pending); | 966 | dapm_seq_run_coalesced(dapm, &pending); |
967 | |||
968 | if (cur_dapm && cur_dapm->seq_notifier) { | ||
969 | for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++) | ||
970 | if (sort[i] == cur_sort) | ||
971 | cur_dapm->seq_notifier(cur_dapm, | ||
972 | i, cur_subseq); | ||
973 | } | ||
937 | } | 974 | } |
938 | 975 | ||
939 | static void dapm_widget_update(struct snd_soc_dapm_context *dapm) | 976 | static void dapm_widget_update(struct snd_soc_dapm_context *dapm) |
@@ -1002,10 +1039,10 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event) | |||
1002 | list_for_each_entry(w, &card->widgets, list) { | 1039 | list_for_each_entry(w, &card->widgets, list) { |
1003 | switch (w->id) { | 1040 | switch (w->id) { |
1004 | case snd_soc_dapm_pre: | 1041 | case snd_soc_dapm_pre: |
1005 | dapm_seq_insert(w, &down_list, dapm_down_seq); | 1042 | dapm_seq_insert(w, &down_list, false); |
1006 | break; | 1043 | break; |
1007 | case snd_soc_dapm_post: | 1044 | case snd_soc_dapm_post: |
1008 | dapm_seq_insert(w, &up_list, dapm_up_seq); | 1045 | dapm_seq_insert(w, &up_list, true); |
1009 | break; | 1046 | break; |
1010 | 1047 | ||
1011 | default: | 1048 | default: |
@@ -1025,9 +1062,9 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event) | |||
1025 | trace_snd_soc_dapm_widget_power(w, power); | 1062 | trace_snd_soc_dapm_widget_power(w, power); |
1026 | 1063 | ||
1027 | if (power) | 1064 | if (power) |
1028 | dapm_seq_insert(w, &up_list, dapm_up_seq); | 1065 | dapm_seq_insert(w, &up_list, true); |
1029 | else | 1066 | else |
1030 | dapm_seq_insert(w, &down_list, dapm_down_seq); | 1067 | dapm_seq_insert(w, &down_list, false); |
1031 | 1068 | ||
1032 | w->power = power; | 1069 | w->power = power; |
1033 | break; | 1070 | break; |
@@ -1086,12 +1123,12 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event) | |||
1086 | } | 1123 | } |
1087 | 1124 | ||
1088 | /* Power down widgets first; try to avoid amplifying pops. */ | 1125 | /* Power down widgets first; try to avoid amplifying pops. */ |
1089 | dapm_seq_run(dapm, &down_list, event, dapm_down_seq); | 1126 | dapm_seq_run(dapm, &down_list, event, false); |
1090 | 1127 | ||
1091 | dapm_widget_update(dapm); | 1128 | dapm_widget_update(dapm); |
1092 | 1129 | ||
1093 | /* Now power up. */ | 1130 | /* Now power up. */ |
1094 | dapm_seq_run(dapm, &up_list, event, dapm_up_seq); | 1131 | dapm_seq_run(dapm, &up_list, event, true); |
1095 | 1132 | ||
1096 | list_for_each_entry(d, &dapm->card->dapm_list, list) { | 1133 | list_for_each_entry(d, &dapm->card->dapm_list, list) { |
1097 | /* If we just powered the last thing off drop to standby bias */ | 1134 | /* If we just powered the last thing off drop to standby bias */ |
@@ -1742,7 +1779,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, | |||
1742 | int max = mc->max; | 1779 | int max = mc->max; |
1743 | unsigned int mask = (1 << fls(max)) - 1; | 1780 | unsigned int mask = (1 << fls(max)) - 1; |
1744 | unsigned int invert = mc->invert; | 1781 | unsigned int invert = mc->invert; |
1745 | unsigned int val, val_mask; | 1782 | unsigned int val; |
1746 | int connect, change; | 1783 | int connect, change; |
1747 | struct snd_soc_dapm_update update; | 1784 | struct snd_soc_dapm_update update; |
1748 | 1785 | ||
@@ -1750,13 +1787,13 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, | |||
1750 | 1787 | ||
1751 | if (invert) | 1788 | if (invert) |
1752 | val = max - val; | 1789 | val = max - val; |
1753 | val_mask = mask << shift; | 1790 | mask = mask << shift; |
1754 | val = val << shift; | 1791 | val = val << shift; |
1755 | 1792 | ||
1756 | mutex_lock(&widget->codec->mutex); | 1793 | mutex_lock(&widget->codec->mutex); |
1757 | widget->value = val; | 1794 | widget->value = val; |
1758 | 1795 | ||
1759 | change = snd_soc_test_bits(widget->codec, reg, val_mask, val); | 1796 | change = snd_soc_test_bits(widget->codec, reg, mask, val); |
1760 | if (change) { | 1797 | if (change) { |
1761 | if (val) | 1798 | if (val) |
1762 | /* new connection */ | 1799 | /* new connection */ |
@@ -2372,7 +2409,7 @@ static void soc_dapm_shutdown_codec(struct snd_soc_dapm_context *dapm) | |||
2372 | if (w->dapm != dapm) | 2409 | if (w->dapm != dapm) |
2373 | continue; | 2410 | continue; |
2374 | if (w->power) { | 2411 | if (w->power) { |
2375 | dapm_seq_insert(w, &down_list, dapm_down_seq); | 2412 | dapm_seq_insert(w, &down_list, false); |
2376 | w->power = 0; | 2413 | w->power = 0; |
2377 | powerdown = 1; | 2414 | powerdown = 1; |
2378 | } | 2415 | } |
@@ -2383,7 +2420,7 @@ static void soc_dapm_shutdown_codec(struct snd_soc_dapm_context *dapm) | |||
2383 | */ | 2420 | */ |
2384 | if (powerdown) { | 2421 | if (powerdown) { |
2385 | snd_soc_dapm_set_bias_level(NULL, dapm, SND_SOC_BIAS_PREPARE); | 2422 | snd_soc_dapm_set_bias_level(NULL, dapm, SND_SOC_BIAS_PREPARE); |
2386 | dapm_seq_run(dapm, &down_list, 0, dapm_down_seq); | 2423 | dapm_seq_run(dapm, &down_list, 0, false); |
2387 | snd_soc_dapm_set_bias_level(NULL, dapm, SND_SOC_BIAS_STANDBY); | 2424 | snd_soc_dapm_set_bias_level(NULL, dapm, SND_SOC_BIAS_STANDBY); |
2388 | } | 2425 | } |
2389 | } | 2426 | } |
diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c index 1d07b931f3d8..3f45e6a439bf 100644 --- a/sound/soc/soc-utils.c +++ b/sound/soc/soc-utils.c | |||
@@ -28,26 +28,9 @@ int snd_soc_params_to_frame_size(struct snd_pcm_hw_params *params) | |||
28 | { | 28 | { |
29 | int sample_size; | 29 | int sample_size; |
30 | 30 | ||
31 | switch (params_format(params)) { | 31 | sample_size = snd_pcm_format_width(params_format(params)); |
32 | case SNDRV_PCM_FORMAT_S16_LE: | 32 | if (sample_size < 0) |
33 | case SNDRV_PCM_FORMAT_S16_BE: | 33 | return sample_size; |
34 | sample_size = 16; | ||
35 | break; | ||
36 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
37 | case SNDRV_PCM_FORMAT_S20_3BE: | ||
38 | sample_size = 20; | ||
39 | break; | ||
40 | case SNDRV_PCM_FORMAT_S24_LE: | ||
41 | case SNDRV_PCM_FORMAT_S24_BE: | ||
42 | sample_size = 24; | ||
43 | break; | ||
44 | case SNDRV_PCM_FORMAT_S32_LE: | ||
45 | case SNDRV_PCM_FORMAT_S32_BE: | ||
46 | sample_size = 32; | ||
47 | break; | ||
48 | default: | ||
49 | return -ENOTSUPP; | ||
50 | } | ||
51 | 34 | ||
52 | return snd_soc_calc_frame_size(sample_size, params_channels(params), | 35 | return snd_soc_calc_frame_size(sample_size, params_channels(params), |
53 | 1); | 36 | 1); |
diff --git a/sound/soc/tegra/harmony.c b/sound/soc/tegra/harmony.c index b160b7113f45..11e2cb825664 100644 --- a/sound/soc/tegra/harmony.c +++ b/sound/soc/tegra/harmony.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * harmony.c - Harmony machine ASoC driver | 2 | * harmony.c - Harmony machine ASoC driver |
3 | * | 3 | * |
4 | * Author: Stephen Warren <swarren@nvidia.com> | 4 | * Author: Stephen Warren <swarren@nvidia.com> |
5 | * Copyright (C) 2010 - NVIDIA, Inc. | 5 | * Copyright (C) 2010-2011 - NVIDIA, Inc. |
6 | * | 6 | * |
7 | * Based on code copyright/by: | 7 | * Based on code copyright/by: |
8 | * | 8 | * |
@@ -29,7 +29,14 @@ | |||
29 | */ | 29 | */ |
30 | 30 | ||
31 | #include <asm/mach-types.h> | 31 | #include <asm/mach-types.h> |
32 | |||
32 | #include <linux/module.h> | 33 | #include <linux/module.h> |
34 | #include <linux/platform_device.h> | ||
35 | #include <linux/slab.h> | ||
36 | #include <linux/gpio.h> | ||
37 | |||
38 | #include <mach/harmony_audio.h> | ||
39 | |||
33 | #include <sound/core.h> | 40 | #include <sound/core.h> |
34 | #include <sound/pcm.h> | 41 | #include <sound/pcm.h> |
35 | #include <sound/pcm_params.h> | 42 | #include <sound/pcm_params.h> |
@@ -40,9 +47,13 @@ | |||
40 | #include "tegra_pcm.h" | 47 | #include "tegra_pcm.h" |
41 | #include "tegra_asoc_utils.h" | 48 | #include "tegra_asoc_utils.h" |
42 | 49 | ||
43 | #define PREFIX "ASoC Harmony: " | 50 | #define DRV_NAME "tegra-snd-harmony" |
44 | 51 | ||
45 | static struct platform_device *harmony_snd_device; | 52 | struct tegra_harmony { |
53 | struct tegra_asoc_utils_data util_data; | ||
54 | struct harmony_audio_platform_data *pdata; | ||
55 | int gpio_spkr_en_requested; | ||
56 | }; | ||
46 | 57 | ||
47 | static int harmony_asoc_hw_params(struct snd_pcm_substream *substream, | 58 | static int harmony_asoc_hw_params(struct snd_pcm_substream *substream, |
48 | struct snd_pcm_hw_params *params) | 59 | struct snd_pcm_hw_params *params) |
@@ -50,6 +61,9 @@ static int harmony_asoc_hw_params(struct snd_pcm_substream *substream, | |||
50 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 61 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
51 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 62 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
52 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 63 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
64 | struct snd_soc_codec *codec = rtd->codec; | ||
65 | struct snd_soc_card *card = codec->card; | ||
66 | struct tegra_harmony *harmony = snd_soc_card_get_drvdata(card); | ||
53 | int srate, mclk, mclk_change; | 67 | int srate, mclk, mclk_change; |
54 | int err; | 68 | int err; |
55 | 69 | ||
@@ -68,9 +82,10 @@ static int harmony_asoc_hw_params(struct snd_pcm_substream *substream, | |||
68 | while (mclk < 6000000) | 82 | while (mclk < 6000000) |
69 | mclk *= 2; | 83 | mclk *= 2; |
70 | 84 | ||
71 | err = tegra_asoc_utils_set_rate(srate, mclk, &mclk_change); | 85 | err = tegra_asoc_utils_set_rate(&harmony->util_data, srate, mclk, |
86 | &mclk_change); | ||
72 | if (err < 0) { | 87 | if (err < 0) { |
73 | pr_err(PREFIX "Can't configure clocks\n"); | 88 | dev_err(card->dev, "Can't configure clocks\n"); |
74 | return err; | 89 | return err; |
75 | } | 90 | } |
76 | 91 | ||
@@ -79,7 +94,7 @@ static int harmony_asoc_hw_params(struct snd_pcm_substream *substream, | |||
79 | SND_SOC_DAIFMT_NB_NF | | 94 | SND_SOC_DAIFMT_NB_NF | |
80 | SND_SOC_DAIFMT_CBS_CFS); | 95 | SND_SOC_DAIFMT_CBS_CFS); |
81 | if (err < 0) { | 96 | if (err < 0) { |
82 | pr_err(PREFIX "codec_dai fmt not set\n"); | 97 | dev_err(card->dev, "codec_dai fmt not set\n"); |
83 | return err; | 98 | return err; |
84 | } | 99 | } |
85 | 100 | ||
@@ -88,16 +103,17 @@ static int harmony_asoc_hw_params(struct snd_pcm_substream *substream, | |||
88 | SND_SOC_DAIFMT_NB_NF | | 103 | SND_SOC_DAIFMT_NB_NF | |
89 | SND_SOC_DAIFMT_CBS_CFS); | 104 | SND_SOC_DAIFMT_CBS_CFS); |
90 | if (err < 0) { | 105 | if (err < 0) { |
91 | pr_err(PREFIX "cpu_dai fmt not set\n"); | 106 | dev_err(card->dev, "cpu_dai fmt not set\n"); |
92 | return err; | 107 | return err; |
93 | } | 108 | } |
94 | 109 | ||
95 | if (mclk_change) { | 110 | if (mclk_change) { |
96 | err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, SND_SOC_CLOCK_IN); | 111 | err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, |
97 | if (err < 0) { | 112 | SND_SOC_CLOCK_IN); |
98 | pr_err(PREFIX "codec_dai clock not set\n"); | 113 | if (err < 0) { |
99 | return err; | 114 | dev_err(card->dev, "codec_dai clock not set\n"); |
100 | } | 115 | return err; |
116 | } | ||
101 | } | 117 | } |
102 | 118 | ||
103 | return 0; | 119 | return 0; |
@@ -107,7 +123,22 @@ static struct snd_soc_ops harmony_asoc_ops = { | |||
107 | .hw_params = harmony_asoc_hw_params, | 123 | .hw_params = harmony_asoc_hw_params, |
108 | }; | 124 | }; |
109 | 125 | ||
126 | static int harmony_event_int_spk(struct snd_soc_dapm_widget *w, | ||
127 | struct snd_kcontrol *k, int event) | ||
128 | { | ||
129 | struct snd_soc_codec *codec = w->codec; | ||
130 | struct snd_soc_card *card = codec->card; | ||
131 | struct tegra_harmony *harmony = snd_soc_card_get_drvdata(card); | ||
132 | struct harmony_audio_platform_data *pdata = harmony->pdata; | ||
133 | |||
134 | gpio_set_value_cansleep(pdata->gpio_spkr_en, | ||
135 | SND_SOC_DAPM_EVENT_ON(event)); | ||
136 | |||
137 | return 0; | ||
138 | } | ||
139 | |||
110 | static const struct snd_soc_dapm_widget harmony_dapm_widgets[] = { | 140 | static const struct snd_soc_dapm_widget harmony_dapm_widgets[] = { |
141 | SND_SOC_DAPM_SPK("Int Spk", harmony_event_int_spk), | ||
111 | SND_SOC_DAPM_HP("Headphone Jack", NULL), | 142 | SND_SOC_DAPM_HP("Headphone Jack", NULL), |
112 | SND_SOC_DAPM_MIC("Mic Jack", NULL), | 143 | SND_SOC_DAPM_MIC("Mic Jack", NULL), |
113 | }; | 144 | }; |
@@ -115,6 +146,10 @@ static const struct snd_soc_dapm_widget harmony_dapm_widgets[] = { | |||
115 | static const struct snd_soc_dapm_route harmony_audio_map[] = { | 146 | static const struct snd_soc_dapm_route harmony_audio_map[] = { |
116 | {"Headphone Jack", NULL, "HPOUTR"}, | 147 | {"Headphone Jack", NULL, "HPOUTR"}, |
117 | {"Headphone Jack", NULL, "HPOUTL"}, | 148 | {"Headphone Jack", NULL, "HPOUTL"}, |
149 | {"Int Spk", NULL, "ROP"}, | ||
150 | {"Int Spk", NULL, "RON"}, | ||
151 | {"Int Spk", NULL, "LOP"}, | ||
152 | {"Int Spk", NULL, "LON"}, | ||
118 | {"Mic Bias", NULL, "Mic Jack"}, | 153 | {"Mic Bias", NULL, "Mic Jack"}, |
119 | {"IN1L", NULL, "Mic Bias"}, | 154 | {"IN1L", NULL, "Mic Bias"}, |
120 | }; | 155 | }; |
@@ -123,6 +158,19 @@ static int harmony_asoc_init(struct snd_soc_pcm_runtime *rtd) | |||
123 | { | 158 | { |
124 | struct snd_soc_codec *codec = rtd->codec; | 159 | struct snd_soc_codec *codec = rtd->codec; |
125 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 160 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
161 | struct snd_soc_card *card = codec->card; | ||
162 | struct tegra_harmony *harmony = snd_soc_card_get_drvdata(card); | ||
163 | struct harmony_audio_platform_data *pdata = harmony->pdata; | ||
164 | int ret; | ||
165 | |||
166 | ret = gpio_request(pdata->gpio_spkr_en, "spkr_en"); | ||
167 | if (ret) { | ||
168 | dev_err(card->dev, "cannot get spkr_en gpio\n"); | ||
169 | return ret; | ||
170 | } | ||
171 | harmony->gpio_spkr_en_requested = 1; | ||
172 | |||
173 | gpio_direction_output(pdata->gpio_spkr_en, 0); | ||
126 | 174 | ||
127 | snd_soc_dapm_new_controls(dapm, harmony_dapm_widgets, | 175 | snd_soc_dapm_new_controls(dapm, harmony_dapm_widgets, |
128 | ARRAY_SIZE(harmony_dapm_widgets)); | 176 | ARRAY_SIZE(harmony_dapm_widgets)); |
@@ -131,6 +179,7 @@ static int harmony_asoc_init(struct snd_soc_pcm_runtime *rtd) | |||
131 | ARRAY_SIZE(harmony_audio_map)); | 179 | ARRAY_SIZE(harmony_audio_map)); |
132 | 180 | ||
133 | snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); | 181 | snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); |
182 | snd_soc_dapm_enable_pin(dapm, "Int Spk"); | ||
134 | snd_soc_dapm_enable_pin(dapm, "Mic Jack"); | 183 | snd_soc_dapm_enable_pin(dapm, "Mic Jack"); |
135 | snd_soc_dapm_sync(dapm); | 184 | snd_soc_dapm_sync(dapm); |
136 | 185 | ||
@@ -154,56 +203,101 @@ static struct snd_soc_card snd_soc_harmony = { | |||
154 | .num_links = 1, | 203 | .num_links = 1, |
155 | }; | 204 | }; |
156 | 205 | ||
157 | static int __init harmony_soc_modinit(void) | 206 | static __devinit int tegra_snd_harmony_probe(struct platform_device *pdev) |
158 | { | 207 | { |
208 | struct snd_soc_card *card = &snd_soc_harmony; | ||
209 | struct tegra_harmony *harmony; | ||
210 | struct harmony_audio_platform_data *pdata; | ||
159 | int ret; | 211 | int ret; |
160 | 212 | ||
161 | if (!machine_is_harmony()) { | 213 | if (!machine_is_harmony()) { |
162 | pr_err(PREFIX "Not running on Tegra Harmony!\n"); | 214 | dev_err(&pdev->dev, "Not running on Tegra Harmony!\n"); |
163 | return -ENODEV; | 215 | return -ENODEV; |
164 | } | 216 | } |
165 | 217 | ||
166 | ret = tegra_asoc_utils_init(); | 218 | pdata = pdev->dev.platform_data; |
167 | if (ret) { | 219 | if (!pdata) { |
168 | return ret; | 220 | dev_err(&pdev->dev, "no platform data supplied\n"); |
221 | return -EINVAL; | ||
169 | } | 222 | } |
170 | 223 | ||
171 | /* | 224 | harmony = kzalloc(sizeof(struct tegra_harmony), GFP_KERNEL); |
172 | * Create and register platform device | 225 | if (!harmony) { |
173 | */ | 226 | dev_err(&pdev->dev, "Can't allocate tegra_harmony\n"); |
174 | harmony_snd_device = platform_device_alloc("soc-audio", -1); | 227 | return -ENOMEM; |
175 | if (harmony_snd_device == NULL) { | ||
176 | pr_err(PREFIX "platform_device_alloc failed\n"); | ||
177 | ret = -ENOMEM; | ||
178 | goto err_clock_utils; | ||
179 | } | 228 | } |
180 | 229 | ||
181 | platform_set_drvdata(harmony_snd_device, &snd_soc_harmony); | 230 | harmony->pdata = pdata; |
231 | |||
232 | ret = tegra_asoc_utils_init(&harmony->util_data, &pdev->dev); | ||
233 | if (ret) | ||
234 | goto err_free_harmony; | ||
235 | |||
236 | card->dev = &pdev->dev; | ||
237 | platform_set_drvdata(pdev, card); | ||
238 | snd_soc_card_set_drvdata(card, harmony); | ||
182 | 239 | ||
183 | ret = platform_device_add(harmony_snd_device); | 240 | ret = snd_soc_register_card(card); |
184 | if (ret) { | 241 | if (ret) { |
185 | pr_err(PREFIX "platform_device_add failed (%d)\n", | 242 | dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", |
186 | ret); | 243 | ret); |
187 | goto err_device_put; | 244 | goto err_clear_drvdata; |
188 | } | 245 | } |
189 | 246 | ||
190 | return 0; | 247 | return 0; |
191 | 248 | ||
192 | err_device_put: | 249 | err_clear_drvdata: |
193 | platform_device_put(harmony_snd_device); | 250 | snd_soc_card_set_drvdata(card, NULL); |
194 | err_clock_utils: | 251 | platform_set_drvdata(pdev, NULL); |
195 | tegra_asoc_utils_fini(); | 252 | card->dev = NULL; |
253 | tegra_asoc_utils_fini(&harmony->util_data); | ||
254 | err_free_harmony: | ||
255 | kfree(harmony); | ||
196 | return ret; | 256 | return ret; |
197 | } | 257 | } |
198 | module_init(harmony_soc_modinit); | ||
199 | 258 | ||
200 | static void __exit harmony_soc_modexit(void) | 259 | static int __devexit tegra_snd_harmony_remove(struct platform_device *pdev) |
201 | { | 260 | { |
202 | platform_device_unregister(harmony_snd_device); | 261 | struct snd_soc_card *card = platform_get_drvdata(pdev); |
262 | struct tegra_harmony *harmony = snd_soc_card_get_drvdata(card); | ||
263 | struct harmony_audio_platform_data *pdata = harmony->pdata; | ||
264 | |||
265 | snd_soc_unregister_card(card); | ||
266 | |||
267 | snd_soc_card_set_drvdata(card, NULL); | ||
268 | platform_set_drvdata(pdev, NULL); | ||
269 | card->dev = NULL; | ||
203 | 270 | ||
204 | tegra_asoc_utils_fini(); | 271 | tegra_asoc_utils_fini(&harmony->util_data); |
272 | |||
273 | if (harmony->gpio_spkr_en_requested) | ||
274 | gpio_free(pdata->gpio_spkr_en); | ||
275 | |||
276 | kfree(harmony); | ||
277 | |||
278 | return 0; | ||
279 | } | ||
280 | |||
281 | static struct platform_driver tegra_snd_harmony_driver = { | ||
282 | .driver = { | ||
283 | .name = DRV_NAME, | ||
284 | .owner = THIS_MODULE, | ||
285 | }, | ||
286 | .probe = tegra_snd_harmony_probe, | ||
287 | .remove = __devexit_p(tegra_snd_harmony_remove), | ||
288 | }; | ||
289 | |||
290 | static int __init snd_tegra_harmony_init(void) | ||
291 | { | ||
292 | return platform_driver_register(&tegra_snd_harmony_driver); | ||
293 | } | ||
294 | module_init(snd_tegra_harmony_init); | ||
295 | |||
296 | static void __exit snd_tegra_harmony_exit(void) | ||
297 | { | ||
298 | platform_driver_unregister(&tegra_snd_harmony_driver); | ||
205 | } | 299 | } |
206 | module_exit(harmony_soc_modexit); | 300 | module_exit(snd_tegra_harmony_exit); |
207 | 301 | ||
208 | MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>"); | 302 | MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>"); |
209 | MODULE_DESCRIPTION("Harmony machine ASoC driver"); | 303 | MODULE_DESCRIPTION("Harmony machine ASoC driver"); |
diff --git a/sound/soc/tegra/tegra_asoc_utils.c b/sound/soc/tegra/tegra_asoc_utils.c index cfe2ea890dc0..cb4fc13c7d22 100644 --- a/sound/soc/tegra/tegra_asoc_utils.c +++ b/sound/soc/tegra/tegra_asoc_utils.c | |||
@@ -21,20 +21,14 @@ | |||
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include <linux/clk.h> | 23 | #include <linux/clk.h> |
24 | #include <linux/device.h> | ||
24 | #include <linux/err.h> | 25 | #include <linux/err.h> |
25 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
26 | 27 | ||
27 | #include "tegra_asoc_utils.h" | 28 | #include "tegra_asoc_utils.h" |
28 | 29 | ||
29 | #define PREFIX "ASoC Tegra: " | 30 | int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate, |
30 | 31 | int mclk, int *mclk_change) | |
31 | static struct clk *clk_pll_a; | ||
32 | static struct clk *clk_pll_a_out0; | ||
33 | static struct clk *clk_cdev1; | ||
34 | |||
35 | static int set_baseclock, set_mclk; | ||
36 | |||
37 | int tegra_asoc_utils_set_rate(int srate, int mclk, int *mclk_change) | ||
38 | { | 32 | { |
39 | int new_baseclock; | 33 | int new_baseclock; |
40 | int err; | 34 | int err; |
@@ -58,95 +52,98 @@ int tegra_asoc_utils_set_rate(int srate, int mclk, int *mclk_change) | |||
58 | return -EINVAL; | 52 | return -EINVAL; |
59 | } | 53 | } |
60 | 54 | ||
61 | *mclk_change = ((new_baseclock != set_baseclock) || | 55 | *mclk_change = ((new_baseclock != data->set_baseclock) || |
62 | (mclk != set_mclk)); | 56 | (mclk != data->set_mclk)); |
63 | if (!*mclk_change) | 57 | if (!*mclk_change) |
64 | return 0; | 58 | return 0; |
65 | 59 | ||
66 | set_baseclock = 0; | 60 | data->set_baseclock = 0; |
67 | set_mclk = 0; | 61 | data->set_mclk = 0; |
68 | 62 | ||
69 | clk_disable(clk_cdev1); | 63 | clk_disable(data->clk_cdev1); |
70 | clk_disable(clk_pll_a_out0); | 64 | clk_disable(data->clk_pll_a_out0); |
71 | clk_disable(clk_pll_a); | 65 | clk_disable(data->clk_pll_a); |
72 | 66 | ||
73 | err = clk_set_rate(clk_pll_a, new_baseclock); | 67 | err = clk_set_rate(data->clk_pll_a, new_baseclock); |
74 | if (err) { | 68 | if (err) { |
75 | pr_err(PREFIX "Can't set pll_a rate: %d\n", err); | 69 | dev_err(data->dev, "Can't set pll_a rate: %d\n", err); |
76 | return err; | 70 | return err; |
77 | } | 71 | } |
78 | 72 | ||
79 | err = clk_set_rate(clk_pll_a_out0, mclk); | 73 | err = clk_set_rate(data->clk_pll_a_out0, mclk); |
80 | if (err) { | 74 | if (err) { |
81 | pr_err(PREFIX "Can't set pll_a_out0 rate: %d\n", err); | 75 | dev_err(data->dev, "Can't set pll_a_out0 rate: %d\n", err); |
82 | return err; | 76 | return err; |
83 | } | 77 | } |
84 | 78 | ||
85 | /* Don't set cdev1 rate; its locked to pll_a_out0 */ | 79 | /* Don't set cdev1 rate; its locked to pll_a_out0 */ |
86 | 80 | ||
87 | err = clk_enable(clk_pll_a); | 81 | err = clk_enable(data->clk_pll_a); |
88 | if (err) { | 82 | if (err) { |
89 | pr_err(PREFIX "Can't enable pll_a: %d\n", err); | 83 | dev_err(data->dev, "Can't enable pll_a: %d\n", err); |
90 | return err; | 84 | return err; |
91 | } | 85 | } |
92 | 86 | ||
93 | err = clk_enable(clk_pll_a_out0); | 87 | err = clk_enable(data->clk_pll_a_out0); |
94 | if (err) { | 88 | if (err) { |
95 | pr_err(PREFIX "Can't enable pll_a_out0: %d\n", err); | 89 | dev_err(data->dev, "Can't enable pll_a_out0: %d\n", err); |
96 | return err; | 90 | return err; |
97 | } | 91 | } |
98 | 92 | ||
99 | err = clk_enable(clk_cdev1); | 93 | err = clk_enable(data->clk_cdev1); |
100 | if (err) { | 94 | if (err) { |
101 | pr_err(PREFIX "Can't enable cdev1: %d\n", err); | 95 | dev_err(data->dev, "Can't enable cdev1: %d\n", err); |
102 | return err; | 96 | return err; |
103 | } | 97 | } |
104 | 98 | ||
105 | set_baseclock = new_baseclock; | 99 | data->set_baseclock = new_baseclock; |
106 | set_mclk = mclk; | 100 | data->set_mclk = mclk; |
107 | 101 | ||
108 | return 0; | 102 | return 0; |
109 | } | 103 | } |
110 | 104 | ||
111 | int tegra_asoc_utils_init(void) | 105 | int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data, |
106 | struct device *dev) | ||
112 | { | 107 | { |
113 | int ret; | 108 | int ret; |
114 | 109 | ||
115 | clk_pll_a = clk_get_sys(NULL, "pll_a"); | 110 | data->dev = dev; |
116 | if (IS_ERR(clk_pll_a)) { | 111 | |
117 | pr_err(PREFIX "Can't retrieve clk pll_a\n"); | 112 | data->clk_pll_a = clk_get_sys(NULL, "pll_a"); |
118 | ret = PTR_ERR(clk_pll_a); | 113 | if (IS_ERR(data->clk_pll_a)) { |
114 | dev_err(data->dev, "Can't retrieve clk pll_a\n"); | ||
115 | ret = PTR_ERR(data->clk_pll_a); | ||
119 | goto err; | 116 | goto err; |
120 | } | 117 | } |
121 | 118 | ||
122 | clk_pll_a_out0 = clk_get_sys(NULL, "pll_a_out0"); | 119 | data->clk_pll_a_out0 = clk_get_sys(NULL, "pll_a_out0"); |
123 | if (IS_ERR(clk_pll_a_out0)) { | 120 | if (IS_ERR(data->clk_pll_a_out0)) { |
124 | pr_err(PREFIX "Can't retrieve clk pll_a_out0\n"); | 121 | dev_err(data->dev, "Can't retrieve clk pll_a_out0\n"); |
125 | ret = PTR_ERR(clk_pll_a_out0); | 122 | ret = PTR_ERR(data->clk_pll_a_out0); |
126 | goto err_put_pll_a; | 123 | goto err_put_pll_a; |
127 | } | 124 | } |
128 | 125 | ||
129 | clk_cdev1 = clk_get_sys(NULL, "cdev1"); | 126 | data->clk_cdev1 = clk_get_sys(NULL, "cdev1"); |
130 | if (IS_ERR(clk_cdev1)) { | 127 | if (IS_ERR(data->clk_cdev1)) { |
131 | pr_err(PREFIX "Can't retrieve clk cdev1\n"); | 128 | dev_err(data->dev, "Can't retrieve clk cdev1\n"); |
132 | ret = PTR_ERR(clk_cdev1); | 129 | ret = PTR_ERR(data->clk_cdev1); |
133 | goto err_put_pll_a_out0; | 130 | goto err_put_pll_a_out0; |
134 | } | 131 | } |
135 | 132 | ||
136 | return 0; | 133 | return 0; |
137 | 134 | ||
138 | err_put_pll_a_out0: | 135 | err_put_pll_a_out0: |
139 | clk_put(clk_pll_a_out0); | 136 | clk_put(data->clk_pll_a_out0); |
140 | err_put_pll_a: | 137 | err_put_pll_a: |
141 | clk_put(clk_pll_a); | 138 | clk_put(data->clk_pll_a); |
142 | err: | 139 | err: |
143 | return ret; | 140 | return ret; |
144 | } | 141 | } |
145 | 142 | ||
146 | void tegra_asoc_utils_fini(void) | 143 | void tegra_asoc_utils_fini(struct tegra_asoc_utils_data *data) |
147 | { | 144 | { |
148 | clk_put(clk_cdev1); | 145 | clk_put(data->clk_cdev1); |
149 | clk_put(clk_pll_a_out0); | 146 | clk_put(data->clk_pll_a_out0); |
150 | clk_put(clk_pll_a); | 147 | clk_put(data->clk_pll_a); |
151 | } | 148 | } |
152 | 149 | ||
diff --git a/sound/soc/tegra/tegra_asoc_utils.h b/sound/soc/tegra/tegra_asoc_utils.h index 855f8f6e44ca..bbba7afdfc2c 100644 --- a/sound/soc/tegra/tegra_asoc_utils.h +++ b/sound/soc/tegra/tegra_asoc_utils.h | |||
@@ -23,9 +23,23 @@ | |||
23 | #ifndef __TEGRA_ASOC_UTILS_H__ | 23 | #ifndef __TEGRA_ASOC_UTILS_H__ |
24 | #define __TEGRA_ASOC_UTILS_H_ | 24 | #define __TEGRA_ASOC_UTILS_H_ |
25 | 25 | ||
26 | int tegra_asoc_utils_set_rate(int srate, int mclk_rate, int *mclk_change); | 26 | struct clk; |
27 | int tegra_asoc_utils_init(void); | 27 | struct device; |
28 | void tegra_asoc_utils_fini(void); | 28 | |
29 | struct tegra_asoc_utils_data { | ||
30 | struct device *dev; | ||
31 | struct clk *clk_pll_a; | ||
32 | struct clk *clk_pll_a_out0; | ||
33 | struct clk *clk_cdev1; | ||
34 | int set_baseclock; | ||
35 | int set_mclk; | ||
36 | }; | ||
37 | |||
38 | int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate, | ||
39 | int mclk, int *mclk_change); | ||
40 | int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data, | ||
41 | struct device *dev); | ||
42 | void tegra_asoc_utils_fini(struct tegra_asoc_utils_data *data); | ||
29 | 43 | ||
30 | #endif | 44 | #endif |
31 | 45 | ||
diff --git a/sound/soc/tegra/tegra_i2s.c b/sound/soc/tegra/tegra_i2s.c index 6d668785e9af..870ee361f757 100644 --- a/sound/soc/tegra/tegra_i2s.c +++ b/sound/soc/tegra/tegra_i2s.c | |||
@@ -386,7 +386,7 @@ static __devinit int tegra_i2s_platform_probe(struct platform_device *pdev) | |||
386 | snprintf(clk_name, sizeof(clk_name), DRV_NAME ".%d", pdev->id); | 386 | snprintf(clk_name, sizeof(clk_name), DRV_NAME ".%d", pdev->id); |
387 | i2s->clk_i2s = clk_get_sys(clk_name, NULL); | 387 | i2s->clk_i2s = clk_get_sys(clk_name, NULL); |
388 | if (IS_ERR(i2s->clk_i2s)) { | 388 | if (IS_ERR(i2s->clk_i2s)) { |
389 | pr_err("Can't retrieve i2s clock\n"); | 389 | dev_err(&pdev->dev, "Can't retrieve i2s clock\n"); |
390 | ret = PTR_ERR(i2s->clk_i2s); | 390 | ret = PTR_ERR(i2s->clk_i2s); |
391 | goto err_free; | 391 | goto err_free; |
392 | } | 392 | } |