diff options
Diffstat (limited to 'sound/soc/s3c24xx')
36 files changed, 2260 insertions, 466 deletions
diff --git a/sound/soc/s3c24xx/Kconfig b/sound/soc/s3c24xx/Kconfig index 213963ac3c28..8a6b53ccd203 100644 --- a/sound/soc/s3c24xx/Kconfig +++ b/sound/soc/s3c24xx/Kconfig | |||
@@ -36,6 +36,10 @@ config SND_S3C_SOC_AC97 | |||
36 | tristate | 36 | tristate |
37 | select SND_SOC_AC97_BUS | 37 | select SND_SOC_AC97_BUS |
38 | 38 | ||
39 | config SND_S5P_SOC_SPDIF | ||
40 | tristate | ||
41 | select SND_SOC_SPDIF | ||
42 | |||
39 | config SND_S3C24XX_SOC_NEO1973_WM8753 | 43 | config SND_S3C24XX_SOC_NEO1973_WM8753 |
40 | tristate "SoC I2S Audio support for NEO1973 - WM8753" | 44 | tristate "SoC I2S Audio support for NEO1973 - WM8753" |
41 | depends on SND_S3C24XX_SOC && MACH_NEO1973_GTA01 | 45 | depends on SND_S3C24XX_SOC && MACH_NEO1973_GTA01 |
@@ -118,6 +122,14 @@ config SND_S3C24XX_SOC_SIMTEC_HERMES | |||
118 | select SND_SOC_TLV320AIC3X | 122 | select SND_SOC_TLV320AIC3X |
119 | select SND_S3C24XX_SOC_SIMTEC | 123 | select SND_S3C24XX_SOC_SIMTEC |
120 | 124 | ||
125 | config SND_S3C24XX_SOC_RX1950_UDA1380 | ||
126 | tristate "Audio support for the HP iPAQ RX1950" | ||
127 | depends on SND_S3C24XX_SOC && MACH_RX1950 | ||
128 | select SND_S3C24XX_SOC_I2S | ||
129 | select SND_SOC_UDA1380 | ||
130 | help | ||
131 | This driver provides audio support for HP iPAQ RX1950 PDA. | ||
132 | |||
121 | config SND_SOC_SMDK_WM9713 | 133 | config SND_SOC_SMDK_WM9713 |
122 | tristate "SoC AC97 Audio support for SMDK with WM9713" | 134 | tristate "SoC AC97 Audio support for SMDK with WM9713" |
123 | depends on SND_S3C24XX_SOC && (MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDKV210 || MACH_SMDKC110) | 135 | depends on SND_S3C24XX_SOC && (MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDKV210 || MACH_SMDKC110) |
@@ -131,3 +143,28 @@ config SND_S3C64XX_SOC_SMARTQ | |||
131 | depends on SND_S3C24XX_SOC && MACH_SMARTQ | 143 | depends on SND_S3C24XX_SOC && MACH_SMARTQ |
132 | select SND_S3C64XX_SOC_I2S | 144 | select SND_S3C64XX_SOC_I2S |
133 | select SND_SOC_WM8750 | 145 | select SND_SOC_WM8750 |
146 | |||
147 | config SND_S5PC110_SOC_AQUILA_WM8994 | ||
148 | tristate "SoC I2S Audio support for AQUILA - WM8994" | ||
149 | depends on SND_S3C24XX_SOC && MACH_AQUILA | ||
150 | select SND_S3C64XX_SOC_I2S_V4 | ||
151 | select SND_SOC_WM8994 | ||
152 | help | ||
153 | Say Y if you want to add support for SoC audio on aquila | ||
154 | with the WM8994. | ||
155 | |||
156 | config SND_S5PV210_SOC_GONI_WM8994 | ||
157 | tristate "SoC I2S Audio support for GONI - WM8994" | ||
158 | depends on SND_S3C24XX_SOC && MACH_GONI | ||
159 | select SND_S3C64XX_SOC_I2S_V4 | ||
160 | select SND_SOC_WM8994 | ||
161 | help | ||
162 | Say Y if you want to add support for SoC audio on goni | ||
163 | with the WM8994. | ||
164 | |||
165 | config SND_SOC_SMDK_SPDIF | ||
166 | tristate "SoC S/PDIF Audio support for SMDK" | ||
167 | depends on SND_S3C24XX_SOC && (MACH_SMDKC100 || MACH_SMDKC110 || MACH_SMDKV210) | ||
168 | select SND_S5P_SOC_SPDIF | ||
169 | help | ||
170 | Say Y if you want to add support for SoC S/PDIF audio on the SMDK. | ||
diff --git a/sound/soc/s3c24xx/Makefile b/sound/soc/s3c24xx/Makefile index 50172c385d90..ee8f41d6df99 100644 --- a/sound/soc/s3c24xx/Makefile +++ b/sound/soc/s3c24xx/Makefile | |||
@@ -7,6 +7,7 @@ snd-soc-s3c-ac97-objs := s3c-ac97.o | |||
7 | snd-soc-s3c64xx-i2s-v4-objs := s3c64xx-i2s-v4.o | 7 | snd-soc-s3c64xx-i2s-v4-objs := s3c64xx-i2s-v4.o |
8 | snd-soc-s3c-i2s-v2-objs := s3c-i2s-v2.o | 8 | snd-soc-s3c-i2s-v2-objs := s3c-i2s-v2.o |
9 | snd-soc-s3c-pcm-objs := s3c-pcm.o | 9 | snd-soc-s3c-pcm-objs := s3c-pcm.o |
10 | snd-soc-samsung-spdif-objs := spdif.o | ||
10 | 11 | ||
11 | obj-$(CONFIG_SND_S3C24XX_SOC) += snd-soc-s3c24xx.o | 12 | obj-$(CONFIG_SND_S3C24XX_SOC) += snd-soc-s3c24xx.o |
12 | obj-$(CONFIG_SND_S3C24XX_SOC_I2S) += snd-soc-s3c24xx-i2s.o | 13 | obj-$(CONFIG_SND_S3C24XX_SOC_I2S) += snd-soc-s3c24xx-i2s.o |
@@ -16,6 +17,7 @@ obj-$(CONFIG_SND_S3C64XX_SOC_I2S) += snd-soc-s3c64xx-i2s.o | |||
16 | obj-$(CONFIG_SND_S3C64XX_SOC_I2S_V4) += snd-soc-s3c64xx-i2s-v4.o | 17 | obj-$(CONFIG_SND_S3C64XX_SOC_I2S_V4) += snd-soc-s3c64xx-i2s-v4.o |
17 | obj-$(CONFIG_SND_S3C_I2SV2_SOC) += snd-soc-s3c-i2s-v2.o | 18 | obj-$(CONFIG_SND_S3C_I2SV2_SOC) += snd-soc-s3c-i2s-v2.o |
18 | obj-$(CONFIG_SND_S3C_SOC_PCM) += snd-soc-s3c-pcm.o | 19 | obj-$(CONFIG_SND_S3C_SOC_PCM) += snd-soc-s3c-pcm.o |
20 | obj-$(CONFIG_SND_S5P_SOC_SPDIF) += snd-soc-samsung-spdif.o | ||
19 | 21 | ||
20 | # S3C24XX Machine Support | 22 | # S3C24XX Machine Support |
21 | snd-soc-jive-wm8750-objs := jive_wm8750.o | 23 | snd-soc-jive-wm8750-objs := jive_wm8750.o |
@@ -27,9 +29,13 @@ snd-soc-s3c24xx-uda134x-objs := s3c24xx_uda134x.o | |||
27 | snd-soc-s3c24xx-simtec-objs := s3c24xx_simtec.o | 29 | snd-soc-s3c24xx-simtec-objs := s3c24xx_simtec.o |
28 | snd-soc-s3c24xx-simtec-hermes-objs := s3c24xx_simtec_hermes.o | 30 | snd-soc-s3c24xx-simtec-hermes-objs := s3c24xx_simtec_hermes.o |
29 | snd-soc-s3c24xx-simtec-tlv320aic23-objs := s3c24xx_simtec_tlv320aic23.o | 31 | snd-soc-s3c24xx-simtec-tlv320aic23-objs := s3c24xx_simtec_tlv320aic23.o |
32 | snd-soc-rx1950-uda1380-objs := rx1950_uda1380.o | ||
30 | snd-soc-smdk64xx-wm8580-objs := smdk64xx_wm8580.o | 33 | snd-soc-smdk64xx-wm8580-objs := smdk64xx_wm8580.o |
31 | snd-soc-smdk-wm9713-objs := smdk_wm9713.o | 34 | snd-soc-smdk-wm9713-objs := smdk_wm9713.o |
32 | snd-soc-s3c64xx-smartq-wm8987-objs := smartq_wm8987.o | 35 | snd-soc-s3c64xx-smartq-wm8987-objs := smartq_wm8987.o |
36 | snd-soc-aquila-wm8994-objs := aquila_wm8994.o | ||
37 | snd-soc-goni-wm8994-objs := goni_wm8994.o | ||
38 | snd-soc-smdk-spdif-objs := smdk_spdif.o | ||
33 | 39 | ||
34 | obj-$(CONFIG_SND_S3C24XX_SOC_JIVE_WM8750) += snd-soc-jive-wm8750.o | 40 | obj-$(CONFIG_SND_S3C24XX_SOC_JIVE_WM8750) += snd-soc-jive-wm8750.o |
35 | obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o | 41 | obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o |
@@ -40,6 +46,10 @@ obj-$(CONFIG_SND_S3C24XX_SOC_S3C24XX_UDA134X) += snd-soc-s3c24xx-uda134x.o | |||
40 | obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC) += snd-soc-s3c24xx-simtec.o | 46 | obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC) += snd-soc-s3c24xx-simtec.o |
41 | obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC_HERMES) += snd-soc-s3c24xx-simtec-hermes.o | 47 | obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC_HERMES) += snd-soc-s3c24xx-simtec-hermes.o |
42 | obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC_TLV320AIC23) += snd-soc-s3c24xx-simtec-tlv320aic23.o | 48 | obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC_TLV320AIC23) += snd-soc-s3c24xx-simtec-tlv320aic23.o |
49 | obj-$(CONFIG_SND_S3C24XX_SOC_RX1950_UDA1380) += snd-soc-rx1950-uda1380.o | ||
43 | obj-$(CONFIG_SND_S3C64XX_SOC_WM8580) += snd-soc-smdk64xx-wm8580.o | 50 | obj-$(CONFIG_SND_S3C64XX_SOC_WM8580) += snd-soc-smdk64xx-wm8580.o |
44 | obj-$(CONFIG_SND_SOC_SMDK_WM9713) += snd-soc-smdk-wm9713.o | 51 | obj-$(CONFIG_SND_SOC_SMDK_WM9713) += snd-soc-smdk-wm9713.o |
45 | obj-$(CONFIG_SND_S3C64XX_SOC_SMARTQ) += snd-soc-s3c64xx-smartq-wm8987.o | 52 | obj-$(CONFIG_SND_S3C64XX_SOC_SMARTQ) += snd-soc-s3c64xx-smartq-wm8987.o |
53 | obj-$(CONFIG_SND_S5PC110_SOC_AQUILA_WM8994) += snd-soc-aquila-wm8994.o | ||
54 | obj-$(CONFIG_SND_S5PV210_SOC_GONI_WM8994) += snd-soc-goni-wm8994.o | ||
55 | obj-$(CONFIG_SND_SOC_SMDK_SPDIF) += snd-soc-smdk-spdif.o | ||
diff --git a/sound/soc/s3c24xx/aquila_wm8994.c b/sound/soc/s3c24xx/aquila_wm8994.c new file mode 100644 index 000000000000..235d1973f7d0 --- /dev/null +++ b/sound/soc/s3c24xx/aquila_wm8994.c | |||
@@ -0,0 +1,295 @@ | |||
1 | /* | ||
2 | * aquila_wm8994.c | ||
3 | * | ||
4 | * Copyright (C) 2010 Samsung Electronics Co.Ltd | ||
5 | * Author: Chanwoo Choi <cw00.choi@samsung.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/moduleparam.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <sound/soc.h> | ||
19 | #include <sound/soc-dapm.h> | ||
20 | #include <sound/jack.h> | ||
21 | #include <asm/mach-types.h> | ||
22 | #include <mach/gpio.h> | ||
23 | #include <mach/regs-clock.h> | ||
24 | |||
25 | #include <linux/mfd/wm8994/core.h> | ||
26 | #include <linux/mfd/wm8994/registers.h> | ||
27 | #include "../codecs/wm8994.h" | ||
28 | #include "s3c-dma.h" | ||
29 | #include "s3c64xx-i2s.h" | ||
30 | |||
31 | static struct snd_soc_card aquila; | ||
32 | static struct platform_device *aquila_snd_device; | ||
33 | |||
34 | /* 3.5 pie jack */ | ||
35 | static struct snd_soc_jack jack; | ||
36 | |||
37 | /* 3.5 pie jack detection DAPM pins */ | ||
38 | static struct snd_soc_jack_pin jack_pins[] = { | ||
39 | { | ||
40 | .pin = "Headset Mic", | ||
41 | .mask = SND_JACK_MICROPHONE, | ||
42 | }, { | ||
43 | .pin = "Headset Stereophone", | ||
44 | .mask = SND_JACK_HEADPHONE | SND_JACK_MECHANICAL | | ||
45 | SND_JACK_AVOUT, | ||
46 | }, | ||
47 | }; | ||
48 | |||
49 | /* 3.5 pie jack detection gpios */ | ||
50 | static struct snd_soc_jack_gpio jack_gpios[] = { | ||
51 | { | ||
52 | .gpio = S5PV210_GPH0(6), | ||
53 | .name = "DET_3.5", | ||
54 | .report = SND_JACK_HEADSET | SND_JACK_MECHANICAL | | ||
55 | SND_JACK_AVOUT, | ||
56 | .debounce_time = 200, | ||
57 | }, | ||
58 | }; | ||
59 | |||
60 | static const struct snd_soc_dapm_widget aquila_dapm_widgets[] = { | ||
61 | SND_SOC_DAPM_SPK("Ext Spk", NULL), | ||
62 | SND_SOC_DAPM_SPK("Ext Rcv", NULL), | ||
63 | SND_SOC_DAPM_HP("Headset Stereophone", NULL), | ||
64 | SND_SOC_DAPM_MIC("Headset Mic", NULL), | ||
65 | SND_SOC_DAPM_MIC("Main Mic", NULL), | ||
66 | SND_SOC_DAPM_MIC("2nd Mic", NULL), | ||
67 | SND_SOC_DAPM_LINE("Radio In", NULL), | ||
68 | }; | ||
69 | |||
70 | static const struct snd_soc_dapm_route aquila_dapm_routes[] = { | ||
71 | {"Ext Spk", NULL, "SPKOUTLP"}, | ||
72 | {"Ext Spk", NULL, "SPKOUTLN"}, | ||
73 | |||
74 | {"Ext Rcv", NULL, "HPOUT2N"}, | ||
75 | {"Ext Rcv", NULL, "HPOUT2P"}, | ||
76 | |||
77 | {"Headset Stereophone", NULL, "HPOUT1L"}, | ||
78 | {"Headset Stereophone", NULL, "HPOUT1R"}, | ||
79 | |||
80 | {"IN1RN", NULL, "Headset Mic"}, | ||
81 | {"IN1RP", NULL, "Headset Mic"}, | ||
82 | |||
83 | {"IN1RN", NULL, "2nd Mic"}, | ||
84 | {"IN1RP", NULL, "2nd Mic"}, | ||
85 | |||
86 | {"IN1LN", NULL, "Main Mic"}, | ||
87 | {"IN1LP", NULL, "Main Mic"}, | ||
88 | |||
89 | {"IN2LN", NULL, "Radio In"}, | ||
90 | {"IN2RN", NULL, "Radio In"}, | ||
91 | }; | ||
92 | |||
93 | static int aquila_wm8994_init(struct snd_soc_pcm_runtime *rtd) | ||
94 | { | ||
95 | struct snd_soc_codec *codec = rtd->codec; | ||
96 | int ret; | ||
97 | |||
98 | /* add aquila specific widgets */ | ||
99 | snd_soc_dapm_new_controls(codec, aquila_dapm_widgets, | ||
100 | ARRAY_SIZE(aquila_dapm_widgets)); | ||
101 | |||
102 | /* set up aquila specific audio routes */ | ||
103 | snd_soc_dapm_add_routes(codec, aquila_dapm_routes, | ||
104 | ARRAY_SIZE(aquila_dapm_routes)); | ||
105 | |||
106 | /* set endpoints to not connected */ | ||
107 | snd_soc_dapm_nc_pin(codec, "IN2LP:VXRN"); | ||
108 | snd_soc_dapm_nc_pin(codec, "IN2RP:VXRP"); | ||
109 | snd_soc_dapm_nc_pin(codec, "LINEOUT1N"); | ||
110 | snd_soc_dapm_nc_pin(codec, "LINEOUT1P"); | ||
111 | snd_soc_dapm_nc_pin(codec, "LINEOUT2N"); | ||
112 | snd_soc_dapm_nc_pin(codec, "LINEOUT2P"); | ||
113 | snd_soc_dapm_nc_pin(codec, "SPKOUTRN"); | ||
114 | snd_soc_dapm_nc_pin(codec, "SPKOUTRP"); | ||
115 | |||
116 | snd_soc_dapm_sync(codec); | ||
117 | |||
118 | /* Headset jack detection */ | ||
119 | ret = snd_soc_jack_new(&aquila, "Headset Jack", | ||
120 | SND_JACK_HEADSET | SND_JACK_MECHANICAL | SND_JACK_AVOUT, | ||
121 | &jack); | ||
122 | if (ret) | ||
123 | return ret; | ||
124 | |||
125 | ret = snd_soc_jack_add_pins(&jack, ARRAY_SIZE(jack_pins), jack_pins); | ||
126 | if (ret) | ||
127 | return ret; | ||
128 | |||
129 | ret = snd_soc_jack_add_gpios(&jack, ARRAY_SIZE(jack_gpios), jack_gpios); | ||
130 | if (ret) | ||
131 | return ret; | ||
132 | |||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | static int aquila_hifi_hw_params(struct snd_pcm_substream *substream, | ||
137 | struct snd_pcm_hw_params *params) | ||
138 | { | ||
139 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
140 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
141 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
142 | unsigned int pll_out = 24000000; | ||
143 | int ret = 0; | ||
144 | |||
145 | /* set the cpu DAI configuration */ | ||
146 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | | ||
147 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); | ||
148 | if (ret < 0) | ||
149 | return ret; | ||
150 | |||
151 | /* set the cpu system clock */ | ||
152 | ret = snd_soc_dai_set_sysclk(cpu_dai, S3C64XX_CLKSRC_PCLK, | ||
153 | 0, SND_SOC_CLOCK_IN); | ||
154 | if (ret < 0) | ||
155 | return ret; | ||
156 | |||
157 | /* set codec DAI configuration */ | ||
158 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | | ||
159 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); | ||
160 | if (ret < 0) | ||
161 | return ret; | ||
162 | |||
163 | /* set the codec FLL */ | ||
164 | ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1, 0, pll_out, | ||
165 | params_rate(params) * 256); | ||
166 | if (ret < 0) | ||
167 | return ret; | ||
168 | |||
169 | /* set the codec system clock */ | ||
170 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL1, | ||
171 | params_rate(params) * 256, SND_SOC_CLOCK_IN); | ||
172 | if (ret < 0) | ||
173 | return ret; | ||
174 | |||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | static struct snd_soc_ops aquila_hifi_ops = { | ||
179 | .hw_params = aquila_hifi_hw_params, | ||
180 | }; | ||
181 | |||
182 | static int aquila_voice_hw_params(struct snd_pcm_substream *substream, | ||
183 | struct snd_pcm_hw_params *params) | ||
184 | { | ||
185 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
186 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
187 | unsigned int pll_out = 24000000; | ||
188 | int ret = 0; | ||
189 | |||
190 | if (params_rate(params) != 8000) | ||
191 | return -EINVAL; | ||
192 | |||
193 | /* set codec DAI configuration */ | ||
194 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_LEFT_J | | ||
195 | SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM); | ||
196 | if (ret < 0) | ||
197 | return ret; | ||
198 | |||
199 | /* set the codec FLL */ | ||
200 | ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL2, 0, pll_out, | ||
201 | params_rate(params) * 256); | ||
202 | if (ret < 0) | ||
203 | return ret; | ||
204 | |||
205 | /* set the codec system clock */ | ||
206 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL2, | ||
207 | params_rate(params) * 256, SND_SOC_CLOCK_IN); | ||
208 | if (ret < 0) | ||
209 | return ret; | ||
210 | |||
211 | return 0; | ||
212 | } | ||
213 | |||
214 | static struct snd_soc_dai_driver voice_dai = { | ||
215 | .name = "aquila-voice-dai", | ||
216 | .playback = { | ||
217 | .channels_min = 1, | ||
218 | .channels_max = 2, | ||
219 | .rates = SNDRV_PCM_RATE_8000, | ||
220 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | ||
221 | .capture = { | ||
222 | .channels_min = 1, | ||
223 | .channels_max = 2, | ||
224 | .rates = SNDRV_PCM_RATE_8000, | ||
225 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | ||
226 | }; | ||
227 | |||
228 | static struct snd_soc_ops aquila_voice_ops = { | ||
229 | .hw_params = aquila_voice_hw_params, | ||
230 | }; | ||
231 | |||
232 | static struct snd_soc_dai_link aquila_dai[] = { | ||
233 | { | ||
234 | .name = "WM8994", | ||
235 | .stream_name = "WM8994 HiFi", | ||
236 | .cpu_dai_name = "s3c64xx-i2s-v4", | ||
237 | .codec_dai_name = "wm8994-hifi", | ||
238 | .platform_name = "s3c24xx-pcm-audio", | ||
239 | .codec_name = "wm8994-codec.0-0x1a", | ||
240 | .init = aquila_wm8994_init, | ||
241 | .ops = &aquila_hifi_ops, | ||
242 | }, { | ||
243 | .name = "WM8994 Voice", | ||
244 | .stream_name = "Voice", | ||
245 | .cpu_dai_name = "aquila-voice-dai", | ||
246 | .codec_dai_name = "wm8994-voice", | ||
247 | .platform_name = "s3c24xx-pcm-audio", | ||
248 | .codec_name = "wm8994-codec.0-0x1a", | ||
249 | .ops = &aquila_voice_ops, | ||
250 | }, | ||
251 | }; | ||
252 | |||
253 | static struct snd_soc_card aquila = { | ||
254 | .name = "aquila", | ||
255 | .dai_link = aquila_dai, | ||
256 | .num_links = ARRAY_SIZE(aquila_dai), | ||
257 | }; | ||
258 | |||
259 | static int __init aquila_init(void) | ||
260 | { | ||
261 | int ret; | ||
262 | |||
263 | if (!machine_is_aquila()) | ||
264 | return -ENODEV; | ||
265 | |||
266 | aquila_snd_device = platform_device_alloc("soc-audio", -1); | ||
267 | if (!aquila_snd_device) | ||
268 | return -ENOMEM; | ||
269 | |||
270 | /* register voice DAI here */ | ||
271 | ret = snd_soc_register_dai(&aquila_snd_device->dev, &voice_dai); | ||
272 | if (ret) | ||
273 | return ret; | ||
274 | |||
275 | platform_set_drvdata(aquila_snd_device, &aquila); | ||
276 | ret = platform_device_add(aquila_snd_device); | ||
277 | |||
278 | if (ret) | ||
279 | platform_device_put(aquila_snd_device); | ||
280 | |||
281 | return ret; | ||
282 | } | ||
283 | |||
284 | static void __exit aquila_exit(void) | ||
285 | { | ||
286 | platform_device_unregister(aquila_snd_device); | ||
287 | } | ||
288 | |||
289 | module_init(aquila_init); | ||
290 | module_exit(aquila_exit); | ||
291 | |||
292 | /* Module information */ | ||
293 | MODULE_DESCRIPTION("ALSA SoC WM8994 Aquila(S5PC110)"); | ||
294 | MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>"); | ||
295 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/s3c24xx/goni_wm8994.c b/sound/soc/s3c24xx/goni_wm8994.c new file mode 100644 index 000000000000..694f702cc8e2 --- /dev/null +++ b/sound/soc/s3c24xx/goni_wm8994.c | |||
@@ -0,0 +1,298 @@ | |||
1 | /* | ||
2 | * goni_wm8994.c | ||
3 | * | ||
4 | * Copyright (C) 2010 Samsung Electronics Co.Ltd | ||
5 | * Author: Chanwoo Choi <cw00.choi@samsung.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/moduleparam.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <sound/soc.h> | ||
19 | #include <sound/soc-dapm.h> | ||
20 | #include <sound/jack.h> | ||
21 | #include <asm/mach-types.h> | ||
22 | #include <mach/gpio.h> | ||
23 | #include <mach/regs-clock.h> | ||
24 | |||
25 | #include <linux/mfd/wm8994/core.h> | ||
26 | #include <linux/mfd/wm8994/registers.h> | ||
27 | #include "../codecs/wm8994.h" | ||
28 | #include "s3c-dma.h" | ||
29 | #include "s3c64xx-i2s.h" | ||
30 | |||
31 | static struct snd_soc_card goni; | ||
32 | static struct platform_device *goni_snd_device; | ||
33 | |||
34 | /* 3.5 pie jack */ | ||
35 | static struct snd_soc_jack jack; | ||
36 | |||
37 | /* 3.5 pie jack detection DAPM pins */ | ||
38 | static struct snd_soc_jack_pin jack_pins[] = { | ||
39 | { | ||
40 | .pin = "Headset Mic", | ||
41 | .mask = SND_JACK_MICROPHONE, | ||
42 | }, { | ||
43 | .pin = "Headset Stereophone", | ||
44 | .mask = SND_JACK_HEADPHONE | SND_JACK_MECHANICAL | | ||
45 | SND_JACK_AVOUT, | ||
46 | }, | ||
47 | }; | ||
48 | |||
49 | /* 3.5 pie jack detection gpios */ | ||
50 | static struct snd_soc_jack_gpio jack_gpios[] = { | ||
51 | { | ||
52 | .gpio = S5PV210_GPH0(6), | ||
53 | .name = "DET_3.5", | ||
54 | .report = SND_JACK_HEADSET | SND_JACK_MECHANICAL | | ||
55 | SND_JACK_AVOUT, | ||
56 | .debounce_time = 200, | ||
57 | }, | ||
58 | }; | ||
59 | |||
60 | static const struct snd_soc_dapm_widget goni_dapm_widgets[] = { | ||
61 | SND_SOC_DAPM_SPK("Ext Left Spk", NULL), | ||
62 | SND_SOC_DAPM_SPK("Ext Right Spk", NULL), | ||
63 | SND_SOC_DAPM_SPK("Ext Rcv", NULL), | ||
64 | SND_SOC_DAPM_HP("Headset Stereophone", NULL), | ||
65 | SND_SOC_DAPM_MIC("Headset Mic", NULL), | ||
66 | SND_SOC_DAPM_MIC("Main Mic", NULL), | ||
67 | SND_SOC_DAPM_MIC("2nd Mic", NULL), | ||
68 | SND_SOC_DAPM_LINE("Radio In", NULL), | ||
69 | }; | ||
70 | |||
71 | static const struct snd_soc_dapm_route goni_dapm_routes[] = { | ||
72 | {"Ext Left Spk", NULL, "SPKOUTLP"}, | ||
73 | {"Ext Left Spk", NULL, "SPKOUTLN"}, | ||
74 | |||
75 | {"Ext Right Spk", NULL, "SPKOUTRP"}, | ||
76 | {"Ext Right Spk", NULL, "SPKOUTRN"}, | ||
77 | |||
78 | {"Ext Rcv", NULL, "HPOUT2N"}, | ||
79 | {"Ext Rcv", NULL, "HPOUT2P"}, | ||
80 | |||
81 | {"Headset Stereophone", NULL, "HPOUT1L"}, | ||
82 | {"Headset Stereophone", NULL, "HPOUT1R"}, | ||
83 | |||
84 | {"IN1RN", NULL, "Headset Mic"}, | ||
85 | {"IN1RP", NULL, "Headset Mic"}, | ||
86 | |||
87 | {"IN1RN", NULL, "2nd Mic"}, | ||
88 | {"IN1RP", NULL, "2nd Mic"}, | ||
89 | |||
90 | {"IN1LN", NULL, "Main Mic"}, | ||
91 | {"IN1LP", NULL, "Main Mic"}, | ||
92 | |||
93 | {"IN2LN", NULL, "Radio In"}, | ||
94 | {"IN2RN", NULL, "Radio In"}, | ||
95 | }; | ||
96 | |||
97 | static int goni_wm8994_init(struct snd_soc_pcm_runtime *rtd) | ||
98 | { | ||
99 | struct snd_soc_codec *codec = rtd->codec; | ||
100 | int ret; | ||
101 | |||
102 | /* add goni specific widgets */ | ||
103 | snd_soc_dapm_new_controls(codec, goni_dapm_widgets, | ||
104 | ARRAY_SIZE(goni_dapm_widgets)); | ||
105 | |||
106 | /* set up goni specific audio routes */ | ||
107 | snd_soc_dapm_add_routes(codec, goni_dapm_routes, | ||
108 | ARRAY_SIZE(goni_dapm_routes)); | ||
109 | |||
110 | /* set endpoints to not connected */ | ||
111 | snd_soc_dapm_nc_pin(codec, "IN2LP:VXRN"); | ||
112 | snd_soc_dapm_nc_pin(codec, "IN2RP:VXRP"); | ||
113 | snd_soc_dapm_nc_pin(codec, "LINEOUT1N"); | ||
114 | snd_soc_dapm_nc_pin(codec, "LINEOUT1P"); | ||
115 | snd_soc_dapm_nc_pin(codec, "LINEOUT2N"); | ||
116 | snd_soc_dapm_nc_pin(codec, "LINEOUT2P"); | ||
117 | |||
118 | snd_soc_dapm_sync(codec); | ||
119 | |||
120 | /* Headset jack detection */ | ||
121 | ret = snd_soc_jack_new(&goni, "Headset Jack", | ||
122 | SND_JACK_HEADSET | SND_JACK_MECHANICAL | SND_JACK_AVOUT, | ||
123 | &jack); | ||
124 | if (ret) | ||
125 | return ret; | ||
126 | |||
127 | ret = snd_soc_jack_add_pins(&jack, ARRAY_SIZE(jack_pins), jack_pins); | ||
128 | if (ret) | ||
129 | return ret; | ||
130 | |||
131 | ret = snd_soc_jack_add_gpios(&jack, ARRAY_SIZE(jack_gpios), jack_gpios); | ||
132 | if (ret) | ||
133 | return ret; | ||
134 | |||
135 | return 0; | ||
136 | } | ||
137 | |||
138 | static int goni_hifi_hw_params(struct snd_pcm_substream *substream, | ||
139 | struct snd_pcm_hw_params *params) | ||
140 | { | ||
141 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
142 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
143 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
144 | unsigned int pll_out = 24000000; | ||
145 | int ret = 0; | ||
146 | |||
147 | /* set the cpu DAI configuration */ | ||
148 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | | ||
149 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); | ||
150 | if (ret < 0) | ||
151 | return ret; | ||
152 | |||
153 | /* set the cpu system clock */ | ||
154 | ret = snd_soc_dai_set_sysclk(cpu_dai, S3C64XX_CLKSRC_PCLK, | ||
155 | 0, SND_SOC_CLOCK_IN); | ||
156 | if (ret < 0) | ||
157 | return ret; | ||
158 | |||
159 | /* set codec DAI configuration */ | ||
160 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | | ||
161 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); | ||
162 | if (ret < 0) | ||
163 | return ret; | ||
164 | |||
165 | /* set the codec FLL */ | ||
166 | ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1, 0, pll_out, | ||
167 | params_rate(params) * 256); | ||
168 | if (ret < 0) | ||
169 | return ret; | ||
170 | |||
171 | /* set the codec system clock */ | ||
172 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL1, | ||
173 | params_rate(params) * 256, SND_SOC_CLOCK_IN); | ||
174 | if (ret < 0) | ||
175 | return ret; | ||
176 | |||
177 | return 0; | ||
178 | } | ||
179 | |||
180 | static struct snd_soc_ops goni_hifi_ops = { | ||
181 | .hw_params = goni_hifi_hw_params, | ||
182 | }; | ||
183 | |||
184 | static int goni_voice_hw_params(struct snd_pcm_substream *substream, | ||
185 | struct snd_pcm_hw_params *params) | ||
186 | { | ||
187 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
188 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
189 | unsigned int pll_out = 24000000; | ||
190 | int ret = 0; | ||
191 | |||
192 | if (params_rate(params) != 8000) | ||
193 | return -EINVAL; | ||
194 | |||
195 | /* set codec DAI configuration */ | ||
196 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_LEFT_J | | ||
197 | SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM); | ||
198 | if (ret < 0) | ||
199 | return ret; | ||
200 | |||
201 | /* set the codec FLL */ | ||
202 | ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL2, 0, pll_out, | ||
203 | params_rate(params) * 256); | ||
204 | if (ret < 0) | ||
205 | return ret; | ||
206 | |||
207 | /* set the codec system clock */ | ||
208 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL2, | ||
209 | params_rate(params) * 256, SND_SOC_CLOCK_IN); | ||
210 | if (ret < 0) | ||
211 | return ret; | ||
212 | |||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | static struct snd_soc_dai_driver voice_dai = { | ||
217 | .name = "goni-voice-dai", | ||
218 | .id = 0, | ||
219 | .playback = { | ||
220 | .channels_min = 1, | ||
221 | .channels_max = 2, | ||
222 | .rates = SNDRV_PCM_RATE_8000, | ||
223 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | ||
224 | .capture = { | ||
225 | .channels_min = 1, | ||
226 | .channels_max = 2, | ||
227 | .rates = SNDRV_PCM_RATE_8000, | ||
228 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | ||
229 | }; | ||
230 | |||
231 | static struct snd_soc_ops goni_voice_ops = { | ||
232 | .hw_params = goni_voice_hw_params, | ||
233 | }; | ||
234 | |||
235 | static struct snd_soc_dai_link goni_dai[] = { | ||
236 | { | ||
237 | .name = "WM8994", | ||
238 | .stream_name = "WM8994 HiFi", | ||
239 | .cpu_dai_name = "s3c64xx-i2s-v4", | ||
240 | .codec_dai_name = "wm8994-hifi", | ||
241 | .platform_name = "s3c24xx-pcm-audio", | ||
242 | .codec_name = "wm8994-codec.0-0x1a", | ||
243 | .init = goni_wm8994_init, | ||
244 | .ops = &goni_hifi_ops, | ||
245 | }, { | ||
246 | .name = "WM8994 Voice", | ||
247 | .stream_name = "Voice", | ||
248 | .cpu_dai_name = "goni-voice-dai", | ||
249 | .codec_dai_name = "wm8994-voice", | ||
250 | .platform_name = "s3c24xx-pcm-audio", | ||
251 | .codec_name = "wm8994-codec.0-0x1a", | ||
252 | .ops = &goni_voice_ops, | ||
253 | }, | ||
254 | }; | ||
255 | |||
256 | static struct snd_soc_card goni = { | ||
257 | .name = "goni", | ||
258 | .dai_link = goni_dai, | ||
259 | .num_links = ARRAY_SIZE(goni_dai), | ||
260 | }; | ||
261 | |||
262 | static int __init goni_init(void) | ||
263 | { | ||
264 | int ret; | ||
265 | |||
266 | if (!machine_is_goni()) | ||
267 | return -ENODEV; | ||
268 | |||
269 | goni_snd_device = platform_device_alloc("soc-audio", -1); | ||
270 | if (!goni_snd_device) | ||
271 | return -ENOMEM; | ||
272 | |||
273 | /* register voice DAI here */ | ||
274 | ret = snd_soc_register_dai(&goni_snd_device->dev, &voice_dai); | ||
275 | if (ret) | ||
276 | return ret; | ||
277 | |||
278 | platform_set_drvdata(goni_snd_device, &goni); | ||
279 | ret = platform_device_add(goni_snd_device); | ||
280 | |||
281 | if (ret) | ||
282 | platform_device_put(goni_snd_device); | ||
283 | |||
284 | return ret; | ||
285 | } | ||
286 | |||
287 | static void __exit goni_exit(void) | ||
288 | { | ||
289 | platform_device_unregister(goni_snd_device); | ||
290 | } | ||
291 | |||
292 | module_init(goni_init); | ||
293 | module_exit(goni_exit); | ||
294 | |||
295 | /* Module information */ | ||
296 | MODULE_DESCRIPTION("ALSA SoC WM8994 GONI(S5PV210)"); | ||
297 | MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>"); | ||
298 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/s3c24xx/jive_wm8750.c b/sound/soc/s3c24xx/jive_wm8750.c index 8c108b121c10..49605cd83947 100644 --- a/sound/soc/s3c24xx/jive_wm8750.c +++ b/sound/soc/s3c24xx/jive_wm8750.c | |||
@@ -49,8 +49,8 @@ static int jive_hw_params(struct snd_pcm_substream *substream, | |||
49 | struct snd_pcm_hw_params *params) | 49 | struct snd_pcm_hw_params *params) |
50 | { | 50 | { |
51 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 51 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
52 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 52 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
53 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 53 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
54 | struct s3c_i2sv2_rate_calc div; | 54 | struct s3c_i2sv2_rate_calc div; |
55 | unsigned int clk = 0; | 55 | unsigned int clk = 0; |
56 | int ret = 0; | 56 | int ret = 0; |
@@ -108,8 +108,9 @@ static struct snd_soc_ops jive_ops = { | |||
108 | .hw_params = jive_hw_params, | 108 | .hw_params = jive_hw_params, |
109 | }; | 109 | }; |
110 | 110 | ||
111 | static int jive_wm8750_init(struct snd_soc_codec *codec) | 111 | static int jive_wm8750_init(struct snd_soc_pcm_runtime *rtd) |
112 | { | 112 | { |
113 | struct snd_soc_codec *codec = rtd->codec; | ||
113 | int err; | 114 | int err; |
114 | 115 | ||
115 | /* These endpoints are not being used. */ | 116 | /* These endpoints are not being used. */ |
@@ -138,8 +139,10 @@ static int jive_wm8750_init(struct snd_soc_codec *codec) | |||
138 | static struct snd_soc_dai_link jive_dai = { | 139 | static struct snd_soc_dai_link jive_dai = { |
139 | .name = "wm8750", | 140 | .name = "wm8750", |
140 | .stream_name = "WM8750", | 141 | .stream_name = "WM8750", |
141 | .cpu_dai = &s3c2412_i2s_dai, | 142 | .cpu_dai_name = "s3c2412-i2s", |
142 | .codec_dai = &wm8750_dai, | 143 | .codec_dai_name = "wm8750-hifi", |
144 | .platform_name = "s3c24xx-pcm-audio", | ||
145 | .codec_name = "wm8750-codec.0-0x1a", | ||
143 | .init = jive_wm8750_init, | 146 | .init = jive_wm8750_init, |
144 | .ops = &jive_ops, | 147 | .ops = &jive_ops, |
145 | }; | 148 | }; |
@@ -147,17 +150,10 @@ static struct snd_soc_dai_link jive_dai = { | |||
147 | /* jive audio machine driver */ | 150 | /* jive audio machine driver */ |
148 | static struct snd_soc_card snd_soc_machine_jive = { | 151 | static struct snd_soc_card snd_soc_machine_jive = { |
149 | .name = "Jive", | 152 | .name = "Jive", |
150 | .platform = &s3c24xx_soc_platform, | ||
151 | .dai_link = &jive_dai, | 153 | .dai_link = &jive_dai, |
152 | .num_links = 1, | 154 | .num_links = 1, |
153 | }; | 155 | }; |
154 | 156 | ||
155 | /* jive audio subsystem */ | ||
156 | static struct snd_soc_device jive_snd_devdata = { | ||
157 | .card = &snd_soc_machine_jive, | ||
158 | .codec_dev = &soc_codec_dev_wm8750, | ||
159 | }; | ||
160 | |||
161 | static struct platform_device *jive_snd_device; | 157 | static struct platform_device *jive_snd_device; |
162 | 158 | ||
163 | static int __init jive_init(void) | 159 | static int __init jive_init(void) |
@@ -173,8 +169,7 @@ static int __init jive_init(void) | |||
173 | if (!jive_snd_device) | 169 | if (!jive_snd_device) |
174 | return -ENOMEM; | 170 | return -ENOMEM; |
175 | 171 | ||
176 | platform_set_drvdata(jive_snd_device, &jive_snd_devdata); | 172 | platform_set_drvdata(jive_snd_device, &snd_soc_machine_jive); |
177 | jive_snd_devdata.dev = &jive_snd_device->dev; | ||
178 | ret = platform_device_add(jive_snd_device); | 173 | ret = platform_device_add(jive_snd_device); |
179 | 174 | ||
180 | if (ret) | 175 | if (ret) |
diff --git a/sound/soc/s3c24xx/ln2440sbc_alc650.c b/sound/soc/s3c24xx/ln2440sbc_alc650.c index ffa954fe6931..abe64abe8c84 100644 --- a/sound/soc/s3c24xx/ln2440sbc_alc650.c +++ b/sound/soc/s3c24xx/ln2440sbc_alc650.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <sound/soc.h> | 23 | #include <sound/soc.h> |
24 | #include <sound/soc-dapm.h> | 24 | #include <sound/soc-dapm.h> |
25 | 25 | ||
26 | #include "../codecs/ac97.h" | ||
27 | #include "s3c-dma.h" | 26 | #include "s3c-dma.h" |
28 | #include "s3c-ac97.h" | 27 | #include "s3c-ac97.h" |
29 | 28 | ||
@@ -33,23 +32,19 @@ static struct snd_soc_dai_link ln2440sbc_dai[] = { | |||
33 | { | 32 | { |
34 | .name = "AC97", | 33 | .name = "AC97", |
35 | .stream_name = "AC97 HiFi", | 34 | .stream_name = "AC97 HiFi", |
36 | .cpu_dai = &s3c_ac97_dai[S3C_AC97_DAI_PCM], | 35 | .cpu_dai_name = "s3c-ac97", |
37 | .codec_dai = &ac97_dai, | 36 | .codec_dai_name = "ac97-hifi", |
37 | .codec_name = "ac97-codec", | ||
38 | .platform_name = "s3c24xx-pcm-audio", | ||
38 | }, | 39 | }, |
39 | }; | 40 | }; |
40 | 41 | ||
41 | static struct snd_soc_card ln2440sbc = { | 42 | static struct snd_soc_card ln2440sbc = { |
42 | .name = "LN2440SBC", | 43 | .name = "LN2440SBC", |
43 | .platform = &s3c24xx_soc_platform, | ||
44 | .dai_link = ln2440sbc_dai, | 44 | .dai_link = ln2440sbc_dai, |
45 | .num_links = ARRAY_SIZE(ln2440sbc_dai), | 45 | .num_links = ARRAY_SIZE(ln2440sbc_dai), |
46 | }; | 46 | }; |
47 | 47 | ||
48 | static struct snd_soc_device ln2440sbc_snd_ac97_devdata = { | ||
49 | .card = &ln2440sbc, | ||
50 | .codec_dev = &soc_codec_dev_ac97, | ||
51 | }; | ||
52 | |||
53 | static struct platform_device *ln2440sbc_snd_ac97_device; | 48 | static struct platform_device *ln2440sbc_snd_ac97_device; |
54 | 49 | ||
55 | static int __init ln2440sbc_init(void) | 50 | static int __init ln2440sbc_init(void) |
@@ -60,9 +55,7 @@ static int __init ln2440sbc_init(void) | |||
60 | if (!ln2440sbc_snd_ac97_device) | 55 | if (!ln2440sbc_snd_ac97_device) |
61 | return -ENOMEM; | 56 | return -ENOMEM; |
62 | 57 | ||
63 | platform_set_drvdata(ln2440sbc_snd_ac97_device, | 58 | platform_set_drvdata(ln2440sbc_snd_ac97_device, &ln2440sbc); |
64 | &ln2440sbc_snd_ac97_devdata); | ||
65 | ln2440sbc_snd_ac97_devdata.dev = &ln2440sbc_snd_ac97_device->dev; | ||
66 | ret = platform_device_add(ln2440sbc_snd_ac97_device); | 59 | ret = platform_device_add(ln2440sbc_snd_ac97_device); |
67 | 60 | ||
68 | if (ret) | 61 | if (ret) |
diff --git a/sound/soc/s3c24xx/neo1973_gta02_wm8753.c b/sound/soc/s3c24xx/neo1973_gta02_wm8753.c index 4719558289d4..e97bdf150a03 100644 --- a/sound/soc/s3c24xx/neo1973_gta02_wm8753.c +++ b/sound/soc/s3c24xx/neo1973_gta02_wm8753.c | |||
@@ -41,8 +41,8 @@ static int neo1973_gta02_hifi_hw_params(struct snd_pcm_substream *substream, | |||
41 | struct snd_pcm_hw_params *params) | 41 | struct snd_pcm_hw_params *params) |
42 | { | 42 | { |
43 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 43 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
44 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 44 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
45 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 45 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
46 | unsigned int pll_out = 0, bclk = 0; | 46 | unsigned int pll_out = 0, bclk = 0; |
47 | int ret = 0; | 47 | int ret = 0; |
48 | unsigned long iis_clkrate; | 48 | unsigned long iis_clkrate; |
@@ -130,7 +130,7 @@ static int neo1973_gta02_hifi_hw_params(struct snd_pcm_substream *substream, | |||
130 | static int neo1973_gta02_hifi_hw_free(struct snd_pcm_substream *substream) | 130 | static int neo1973_gta02_hifi_hw_free(struct snd_pcm_substream *substream) |
131 | { | 131 | { |
132 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 132 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
133 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 133 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
134 | 134 | ||
135 | /* disable the PLL */ | 135 | /* disable the PLL */ |
136 | return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0, 0); | 136 | return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0, 0); |
@@ -149,7 +149,7 @@ static int neo1973_gta02_voice_hw_params( | |||
149 | struct snd_pcm_hw_params *params) | 149 | struct snd_pcm_hw_params *params) |
150 | { | 150 | { |
151 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 151 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
152 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 152 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
153 | unsigned int pcmdiv = 0; | 153 | unsigned int pcmdiv = 0; |
154 | int ret = 0; | 154 | int ret = 0; |
155 | unsigned long iis_clkrate; | 155 | unsigned long iis_clkrate; |
@@ -194,7 +194,7 @@ static int neo1973_gta02_voice_hw_params( | |||
194 | static int neo1973_gta02_voice_hw_free(struct snd_pcm_substream *substream) | 194 | static int neo1973_gta02_voice_hw_free(struct snd_pcm_substream *substream) |
195 | { | 195 | { |
196 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 196 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
197 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 197 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
198 | 198 | ||
199 | /* disable the PLL */ | 199 | /* disable the PLL */ |
200 | return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0, 0); | 200 | return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0, 0); |
@@ -262,7 +262,7 @@ static int lm4853_event(struct snd_soc_dapm_widget *w, | |||
262 | struct snd_kcontrol *k, | 262 | struct snd_kcontrol *k, |
263 | int event) | 263 | int event) |
264 | { | 264 | { |
265 | gpio_set_value(GTA02_GPIO_AMP_SHUT, SND_SOC_DAPM_EVENT_OFF(value)); | 265 | gpio_set_value(GTA02_GPIO_AMP_SHUT, SND_SOC_DAPM_EVENT_OFF(event)); |
266 | 266 | ||
267 | return 0; | 267 | return 0; |
268 | } | 268 | } |
@@ -330,8 +330,9 @@ static const struct snd_kcontrol_new wm8753_neo1973_gta02_controls[] = { | |||
330 | * This is an example machine initialisation for a wm8753 connected to a | 330 | * This is an example machine initialisation for a wm8753 connected to a |
331 | * neo1973 GTA02. | 331 | * neo1973 GTA02. |
332 | */ | 332 | */ |
333 | static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec) | 333 | static int neo1973_gta02_wm8753_init(struct snd_soc_pcm_runtime *rtd) |
334 | { | 334 | { |
335 | struct snd_soc_codec *codec = rtd->codec; | ||
335 | int err; | 336 | int err; |
336 | 337 | ||
337 | /* set up NC codec pins */ | 338 | /* set up NC codec pins */ |
@@ -378,9 +379,8 @@ static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec) | |||
378 | /* | 379 | /* |
379 | * BT Codec DAI | 380 | * BT Codec DAI |
380 | */ | 381 | */ |
381 | static struct snd_soc_dai bt_dai = { | 382 | static struct snd_soc_dai_driver bt_dai = { |
382 | .name = "Bluetooth", | 383 | .name = "bluetooth-dai", |
383 | .id = 0, | ||
384 | .playback = { | 384 | .playback = { |
385 | .channels_min = 1, | 385 | .channels_min = 1, |
386 | .channels_max = 1, | 386 | .channels_max = 1, |
@@ -397,32 +397,30 @@ static struct snd_soc_dai_link neo1973_gta02_dai[] = { | |||
397 | { /* Hifi Playback - for similatious use with voice below */ | 397 | { /* Hifi Playback - for similatious use with voice below */ |
398 | .name = "WM8753", | 398 | .name = "WM8753", |
399 | .stream_name = "WM8753 HiFi", | 399 | .stream_name = "WM8753 HiFi", |
400 | .cpu_dai = &s3c24xx_i2s_dai, | 400 | .cpu_dai_name = "s3c24xx-i2s", |
401 | .codec_dai = &wm8753_dai[WM8753_DAI_HIFI], | 401 | .codec_dai_name = "wm8753-hifi", |
402 | .init = neo1973_gta02_wm8753_init, | 402 | .init = neo1973_gta02_wm8753_init, |
403 | .platform_name = "s3c24xx-pcm-audio", | ||
404 | .codec_name = "wm8753-codec.0-0x1a", | ||
403 | .ops = &neo1973_gta02_hifi_ops, | 405 | .ops = &neo1973_gta02_hifi_ops, |
404 | }, | 406 | }, |
405 | { /* Voice via BT */ | 407 | { /* Voice via BT */ |
406 | .name = "Bluetooth", | 408 | .name = "Bluetooth", |
407 | .stream_name = "Voice", | 409 | .stream_name = "Voice", |
408 | .cpu_dai = &bt_dai, | 410 | .cpu_dai_name = "bluetooth-dai", |
409 | .codec_dai = &wm8753_dai[WM8753_DAI_VOICE], | 411 | .codec_dai_name = "wm8753-voice", |
410 | .ops = &neo1973_gta02_voice_ops, | 412 | .ops = &neo1973_gta02_voice_ops, |
413 | .codec_name = "wm8753-codec.0-0x1a", | ||
414 | .platform_name = "s3c24xx-pcm-audio", | ||
411 | }, | 415 | }, |
412 | }; | 416 | }; |
413 | 417 | ||
414 | static struct snd_soc_card neo1973_gta02 = { | 418 | static struct snd_soc_card neo1973_gta02 = { |
415 | .name = "neo1973-gta02", | 419 | .name = "neo1973-gta02", |
416 | .platform = &s3c24xx_soc_platform, | ||
417 | .dai_link = neo1973_gta02_dai, | 420 | .dai_link = neo1973_gta02_dai, |
418 | .num_links = ARRAY_SIZE(neo1973_gta02_dai), | 421 | .num_links = ARRAY_SIZE(neo1973_gta02_dai), |
419 | }; | 422 | }; |
420 | 423 | ||
421 | static struct snd_soc_device neo1973_gta02_snd_devdata = { | ||
422 | .card = &neo1973_gta02, | ||
423 | .codec_dev = &soc_codec_dev_wm8753, | ||
424 | }; | ||
425 | |||
426 | static struct platform_device *neo1973_gta02_snd_device; | 424 | static struct platform_device *neo1973_gta02_snd_device; |
427 | 425 | ||
428 | static int __init neo1973_gta02_init(void) | 426 | static int __init neo1973_gta02_init(void) |
@@ -435,18 +433,18 @@ static int __init neo1973_gta02_init(void) | |||
435 | return -ENODEV; | 433 | return -ENODEV; |
436 | } | 434 | } |
437 | 435 | ||
438 | /* register bluetooth DAI here */ | ||
439 | ret = snd_soc_register_dai(&bt_dai); | ||
440 | if (ret) | ||
441 | return ret; | ||
442 | |||
443 | neo1973_gta02_snd_device = platform_device_alloc("soc-audio", -1); | 436 | neo1973_gta02_snd_device = platform_device_alloc("soc-audio", -1); |
444 | if (!neo1973_gta02_snd_device) | 437 | if (!neo1973_gta02_snd_device) |
445 | return -ENOMEM; | 438 | return -ENOMEM; |
446 | 439 | ||
447 | platform_set_drvdata(neo1973_gta02_snd_device, | 440 | /* register bluetooth DAI here */ |
448 | &neo1973_gta02_snd_devdata); | 441 | ret = snd_soc_register_dai(&neo1973_gta02_snd_device->dev, -1, &bt_dai); |
449 | neo1973_gta02_snd_devdata.dev = &neo1973_gta02_snd_device->dev; | 442 | if (ret) { |
443 | platform_device_put(neo1973_gta02_snd_device); | ||
444 | return ret; | ||
445 | } | ||
446 | |||
447 | platform_set_drvdata(neo1973_gta02_snd_device, &neo1973_gta02); | ||
450 | ret = platform_device_add(neo1973_gta02_snd_device); | 448 | ret = platform_device_add(neo1973_gta02_snd_device); |
451 | 449 | ||
452 | if (ret) { | 450 | if (ret) { |
@@ -461,7 +459,7 @@ static int __init neo1973_gta02_init(void) | |||
461 | goto err_unregister_device; | 459 | goto err_unregister_device; |
462 | } | 460 | } |
463 | 461 | ||
464 | ret = gpio_direction_output(GTA02_GPIO_AMP_HP_IN, 1); | 462 | ret = gpio_direction_output(GTA02_GPIO_HP_IN, 1); |
465 | if (ret) { | 463 | if (ret) { |
466 | pr_err("gta02_wm8753: Failed to configure GPIO %d\n", GTA02_GPIO_HP_IN); | 464 | pr_err("gta02_wm8753: Failed to configure GPIO %d\n", GTA02_GPIO_HP_IN); |
467 | goto err_free_gpio_hp_in; | 465 | goto err_free_gpio_hp_in; |
@@ -493,7 +491,7 @@ module_init(neo1973_gta02_init); | |||
493 | 491 | ||
494 | static void __exit neo1973_gta02_exit(void) | 492 | static void __exit neo1973_gta02_exit(void) |
495 | { | 493 | { |
496 | snd_soc_unregister_dai(&bt_dai); | 494 | snd_soc_unregister_dai(&neo1973_gta02_snd_device->dev, -1); |
497 | platform_device_unregister(neo1973_gta02_snd_device); | 495 | platform_device_unregister(neo1973_gta02_snd_device); |
498 | gpio_free(GTA02_GPIO_HP_IN); | 496 | gpio_free(GTA02_GPIO_HP_IN); |
499 | gpio_free(GTA02_GPIO_AMP_SHUT); | 497 | gpio_free(GTA02_GPIO_AMP_SHUT); |
diff --git a/sound/soc/s3c24xx/neo1973_wm8753.c b/sound/soc/s3c24xx/neo1973_wm8753.c index 4ac620988e7c..f4f2ee731f01 100644 --- a/sound/soc/s3c24xx/neo1973_wm8753.c +++ b/sound/soc/s3c24xx/neo1973_wm8753.c | |||
@@ -57,8 +57,8 @@ static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream, | |||
57 | struct snd_pcm_hw_params *params) | 57 | struct snd_pcm_hw_params *params) |
58 | { | 58 | { |
59 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 59 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
60 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 60 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
61 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 61 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
62 | unsigned int pll_out = 0, bclk = 0; | 62 | unsigned int pll_out = 0, bclk = 0; |
63 | int ret = 0; | 63 | int ret = 0; |
64 | unsigned long iis_clkrate; | 64 | unsigned long iis_clkrate; |
@@ -147,7 +147,7 @@ static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream, | |||
147 | static int neo1973_hifi_hw_free(struct snd_pcm_substream *substream) | 147 | static int neo1973_hifi_hw_free(struct snd_pcm_substream *substream) |
148 | { | 148 | { |
149 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 149 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
150 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 150 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
151 | 151 | ||
152 | pr_debug("Entered %s\n", __func__); | 152 | pr_debug("Entered %s\n", __func__); |
153 | 153 | ||
@@ -167,7 +167,7 @@ static int neo1973_voice_hw_params(struct snd_pcm_substream *substream, | |||
167 | struct snd_pcm_hw_params *params) | 167 | struct snd_pcm_hw_params *params) |
168 | { | 168 | { |
169 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 169 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
170 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 170 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
171 | unsigned int pcmdiv = 0; | 171 | unsigned int pcmdiv = 0; |
172 | int ret = 0; | 172 | int ret = 0; |
173 | unsigned long iis_clkrate; | 173 | unsigned long iis_clkrate; |
@@ -213,7 +213,7 @@ static int neo1973_voice_hw_params(struct snd_pcm_substream *substream, | |||
213 | static int neo1973_voice_hw_free(struct snd_pcm_substream *substream) | 213 | static int neo1973_voice_hw_free(struct snd_pcm_substream *substream) |
214 | { | 214 | { |
215 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 215 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
216 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 216 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
217 | 217 | ||
218 | pr_debug("Entered %s\n", __func__); | 218 | pr_debug("Entered %s\n", __func__); |
219 | 219 | ||
@@ -499,8 +499,9 @@ static const struct snd_kcontrol_new wm8753_neo1973_controls[] = { | |||
499 | * neo1973 II. It is missing logic to detect hp/mic insertions and logic | 499 | * neo1973 II. It is missing logic to detect hp/mic insertions and logic |
500 | * to re-route the audio in such an event. | 500 | * to re-route the audio in such an event. |
501 | */ | 501 | */ |
502 | static int neo1973_wm8753_init(struct snd_soc_codec *codec) | 502 | static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd) |
503 | { | 503 | { |
504 | struct snd_soc_codec *codec = rtd->codec; | ||
504 | int err; | 505 | int err; |
505 | 506 | ||
506 | pr_debug("Entered %s\n", __func__); | 507 | pr_debug("Entered %s\n", __func__); |
@@ -538,8 +539,7 @@ static int neo1973_wm8753_init(struct snd_soc_codec *codec) | |||
538 | * BT Codec DAI | 539 | * BT Codec DAI |
539 | */ | 540 | */ |
540 | static struct snd_soc_dai bt_dai = { | 541 | static struct snd_soc_dai bt_dai = { |
541 | .name = "Bluetooth", | 542 | .name = "bluetooth-dai", |
542 | .id = 0, | ||
543 | .playback = { | 543 | .playback = { |
544 | .channels_min = 1, | 544 | .channels_min = 1, |
545 | .channels_max = 1, | 545 | .channels_max = 1, |
@@ -556,32 +556,30 @@ static struct snd_soc_dai_link neo1973_dai[] = { | |||
556 | { /* Hifi Playback - for similatious use with voice below */ | 556 | { /* Hifi Playback - for similatious use with voice below */ |
557 | .name = "WM8753", | 557 | .name = "WM8753", |
558 | .stream_name = "WM8753 HiFi", | 558 | .stream_name = "WM8753 HiFi", |
559 | .cpu_dai = &s3c24xx_i2s_dai, | 559 | .platform_name = "s3c24xx-pcm-audio", |
560 | .codec_dai = &wm8753_dai[WM8753_DAI_HIFI], | 560 | .cpu_dai_name = "s3c24xx-i2s", |
561 | .codec_dai_name = "wm8753-hifi", | ||
562 | .codec_name = "wm8753-codec.0-0x1a", | ||
561 | .init = neo1973_wm8753_init, | 563 | .init = neo1973_wm8753_init, |
562 | .ops = &neo1973_hifi_ops, | 564 | .ops = &neo1973_hifi_ops, |
563 | }, | 565 | }, |
564 | { /* Voice via BT */ | 566 | { /* Voice via BT */ |
565 | .name = "Bluetooth", | 567 | .name = "Bluetooth", |
566 | .stream_name = "Voice", | 568 | .stream_name = "Voice", |
567 | .cpu_dai = &bt_dai, | 569 | .platform_name = "s3c24xx-pcm-audio", |
568 | .codec_dai = &wm8753_dai[WM8753_DAI_VOICE], | 570 | .cpu_dai_name = "bluetooth-dai", |
571 | .codec_dai_name = "wm8753-voice", | ||
572 | .codec_name = "wm8753-codec.0-0x1a", | ||
569 | .ops = &neo1973_voice_ops, | 573 | .ops = &neo1973_voice_ops, |
570 | }, | 574 | }, |
571 | }; | 575 | }; |
572 | 576 | ||
573 | static struct snd_soc_card neo1973 = { | 577 | static struct snd_soc_card neo1973 = { |
574 | .name = "neo1973", | 578 | .name = "neo1973", |
575 | .platform = &s3c24xx_soc_platform, | ||
576 | .dai_link = neo1973_dai, | 579 | .dai_link = neo1973_dai, |
577 | .num_links = ARRAY_SIZE(neo1973_dai), | 580 | .num_links = ARRAY_SIZE(neo1973_dai), |
578 | }; | 581 | }; |
579 | 582 | ||
580 | static struct snd_soc_device neo1973_snd_devdata = { | ||
581 | .card = &neo1973, | ||
582 | .codec_dev = &soc_codec_dev_wm8753, | ||
583 | }; | ||
584 | |||
585 | static int lm4857_i2c_probe(struct i2c_client *client, | 583 | static int lm4857_i2c_probe(struct i2c_client *client, |
586 | const struct i2c_device_id *id) | 584 | const struct i2c_device_id *id) |
587 | { | 585 | { |
@@ -673,8 +671,7 @@ static int __init neo1973_init(void) | |||
673 | if (!neo1973_snd_device) | 671 | if (!neo1973_snd_device) |
674 | return -ENOMEM; | 672 | return -ENOMEM; |
675 | 673 | ||
676 | platform_set_drvdata(neo1973_snd_device, &neo1973_snd_devdata); | 674 | platform_set_drvdata(neo1973_snd_device, &neo1973); |
677 | neo1973_snd_devdata.dev = &neo1973_snd_device->dev; | ||
678 | ret = platform_device_add(neo1973_snd_device); | 675 | ret = platform_device_add(neo1973_snd_device); |
679 | 676 | ||
680 | if (ret) { | 677 | if (ret) { |
diff --git a/sound/soc/s3c24xx/rx1950_uda1380.c b/sound/soc/s3c24xx/rx1950_uda1380.c new file mode 100644 index 000000000000..ffd5cf2fb0a9 --- /dev/null +++ b/sound/soc/s3c24xx/rx1950_uda1380.c | |||
@@ -0,0 +1,333 @@ | |||
1 | /* | ||
2 | * rx1950.c -- ALSA Soc Audio Layer | ||
3 | * | ||
4 | * Copyright (c) 2010 Vasily Khoruzhick <anarsoul@gmail.com> | ||
5 | * | ||
6 | * Based on smdk2440.c and magician.c | ||
7 | * | ||
8 | * Authors: Graeme Gregory graeme.gregory@wolfsonmicro.com | ||
9 | * Philipp Zabel <philipp.zabel@gmail.com> | ||
10 | * Denis Grigoriev <dgreenday@gmail.com> | ||
11 | * Vasily Khoruzhick <anarsoul@gmail.com> | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify it | ||
14 | * under the terms of the GNU General Public License as published by the | ||
15 | * Free Software Foundation; either version 2 of the License, or (at your | ||
16 | * option) any later version. | ||
17 | * | ||
18 | */ | ||
19 | |||
20 | #include <linux/module.h> | ||
21 | #include <linux/moduleparam.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/i2c.h> | ||
24 | #include <linux/gpio.h> | ||
25 | #include <linux/clk.h> | ||
26 | |||
27 | #include <sound/soc.h> | ||
28 | #include <sound/soc-dapm.h> | ||
29 | #include <sound/uda1380.h> | ||
30 | #include <sound/jack.h> | ||
31 | |||
32 | #include <plat/regs-iis.h> | ||
33 | |||
34 | #include <mach/regs-clock.h> | ||
35 | |||
36 | #include <asm/mach-types.h> | ||
37 | |||
38 | #include "s3c-dma.h" | ||
39 | #include "s3c24xx-i2s.h" | ||
40 | #include "../codecs/uda1380.h" | ||
41 | |||
42 | static int rx1950_uda1380_init(struct snd_soc_pcm_runtime *rtd); | ||
43 | static int rx1950_startup(struct snd_pcm_substream *substream); | ||
44 | static int rx1950_hw_params(struct snd_pcm_substream *substream, | ||
45 | struct snd_pcm_hw_params *params); | ||
46 | static int rx1950_spk_power(struct snd_soc_dapm_widget *w, | ||
47 | struct snd_kcontrol *kcontrol, int event); | ||
48 | |||
49 | static unsigned int rates[] = { | ||
50 | 16000, | ||
51 | 44100, | ||
52 | 48000, | ||
53 | 88200, | ||
54 | }; | ||
55 | |||
56 | static struct snd_pcm_hw_constraint_list hw_rates = { | ||
57 | .count = ARRAY_SIZE(rates), | ||
58 | .list = rates, | ||
59 | .mask = 0, | ||
60 | }; | ||
61 | |||
62 | static struct snd_soc_jack hp_jack; | ||
63 | |||
64 | static struct snd_soc_jack_pin hp_jack_pins[] = { | ||
65 | { | ||
66 | .pin = "Headphone Jack", | ||
67 | .mask = SND_JACK_HEADPHONE, | ||
68 | }, | ||
69 | { | ||
70 | .pin = "Speaker", | ||
71 | .mask = SND_JACK_HEADPHONE, | ||
72 | .invert = 1, | ||
73 | }, | ||
74 | }; | ||
75 | |||
76 | static struct snd_soc_jack_gpio hp_jack_gpios[] = { | ||
77 | [0] = { | ||
78 | .gpio = S3C2410_GPG(12), | ||
79 | .name = "hp-gpio", | ||
80 | .report = SND_JACK_HEADPHONE, | ||
81 | .invert = 1, | ||
82 | .debounce_time = 200, | ||
83 | }, | ||
84 | }; | ||
85 | |||
86 | static struct snd_soc_ops rx1950_ops = { | ||
87 | .startup = rx1950_startup, | ||
88 | .hw_params = rx1950_hw_params, | ||
89 | }; | ||
90 | |||
91 | /* s3c24xx digital audio interface glue - connects codec <--> CPU */ | ||
92 | static struct snd_soc_dai_link rx1950_uda1380_dai[] = { | ||
93 | { | ||
94 | .name = "uda1380", | ||
95 | .stream_name = "UDA1380 Duplex", | ||
96 | .cpu_dai_name = "s3c24xx-iis", | ||
97 | .codec_dai_name = "uda1380-hifi", | ||
98 | .init = rx1950_uda1380_init, | ||
99 | .platform_name = "s3c24xx-pcm-audio", | ||
100 | .codec_name = "uda1380-codec.0-001a", | ||
101 | .ops = &rx1950_ops, | ||
102 | }, | ||
103 | }; | ||
104 | |||
105 | static struct snd_soc_card rx1950_asoc = { | ||
106 | .name = "rx1950", | ||
107 | .dai_link = rx1950_uda1380_dai, | ||
108 | .num_links = ARRAY_SIZE(rx1950_uda1380_dai), | ||
109 | }; | ||
110 | |||
111 | /* rx1950 machine dapm widgets */ | ||
112 | static const struct snd_soc_dapm_widget uda1380_dapm_widgets[] = { | ||
113 | SND_SOC_DAPM_HP("Headphone Jack", NULL), | ||
114 | SND_SOC_DAPM_MIC("Mic Jack", NULL), | ||
115 | SND_SOC_DAPM_SPK("Speaker", rx1950_spk_power), | ||
116 | }; | ||
117 | |||
118 | /* rx1950 machine audio_map */ | ||
119 | static const struct snd_soc_dapm_route audio_map[] = { | ||
120 | /* headphone connected to VOUTLHP, VOUTRHP */ | ||
121 | {"Headphone Jack", NULL, "VOUTLHP"}, | ||
122 | {"Headphone Jack", NULL, "VOUTRHP"}, | ||
123 | |||
124 | /* ext speaker connected to VOUTL, VOUTR */ | ||
125 | {"Speaker", NULL, "VOUTL"}, | ||
126 | {"Speaker", NULL, "VOUTR"}, | ||
127 | |||
128 | /* mic is connected to VINM */ | ||
129 | {"VINM", NULL, "Mic Jack"}, | ||
130 | }; | ||
131 | |||
132 | static struct platform_device *s3c24xx_snd_device; | ||
133 | static struct clk *xtal; | ||
134 | |||
135 | static int rx1950_startup(struct snd_pcm_substream *substream) | ||
136 | { | ||
137 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
138 | |||
139 | runtime->hw.rate_min = hw_rates.list[0]; | ||
140 | runtime->hw.rate_max = hw_rates.list[hw_rates.count - 1]; | ||
141 | runtime->hw.rates = SNDRV_PCM_RATE_KNOT; | ||
142 | |||
143 | return snd_pcm_hw_constraint_list(runtime, 0, | ||
144 | SNDRV_PCM_HW_PARAM_RATE, | ||
145 | &hw_rates); | ||
146 | } | ||
147 | |||
148 | static int rx1950_spk_power(struct snd_soc_dapm_widget *w, | ||
149 | struct snd_kcontrol *kcontrol, int event) | ||
150 | { | ||
151 | if (SND_SOC_DAPM_EVENT_ON(event)) | ||
152 | gpio_set_value(S3C2410_GPA(1), 1); | ||
153 | else | ||
154 | gpio_set_value(S3C2410_GPA(1), 0); | ||
155 | |||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | static int rx1950_hw_params(struct snd_pcm_substream *substream, | ||
160 | struct snd_pcm_hw_params *params) | ||
161 | { | ||
162 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
163 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
164 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
165 | int div; | ||
166 | int ret; | ||
167 | unsigned int rate = params_rate(params); | ||
168 | int clk_source, fs_mode; | ||
169 | |||
170 | switch (rate) { | ||
171 | case 16000: | ||
172 | case 48000: | ||
173 | clk_source = S3C24XX_CLKSRC_PCLK; | ||
174 | fs_mode = S3C2410_IISMOD_256FS; | ||
175 | div = s3c24xx_i2s_get_clockrate() / (256 * rate); | ||
176 | if (s3c24xx_i2s_get_clockrate() % (256 * rate) > (128 * rate)) | ||
177 | div++; | ||
178 | break; | ||
179 | case 44100: | ||
180 | case 88200: | ||
181 | clk_source = S3C24XX_CLKSRC_MPLL; | ||
182 | fs_mode = S3C2410_IISMOD_256FS; | ||
183 | div = clk_get_rate(xtal) / (256 * rate); | ||
184 | if (clk_get_rate(xtal) % (256 * rate) > (128 * rate)) | ||
185 | div++; | ||
186 | break; | ||
187 | default: | ||
188 | printk(KERN_ERR "%s: rate %d is not supported\n", | ||
189 | __func__, rate); | ||
190 | return -EINVAL; | ||
191 | } | ||
192 | |||
193 | /* set codec DAI configuration */ | ||
194 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | | ||
195 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); | ||
196 | if (ret < 0) | ||
197 | return ret; | ||
198 | |||
199 | /* set cpu DAI configuration */ | ||
200 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | | ||
201 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); | ||
202 | if (ret < 0) | ||
203 | return ret; | ||
204 | |||
205 | /* select clock source */ | ||
206 | ret = snd_soc_dai_set_sysclk(cpu_dai, clk_source, rate, | ||
207 | SND_SOC_CLOCK_OUT); | ||
208 | if (ret < 0) | ||
209 | return ret; | ||
210 | |||
211 | /* set MCLK division for sample rate */ | ||
212 | ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK, | ||
213 | S3C2410_IISMOD_384FS); | ||
214 | if (ret < 0) | ||
215 | return ret; | ||
216 | |||
217 | /* set BCLK division for sample rate */ | ||
218 | ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_BCLK, | ||
219 | S3C2410_IISMOD_32FS); | ||
220 | if (ret < 0) | ||
221 | return ret; | ||
222 | |||
223 | /* set prescaler division for sample rate */ | ||
224 | ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER, | ||
225 | S3C24XX_PRESCALE(div, div)); | ||
226 | if (ret < 0) | ||
227 | return ret; | ||
228 | |||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | static int rx1950_uda1380_init(struct snd_soc_pcm_runtime *rtd) | ||
233 | { | ||
234 | struct snd_soc_codec *codec = rtd->codec; | ||
235 | int err; | ||
236 | |||
237 | /* Add rx1950 specific widgets */ | ||
238 | err = snd_soc_dapm_new_controls(codec, uda1380_dapm_widgets, | ||
239 | ARRAY_SIZE(uda1380_dapm_widgets)); | ||
240 | |||
241 | if (err) | ||
242 | return err; | ||
243 | |||
244 | /* Set up rx1950 specific audio path audio_mapnects */ | ||
245 | err = snd_soc_dapm_add_routes(codec, audio_map, | ||
246 | ARRAY_SIZE(audio_map)); | ||
247 | |||
248 | if (err) | ||
249 | return err; | ||
250 | |||
251 | snd_soc_dapm_enable_pin(codec, "Headphone Jack"); | ||
252 | snd_soc_dapm_enable_pin(codec, "Speaker"); | ||
253 | |||
254 | snd_soc_dapm_sync(codec); | ||
255 | |||
256 | snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE, | ||
257 | &hp_jack); | ||
258 | |||
259 | snd_soc_jack_add_pins(&hp_jack, ARRAY_SIZE(hp_jack_pins), | ||
260 | hp_jack_pins); | ||
261 | |||
262 | snd_soc_jack_add_gpios(&hp_jack, ARRAY_SIZE(hp_jack_gpios), | ||
263 | hp_jack_gpios); | ||
264 | |||
265 | return 0; | ||
266 | } | ||
267 | |||
268 | static int __init rx1950_init(void) | ||
269 | { | ||
270 | int ret; | ||
271 | |||
272 | if (!machine_is_rx1950()) | ||
273 | return -ENODEV; | ||
274 | |||
275 | /* configure some gpios */ | ||
276 | ret = gpio_request(S3C2410_GPA(1), "speaker-power"); | ||
277 | if (ret) | ||
278 | goto err_gpio; | ||
279 | |||
280 | ret = gpio_direction_output(S3C2410_GPA(1), 0); | ||
281 | if (ret) | ||
282 | goto err_gpio_conf; | ||
283 | |||
284 | s3c24xx_snd_device = platform_device_alloc("soc-audio", -1); | ||
285 | if (!s3c24xx_snd_device) { | ||
286 | ret = -ENOMEM; | ||
287 | goto err_plat_alloc; | ||
288 | } | ||
289 | |||
290 | platform_set_drvdata(s3c24xx_snd_device, &rx1950_asoc); | ||
291 | ret = platform_device_add(s3c24xx_snd_device); | ||
292 | |||
293 | if (ret) { | ||
294 | platform_device_put(s3c24xx_snd_device); | ||
295 | goto err_plat_add; | ||
296 | } | ||
297 | |||
298 | xtal = clk_get(&s3c24xx_snd_device->dev, "xtal"); | ||
299 | |||
300 | if (IS_ERR(xtal)) { | ||
301 | ret = PTR_ERR(xtal); | ||
302 | platform_device_unregister(s3c24xx_snd_device); | ||
303 | goto err_clk; | ||
304 | } | ||
305 | |||
306 | return 0; | ||
307 | |||
308 | err_clk: | ||
309 | err_plat_add: | ||
310 | err_plat_alloc: | ||
311 | err_gpio_conf: | ||
312 | gpio_free(S3C2410_GPA(1)); | ||
313 | |||
314 | err_gpio: | ||
315 | return ret; | ||
316 | } | ||
317 | |||
318 | static void __exit rx1950_exit(void) | ||
319 | { | ||
320 | platform_device_unregister(s3c24xx_snd_device); | ||
321 | snd_soc_jack_free_gpios(&hp_jack, ARRAY_SIZE(hp_jack_gpios), | ||
322 | hp_jack_gpios); | ||
323 | clk_put(xtal); | ||
324 | gpio_free(S3C2410_GPA(1)); | ||
325 | } | ||
326 | |||
327 | module_init(rx1950_init); | ||
328 | module_exit(rx1950_exit); | ||
329 | |||
330 | /* Module information */ | ||
331 | MODULE_AUTHOR("Vasily Khoruzhick"); | ||
332 | MODULE_DESCRIPTION("ALSA SoC RX1950"); | ||
333 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/s3c24xx/s3c-ac97.c b/sound/soc/s3c24xx/s3c-ac97.c index 31f6d45b6384..f891eb79b575 100644 --- a/sound/soc/s3c24xx/s3c-ac97.c +++ b/sound/soc/s3c24xx/s3c-ac97.c | |||
@@ -89,7 +89,7 @@ static void s3c_ac97_activate(struct snd_ac97 *ac97) | |||
89 | writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); | 89 | writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); |
90 | 90 | ||
91 | if (!wait_for_completion_timeout(&s3c_ac97.done, HZ)) | 91 | if (!wait_for_completion_timeout(&s3c_ac97.done, HZ)) |
92 | printk(KERN_ERR "AC97: Unable to activate!"); | 92 | pr_err("AC97: Unable to activate!"); |
93 | } | 93 | } |
94 | 94 | ||
95 | static unsigned short s3c_ac97_read(struct snd_ac97 *ac97, | 95 | static unsigned short s3c_ac97_read(struct snd_ac97 *ac97, |
@@ -115,14 +115,15 @@ static unsigned short s3c_ac97_read(struct snd_ac97 *ac97, | |||
115 | writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); | 115 | writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); |
116 | 116 | ||
117 | if (!wait_for_completion_timeout(&s3c_ac97.done, HZ)) | 117 | if (!wait_for_completion_timeout(&s3c_ac97.done, HZ)) |
118 | printk(KERN_ERR "AC97: Unable to read!"); | 118 | pr_err("AC97: Unable to read!"); |
119 | 119 | ||
120 | stat = readl(s3c_ac97.regs + S3C_AC97_STAT); | 120 | stat = readl(s3c_ac97.regs + S3C_AC97_STAT); |
121 | addr = (stat >> 16) & 0x7f; | 121 | addr = (stat >> 16) & 0x7f; |
122 | data = (stat & 0xffff); | 122 | data = (stat & 0xffff); |
123 | 123 | ||
124 | if (addr != reg) | 124 | if (addr != reg) |
125 | printk(KERN_ERR "s3c-ac97: req addr = %02x, rep addr = %02x\n", reg, addr); | 125 | pr_err("s3c-ac97: req addr = %02x, rep addr = %02x\n", |
126 | reg, addr); | ||
126 | 127 | ||
127 | mutex_unlock(&s3c_ac97.lock); | 128 | mutex_unlock(&s3c_ac97.lock); |
128 | 129 | ||
@@ -151,7 +152,7 @@ static void s3c_ac97_write(struct snd_ac97 *ac97, unsigned short reg, | |||
151 | writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); | 152 | writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); |
152 | 153 | ||
153 | if (!wait_for_completion_timeout(&s3c_ac97.done, HZ)) | 154 | if (!wait_for_completion_timeout(&s3c_ac97.done, HZ)) |
154 | printk(KERN_ERR "AC97: Unable to write!"); | 155 | pr_err("AC97: Unable to write!"); |
155 | 156 | ||
156 | ac_codec_cmd = readl(s3c_ac97.regs + S3C_AC97_CODEC_CMD); | 157 | ac_codec_cmd = readl(s3c_ac97.regs + S3C_AC97_CODEC_CMD); |
157 | ac_codec_cmd |= S3C_AC97_CODEC_CMD_READ; | 158 | ac_codec_cmd |= S3C_AC97_CODEC_CMD_READ; |
@@ -162,6 +163,7 @@ static void s3c_ac97_write(struct snd_ac97 *ac97, unsigned short reg, | |||
162 | 163 | ||
163 | static void s3c_ac97_cold_reset(struct snd_ac97 *ac97) | 164 | static void s3c_ac97_cold_reset(struct snd_ac97 *ac97) |
164 | { | 165 | { |
166 | pr_debug("AC97: Cold reset\n"); | ||
165 | writel(S3C_AC97_GLBCTRL_COLDRESET, | 167 | writel(S3C_AC97_GLBCTRL_COLDRESET, |
166 | s3c_ac97.regs + S3C_AC97_GLBCTRL); | 168 | s3c_ac97.regs + S3C_AC97_GLBCTRL); |
167 | msleep(1); | 169 | msleep(1); |
@@ -178,6 +180,8 @@ static void s3c_ac97_warm_reset(struct snd_ac97 *ac97) | |||
178 | if (stat == S3C_AC97_GLBSTAT_MAINSTATE_ACTIVE) | 180 | if (stat == S3C_AC97_GLBSTAT_MAINSTATE_ACTIVE) |
179 | return; /* Return if already active */ | 181 | return; /* Return if already active */ |
180 | 182 | ||
183 | pr_debug("AC97: Warm reset\n"); | ||
184 | |||
181 | writel(S3C_AC97_GLBCTRL_WARMRESET, s3c_ac97.regs + S3C_AC97_GLBCTRL); | 185 | writel(S3C_AC97_GLBCTRL_WARMRESET, s3c_ac97.regs + S3C_AC97_GLBCTRL); |
182 | msleep(1); | 186 | msleep(1); |
183 | 187 | ||
@@ -222,7 +226,7 @@ static int s3c_ac97_hw_params(struct snd_pcm_substream *substream, | |||
222 | struct snd_soc_dai *dai) | 226 | struct snd_soc_dai *dai) |
223 | { | 227 | { |
224 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 228 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
225 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 229 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
226 | struct s3c_dma_params *dma_data; | 230 | struct s3c_dma_params *dma_data; |
227 | 231 | ||
228 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 232 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
@@ -241,7 +245,7 @@ static int s3c_ac97_trigger(struct snd_pcm_substream *substream, int cmd, | |||
241 | u32 ac_glbctrl; | 245 | u32 ac_glbctrl; |
242 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 246 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
243 | struct s3c_dma_params *dma_data = | 247 | struct s3c_dma_params *dma_data = |
244 | snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); | 248 | snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); |
245 | 249 | ||
246 | ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL); | 250 | ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL); |
247 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) | 251 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) |
@@ -277,7 +281,7 @@ static int s3c_ac97_hw_mic_params(struct snd_pcm_substream *substream, | |||
277 | struct snd_soc_dai *dai) | 281 | struct snd_soc_dai *dai) |
278 | { | 282 | { |
279 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 283 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
280 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 284 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
281 | 285 | ||
282 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 286 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
283 | return -ENODEV; | 287 | return -ENODEV; |
@@ -293,7 +297,7 @@ static int s3c_ac97_mic_trigger(struct snd_pcm_substream *substream, | |||
293 | u32 ac_glbctrl; | 297 | u32 ac_glbctrl; |
294 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 298 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
295 | struct s3c_dma_params *dma_data = | 299 | struct s3c_dma_params *dma_data = |
296 | snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); | 300 | snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); |
297 | 301 | ||
298 | ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL); | 302 | ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL); |
299 | ac_glbctrl &= ~S3C_AC97_GLBCTRL_MICINTM_MASK; | 303 | ac_glbctrl &= ~S3C_AC97_GLBCTRL_MICINTM_MASK; |
@@ -328,10 +332,9 @@ static struct snd_soc_dai_ops s3c_ac97_mic_dai_ops = { | |||
328 | .trigger = s3c_ac97_mic_trigger, | 332 | .trigger = s3c_ac97_mic_trigger, |
329 | }; | 333 | }; |
330 | 334 | ||
331 | struct snd_soc_dai s3c_ac97_dai[] = { | 335 | static struct snd_soc_dai_driver s3c_ac97_dai[] = { |
332 | [S3C_AC97_DAI_PCM] = { | 336 | [S3C_AC97_DAI_PCM] = { |
333 | .name = "s3c-ac97", | 337 | .name = "s3c-ac97", |
334 | .id = S3C_AC97_DAI_PCM, | ||
335 | .ac97_control = 1, | 338 | .ac97_control = 1, |
336 | .playback = { | 339 | .playback = { |
337 | .stream_name = "AC97 Playback", | 340 | .stream_name = "AC97 Playback", |
@@ -349,7 +352,6 @@ struct snd_soc_dai s3c_ac97_dai[] = { | |||
349 | }, | 352 | }, |
350 | [S3C_AC97_DAI_MIC] = { | 353 | [S3C_AC97_DAI_MIC] = { |
351 | .name = "s3c-ac97-mic", | 354 | .name = "s3c-ac97-mic", |
352 | .id = S3C_AC97_DAI_MIC, | ||
353 | .ac97_control = 1, | 355 | .ac97_control = 1, |
354 | .capture = { | 356 | .capture = { |
355 | .stream_name = "AC97 Mic Capture", | 357 | .stream_name = "AC97 Mic Capture", |
@@ -360,7 +362,6 @@ struct snd_soc_dai s3c_ac97_dai[] = { | |||
360 | .ops = &s3c_ac97_mic_dai_ops, | 362 | .ops = &s3c_ac97_mic_dai_ops, |
361 | }, | 363 | }, |
362 | }; | 364 | }; |
363 | EXPORT_SYMBOL_GPL(s3c_ac97_dai); | ||
364 | 365 | ||
365 | static __devinit int s3c_ac97_probe(struct platform_device *pdev) | 366 | static __devinit int s3c_ac97_probe(struct platform_device *pdev) |
366 | { | 367 | { |
@@ -445,14 +446,12 @@ static __devinit int s3c_ac97_probe(struct platform_device *pdev) | |||
445 | ret = request_irq(irq_res->start, s3c_ac97_irq, | 446 | ret = request_irq(irq_res->start, s3c_ac97_irq, |
446 | IRQF_DISABLED, "AC97", NULL); | 447 | IRQF_DISABLED, "AC97", NULL); |
447 | if (ret < 0) { | 448 | if (ret < 0) { |
448 | printk(KERN_ERR "s3c-ac97: interrupt request failed.\n"); | 449 | dev_err(&pdev->dev, "s3c-ac97: interrupt request failed.\n"); |
449 | goto err4; | 450 | goto err4; |
450 | } | 451 | } |
451 | 452 | ||
452 | s3c_ac97_dai[S3C_AC97_DAI_PCM].dev = &pdev->dev; | 453 | ret = snd_soc_register_dais(&pdev->dev, s3c_ac97_dai, |
453 | s3c_ac97_dai[S3C_AC97_DAI_MIC].dev = &pdev->dev; | 454 | ARRAY_SIZE(s3c_ac97_dai)); |
454 | |||
455 | ret = snd_soc_register_dais(s3c_ac97_dai, ARRAY_SIZE(s3c_ac97_dai)); | ||
456 | if (ret) | 455 | if (ret) |
457 | goto err5; | 456 | goto err5; |
458 | 457 | ||
@@ -476,7 +475,7 @@ static __devexit int s3c_ac97_remove(struct platform_device *pdev) | |||
476 | { | 475 | { |
477 | struct resource *mem_res, *irq_res; | 476 | struct resource *mem_res, *irq_res; |
478 | 477 | ||
479 | snd_soc_unregister_dais(s3c_ac97_dai, ARRAY_SIZE(s3c_ac97_dai)); | 478 | snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(s3c_ac97_dai)); |
480 | 479 | ||
481 | irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | 480 | irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); |
482 | if (irq_res) | 481 | if (irq_res) |
@@ -518,3 +517,4 @@ module_exit(s3c_ac97_exit); | |||
518 | MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>"); | 517 | MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>"); |
519 | MODULE_DESCRIPTION("AC97 driver for the Samsung SoC"); | 518 | MODULE_DESCRIPTION("AC97 driver for the Samsung SoC"); |
520 | MODULE_LICENSE("GPL"); | 519 | MODULE_LICENSE("GPL"); |
520 | MODULE_ALIAS("platform:s3c-ac97"); | ||
diff --git a/sound/soc/s3c24xx/s3c-ac97.h b/sound/soc/s3c24xx/s3c-ac97.h index 278198379def..5dcedd07fdbb 100644 --- a/sound/soc/s3c24xx/s3c-ac97.h +++ b/sound/soc/s3c24xx/s3c-ac97.h | |||
@@ -18,6 +18,4 @@ | |||
18 | #define S3C_AC97_DAI_PCM 0 | 18 | #define S3C_AC97_DAI_PCM 0 |
19 | #define S3C_AC97_DAI_MIC 1 | 19 | #define S3C_AC97_DAI_MIC 1 |
20 | 20 | ||
21 | extern struct snd_soc_dai s3c_ac97_dai[]; | ||
22 | |||
23 | #endif /* __S3C_AC97_H_ */ | 21 | #endif /* __S3C_AC97_H_ */ |
diff --git a/sound/soc/s3c24xx/s3c-dma.c b/sound/soc/s3c24xx/s3c-dma.c index f1b1bc4bacfb..243f79bf43bb 100644 --- a/sound/soc/s3c24xx/s3c-dma.c +++ b/sound/soc/s3c24xx/s3c-dma.c | |||
@@ -146,7 +146,7 @@ static int s3c_dma_hw_params(struct snd_pcm_substream *substream, | |||
146 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 146 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
147 | unsigned long totbytes = params_buffer_bytes(params); | 147 | unsigned long totbytes = params_buffer_bytes(params); |
148 | struct s3c_dma_params *dma = | 148 | struct s3c_dma_params *dma = |
149 | snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); | 149 | snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); |
150 | int ret = 0; | 150 | int ret = 0; |
151 | 151 | ||
152 | 152 | ||
@@ -440,14 +440,14 @@ static int s3c_dma_new(struct snd_card *card, | |||
440 | if (!card->dev->coherent_dma_mask) | 440 | if (!card->dev->coherent_dma_mask) |
441 | card->dev->coherent_dma_mask = 0xffffffff; | 441 | card->dev->coherent_dma_mask = 0xffffffff; |
442 | 442 | ||
443 | if (dai->playback.channels_min) { | 443 | if (dai->driver->playback.channels_min) { |
444 | ret = s3c_preallocate_dma_buffer(pcm, | 444 | ret = s3c_preallocate_dma_buffer(pcm, |
445 | SNDRV_PCM_STREAM_PLAYBACK); | 445 | SNDRV_PCM_STREAM_PLAYBACK); |
446 | if (ret) | 446 | if (ret) |
447 | goto out; | 447 | goto out; |
448 | } | 448 | } |
449 | 449 | ||
450 | if (dai->capture.channels_min) { | 450 | if (dai->driver->capture.channels_min) { |
451 | ret = s3c_preallocate_dma_buffer(pcm, | 451 | ret = s3c_preallocate_dma_buffer(pcm, |
452 | SNDRV_PCM_STREAM_CAPTURE); | 452 | SNDRV_PCM_STREAM_CAPTURE); |
453 | if (ret) | 453 | if (ret) |
@@ -457,26 +457,46 @@ static int s3c_dma_new(struct snd_card *card, | |||
457 | return ret; | 457 | return ret; |
458 | } | 458 | } |
459 | 459 | ||
460 | struct snd_soc_platform s3c24xx_soc_platform = { | 460 | static struct snd_soc_platform_driver s3c24xx_soc_platform = { |
461 | .name = "s3c24xx-audio", | 461 | .ops = &s3c_dma_ops, |
462 | .pcm_ops = &s3c_dma_ops, | ||
463 | .pcm_new = s3c_dma_new, | 462 | .pcm_new = s3c_dma_new, |
464 | .pcm_free = s3c_dma_free_dma_buffers, | 463 | .pcm_free = s3c_dma_free_dma_buffers, |
465 | }; | 464 | }; |
466 | EXPORT_SYMBOL_GPL(s3c24xx_soc_platform); | ||
467 | 465 | ||
468 | static int __init s3c24xx_soc_platform_init(void) | 466 | static int __devinit s3c24xx_soc_platform_probe(struct platform_device *pdev) |
469 | { | 467 | { |
470 | return snd_soc_register_platform(&s3c24xx_soc_platform); | 468 | return snd_soc_register_platform(&pdev->dev, &s3c24xx_soc_platform); |
471 | } | 469 | } |
472 | module_init(s3c24xx_soc_platform_init); | ||
473 | 470 | ||
474 | static void __exit s3c24xx_soc_platform_exit(void) | 471 | static int __devexit s3c24xx_soc_platform_remove(struct platform_device *pdev) |
475 | { | 472 | { |
476 | snd_soc_unregister_platform(&s3c24xx_soc_platform); | 473 | snd_soc_unregister_platform(&pdev->dev); |
474 | return 0; | ||
475 | } | ||
476 | |||
477 | static struct platform_driver s3c24xx_pcm_driver = { | ||
478 | .driver = { | ||
479 | .name = "s3c24xx-pcm-audio", | ||
480 | .owner = THIS_MODULE, | ||
481 | }, | ||
482 | |||
483 | .probe = s3c24xx_soc_platform_probe, | ||
484 | .remove = __devexit_p(s3c24xx_soc_platform_remove), | ||
485 | }; | ||
486 | |||
487 | static int __init snd_s3c24xx_pcm_init(void) | ||
488 | { | ||
489 | return platform_driver_register(&s3c24xx_pcm_driver); | ||
490 | } | ||
491 | module_init(snd_s3c24xx_pcm_init); | ||
492 | |||
493 | static void __exit snd_s3c24xx_pcm_exit(void) | ||
494 | { | ||
495 | platform_driver_unregister(&s3c24xx_pcm_driver); | ||
477 | } | 496 | } |
478 | module_exit(s3c24xx_soc_platform_exit); | 497 | module_exit(snd_s3c24xx_pcm_exit); |
479 | 498 | ||
480 | MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); | 499 | MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); |
481 | MODULE_DESCRIPTION("Samsung S3C Audio DMA module"); | 500 | MODULE_DESCRIPTION("Samsung S3C Audio DMA module"); |
482 | MODULE_LICENSE("GPL"); | 501 | MODULE_LICENSE("GPL"); |
502 | MODULE_ALIAS("platform:s3c24xx-pcm-audio"); | ||
diff --git a/sound/soc/s3c24xx/s3c-dma.h b/sound/soc/s3c24xx/s3c-dma.h index 69bb6bf6fc1c..748c07d7c075 100644 --- a/sound/soc/s3c24xx/s3c-dma.h +++ b/sound/soc/s3c24xx/s3c-dma.h | |||
@@ -25,7 +25,6 @@ struct s3c_dma_params { | |||
25 | #define S3C24XX_DAI_I2S 0 | 25 | #define S3C24XX_DAI_I2S 0 |
26 | 26 | ||
27 | /* platform data */ | 27 | /* platform data */ |
28 | extern struct snd_soc_platform s3c24xx_soc_platform; | ||
29 | extern struct snd_ac97_bus_ops s3c24xx_ac97_ops; | 28 | extern struct snd_ac97_bus_ops s3c24xx_ac97_ops; |
30 | 29 | ||
31 | #endif | 30 | #endif |
diff --git a/sound/soc/s3c24xx/s3c-i2s-v2.c b/sound/soc/s3c24xx/s3c-i2s-v2.c index 64376b2aac73..b3866d5b19e9 100644 --- a/sound/soc/s3c24xx/s3c-i2s-v2.c +++ b/sound/soc/s3c24xx/s3c-i2s-v2.c | |||
@@ -49,7 +49,7 @@ | |||
49 | 49 | ||
50 | static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai) | 50 | static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai) |
51 | { | 51 | { |
52 | return cpu_dai->private_data; | 52 | return snd_soc_dai_get_drvdata(cpu_dai); |
53 | } | 53 | } |
54 | 54 | ||
55 | #define bit_set(v, b) (((v) & (b)) ? 1 : 0) | 55 | #define bit_set(v, b) (((v) & (b)) ? 1 : 0) |
@@ -307,11 +307,9 @@ static int s3c2412_i2s_set_fmt(struct snd_soc_dai *cpu_dai, | |||
307 | 307 | ||
308 | static int s3c_i2sv2_hw_params(struct snd_pcm_substream *substream, | 308 | static int s3c_i2sv2_hw_params(struct snd_pcm_substream *substream, |
309 | struct snd_pcm_hw_params *params, | 309 | struct snd_pcm_hw_params *params, |
310 | struct snd_soc_dai *socdai) | 310 | struct snd_soc_dai *dai) |
311 | { | 311 | { |
312 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 312 | struct s3c_i2sv2_info *i2s = to_info(dai); |
313 | struct snd_soc_dai_link *dai = rtd->dai; | ||
314 | struct s3c_i2sv2_info *i2s = to_info(dai->cpu_dai); | ||
315 | struct s3c_dma_params *dma_data; | 313 | struct s3c_dma_params *dma_data; |
316 | u32 iismod; | 314 | u32 iismod; |
317 | 315 | ||
@@ -322,7 +320,7 @@ static int s3c_i2sv2_hw_params(struct snd_pcm_substream *substream, | |||
322 | else | 320 | else |
323 | dma_data = i2s->dma_capture; | 321 | dma_data = i2s->dma_capture; |
324 | 322 | ||
325 | snd_soc_dai_set_dma_data(dai->cpu_dai, substream, dma_data); | 323 | snd_soc_dai_set_dma_data(dai, substream, dma_data); |
326 | 324 | ||
327 | /* Working copies of register */ | 325 | /* Working copies of register */ |
328 | iismod = readl(i2s->regs + S3C2412_IISMOD); | 326 | iismod = readl(i2s->regs + S3C2412_IISMOD); |
@@ -396,12 +394,12 @@ static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd, | |||
396 | struct snd_soc_dai *dai) | 394 | struct snd_soc_dai *dai) |
397 | { | 395 | { |
398 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 396 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
399 | struct s3c_i2sv2_info *i2s = to_info(rtd->dai->cpu_dai); | 397 | struct s3c_i2sv2_info *i2s = to_info(rtd->cpu_dai); |
400 | int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); | 398 | int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); |
401 | unsigned long irqs; | 399 | unsigned long irqs; |
402 | int ret = 0; | 400 | int ret = 0; |
403 | struct s3c_dma_params *dma_data = | 401 | struct s3c_dma_params *dma_data = |
404 | snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); | 402 | snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); |
405 | 403 | ||
406 | pr_debug("Entered %s\n", __func__); | 404 | pr_debug("Entered %s\n", __func__); |
407 | 405 | ||
@@ -640,36 +638,17 @@ int s3c_i2sv2_iis_calc_rate(struct s3c_i2sv2_rate_calc *info, | |||
640 | } | 638 | } |
641 | EXPORT_SYMBOL_GPL(s3c_i2sv2_iis_calc_rate); | 639 | EXPORT_SYMBOL_GPL(s3c_i2sv2_iis_calc_rate); |
642 | 640 | ||
643 | int s3c_i2sv2_probe(struct platform_device *pdev, | 641 | int s3c_i2sv2_probe(struct snd_soc_dai *dai, |
644 | struct snd_soc_dai *dai, | ||
645 | struct s3c_i2sv2_info *i2s, | 642 | struct s3c_i2sv2_info *i2s, |
646 | unsigned long base) | 643 | unsigned long base) |
647 | { | 644 | { |
648 | struct device *dev = &pdev->dev; | 645 | struct device *dev = dai->dev; |
649 | unsigned int iismod; | 646 | unsigned int iismod; |
650 | 647 | ||
651 | i2s->dev = dev; | 648 | i2s->dev = dev; |
652 | 649 | ||
653 | /* record our i2s structure for later use in the callbacks */ | 650 | /* record our i2s structure for later use in the callbacks */ |
654 | dai->private_data = i2s; | 651 | snd_soc_dai_set_drvdata(dai, i2s); |
655 | |||
656 | if (!base) { | ||
657 | struct resource *res = platform_get_resource(pdev, | ||
658 | IORESOURCE_MEM, | ||
659 | 0); | ||
660 | if (!res) { | ||
661 | dev_err(dev, "Unable to get register resource\n"); | ||
662 | return -ENXIO; | ||
663 | } | ||
664 | |||
665 | if (!request_mem_region(res->start, resource_size(res), | ||
666 | "s3c64xx-i2s-v4")) { | ||
667 | dev_err(dev, "Unable to request register region\n"); | ||
668 | return -EBUSY; | ||
669 | } | ||
670 | |||
671 | base = res->start; | ||
672 | } | ||
673 | 652 | ||
674 | i2s->regs = ioremap(base, 0x100); | 653 | i2s->regs = ioremap(base, 0x100); |
675 | if (i2s->regs == NULL) { | 654 | if (i2s->regs == NULL) { |
@@ -752,9 +731,10 @@ static int s3c2412_i2s_resume(struct snd_soc_dai *dai) | |||
752 | #define s3c2412_i2s_resume NULL | 731 | #define s3c2412_i2s_resume NULL |
753 | #endif | 732 | #endif |
754 | 733 | ||
755 | int s3c_i2sv2_register_dai(struct snd_soc_dai *dai) | 734 | int s3c_i2sv2_register_dai(struct device *dev, int id, |
735 | struct snd_soc_dai_driver *drv) | ||
756 | { | 736 | { |
757 | struct snd_soc_dai_ops *ops = dai->ops; | 737 | struct snd_soc_dai_ops *ops = drv->ops; |
758 | 738 | ||
759 | ops->trigger = s3c2412_i2s_trigger; | 739 | ops->trigger = s3c2412_i2s_trigger; |
760 | if (!ops->hw_params) | 740 | if (!ops->hw_params) |
@@ -767,10 +747,10 @@ int s3c_i2sv2_register_dai(struct snd_soc_dai *dai) | |||
767 | if (!ops->delay) | 747 | if (!ops->delay) |
768 | ops->delay = s3c2412_i2s_delay; | 748 | ops->delay = s3c2412_i2s_delay; |
769 | 749 | ||
770 | dai->suspend = s3c2412_i2s_suspend; | 750 | drv->suspend = s3c2412_i2s_suspend; |
771 | dai->resume = s3c2412_i2s_resume; | 751 | drv->resume = s3c2412_i2s_resume; |
772 | 752 | ||
773 | return snd_soc_register_dai(dai); | 753 | return snd_soc_register_dai(dev, drv); |
774 | } | 754 | } |
775 | EXPORT_SYMBOL_GPL(s3c_i2sv2_register_dai); | 755 | EXPORT_SYMBOL_GPL(s3c_i2sv2_register_dai); |
776 | 756 | ||
diff --git a/sound/soc/s3c24xx/s3c-i2s-v2.h b/sound/soc/s3c24xx/s3c-i2s-v2.h index 766f43a13d8b..d45830151484 100644 --- a/sound/soc/s3c24xx/s3c-i2s-v2.h +++ b/sound/soc/s3c24xx/s3c-i2s-v2.h | |||
@@ -66,6 +66,8 @@ struct s3c_i2sv2_info { | |||
66 | u32 suspend_iismod; | 66 | u32 suspend_iismod; |
67 | u32 suspend_iiscon; | 67 | u32 suspend_iiscon; |
68 | u32 suspend_iispsr; | 68 | u32 suspend_iispsr; |
69 | |||
70 | unsigned long base; | ||
69 | }; | 71 | }; |
70 | 72 | ||
71 | extern struct clk *s3c_i2sv2_get_clock(struct snd_soc_dai *cpu_dai); | 73 | extern struct clk *s3c_i2sv2_get_clock(struct snd_soc_dai *cpu_dai); |
@@ -81,23 +83,24 @@ extern int s3c_i2sv2_iis_calc_rate(struct s3c_i2sv2_rate_calc *info, | |||
81 | 83 | ||
82 | /** | 84 | /** |
83 | * s3c_i2sv2_probe - probe for i2s device helper | 85 | * s3c_i2sv2_probe - probe for i2s device helper |
84 | * @pdev: The platform device supplied to the original probe. | ||
85 | * @dai: The ASoC DAI structure supplied to the original probe. | 86 | * @dai: The ASoC DAI structure supplied to the original probe. |
86 | * @i2s: Our local i2s structure to fill in. | 87 | * @i2s: Our local i2s structure to fill in. |
87 | * @base: The base address for the registers. | 88 | * @base: The base address for the registers. |
88 | */ | 89 | */ |
89 | extern int s3c_i2sv2_probe(struct platform_device *pdev, | 90 | extern int s3c_i2sv2_probe(struct snd_soc_dai *dai, |
90 | struct snd_soc_dai *dai, | ||
91 | struct s3c_i2sv2_info *i2s, | 91 | struct s3c_i2sv2_info *i2s, |
92 | unsigned long base); | 92 | unsigned long base); |
93 | 93 | ||
94 | /** | 94 | /** |
95 | * s3c_i2sv2_register_dai - register dai with soc core | 95 | * s3c_i2sv2_register_dai - register dai with soc core |
96 | * @dai: The snd_soc_dai structure to register | 96 | * @dev: DAI device |
97 | * @id: DAI ID | ||
98 | * @drv: The driver structure to register | ||
97 | * | 99 | * |
98 | * Fill in any missing fields and then register the given dai with the | 100 | * Fill in any missing fields and then register the given dai with the |
99 | * soc core. | 101 | * soc core. |
100 | */ | 102 | */ |
101 | extern int s3c_i2sv2_register_dai(struct snd_soc_dai *dai); | 103 | extern int s3c_i2sv2_register_dai(struct device *dev, int id, |
104 | struct snd_soc_dai_driver *drv); | ||
102 | 105 | ||
103 | #endif /* __SND_SOC_S3C24XX_S3C_I2SV2_I2S_H */ | 106 | #endif /* __SND_SOC_S3C24XX_S3C_I2SV2_I2S_H */ |
diff --git a/sound/soc/s3c24xx/s3c-pcm.c b/sound/soc/s3c24xx/s3c-pcm.c index 326f0a9e7e30..2e020e1b4eab 100644 --- a/sound/soc/s3c24xx/s3c-pcm.c +++ b/sound/soc/s3c24xx/s3c-pcm.c | |||
@@ -64,11 +64,6 @@ static struct s3c_dma_params s3c_pcm_stereo_in[] = { | |||
64 | 64 | ||
65 | static struct s3c_pcm_info s3c_pcm[2]; | 65 | static struct s3c_pcm_info s3c_pcm[2]; |
66 | 66 | ||
67 | static inline struct s3c_pcm_info *to_info(struct snd_soc_dai *cpu_dai) | ||
68 | { | ||
69 | return cpu_dai->private_data; | ||
70 | } | ||
71 | |||
72 | static void s3c_pcm_snd_txctrl(struct s3c_pcm_info *pcm, int on) | 67 | static void s3c_pcm_snd_txctrl(struct s3c_pcm_info *pcm, int on) |
73 | { | 68 | { |
74 | void __iomem *regs = pcm->regs; | 69 | void __iomem *regs = pcm->regs; |
@@ -83,7 +78,7 @@ static void s3c_pcm_snd_txctrl(struct s3c_pcm_info *pcm, int on) | |||
83 | ctl |= S3C_PCM_CTL_TXDMA_EN; | 78 | ctl |= S3C_PCM_CTL_TXDMA_EN; |
84 | ctl |= S3C_PCM_CTL_TXFIFO_EN; | 79 | ctl |= S3C_PCM_CTL_TXFIFO_EN; |
85 | ctl |= S3C_PCM_CTL_ENABLE; | 80 | ctl |= S3C_PCM_CTL_ENABLE; |
86 | ctl |= (0x20<<S3C_PCM_CTL_TXDIPSTICK_SHIFT); | 81 | ctl |= (0x4<<S3C_PCM_CTL_TXDIPSTICK_SHIFT); |
87 | clkctl |= S3C_PCM_CLKCTL_SERCLK_EN; | 82 | clkctl |= S3C_PCM_CLKCTL_SERCLK_EN; |
88 | } else { | 83 | } else { |
89 | ctl &= ~S3C_PCM_CTL_TXDMA_EN; | 84 | ctl &= ~S3C_PCM_CTL_TXDMA_EN; |
@@ -107,11 +102,14 @@ static void s3c_pcm_snd_rxctrl(struct s3c_pcm_info *pcm, int on) | |||
107 | 102 | ||
108 | ctl = readl(regs + S3C_PCM_CTL); | 103 | ctl = readl(regs + S3C_PCM_CTL); |
109 | clkctl = readl(regs + S3C_PCM_CLKCTL); | 104 | clkctl = readl(regs + S3C_PCM_CLKCTL); |
105 | ctl &= ~(S3C_PCM_CTL_RXDIPSTICK_MASK | ||
106 | << S3C_PCM_CTL_RXDIPSTICK_SHIFT); | ||
110 | 107 | ||
111 | if (on) { | 108 | if (on) { |
112 | ctl |= S3C_PCM_CTL_RXDMA_EN; | 109 | ctl |= S3C_PCM_CTL_RXDMA_EN; |
113 | ctl |= S3C_PCM_CTL_RXFIFO_EN; | 110 | ctl |= S3C_PCM_CTL_RXFIFO_EN; |
114 | ctl |= S3C_PCM_CTL_ENABLE; | 111 | ctl |= S3C_PCM_CTL_ENABLE; |
112 | ctl |= (0x20<<S3C_PCM_CTL_RXDIPSTICK_SHIFT); | ||
115 | clkctl |= S3C_PCM_CLKCTL_SERCLK_EN; | 113 | clkctl |= S3C_PCM_CLKCTL_SERCLK_EN; |
116 | } else { | 114 | } else { |
117 | ctl &= ~S3C_PCM_CTL_RXDMA_EN; | 115 | ctl &= ~S3C_PCM_CTL_RXDMA_EN; |
@@ -132,7 +130,7 @@ static int s3c_pcm_trigger(struct snd_pcm_substream *substream, int cmd, | |||
132 | struct snd_soc_dai *dai) | 130 | struct snd_soc_dai *dai) |
133 | { | 131 | { |
134 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 132 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
135 | struct s3c_pcm_info *pcm = to_info(rtd->dai->cpu_dai); | 133 | struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(rtd->cpu_dai); |
136 | unsigned long flags; | 134 | unsigned long flags; |
137 | 135 | ||
138 | dev_dbg(pcm->dev, "Entered %s\n", __func__); | 136 | dev_dbg(pcm->dev, "Entered %s\n", __func__); |
@@ -176,8 +174,7 @@ static int s3c_pcm_hw_params(struct snd_pcm_substream *substream, | |||
176 | struct snd_soc_dai *socdai) | 174 | struct snd_soc_dai *socdai) |
177 | { | 175 | { |
178 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 176 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
179 | struct snd_soc_dai_link *dai = rtd->dai; | 177 | struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(rtd->cpu_dai); |
180 | struct s3c_pcm_info *pcm = to_info(dai->cpu_dai); | ||
181 | struct s3c_dma_params *dma_data; | 178 | struct s3c_dma_params *dma_data; |
182 | void __iomem *regs = pcm->regs; | 179 | void __iomem *regs = pcm->regs; |
183 | struct clk *clk; | 180 | struct clk *clk; |
@@ -192,7 +189,7 @@ static int s3c_pcm_hw_params(struct snd_pcm_substream *substream, | |||
192 | else | 189 | else |
193 | dma_data = pcm->dma_capture; | 190 | dma_data = pcm->dma_capture; |
194 | 191 | ||
195 | snd_soc_dai_set_dma_data(dai->cpu_dai, substream, dma_data); | 192 | snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_data); |
196 | 193 | ||
197 | /* Strictly check for sample size */ | 194 | /* Strictly check for sample size */ |
198 | switch (params_format(params)) { | 195 | switch (params_format(params)) { |
@@ -242,7 +239,7 @@ static int s3c_pcm_hw_params(struct snd_pcm_substream *substream, | |||
242 | static int s3c_pcm_set_fmt(struct snd_soc_dai *cpu_dai, | 239 | static int s3c_pcm_set_fmt(struct snd_soc_dai *cpu_dai, |
243 | unsigned int fmt) | 240 | unsigned int fmt) |
244 | { | 241 | { |
245 | struct s3c_pcm_info *pcm = to_info(cpu_dai); | 242 | struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(cpu_dai); |
246 | void __iomem *regs = pcm->regs; | 243 | void __iomem *regs = pcm->regs; |
247 | unsigned long flags; | 244 | unsigned long flags; |
248 | int ret = 0; | 245 | int ret = 0; |
@@ -313,7 +310,7 @@ exit: | |||
313 | static int s3c_pcm_set_clkdiv(struct snd_soc_dai *cpu_dai, | 310 | static int s3c_pcm_set_clkdiv(struct snd_soc_dai *cpu_dai, |
314 | int div_id, int div) | 311 | int div_id, int div) |
315 | { | 312 | { |
316 | struct s3c_pcm_info *pcm = to_info(cpu_dai); | 313 | struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(cpu_dai); |
317 | 314 | ||
318 | switch (div_id) { | 315 | switch (div_id) { |
319 | case S3C_PCM_SCLK_PER_FS: | 316 | case S3C_PCM_SCLK_PER_FS: |
@@ -330,7 +327,7 @@ static int s3c_pcm_set_clkdiv(struct snd_soc_dai *cpu_dai, | |||
330 | static int s3c_pcm_set_sysclk(struct snd_soc_dai *cpu_dai, | 327 | static int s3c_pcm_set_sysclk(struct snd_soc_dai *cpu_dai, |
331 | int clk_id, unsigned int freq, int dir) | 328 | int clk_id, unsigned int freq, int dir) |
332 | { | 329 | { |
333 | struct s3c_pcm_info *pcm = to_info(cpu_dai); | 330 | struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(cpu_dai); |
334 | void __iomem *regs = pcm->regs; | 331 | void __iomem *regs = pcm->regs; |
335 | u32 clkctl = readl(regs + S3C_PCM_CLKCTL); | 332 | u32 clkctl = readl(regs + S3C_PCM_CLKCTL); |
336 | 333 | ||
@@ -366,10 +363,7 @@ static struct snd_soc_dai_ops s3c_pcm_dai_ops = { | |||
366 | 363 | ||
367 | #define S3C_PCM_RATES SNDRV_PCM_RATE_8000_96000 | 364 | #define S3C_PCM_RATES SNDRV_PCM_RATE_8000_96000 |
368 | 365 | ||
369 | #define S3C_PCM_DECLARE(n) \ | 366 | #define S3C_PCM_DAI_DECLARE \ |
370 | { \ | ||
371 | .name = "samsung-pcm", \ | ||
372 | .id = (n), \ | ||
373 | .symmetric_rates = 1, \ | 367 | .symmetric_rates = 1, \ |
374 | .ops = &s3c_pcm_dai_ops, \ | 368 | .ops = &s3c_pcm_dai_ops, \ |
375 | .playback = { \ | 369 | .playback = { \ |
@@ -383,19 +377,23 @@ static struct snd_soc_dai_ops s3c_pcm_dai_ops = { | |||
383 | .channels_max = 2, \ | 377 | .channels_max = 2, \ |
384 | .rates = S3C_PCM_RATES, \ | 378 | .rates = S3C_PCM_RATES, \ |
385 | .formats = SNDRV_PCM_FMTBIT_S16_LE, \ | 379 | .formats = SNDRV_PCM_FMTBIT_S16_LE, \ |
386 | }, \ | 380 | } |
387 | } | ||
388 | 381 | ||
389 | struct snd_soc_dai s3c_pcm_dai[] = { | 382 | struct snd_soc_dai_driver s3c_pcm_dai[] = { |
390 | S3C_PCM_DECLARE(0), | 383 | [0] = { |
391 | S3C_PCM_DECLARE(1), | 384 | .name = "samsung-pcm.0", |
385 | S3C_PCM_DAI_DECLARE, | ||
386 | }, | ||
387 | [1] = { | ||
388 | .name = "samsung-pcm.1", | ||
389 | S3C_PCM_DAI_DECLARE, | ||
390 | }, | ||
392 | }; | 391 | }; |
393 | EXPORT_SYMBOL_GPL(s3c_pcm_dai); | 392 | EXPORT_SYMBOL_GPL(s3c_pcm_dai); |
394 | 393 | ||
395 | static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev) | 394 | static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev) |
396 | { | 395 | { |
397 | struct s3c_pcm_info *pcm; | 396 | struct s3c_pcm_info *pcm; |
398 | struct snd_soc_dai *dai; | ||
399 | struct resource *mem_res, *dmatx_res, *dmarx_res; | 397 | struct resource *mem_res, *dmatx_res, *dmarx_res; |
400 | struct s3c_audio_pdata *pcm_pdata; | 398 | struct s3c_audio_pdata *pcm_pdata; |
401 | int ret; | 399 | int ret; |
@@ -437,9 +435,6 @@ static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev) | |||
437 | 435 | ||
438 | spin_lock_init(&pcm->lock); | 436 | spin_lock_init(&pcm->lock); |
439 | 437 | ||
440 | dai = &s3c_pcm_dai[pdev->id]; | ||
441 | dai->dev = &pdev->dev; | ||
442 | |||
443 | /* Default is 128fs */ | 438 | /* Default is 128fs */ |
444 | pcm->sclk_per_fs = 128; | 439 | pcm->sclk_per_fs = 128; |
445 | 440 | ||
@@ -452,7 +447,7 @@ static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev) | |||
452 | clk_enable(pcm->cclk); | 447 | clk_enable(pcm->cclk); |
453 | 448 | ||
454 | /* record our pcm structure for later use in the callbacks */ | 449 | /* record our pcm structure for later use in the callbacks */ |
455 | dai->private_data = pcm; | 450 | dev_set_drvdata(&pdev->dev, pcm); |
456 | 451 | ||
457 | if (!request_mem_region(mem_res->start, | 452 | if (!request_mem_region(mem_res->start, |
458 | resource_size(mem_res), "samsung-pcm")) { | 453 | resource_size(mem_res), "samsung-pcm")) { |
@@ -476,7 +471,7 @@ static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev) | |||
476 | } | 471 | } |
477 | clk_enable(pcm->pclk); | 472 | clk_enable(pcm->pclk); |
478 | 473 | ||
479 | ret = snd_soc_register_dai(dai); | 474 | ret = snd_soc_register_dai(&pdev->dev, &s3c_pcm_dai[pdev->id]); |
480 | if (ret != 0) { | 475 | if (ret != 0) { |
481 | dev_err(&pdev->dev, "failed to get pcm_clock\n"); | 476 | dev_err(&pdev->dev, "failed to get pcm_clock\n"); |
482 | goto err5; | 477 | goto err5; |
@@ -514,6 +509,8 @@ static __devexit int s3c_pcm_dev_remove(struct platform_device *pdev) | |||
514 | struct s3c_pcm_info *pcm = &s3c_pcm[pdev->id]; | 509 | struct s3c_pcm_info *pcm = &s3c_pcm[pdev->id]; |
515 | struct resource *mem_res; | 510 | struct resource *mem_res; |
516 | 511 | ||
512 | snd_soc_unregister_dai(&pdev->dev); | ||
513 | |||
517 | iounmap(pcm->regs); | 514 | iounmap(pcm->regs); |
518 | 515 | ||
519 | mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 516 | mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
@@ -552,3 +549,4 @@ module_exit(s3c_pcm_exit); | |||
552 | MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>"); | 549 | MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>"); |
553 | MODULE_DESCRIPTION("S3C PCM Controller Driver"); | 550 | MODULE_DESCRIPTION("S3C PCM Controller Driver"); |
554 | MODULE_LICENSE("GPL"); | 551 | MODULE_LICENSE("GPL"); |
552 | MODULE_ALIAS("platform:samsung-pcm"); | ||
diff --git a/sound/soc/s3c24xx/s3c-pcm.h b/sound/soc/s3c24xx/s3c-pcm.h index 69ff9971692f..f60baa19387d 100644 --- a/sound/soc/s3c24xx/s3c-pcm.h +++ b/sound/soc/s3c24xx/s3c-pcm.h | |||
@@ -22,7 +22,8 @@ | |||
22 | /* PCM_CTL Bit-Fields */ | 22 | /* PCM_CTL Bit-Fields */ |
23 | #define S3C_PCM_CTL_TXDIPSTICK_MASK (0x3f) | 23 | #define S3C_PCM_CTL_TXDIPSTICK_MASK (0x3f) |
24 | #define S3C_PCM_CTL_TXDIPSTICK_SHIFT (13) | 24 | #define S3C_PCM_CTL_TXDIPSTICK_SHIFT (13) |
25 | #define S3C_PCM_CTL_RXDIPSTICK_MSK (0x3f<<7) | 25 | #define S3C_PCM_CTL_RXDIPSTICK_MASK (0x3f) |
26 | #define S3C_PCM_CTL_RXDIPSTICK_SHIFT (7) | ||
26 | #define S3C_PCM_CTL_TXDMA_EN (0x1<<6) | 27 | #define S3C_PCM_CTL_TXDMA_EN (0x1<<6) |
27 | #define S3C_PCM_CTL_RXDMA_EN (0x1<<5) | 28 | #define S3C_PCM_CTL_RXDMA_EN (0x1<<5) |
28 | #define S3C_PCM_CTL_TXMSB_AFTER_FSYNC (0x1<<4) | 29 | #define S3C_PCM_CTL_TXMSB_AFTER_FSYNC (0x1<<4) |
diff --git a/sound/soc/s3c24xx/s3c2412-i2s.c b/sound/soc/s3c24xx/s3c2412-i2s.c index 709adef9d043..4a861cfa52c5 100644 --- a/sound/soc/s3c24xx/s3c2412-i2s.c +++ b/sound/soc/s3c24xx/s3c2412-i2s.c | |||
@@ -65,26 +65,20 @@ static struct s3c_dma_params s3c2412_i2s_pcm_stereo_in = { | |||
65 | 65 | ||
66 | static struct s3c_i2sv2_info s3c2412_i2s; | 66 | static struct s3c_i2sv2_info s3c2412_i2s; |
67 | 67 | ||
68 | static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai) | 68 | static int s3c2412_i2s_probe(struct snd_soc_dai *dai) |
69 | { | ||
70 | return cpu_dai->private_data; | ||
71 | } | ||
72 | |||
73 | static int s3c2412_i2s_probe(struct platform_device *pdev, | ||
74 | struct snd_soc_dai *dai) | ||
75 | { | 69 | { |
76 | int ret; | 70 | int ret; |
77 | 71 | ||
78 | pr_debug("Entered %s\n", __func__); | 72 | pr_debug("Entered %s\n", __func__); |
79 | 73 | ||
80 | ret = s3c_i2sv2_probe(pdev, dai, &s3c2412_i2s, S3C2410_PA_IIS); | 74 | ret = s3c_i2sv2_probe(dai, &s3c2412_i2s, S3C2410_PA_IIS); |
81 | if (ret) | 75 | if (ret) |
82 | return ret; | 76 | return ret; |
83 | 77 | ||
84 | s3c2412_i2s.dma_capture = &s3c2412_i2s_pcm_stereo_in; | 78 | s3c2412_i2s.dma_capture = &s3c2412_i2s_pcm_stereo_in; |
85 | s3c2412_i2s.dma_playback = &s3c2412_i2s_pcm_stereo_out; | 79 | s3c2412_i2s.dma_playback = &s3c2412_i2s_pcm_stereo_out; |
86 | 80 | ||
87 | s3c2412_i2s.iis_cclk = clk_get(&pdev->dev, "i2sclk"); | 81 | s3c2412_i2s.iis_cclk = clk_get(dai->dev, "i2sclk"); |
88 | if (s3c2412_i2s.iis_cclk == NULL) { | 82 | if (s3c2412_i2s.iis_cclk == NULL) { |
89 | pr_err("failed to get i2sclk clock\n"); | 83 | pr_err("failed to get i2sclk clock\n"); |
90 | iounmap(s3c2412_i2s.regs); | 84 | iounmap(s3c2412_i2s.regs); |
@@ -108,11 +102,20 @@ static int s3c2412_i2s_probe(struct platform_device *pdev, | |||
108 | return 0; | 102 | return 0; |
109 | } | 103 | } |
110 | 104 | ||
105 | static int s3c2412_i2s_remove(struct snd_soc_dai *dai) | ||
106 | { | ||
107 | clk_disable(s3c2412_i2s.iis_cclk); | ||
108 | clk_put(s3c2412_i2s.iis_cclk); | ||
109 | iounmap(s3c2412_i2s.regs); | ||
110 | |||
111 | return 0; | ||
112 | } | ||
113 | |||
111 | static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream, | 114 | static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream, |
112 | struct snd_pcm_hw_params *params, | 115 | struct snd_pcm_hw_params *params, |
113 | struct snd_soc_dai *cpu_dai) | 116 | struct snd_soc_dai *cpu_dai) |
114 | { | 117 | { |
115 | struct s3c_i2sv2_info *i2s = to_info(cpu_dai); | 118 | struct s3c_i2sv2_info *i2s = snd_soc_dai_get_drvdata(cpu_dai); |
116 | struct s3c_dma_params *dma_data; | 119 | struct s3c_dma_params *dma_data; |
117 | u32 iismod; | 120 | u32 iismod; |
118 | 121 | ||
@@ -152,10 +155,9 @@ static struct snd_soc_dai_ops s3c2412_i2s_dai_ops = { | |||
152 | .hw_params = s3c2412_i2s_hw_params, | 155 | .hw_params = s3c2412_i2s_hw_params, |
153 | }; | 156 | }; |
154 | 157 | ||
155 | struct snd_soc_dai s3c2412_i2s_dai = { | 158 | static struct snd_soc_dai_driver s3c2412_i2s_dai = { |
156 | .name = "s3c2412-i2s", | ||
157 | .id = 0, | ||
158 | .probe = s3c2412_i2s_probe, | 159 | .probe = s3c2412_i2s_probe, |
160 | .remove = s3c2412_i2s_remove, | ||
159 | .playback = { | 161 | .playback = { |
160 | .channels_min = 2, | 162 | .channels_min = 2, |
161 | .channels_max = 2, | 163 | .channels_max = 2, |
@@ -170,17 +172,36 @@ struct snd_soc_dai s3c2412_i2s_dai = { | |||
170 | }, | 172 | }, |
171 | .ops = &s3c2412_i2s_dai_ops, | 173 | .ops = &s3c2412_i2s_dai_ops, |
172 | }; | 174 | }; |
173 | EXPORT_SYMBOL_GPL(s3c2412_i2s_dai); | 175 | |
176 | static __devinit int s3c2412_iis_dev_probe(struct platform_device *pdev) | ||
177 | { | ||
178 | return snd_soc_register_dai(&pdev->dev, &s3c2412_i2s_dai); | ||
179 | } | ||
180 | |||
181 | static __devexit int s3c2412_iis_dev_remove(struct platform_device *pdev) | ||
182 | { | ||
183 | snd_soc_unregister_dai(&pdev->dev); | ||
184 | return 0; | ||
185 | } | ||
186 | |||
187 | static struct platform_driver s3c2412_iis_driver = { | ||
188 | .probe = s3c2412_iis_dev_probe, | ||
189 | .remove = s3c2412_iis_dev_remove, | ||
190 | .driver = { | ||
191 | .name = "s3c2412-iis", | ||
192 | .owner = THIS_MODULE, | ||
193 | }, | ||
194 | }; | ||
174 | 195 | ||
175 | static int __init s3c2412_i2s_init(void) | 196 | static int __init s3c2412_i2s_init(void) |
176 | { | 197 | { |
177 | return s3c_i2sv2_register_dai(&s3c2412_i2s_dai); | 198 | return platform_driver_register(&s3c2412_iis_driver); |
178 | } | 199 | } |
179 | module_init(s3c2412_i2s_init); | 200 | module_init(s3c2412_i2s_init); |
180 | 201 | ||
181 | static void __exit s3c2412_i2s_exit(void) | 202 | static void __exit s3c2412_i2s_exit(void) |
182 | { | 203 | { |
183 | snd_soc_unregister_dai(&s3c2412_i2s_dai); | 204 | platform_driver_unregister(&s3c2412_iis_driver); |
184 | } | 205 | } |
185 | module_exit(s3c2412_i2s_exit); | 206 | module_exit(s3c2412_i2s_exit); |
186 | 207 | ||
@@ -188,3 +209,4 @@ module_exit(s3c2412_i2s_exit); | |||
188 | MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); | 209 | MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); |
189 | MODULE_DESCRIPTION("S3C2412 I2S SoC Interface"); | 210 | MODULE_DESCRIPTION("S3C2412 I2S SoC Interface"); |
190 | MODULE_LICENSE("GPL"); | 211 | MODULE_LICENSE("GPL"); |
212 | MODULE_ALIAS("platform:s3c2412-iis"); | ||
diff --git a/sound/soc/s3c24xx/s3c2412-i2s.h b/sound/soc/s3c24xx/s3c2412-i2s.h index 0b5686b4d5c3..01a0471ac65c 100644 --- a/sound/soc/s3c24xx/s3c2412-i2s.h +++ b/sound/soc/s3c24xx/s3c2412-i2s.h | |||
@@ -24,6 +24,4 @@ | |||
24 | #define S3C2412_CLKSRC_PCLK S3C_I2SV2_CLKSRC_PCLK | 24 | #define S3C2412_CLKSRC_PCLK S3C_I2SV2_CLKSRC_PCLK |
25 | #define S3C2412_CLKSRC_I2SCLK S3C_I2SV2_CLKSRC_AUDIOBUS | 25 | #define S3C2412_CLKSRC_I2SCLK S3C_I2SV2_CLKSRC_AUDIOBUS |
26 | 26 | ||
27 | extern struct snd_soc_dai s3c2412_i2s_dai; | ||
28 | |||
29 | #endif /* __SND_SOC_S3C24XX_S3C2412_I2S_H */ | 27 | #endif /* __SND_SOC_S3C24XX_S3C2412_I2S_H */ |
diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.c b/sound/soc/s3c24xx/s3c24xx-i2s.c index c3ac890a3986..e060daaa458f 100644 --- a/sound/soc/s3c24xx/s3c24xx-i2s.c +++ b/sound/soc/s3c24xx/s3c24xx-i2s.c | |||
@@ -252,7 +252,7 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream, | |||
252 | else | 252 | else |
253 | dma_data = &s3c24xx_i2s_pcm_stereo_in; | 253 | dma_data = &s3c24xx_i2s_pcm_stereo_in; |
254 | 254 | ||
255 | snd_soc_dai_set_dma_data(rtd->dai->cpu_dai, substream, dma_data); | 255 | snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_data); |
256 | 256 | ||
257 | /* Working copies of register */ | 257 | /* Working copies of register */ |
258 | iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); | 258 | iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); |
@@ -280,9 +280,8 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd, | |||
280 | struct snd_soc_dai *dai) | 280 | struct snd_soc_dai *dai) |
281 | { | 281 | { |
282 | int ret = 0; | 282 | int ret = 0; |
283 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
284 | struct s3c_dma_params *dma_data = | 283 | struct s3c_dma_params *dma_data = |
285 | snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); | 284 | snd_soc_dai_get_dma_data(dai, substream); |
286 | 285 | ||
287 | pr_debug("Entered %s\n", __func__); | 286 | pr_debug("Entered %s\n", __func__); |
288 | 287 | ||
@@ -387,8 +386,7 @@ u32 s3c24xx_i2s_get_clockrate(void) | |||
387 | } | 386 | } |
388 | EXPORT_SYMBOL_GPL(s3c24xx_i2s_get_clockrate); | 387 | EXPORT_SYMBOL_GPL(s3c24xx_i2s_get_clockrate); |
389 | 388 | ||
390 | static int s3c24xx_i2s_probe(struct platform_device *pdev, | 389 | static int s3c24xx_i2s_probe(struct snd_soc_dai *dai) |
391 | struct snd_soc_dai *dai) | ||
392 | { | 390 | { |
393 | pr_debug("Entered %s\n", __func__); | 391 | pr_debug("Entered %s\n", __func__); |
394 | 392 | ||
@@ -396,7 +394,7 @@ static int s3c24xx_i2s_probe(struct platform_device *pdev, | |||
396 | if (s3c24xx_i2s.regs == NULL) | 394 | if (s3c24xx_i2s.regs == NULL) |
397 | return -ENXIO; | 395 | return -ENXIO; |
398 | 396 | ||
399 | s3c24xx_i2s.iis_clk = clk_get(&pdev->dev, "iis"); | 397 | s3c24xx_i2s.iis_clk = clk_get(dai->dev, "iis"); |
400 | if (s3c24xx_i2s.iis_clk == NULL) { | 398 | if (s3c24xx_i2s.iis_clk == NULL) { |
401 | pr_err("failed to get iis_clock\n"); | 399 | pr_err("failed to get iis_clock\n"); |
402 | iounmap(s3c24xx_i2s.regs); | 400 | iounmap(s3c24xx_i2s.regs); |
@@ -465,9 +463,7 @@ static struct snd_soc_dai_ops s3c24xx_i2s_dai_ops = { | |||
465 | .set_sysclk = s3c24xx_i2s_set_sysclk, | 463 | .set_sysclk = s3c24xx_i2s_set_sysclk, |
466 | }; | 464 | }; |
467 | 465 | ||
468 | struct snd_soc_dai s3c24xx_i2s_dai = { | 466 | static struct snd_soc_dai_driver s3c24xx_i2s_dai = { |
469 | .name = "s3c24xx-i2s", | ||
470 | .id = 0, | ||
471 | .probe = s3c24xx_i2s_probe, | 467 | .probe = s3c24xx_i2s_probe, |
472 | .suspend = s3c24xx_i2s_suspend, | 468 | .suspend = s3c24xx_i2s_suspend, |
473 | .resume = s3c24xx_i2s_resume, | 469 | .resume = s3c24xx_i2s_resume, |
@@ -483,17 +479,36 @@ struct snd_soc_dai s3c24xx_i2s_dai = { | |||
483 | .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,}, | 479 | .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,}, |
484 | .ops = &s3c24xx_i2s_dai_ops, | 480 | .ops = &s3c24xx_i2s_dai_ops, |
485 | }; | 481 | }; |
486 | EXPORT_SYMBOL_GPL(s3c24xx_i2s_dai); | 482 | |
483 | static __devinit int s3c24xx_iis_dev_probe(struct platform_device *pdev) | ||
484 | { | ||
485 | return snd_soc_register_dai(&pdev->dev, &s3c24xx_i2s_dai); | ||
486 | } | ||
487 | |||
488 | static __devexit int s3c24xx_iis_dev_remove(struct platform_device *pdev) | ||
489 | { | ||
490 | snd_soc_unregister_dai(&pdev->dev); | ||
491 | return 0; | ||
492 | } | ||
493 | |||
494 | static struct platform_driver s3c24xx_iis_driver = { | ||
495 | .probe = s3c24xx_iis_dev_probe, | ||
496 | .remove = s3c24xx_iis_dev_remove, | ||
497 | .driver = { | ||
498 | .name = "s3c24xx-iis", | ||
499 | .owner = THIS_MODULE, | ||
500 | }, | ||
501 | }; | ||
487 | 502 | ||
488 | static int __init s3c24xx_i2s_init(void) | 503 | static int __init s3c24xx_i2s_init(void) |
489 | { | 504 | { |
490 | return snd_soc_register_dai(&s3c24xx_i2s_dai); | 505 | return platform_driver_register(&s3c24xx_iis_driver); |
491 | } | 506 | } |
492 | module_init(s3c24xx_i2s_init); | 507 | module_init(s3c24xx_i2s_init); |
493 | 508 | ||
494 | static void __exit s3c24xx_i2s_exit(void) | 509 | static void __exit s3c24xx_i2s_exit(void) |
495 | { | 510 | { |
496 | snd_soc_unregister_dai(&s3c24xx_i2s_dai); | 511 | platform_driver_unregister(&s3c24xx_iis_driver); |
497 | } | 512 | } |
498 | module_exit(s3c24xx_i2s_exit); | 513 | module_exit(s3c24xx_i2s_exit); |
499 | 514 | ||
@@ -501,3 +516,4 @@ module_exit(s3c24xx_i2s_exit); | |||
501 | MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); | 516 | MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); |
502 | MODULE_DESCRIPTION("s3c24xx I2S SoC Interface"); | 517 | MODULE_DESCRIPTION("s3c24xx I2S SoC Interface"); |
503 | MODULE_LICENSE("GPL"); | 518 | MODULE_LICENSE("GPL"); |
519 | MODULE_ALIAS("platform:s3c24xx-iis"); | ||
diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.h b/sound/soc/s3c24xx/s3c24xx-i2s.h index 726d91cf4e1c..f9ca04edacb7 100644 --- a/sound/soc/s3c24xx/s3c24xx-i2s.h +++ b/sound/soc/s3c24xx/s3c24xx-i2s.h | |||
@@ -32,6 +32,4 @@ | |||
32 | 32 | ||
33 | u32 s3c24xx_i2s_get_clockrate(void); | 33 | u32 s3c24xx_i2s_get_clockrate(void); |
34 | 34 | ||
35 | extern struct snd_soc_dai s3c24xx_i2s_dai; | ||
36 | |||
37 | #endif /*S3C24XXI2S_H_*/ | 35 | #endif /*S3C24XXI2S_H_*/ |
diff --git a/sound/soc/s3c24xx/s3c24xx_simtec.c b/sound/soc/s3c24xx/s3c24xx_simtec.c index 4984754f3298..c4c111442010 100644 --- a/sound/soc/s3c24xx/s3c24xx_simtec.c +++ b/sound/soc/s3c24xx/s3c24xx_simtec.c | |||
@@ -139,8 +139,10 @@ static const struct snd_kcontrol_new amp_unmute_controls[] = { | |||
139 | speaker_unmute_get, speaker_unmute_put), | 139 | speaker_unmute_get, speaker_unmute_put), |
140 | }; | 140 | }; |
141 | 141 | ||
142 | void simtec_audio_init(struct snd_soc_codec *codec) | 142 | void simtec_audio_init(struct snd_soc_pcm_runtime *rtd) |
143 | { | 143 | { |
144 | struct snd_soc_codec *codec = rtd->codec; | ||
145 | |||
144 | if (pdata->amp_gpio > 0) { | 146 | if (pdata->amp_gpio > 0) { |
145 | pr_debug("%s: adding amp routes\n", __func__); | 147 | pr_debug("%s: adding amp routes\n", __func__); |
146 | 148 | ||
@@ -170,8 +172,8 @@ static int simtec_hw_params(struct snd_pcm_substream *substream, | |||
170 | struct snd_pcm_hw_params *params) | 172 | struct snd_pcm_hw_params *params) |
171 | { | 173 | { |
172 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 174 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
173 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 175 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
174 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 176 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
175 | int ret; | 177 | int ret; |
176 | 178 | ||
177 | /* Set the CODEC as the bus clock master, I2S */ | 179 | /* Set the CODEC as the bus clock master, I2S */ |
@@ -319,12 +321,12 @@ EXPORT_SYMBOL_GPL(simtec_audio_pmops); | |||
319 | #endif | 321 | #endif |
320 | 322 | ||
321 | int __devinit simtec_audio_core_probe(struct platform_device *pdev, | 323 | int __devinit simtec_audio_core_probe(struct platform_device *pdev, |
322 | struct snd_soc_device *socdev) | 324 | struct snd_soc_card *card) |
323 | { | 325 | { |
324 | struct platform_device *snd_dev; | 326 | struct platform_device *snd_dev; |
325 | int ret; | 327 | int ret; |
326 | 328 | ||
327 | socdev->card->dai_link->ops = &simtec_snd_ops; | 329 | card->dai_link->ops = &simtec_snd_ops; |
328 | 330 | ||
329 | pdata = pdev->dev.platform_data; | 331 | pdata = pdev->dev.platform_data; |
330 | if (!pdata) { | 332 | if (!pdata) { |
@@ -353,8 +355,7 @@ int __devinit simtec_audio_core_probe(struct platform_device *pdev, | |||
353 | goto err_gpio; | 355 | goto err_gpio; |
354 | } | 356 | } |
355 | 357 | ||
356 | platform_set_drvdata(snd_dev, socdev); | 358 | platform_set_drvdata(snd_dev, card); |
357 | socdev->dev = &snd_dev->dev; | ||
358 | 359 | ||
359 | ret = platform_device_add(snd_dev); | 360 | ret = platform_device_add(snd_dev); |
360 | if (ret) { | 361 | if (ret) { |
diff --git a/sound/soc/s3c24xx/s3c24xx_simtec.h b/sound/soc/s3c24xx/s3c24xx_simtec.h index e18faee30cce..e63d5ff9c41f 100644 --- a/sound/soc/s3c24xx/s3c24xx_simtec.h +++ b/sound/soc/s3c24xx/s3c24xx_simtec.h | |||
@@ -7,10 +7,10 @@ | |||
7 | * published by the Free Software Foundation. | 7 | * published by the Free Software Foundation. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | extern void simtec_audio_init(struct snd_soc_codec *codec); | 10 | extern void simtec_audio_init(struct snd_soc_pcm_runtime *rtd); |
11 | 11 | ||
12 | extern int simtec_audio_core_probe(struct platform_device *pdev, | 12 | extern int simtec_audio_core_probe(struct platform_device *pdev, |
13 | struct snd_soc_device *socdev); | 13 | struct snd_soc_card *card); |
14 | 14 | ||
15 | extern int simtec_audio_remove(struct platform_device *pdev); | 15 | extern int simtec_audio_remove(struct platform_device *pdev); |
16 | 16 | ||
diff --git a/sound/soc/s3c24xx/s3c24xx_simtec_hermes.c b/sound/soc/s3c24xx/s3c24xx_simtec_hermes.c index bdf8951af8e3..f88453735ae2 100644 --- a/sound/soc/s3c24xx/s3c24xx_simtec_hermes.c +++ b/sound/soc/s3c24xx/s3c24xx_simtec_hermes.c | |||
@@ -73,8 +73,10 @@ static const struct snd_soc_dapm_route base_map[] = { | |||
73 | * Attach our controls and configure the necessary codec | 73 | * Attach our controls and configure the necessary codec |
74 | * mappings for our sound card instance. | 74 | * mappings for our sound card instance. |
75 | */ | 75 | */ |
76 | static int simtec_hermes_init(struct snd_soc_codec *codec) | 76 | static int simtec_hermes_init(struct snd_soc_pcm_runtime *rtd) |
77 | { | 77 | { |
78 | struct snd_soc_codec *codec = rtd->codec; | ||
79 | |||
78 | snd_soc_dapm_new_controls(codec, dapm_widgets, | 80 | snd_soc_dapm_new_controls(codec, dapm_widgets, |
79 | ARRAY_SIZE(dapm_widgets)); | 81 | ARRAY_SIZE(dapm_widgets)); |
80 | 82 | ||
@@ -85,42 +87,33 @@ static int simtec_hermes_init(struct snd_soc_codec *codec) | |||
85 | snd_soc_dapm_enable_pin(codec, "Line Out"); | 87 | snd_soc_dapm_enable_pin(codec, "Line Out"); |
86 | snd_soc_dapm_enable_pin(codec, "Mic Jack"); | 88 | snd_soc_dapm_enable_pin(codec, "Mic Jack"); |
87 | 89 | ||
88 | simtec_audio_init(codec); | 90 | simtec_audio_init(rtd); |
89 | snd_soc_dapm_sync(codec); | 91 | snd_soc_dapm_sync(codec); |
90 | 92 | ||
91 | return 0; | 93 | return 0; |
92 | } | 94 | } |
93 | 95 | ||
94 | static struct aic3x_setup_data codec_setup = { | ||
95 | }; | ||
96 | |||
97 | static struct snd_soc_dai_link simtec_dai_aic33 = { | 96 | static struct snd_soc_dai_link simtec_dai_aic33 = { |
98 | .name = "tlv320aic33", | 97 | .name = "tlv320aic33", |
99 | .stream_name = "TLV320AIC33", | 98 | .stream_name = "TLV320AIC33", |
100 | .cpu_dai = &s3c24xx_i2s_dai, | 99 | .codec_name = "tlv320aic3x-codec.0-0x1a", |
101 | .codec_dai = &aic3x_dai, | 100 | .cpu_dai_name = "s3c24xx-i2s", |
101 | .codec_dai_name = "tlv320aic3x-hifi", | ||
102 | .platform_name = "s3c24xx-pcm-audio", | ||
102 | .init = simtec_hermes_init, | 103 | .init = simtec_hermes_init, |
103 | }; | 104 | }; |
104 | 105 | ||
105 | /* simtec audio machine driver */ | 106 | /* simtec audio machine driver */ |
106 | static struct snd_soc_card snd_soc_machine_simtec_aic33 = { | 107 | static struct snd_soc_card snd_soc_machine_simtec_aic33 = { |
107 | .name = "Simtec-Hermes", | 108 | .name = "Simtec-Hermes", |
108 | .platform = &s3c24xx_soc_platform, | ||
109 | .dai_link = &simtec_dai_aic33, | 109 | .dai_link = &simtec_dai_aic33, |
110 | .num_links = 1, | 110 | .num_links = 1, |
111 | }; | 111 | }; |
112 | 112 | ||
113 | /* simtec audio subsystem */ | ||
114 | static struct snd_soc_device simtec_snd_devdata_aic33 = { | ||
115 | .card = &snd_soc_machine_simtec_aic33, | ||
116 | .codec_dev = &soc_codec_dev_aic3x, | ||
117 | .codec_data = &codec_setup, | ||
118 | }; | ||
119 | |||
120 | static int __devinit simtec_audio_hermes_probe(struct platform_device *pd) | 113 | static int __devinit simtec_audio_hermes_probe(struct platform_device *pd) |
121 | { | 114 | { |
122 | dev_info(&pd->dev, "probing....\n"); | 115 | dev_info(&pd->dev, "probing....\n"); |
123 | return simtec_audio_core_probe(pd, &simtec_snd_devdata_aic33); | 116 | return simtec_audio_core_probe(pd, &snd_soc_machine_simtec_aic33); |
124 | } | 117 | } |
125 | 118 | ||
126 | static struct platform_driver simtec_audio_hermes_platdrv = { | 119 | static struct platform_driver simtec_audio_hermes_platdrv = { |
diff --git a/sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c b/sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c index 185c0acb5ce6..c0967593510d 100644 --- a/sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c +++ b/sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c | |||
@@ -62,8 +62,10 @@ static const struct snd_soc_dapm_route base_map[] = { | |||
62 | * Attach our controls and configure the necessary codec | 62 | * Attach our controls and configure the necessary codec |
63 | * mappings for our sound card instance. | 63 | * mappings for our sound card instance. |
64 | */ | 64 | */ |
65 | static int simtec_tlv320aic23_init(struct snd_soc_codec *codec) | 65 | static int simtec_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd) |
66 | { | 66 | { |
67 | struct snd_soc_codec *codec = rtd->codec; | ||
68 | |||
67 | snd_soc_dapm_new_controls(codec, dapm_widgets, | 69 | snd_soc_dapm_new_controls(codec, dapm_widgets, |
68 | ARRAY_SIZE(dapm_widgets)); | 70 | ARRAY_SIZE(dapm_widgets)); |
69 | 71 | ||
@@ -74,7 +76,7 @@ static int simtec_tlv320aic23_init(struct snd_soc_codec *codec) | |||
74 | snd_soc_dapm_enable_pin(codec, "Line Out"); | 76 | snd_soc_dapm_enable_pin(codec, "Line Out"); |
75 | snd_soc_dapm_enable_pin(codec, "Mic Jack"); | 77 | snd_soc_dapm_enable_pin(codec, "Mic Jack"); |
76 | 78 | ||
77 | simtec_audio_init(codec); | 79 | simtec_audio_init(rtd); |
78 | snd_soc_dapm_sync(codec); | 80 | snd_soc_dapm_sync(codec); |
79 | 81 | ||
80 | return 0; | 82 | return 0; |
@@ -83,28 +85,23 @@ static int simtec_tlv320aic23_init(struct snd_soc_codec *codec) | |||
83 | static struct snd_soc_dai_link simtec_dai_aic23 = { | 85 | static struct snd_soc_dai_link simtec_dai_aic23 = { |
84 | .name = "tlv320aic23", | 86 | .name = "tlv320aic23", |
85 | .stream_name = "TLV320AIC23", | 87 | .stream_name = "TLV320AIC23", |
86 | .cpu_dai = &s3c24xx_i2s_dai, | 88 | .codec_name = "tlv320aic3x-codec.0-0x1a", |
87 | .codec_dai = &tlv320aic23_dai, | 89 | .cpu_dai_name = "s3c24xx-i2s", |
90 | .codec_dai_name = "tlv320aic3x-hifi", | ||
91 | .platform_name = "s3c24xx-pcm-audio", | ||
88 | .init = simtec_tlv320aic23_init, | 92 | .init = simtec_tlv320aic23_init, |
89 | }; | 93 | }; |
90 | 94 | ||
91 | /* simtec audio machine driver */ | 95 | /* simtec audio machine driver */ |
92 | static struct snd_soc_card snd_soc_machine_simtec_aic23 = { | 96 | static struct snd_soc_card snd_soc_machine_simtec_aic23 = { |
93 | .name = "Simtec", | 97 | .name = "Simtec", |
94 | .platform = &s3c24xx_soc_platform, | ||
95 | .dai_link = &simtec_dai_aic23, | 98 | .dai_link = &simtec_dai_aic23, |
96 | .num_links = 1, | 99 | .num_links = 1, |
97 | }; | 100 | }; |
98 | 101 | ||
99 | /* simtec audio subsystem */ | ||
100 | static struct snd_soc_device simtec_snd_devdata_aic23 = { | ||
101 | .card = &snd_soc_machine_simtec_aic23, | ||
102 | .codec_dev = &soc_codec_dev_tlv320aic23, | ||
103 | }; | ||
104 | |||
105 | static int __devinit simtec_audio_tlv320aic23_probe(struct platform_device *pd) | 102 | static int __devinit simtec_audio_tlv320aic23_probe(struct platform_device *pd) |
106 | { | 103 | { |
107 | return simtec_audio_core_probe(pd, &simtec_snd_devdata_aic23); | 104 | return simtec_audio_core_probe(pd, &snd_soc_machine_simtec_aic23); |
108 | } | 105 | } |
109 | 106 | ||
110 | static struct platform_driver simtec_audio_tlv320aic23_platdrv = { | 107 | static struct platform_driver simtec_audio_tlv320aic23_platdrv = { |
diff --git a/sound/soc/s3c24xx/s3c24xx_uda134x.c b/sound/soc/s3c24xx/s3c24xx_uda134x.c index 052d59659c29..bd48ffbde880 100644 --- a/sound/soc/s3c24xx/s3c24xx_uda134x.c +++ b/sound/soc/s3c24xx/s3c24xx_uda134x.c | |||
@@ -133,8 +133,8 @@ static int s3c24xx_uda134x_hw_params(struct snd_pcm_substream *substream, | |||
133 | struct snd_pcm_hw_params *params) | 133 | struct snd_pcm_hw_params *params) |
134 | { | 134 | { |
135 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 135 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
136 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 136 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
137 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 137 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
138 | unsigned int clk = 0; | 138 | unsigned int clk = 0; |
139 | int ret = 0; | 139 | int ret = 0; |
140 | int clk_source, fs_mode; | 140 | int clk_source, fs_mode; |
@@ -227,14 +227,15 @@ static struct snd_soc_ops s3c24xx_uda134x_ops = { | |||
227 | static struct snd_soc_dai_link s3c24xx_uda134x_dai_link = { | 227 | static struct snd_soc_dai_link s3c24xx_uda134x_dai_link = { |
228 | .name = "UDA134X", | 228 | .name = "UDA134X", |
229 | .stream_name = "UDA134X", | 229 | .stream_name = "UDA134X", |
230 | .codec_dai = &uda134x_dai, | 230 | .codec_name = "uda134x-hifi", |
231 | .cpu_dai = &s3c24xx_i2s_dai, | 231 | .codec_dai_name = "uda134x-hifi", |
232 | .cpu_dai_name = "s3c24xx-i2s", | ||
232 | .ops = &s3c24xx_uda134x_ops, | 233 | .ops = &s3c24xx_uda134x_ops, |
234 | .platform_name = "s3c24xx-pcm-audio", | ||
233 | }; | 235 | }; |
234 | 236 | ||
235 | static struct snd_soc_card snd_soc_s3c24xx_uda134x = { | 237 | static struct snd_soc_card snd_soc_s3c24xx_uda134x = { |
236 | .name = "S3C24XX_UDA134X", | 238 | .name = "S3C24XX_UDA134X", |
237 | .platform = &s3c24xx_soc_platform, | ||
238 | .dai_link = &s3c24xx_uda134x_dai_link, | 239 | .dai_link = &s3c24xx_uda134x_dai_link, |
239 | .num_links = 1, | 240 | .num_links = 1, |
240 | }; | 241 | }; |
@@ -256,6 +257,7 @@ static void setmode(int v) | |||
256 | gpio_set_value(s3c24xx_uda134x_l3_pins->l3_mode, v > 0); | 257 | gpio_set_value(s3c24xx_uda134x_l3_pins->l3_mode, v > 0); |
257 | } | 258 | } |
258 | 259 | ||
260 | /* FIXME - This must be codec platform data but in which board file ?? */ | ||
259 | static struct uda134x_platform_data s3c24xx_uda134x = { | 261 | static struct uda134x_platform_data s3c24xx_uda134x = { |
260 | .l3 = { | 262 | .l3 = { |
261 | .setdat = setdat, | 263 | .setdat = setdat, |
@@ -270,12 +272,6 @@ static struct uda134x_platform_data s3c24xx_uda134x = { | |||
270 | }, | 272 | }, |
271 | }; | 273 | }; |
272 | 274 | ||
273 | static struct snd_soc_device s3c24xx_uda134x_snd_devdata = { | ||
274 | .card = &snd_soc_s3c24xx_uda134x, | ||
275 | .codec_dev = &soc_codec_dev_uda134x, | ||
276 | .codec_data = &s3c24xx_uda134x, | ||
277 | }; | ||
278 | |||
279 | static int s3c24xx_uda134x_setup_pin(int pin, char *fun) | 275 | static int s3c24xx_uda134x_setup_pin(int pin, char *fun) |
280 | { | 276 | { |
281 | if (gpio_request(pin, "s3c24xx_uda134x") < 0) { | 277 | if (gpio_request(pin, "s3c24xx_uda134x") < 0) { |
@@ -325,8 +321,7 @@ static int s3c24xx_uda134x_probe(struct platform_device *pdev) | |||
325 | } | 321 | } |
326 | 322 | ||
327 | platform_set_drvdata(s3c24xx_uda134x_snd_device, | 323 | platform_set_drvdata(s3c24xx_uda134x_snd_device, |
328 | &s3c24xx_uda134x_snd_devdata); | 324 | &snd_soc_s3c24xx_uda134x); |
329 | s3c24xx_uda134x_snd_devdata.dev = &s3c24xx_uda134x_snd_device->dev; | ||
330 | ret = platform_device_add(s3c24xx_uda134x_snd_device); | 325 | ret = platform_device_add(s3c24xx_uda134x_snd_device); |
331 | if (ret) { | 326 | if (ret) { |
332 | printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: Unable to add\n"); | 327 | printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: Unable to add\n"); |
diff --git a/sound/soc/s3c24xx/s3c64xx-i2s-v4.c b/sound/soc/s3c24xx/s3c64xx-i2s-v4.c index 06db130030a1..a9628472ebfe 100644 --- a/sound/soc/s3c24xx/s3c64xx-i2s-v4.c +++ b/sound/soc/s3c24xx/s3c64xx-i2s-v4.c | |||
@@ -16,9 +16,7 @@ | |||
16 | #include <sound/soc.h> | 16 | #include <sound/soc.h> |
17 | #include <sound/pcm_params.h> | 17 | #include <sound/pcm_params.h> |
18 | 18 | ||
19 | #include <mach/gpio-bank-c.h> | 19 | #include <plat/audio.h> |
20 | #include <mach/gpio-bank-h.h> | ||
21 | #include <plat/gpio-cfg.h> | ||
22 | 20 | ||
23 | #include <mach/map.h> | 21 | #include <mach/map.h> |
24 | #include <mach/dma.h> | 22 | #include <mach/dma.h> |
@@ -39,34 +37,23 @@ static struct s3c_dma_params s3c64xx_i2sv4_pcm_stereo_out; | |||
39 | static struct s3c_dma_params s3c64xx_i2sv4_pcm_stereo_in; | 37 | static struct s3c_dma_params s3c64xx_i2sv4_pcm_stereo_in; |
40 | static struct s3c_i2sv2_info s3c64xx_i2sv4; | 38 | static struct s3c_i2sv2_info s3c64xx_i2sv4; |
41 | 39 | ||
42 | struct snd_soc_dai s3c64xx_i2s_v4_dai; | 40 | static int s3c64xx_i2sv4_probe(struct snd_soc_dai *dai) |
43 | EXPORT_SYMBOL_GPL(s3c64xx_i2s_v4_dai); | ||
44 | |||
45 | static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai) | ||
46 | { | 41 | { |
47 | return cpu_dai->private_data; | 42 | struct s3c_i2sv2_info *i2s = &s3c64xx_i2sv4; |
48 | } | 43 | int ret = 0; |
49 | 44 | ||
50 | static int s3c64xx_i2sv4_probe(struct platform_device *pdev, | 45 | snd_soc_dai_set_drvdata(dai, i2s); |
51 | struct snd_soc_dai *dai) | ||
52 | { | ||
53 | /* configure GPIO for i2s port */ | ||
54 | s3c_gpio_cfgpin(S3C64XX_GPC(4), S3C64XX_GPC4_I2S_V40_DO0); | ||
55 | s3c_gpio_cfgpin(S3C64XX_GPC(5), S3C64XX_GPC5_I2S_V40_DO1); | ||
56 | s3c_gpio_cfgpin(S3C64XX_GPC(7), S3C64XX_GPC7_I2S_V40_DO2); | ||
57 | s3c_gpio_cfgpin(S3C64XX_GPH(6), S3C64XX_GPH6_I2S_V40_BCLK); | ||
58 | s3c_gpio_cfgpin(S3C64XX_GPH(7), S3C64XX_GPH7_I2S_V40_CDCLK); | ||
59 | s3c_gpio_cfgpin(S3C64XX_GPH(8), S3C64XX_GPH8_I2S_V40_LRCLK); | ||
60 | s3c_gpio_cfgpin(S3C64XX_GPH(9), S3C64XX_GPH9_I2S_V40_DI); | ||
61 | 46 | ||
62 | return 0; | 47 | ret = s3c_i2sv2_probe(dai, i2s, i2s->base); |
48 | |||
49 | return ret; | ||
63 | } | 50 | } |
64 | 51 | ||
65 | static int s3c_i2sv4_hw_params(struct snd_pcm_substream *substream, | 52 | static int s3c_i2sv4_hw_params(struct snd_pcm_substream *substream, |
66 | struct snd_pcm_hw_params *params, | 53 | struct snd_pcm_hw_params *params, |
67 | struct snd_soc_dai *cpu_dai) | 54 | struct snd_soc_dai *cpu_dai) |
68 | { | 55 | { |
69 | struct s3c_i2sv2_info *i2s = to_info(cpu_dai); | 56 | struct s3c_i2sv2_info *i2s = snd_soc_dai_get_drvdata(cpu_dai); |
70 | struct s3c_dma_params *dma_data; | 57 | struct s3c_dma_params *dma_data; |
71 | u32 iismod; | 58 | u32 iismod; |
72 | 59 | ||
@@ -104,51 +91,79 @@ static struct snd_soc_dai_ops s3c64xx_i2sv4_dai_ops = { | |||
104 | .hw_params = s3c_i2sv4_hw_params, | 91 | .hw_params = s3c_i2sv4_hw_params, |
105 | }; | 92 | }; |
106 | 93 | ||
94 | static struct snd_soc_dai_driver s3c64xx_i2s_v4_dai = { | ||
95 | .symmetric_rates = 1, | ||
96 | .playback = { | ||
97 | .channels_min = 2, | ||
98 | .channels_max = 2, | ||
99 | .rates = S3C64XX_I2S_RATES, | ||
100 | .formats = S3C64XX_I2S_FMTS, | ||
101 | }, | ||
102 | .capture = { | ||
103 | .channels_min = 2, | ||
104 | .channels_max = 2, | ||
105 | .rates = S3C64XX_I2S_RATES, | ||
106 | .formats = S3C64XX_I2S_FMTS, | ||
107 | }, | ||
108 | .probe = s3c64xx_i2sv4_probe, | ||
109 | .ops = &s3c64xx_i2sv4_dai_ops, | ||
110 | }; | ||
111 | |||
107 | static __devinit int s3c64xx_i2sv4_dev_probe(struct platform_device *pdev) | 112 | static __devinit int s3c64xx_i2sv4_dev_probe(struct platform_device *pdev) |
108 | { | 113 | { |
114 | struct s3c_audio_pdata *i2s_pdata; | ||
109 | struct s3c_i2sv2_info *i2s; | 115 | struct s3c_i2sv2_info *i2s; |
110 | struct snd_soc_dai *dai; | 116 | struct resource *res; |
111 | int ret; | 117 | int ret; |
112 | 118 | ||
113 | i2s = &s3c64xx_i2sv4; | 119 | i2s = &s3c64xx_i2sv4; |
114 | dai = &s3c64xx_i2s_v4_dai; | ||
115 | |||
116 | if (dai->dev) { | ||
117 | dev_dbg(dai->dev, "%s: \ | ||
118 | I2Sv4 instance already registered!\n", __func__); | ||
119 | return -EBUSY; | ||
120 | } | ||
121 | |||
122 | dai->dev = &pdev->dev; | ||
123 | dai->name = "s3c64xx-i2s-v4"; | ||
124 | dai->id = 0; | ||
125 | dai->symmetric_rates = 1; | ||
126 | dai->playback.channels_min = 2; | ||
127 | dai->playback.channels_max = 2; | ||
128 | dai->playback.rates = S3C64XX_I2S_RATES; | ||
129 | dai->playback.formats = S3C64XX_I2S_FMTS; | ||
130 | dai->capture.channels_min = 2; | ||
131 | dai->capture.channels_max = 2; | ||
132 | dai->capture.rates = S3C64XX_I2S_RATES; | ||
133 | dai->capture.formats = S3C64XX_I2S_FMTS; | ||
134 | dai->probe = s3c64xx_i2sv4_probe; | ||
135 | dai->ops = &s3c64xx_i2sv4_dai_ops; | ||
136 | 120 | ||
137 | i2s->feature |= S3C_FEATURE_CDCLKCON; | 121 | i2s->feature |= S3C_FEATURE_CDCLKCON; |
138 | 122 | ||
139 | i2s->dma_capture = &s3c64xx_i2sv4_pcm_stereo_in; | 123 | i2s->dma_capture = &s3c64xx_i2sv4_pcm_stereo_in; |
140 | i2s->dma_playback = &s3c64xx_i2sv4_pcm_stereo_out; | 124 | i2s->dma_playback = &s3c64xx_i2sv4_pcm_stereo_out; |
141 | 125 | ||
142 | i2s->dma_capture->channel = DMACH_HSI_I2SV40_RX; | 126 | res = platform_get_resource(pdev, IORESOURCE_DMA, 0); |
143 | i2s->dma_capture->dma_addr = S3C64XX_PA_IISV4 + S3C2412_IISRXD; | 127 | if (!res) { |
144 | i2s->dma_playback->channel = DMACH_HSI_I2SV40_TX; | 128 | dev_err(&pdev->dev, "Unable to get I2S-TX dma resource\n"); |
145 | i2s->dma_playback->dma_addr = S3C64XX_PA_IISV4 + S3C2412_IISTXD; | 129 | return -ENXIO; |
130 | } | ||
131 | i2s->dma_playback->channel = res->start; | ||
132 | |||
133 | res = platform_get_resource(pdev, IORESOURCE_DMA, 1); | ||
134 | if (!res) { | ||
135 | dev_err(&pdev->dev, "Unable to get I2S-RX dma resource\n"); | ||
136 | return -ENXIO; | ||
137 | } | ||
138 | i2s->dma_capture->channel = res->start; | ||
139 | |||
140 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
141 | if (!res) { | ||
142 | dev_err(&pdev->dev, "Unable to get I2S SFR address\n"); | ||
143 | return -ENXIO; | ||
144 | } | ||
145 | |||
146 | if (!request_mem_region(res->start, resource_size(res), | ||
147 | "s3c64xx-i2s-v4")) { | ||
148 | dev_err(&pdev->dev, "Unable to request SFR region\n"); | ||
149 | return -EBUSY; | ||
150 | } | ||
151 | i2s->dma_capture->dma_addr = res->start + S3C2412_IISRXD; | ||
152 | i2s->dma_playback->dma_addr = res->start + S3C2412_IISTXD; | ||
146 | 153 | ||
147 | i2s->dma_capture->client = &s3c64xx_dma_client_in; | 154 | i2s->dma_capture->client = &s3c64xx_dma_client_in; |
148 | i2s->dma_capture->dma_size = 4; | 155 | i2s->dma_capture->dma_size = 4; |
149 | i2s->dma_playback->client = &s3c64xx_dma_client_out; | 156 | i2s->dma_playback->client = &s3c64xx_dma_client_out; |
150 | i2s->dma_playback->dma_size = 4; | 157 | i2s->dma_playback->dma_size = 4; |
151 | 158 | ||
159 | i2s->base = res->start; | ||
160 | |||
161 | i2s_pdata = pdev->dev.platform_data; | ||
162 | if (i2s_pdata && i2s_pdata->cfg_gpio && i2s_pdata->cfg_gpio(pdev)) { | ||
163 | dev_err(&pdev->dev, "Unable to configure gpio\n"); | ||
164 | return -EINVAL; | ||
165 | } | ||
166 | |||
152 | i2s->iis_cclk = clk_get(&pdev->dev, "audio-bus"); | 167 | i2s->iis_cclk = clk_get(&pdev->dev, "audio-bus"); |
153 | if (IS_ERR(i2s->iis_cclk)) { | 168 | if (IS_ERR(i2s->iis_cclk)) { |
154 | dev_err(&pdev->dev, "failed to get audio-bus\n"); | 169 | dev_err(&pdev->dev, "failed to get audio-bus\n"); |
@@ -158,19 +173,13 @@ static __devinit int s3c64xx_i2sv4_dev_probe(struct platform_device *pdev) | |||
158 | 173 | ||
159 | clk_enable(i2s->iis_cclk); | 174 | clk_enable(i2s->iis_cclk); |
160 | 175 | ||
161 | ret = s3c_i2sv2_probe(pdev, dai, i2s, 0); | 176 | ret = s3c_i2sv2_register_dai(&pdev->dev, pdev->id, &s3c64xx_i2s_v4_dai); |
162 | if (ret) | ||
163 | goto err_clk; | ||
164 | |||
165 | ret = s3c_i2sv2_register_dai(dai); | ||
166 | if (ret != 0) | 177 | if (ret != 0) |
167 | goto err_i2sv2; | 178 | goto err_i2sv2; |
168 | 179 | ||
169 | return 0; | 180 | return 0; |
170 | 181 | ||
171 | err_i2sv2: | 182 | err_i2sv2: |
172 | /* Not implemented for I2Sv2 core yet */ | ||
173 | err_clk: | ||
174 | clk_put(i2s->iis_cclk); | 183 | clk_put(i2s->iis_cclk); |
175 | err: | 184 | err: |
176 | return ret; | 185 | return ret; |
@@ -178,7 +187,18 @@ err: | |||
178 | 187 | ||
179 | static __devexit int s3c64xx_i2sv4_dev_remove(struct platform_device *pdev) | 188 | static __devexit int s3c64xx_i2sv4_dev_remove(struct platform_device *pdev) |
180 | { | 189 | { |
181 | dev_err(&pdev->dev, "Device removal not yet supported\n"); | 190 | struct s3c_i2sv2_info *i2s = &s3c64xx_i2sv4; |
191 | struct resource *res; | ||
192 | |||
193 | snd_soc_unregister_dai(&pdev->dev); | ||
194 | clk_put(i2s->iis_cclk); | ||
195 | |||
196 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
197 | if (res) | ||
198 | release_mem_region(res->start, resource_size(res)); | ||
199 | else | ||
200 | dev_warn(&pdev->dev, "Unable to get I2S SFR address\n"); | ||
201 | |||
182 | return 0; | 202 | return 0; |
183 | } | 203 | } |
184 | 204 | ||
@@ -207,3 +227,4 @@ module_exit(s3c64xx_i2sv4_exit); | |||
207 | MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>"); | 227 | MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>"); |
208 | MODULE_DESCRIPTION("S3C64XX I2Sv4 SoC Interface"); | 228 | MODULE_DESCRIPTION("S3C64XX I2Sv4 SoC Interface"); |
209 | MODULE_LICENSE("GPL"); | 229 | MODULE_LICENSE("GPL"); |
230 | MODULE_ALIAS("platform:s3c64xx-iis-v4"); | ||
diff --git a/sound/soc/s3c24xx/s3c64xx-i2s.c b/sound/soc/s3c24xx/s3c64xx-i2s.c index 1d85cb85a7d2..ae7acb6c4f1d 100644 --- a/sound/soc/s3c24xx/s3c64xx-i2s.c +++ b/sound/soc/s3c24xx/s3c64xx-i2s.c | |||
@@ -12,15 +12,15 @@ | |||
12 | * published by the Free Software Foundation. | 12 | * published by the Free Software Foundation. |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/module.h> | ||
15 | #include <linux/clk.h> | 16 | #include <linux/clk.h> |
16 | #include <linux/gpio.h> | 17 | #include <linux/gpio.h> |
17 | #include <linux/io.h> | 18 | #include <linux/io.h> |
19 | #include <linux/slab.h> | ||
18 | 20 | ||
19 | #include <sound/soc.h> | 21 | #include <sound/soc.h> |
20 | 22 | ||
21 | #include <mach/gpio-bank-d.h> | 23 | #include <plat/audio.h> |
22 | #include <mach/gpio-bank-e.h> | ||
23 | #include <plat/gpio-cfg.h> | ||
24 | 24 | ||
25 | #include <mach/map.h> | 25 | #include <mach/map.h> |
26 | #include <mach/dma.h> | 26 | #include <mach/dma.h> |
@@ -46,45 +46,107 @@ static struct s3c_dma_params s3c64xx_i2s_pcm_stereo_out[MAX_I2SV3]; | |||
46 | static struct s3c_dma_params s3c64xx_i2s_pcm_stereo_in[MAX_I2SV3]; | 46 | static struct s3c_dma_params s3c64xx_i2s_pcm_stereo_in[MAX_I2SV3]; |
47 | static struct s3c_i2sv2_info s3c64xx_i2s[MAX_I2SV3]; | 47 | static struct s3c_i2sv2_info s3c64xx_i2s[MAX_I2SV3]; |
48 | 48 | ||
49 | struct snd_soc_dai s3c64xx_i2s_dai[MAX_I2SV3]; | 49 | struct clk *s3c64xx_i2s_get_clock(struct snd_soc_dai *dai) |
50 | EXPORT_SYMBOL_GPL(s3c64xx_i2s_dai); | ||
51 | |||
52 | static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai) | ||
53 | { | 50 | { |
54 | return cpu_dai->private_data; | 51 | struct s3c_i2sv2_info *i2s = snd_soc_dai_get_drvdata(dai); |
52 | u32 iismod = readl(i2s->regs + S3C2412_IISMOD); | ||
53 | |||
54 | if (iismod & S3C2412_IISMOD_IMS_SYSMUX) | ||
55 | return i2s->iis_cclk; | ||
56 | else | ||
57 | return i2s->iis_pclk; | ||
55 | } | 58 | } |
59 | EXPORT_SYMBOL_GPL(s3c64xx_i2s_get_clock); | ||
56 | 60 | ||
57 | static int s3c64xx_i2s_probe(struct platform_device *pdev, | 61 | static int s3c64xx_i2s_probe(struct snd_soc_dai *dai) |
58 | struct snd_soc_dai *dai) | ||
59 | { | 62 | { |
60 | /* configure GPIO for i2s port */ | 63 | struct s3c_i2sv2_info *i2s; |
61 | switch (dai->id) { | 64 | int ret; |
62 | case 0: | 65 | |
63 | s3c_gpio_cfgpin(S3C64XX_GPD(0), S3C64XX_GPD0_I2S0_CLK); | 66 | if (dai->id >= MAX_I2SV3) { |
64 | s3c_gpio_cfgpin(S3C64XX_GPD(1), S3C64XX_GPD1_I2S0_CDCLK); | 67 | dev_err(dai->dev, "id %d out of range\n", dai->id); |
65 | s3c_gpio_cfgpin(S3C64XX_GPD(2), S3C64XX_GPD2_I2S0_LRCLK); | 68 | return -EINVAL; |
66 | s3c_gpio_cfgpin(S3C64XX_GPD(3), S3C64XX_GPD3_I2S0_DI); | 69 | } |
67 | s3c_gpio_cfgpin(S3C64XX_GPD(4), S3C64XX_GPD4_I2S0_D0); | 70 | |
68 | break; | 71 | i2s = &s3c64xx_i2s[dai->id]; |
69 | case 1: | 72 | snd_soc_dai_set_drvdata(dai, i2s); |
70 | s3c_gpio_cfgpin(S3C64XX_GPE(0), S3C64XX_GPE0_I2S1_CLK); | 73 | |
71 | s3c_gpio_cfgpin(S3C64XX_GPE(1), S3C64XX_GPE1_I2S1_CDCLK); | 74 | i2s->iis_cclk = clk_get(dai->dev, "audio-bus"); |
72 | s3c_gpio_cfgpin(S3C64XX_GPE(2), S3C64XX_GPE2_I2S1_LRCLK); | 75 | if (IS_ERR(i2s->iis_cclk)) { |
73 | s3c_gpio_cfgpin(S3C64XX_GPE(3), S3C64XX_GPE3_I2S1_DI); | 76 | dev_err(dai->dev, "failed to get audio-bus\n"); |
74 | s3c_gpio_cfgpin(S3C64XX_GPE(4), S3C64XX_GPE4_I2S1_D0); | 77 | ret = PTR_ERR(i2s->iis_cclk); |
78 | goto err; | ||
75 | } | 79 | } |
76 | 80 | ||
81 | clk_enable(i2s->iis_cclk); | ||
82 | |||
83 | ret = s3c_i2sv2_probe(dai, i2s, i2s->base); | ||
84 | if (ret) | ||
85 | goto err_clk; | ||
86 | |||
77 | return 0; | 87 | return 0; |
88 | |||
89 | err_clk: | ||
90 | clk_disable(i2s->iis_cclk); | ||
91 | clk_put(i2s->iis_cclk); | ||
92 | err: | ||
93 | kfree(i2s); | ||
94 | return ret; | ||
78 | } | 95 | } |
79 | 96 | ||
97 | static int s3c64xx_i2s_remove(struct snd_soc_dai *dai) | ||
98 | { | ||
99 | struct s3c_i2sv2_info *i2s = snd_soc_dai_get_drvdata(dai); | ||
100 | |||
101 | clk_disable(i2s->iis_cclk); | ||
102 | clk_put(i2s->iis_cclk); | ||
103 | kfree(i2s); | ||
104 | return 0; | ||
105 | } | ||
80 | 106 | ||
81 | static struct snd_soc_dai_ops s3c64xx_i2s_dai_ops; | 107 | static struct snd_soc_dai_ops s3c64xx_i2s_dai_ops; |
82 | 108 | ||
109 | static struct snd_soc_dai_driver s3c64xx_i2s_dai[MAX_I2SV3] = { | ||
110 | { | ||
111 | .name = "s3c64xx-i2s-0", | ||
112 | .probe = s3c64xx_i2s_probe, | ||
113 | .remove = s3c64xx_i2s_remove, | ||
114 | .playback = { | ||
115 | .channels_min = 2, | ||
116 | .channels_max = 2, | ||
117 | .rates = S3C64XX_I2S_RATES, | ||
118 | .formats = S3C64XX_I2S_FMTS,}, | ||
119 | .capture = { | ||
120 | .channels_min = 2, | ||
121 | .channels_max = 2, | ||
122 | .rates = S3C64XX_I2S_RATES, | ||
123 | .formats = S3C64XX_I2S_FMTS,}, | ||
124 | .ops = &s3c64xx_i2s_dai_ops, | ||
125 | .symmetric_rates = 1, | ||
126 | }, { | ||
127 | .name = "s3c64xx-i2s-1", | ||
128 | .probe = s3c64xx_i2s_probe, | ||
129 | .remove = s3c64xx_i2s_remove, | ||
130 | .playback = { | ||
131 | .channels_min = 2, | ||
132 | .channels_max = 2, | ||
133 | .rates = S3C64XX_I2S_RATES, | ||
134 | .formats = S3C64XX_I2S_FMTS,}, | ||
135 | .capture = { | ||
136 | .channels_min = 2, | ||
137 | .channels_max = 2, | ||
138 | .rates = S3C64XX_I2S_RATES, | ||
139 | .formats = S3C64XX_I2S_FMTS,}, | ||
140 | .ops = &s3c64xx_i2s_dai_ops, | ||
141 | .symmetric_rates = 1, | ||
142 | },}; | ||
143 | |||
83 | static __devinit int s3c64xx_iis_dev_probe(struct platform_device *pdev) | 144 | static __devinit int s3c64xx_iis_dev_probe(struct platform_device *pdev) |
84 | { | 145 | { |
146 | struct s3c_audio_pdata *i2s_pdata; | ||
85 | struct s3c_i2sv2_info *i2s; | 147 | struct s3c_i2sv2_info *i2s; |
86 | struct snd_soc_dai *dai; | 148 | struct resource *res; |
87 | int ret; | 149 | int i, ret; |
88 | 150 | ||
89 | if (pdev->id >= MAX_I2SV3) { | 151 | if (pdev->id >= MAX_I2SV3) { |
90 | dev_err(&pdev->dev, "id %d out of range\n", pdev->id); | 152 | dev_err(&pdev->dev, "id %d out of range\n", pdev->id); |
@@ -92,74 +154,63 @@ static __devinit int s3c64xx_iis_dev_probe(struct platform_device *pdev) | |||
92 | } | 154 | } |
93 | 155 | ||
94 | i2s = &s3c64xx_i2s[pdev->id]; | 156 | i2s = &s3c64xx_i2s[pdev->id]; |
95 | dai = &s3c64xx_i2s_dai[pdev->id]; | ||
96 | dai->dev = &pdev->dev; | ||
97 | dai->name = "s3c64xx-i2s"; | ||
98 | dai->id = pdev->id; | ||
99 | dai->symmetric_rates = 1; | ||
100 | dai->playback.channels_min = 2; | ||
101 | dai->playback.channels_max = 2; | ||
102 | dai->playback.rates = S3C64XX_I2S_RATES; | ||
103 | dai->playback.formats = S3C64XX_I2S_FMTS; | ||
104 | dai->capture.channels_min = 2; | ||
105 | dai->capture.channels_max = 2; | ||
106 | dai->capture.rates = S3C64XX_I2S_RATES; | ||
107 | dai->capture.formats = S3C64XX_I2S_FMTS; | ||
108 | dai->probe = s3c64xx_i2s_probe; | ||
109 | dai->ops = &s3c64xx_i2s_dai_ops; | ||
110 | |||
111 | i2s->feature |= S3C_FEATURE_CDCLKCON; | ||
112 | 157 | ||
113 | i2s->dma_capture = &s3c64xx_i2s_pcm_stereo_in[pdev->id]; | 158 | i2s->dma_capture = &s3c64xx_i2s_pcm_stereo_in[pdev->id]; |
114 | i2s->dma_playback = &s3c64xx_i2s_pcm_stereo_out[pdev->id]; | 159 | i2s->dma_playback = &s3c64xx_i2s_pcm_stereo_out[pdev->id]; |
115 | 160 | ||
116 | if (pdev->id == 0) { | 161 | res = platform_get_resource(pdev, IORESOURCE_DMA, 0); |
117 | i2s->dma_capture->channel = DMACH_I2S0_IN; | 162 | if (!res) { |
118 | i2s->dma_capture->dma_addr = S3C64XX_PA_IIS0 + S3C2412_IISRXD; | 163 | dev_err(&pdev->dev, "Unable to get I2S-TX dma resource\n"); |
119 | i2s->dma_playback->channel = DMACH_I2S0_OUT; | 164 | return -ENXIO; |
120 | i2s->dma_playback->dma_addr = S3C64XX_PA_IIS0 + S3C2412_IISTXD; | 165 | } |
121 | } else { | 166 | i2s->dma_playback->channel = res->start; |
122 | i2s->dma_capture->channel = DMACH_I2S1_IN; | 167 | |
123 | i2s->dma_capture->dma_addr = S3C64XX_PA_IIS1 + S3C2412_IISRXD; | 168 | res = platform_get_resource(pdev, IORESOURCE_DMA, 1); |
124 | i2s->dma_playback->channel = DMACH_I2S1_OUT; | 169 | if (!res) { |
125 | i2s->dma_playback->dma_addr = S3C64XX_PA_IIS1 + S3C2412_IISTXD; | 170 | dev_err(&pdev->dev, "Unable to get I2S-RX dma resource\n"); |
171 | return -ENXIO; | ||
172 | } | ||
173 | i2s->dma_capture->channel = res->start; | ||
174 | |||
175 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
176 | if (!res) { | ||
177 | dev_err(&pdev->dev, "Unable to get I2S SFR address\n"); | ||
178 | return -ENXIO; | ||
126 | } | 179 | } |
127 | 180 | ||
181 | if (!request_mem_region(res->start, resource_size(res), | ||
182 | "s3c64xx-i2s")) { | ||
183 | dev_err(&pdev->dev, "Unable to request SFR region\n"); | ||
184 | return -EBUSY; | ||
185 | } | ||
186 | i2s->base = res->start; | ||
187 | |||
188 | i2s_pdata = pdev->dev.platform_data; | ||
189 | if (i2s_pdata && i2s_pdata->cfg_gpio && i2s_pdata->cfg_gpio(pdev)) { | ||
190 | dev_err(&pdev->dev, "Unable to configure gpio\n"); | ||
191 | return -EINVAL; | ||
192 | } | ||
193 | i2s->dma_capture->dma_addr = res->start + S3C2412_IISRXD; | ||
194 | i2s->dma_playback->dma_addr = res->start + S3C2412_IISTXD; | ||
195 | |||
128 | i2s->dma_capture->client = &s3c64xx_dma_client_in; | 196 | i2s->dma_capture->client = &s3c64xx_dma_client_in; |
129 | i2s->dma_capture->dma_size = 4; | 197 | i2s->dma_capture->dma_size = 4; |
130 | i2s->dma_playback->client = &s3c64xx_dma_client_out; | 198 | i2s->dma_playback->client = &s3c64xx_dma_client_out; |
131 | i2s->dma_playback->dma_size = 4; | 199 | i2s->dma_playback->dma_size = 4; |
132 | 200 | ||
133 | i2s->iis_cclk = clk_get(&pdev->dev, "audio-bus"); | 201 | for (i = 0; i < ARRAY_SIZE(s3c64xx_i2s_dai); i++) { |
134 | if (IS_ERR(i2s->iis_cclk)) { | 202 | ret = s3c_i2sv2_register_dai(&pdev->dev, i, |
135 | dev_err(&pdev->dev, "failed to get audio-bus\n"); | 203 | &s3c64xx_i2s_dai[i]); |
136 | ret = PTR_ERR(i2s->iis_cclk); | 204 | if (ret != 0) |
137 | goto err; | 205 | return ret; |
138 | } | 206 | } |
139 | 207 | ||
140 | clk_enable(i2s->iis_cclk); | ||
141 | |||
142 | ret = s3c_i2sv2_probe(pdev, dai, i2s, 0); | ||
143 | if (ret) | ||
144 | goto err_clk; | ||
145 | |||
146 | ret = s3c_i2sv2_register_dai(dai); | ||
147 | if (ret != 0) | ||
148 | goto err_i2sv2; | ||
149 | |||
150 | return 0; | 208 | return 0; |
151 | |||
152 | err_i2sv2: | ||
153 | /* Not implemented for I2Sv2 core yet */ | ||
154 | err_clk: | ||
155 | clk_put(i2s->iis_cclk); | ||
156 | err: | ||
157 | return ret; | ||
158 | } | 209 | } |
159 | 210 | ||
160 | static __devexit int s3c64xx_iis_dev_remove(struct platform_device *pdev) | 211 | static __devexit int s3c64xx_iis_dev_remove(struct platform_device *pdev) |
161 | { | 212 | { |
162 | dev_err(&pdev->dev, "Device removal not yet supported\n"); | 213 | snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(s3c64xx_i2s_dai)); |
163 | return 0; | 214 | return 0; |
164 | } | 215 | } |
165 | 216 | ||
@@ -188,3 +239,4 @@ module_exit(s3c64xx_i2s_exit); | |||
188 | MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); | 239 | MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); |
189 | MODULE_DESCRIPTION("S3C64XX I2S SoC Interface"); | 240 | MODULE_DESCRIPTION("S3C64XX I2S SoC Interface"); |
190 | MODULE_LICENSE("GPL"); | 241 | MODULE_LICENSE("GPL"); |
242 | MODULE_ALIAS("platform:s3c64xx-iis"); | ||
diff --git a/sound/soc/s3c24xx/s3c64xx-i2s.h b/sound/soc/s3c24xx/s3c64xx-i2s.h index 7a40f43d1d51..de4075d26f0c 100644 --- a/sound/soc/s3c24xx/s3c64xx-i2s.h +++ b/sound/soc/s3c24xx/s3c64xx-i2s.h | |||
@@ -36,7 +36,6 @@ struct clk; | |||
36 | (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\ | 36 | (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\ |
37 | SNDRV_PCM_FMTBIT_S24_LE) | 37 | SNDRV_PCM_FMTBIT_S24_LE) |
38 | 38 | ||
39 | extern struct snd_soc_dai s3c64xx_i2s_dai[]; | 39 | struct clk *s3c64xx_i2s_get_clock(struct snd_soc_dai *dai); |
40 | extern struct snd_soc_dai s3c64xx_i2s_v4_dai; | ||
41 | 40 | ||
42 | #endif /* __SND_SOC_S3C24XX_S3C64XX_I2S_H */ | 41 | #endif /* __SND_SOC_S3C24XX_S3C64XX_I2S_H */ |
diff --git a/sound/soc/s3c24xx/smartq_wm8987.c b/sound/soc/s3c24xx/smartq_wm8987.c index b480348140b0..dd20ca7f4681 100644 --- a/sound/soc/s3c24xx/smartq_wm8987.c +++ b/sound/soc/s3c24xx/smartq_wm8987.c | |||
@@ -211,8 +211,10 @@ static struct snd_soc_dai_link smartq_dai[] = { | |||
211 | { | 211 | { |
212 | .name = "wm8987", | 212 | .name = "wm8987", |
213 | .stream_name = "SmartQ Hi-Fi", | 213 | .stream_name = "SmartQ Hi-Fi", |
214 | .cpu_dai = &s3c64xx_i2s_dai[0], | 214 | .cpu_dai_name = "s3c64xx-i2s.0", |
215 | .codec_dai = &wm8750_dai, | 215 | .codec_dai_name = "wm8750-hifi", |
216 | .platform_name = "s3c24xx-pcm-audio", | ||
217 | .codec_name = "wm8750-codec.0-0x1a", | ||
216 | .init = smartq_wm8987_init, | 218 | .init = smartq_wm8987_init, |
217 | .ops = &smartq_hifi_ops, | 219 | .ops = &smartq_hifi_ops, |
218 | }, | 220 | }, |
@@ -220,16 +222,10 @@ static struct snd_soc_dai_link smartq_dai[] = { | |||
220 | 222 | ||
221 | static struct snd_soc_card snd_soc_smartq = { | 223 | static struct snd_soc_card snd_soc_smartq = { |
222 | .name = "SmartQ", | 224 | .name = "SmartQ", |
223 | .platform = &s3c24xx_soc_platform, | ||
224 | .dai_link = smartq_dai, | 225 | .dai_link = smartq_dai, |
225 | .num_links = ARRAY_SIZE(smartq_dai), | 226 | .num_links = ARRAY_SIZE(smartq_dai), |
226 | }; | 227 | }; |
227 | 228 | ||
228 | static struct snd_soc_device smartq_snd_devdata = { | ||
229 | .card = &snd_soc_smartq, | ||
230 | .codec_dev = &soc_codec_dev_wm8750, | ||
231 | }; | ||
232 | |||
233 | static struct platform_device *smartq_snd_device; | 229 | static struct platform_device *smartq_snd_device; |
234 | 230 | ||
235 | static int __init smartq_init(void) | 231 | static int __init smartq_init(void) |
@@ -245,8 +241,7 @@ static int __init smartq_init(void) | |||
245 | if (!smartq_snd_device) | 241 | if (!smartq_snd_device) |
246 | return -ENOMEM; | 242 | return -ENOMEM; |
247 | 243 | ||
248 | platform_set_drvdata(smartq_snd_device, &smartq_snd_devdata); | 244 | platform_set_drvdata(smartq_snd_device, &snd_soc_smartq); |
249 | smartq_snd_devdata.dev = &smartq_snd_device->dev; | ||
250 | 245 | ||
251 | ret = platform_device_add(smartq_snd_device); | 246 | ret = platform_device_add(smartq_snd_device); |
252 | if (ret) { | 247 | if (ret) { |
diff --git a/sound/soc/s3c24xx/smdk2443_wm9710.c b/sound/soc/s3c24xx/smdk2443_wm9710.c index 362258835e8d..4613288c2772 100644 --- a/sound/soc/s3c24xx/smdk2443_wm9710.c +++ b/sound/soc/s3c24xx/smdk2443_wm9710.c | |||
@@ -19,7 +19,6 @@ | |||
19 | #include <sound/soc.h> | 19 | #include <sound/soc.h> |
20 | #include <sound/soc-dapm.h> | 20 | #include <sound/soc-dapm.h> |
21 | 21 | ||
22 | #include "../codecs/ac97.h" | ||
23 | #include "s3c-dma.h" | 22 | #include "s3c-dma.h" |
24 | #include "s3c-ac97.h" | 23 | #include "s3c-ac97.h" |
25 | 24 | ||
@@ -29,23 +28,19 @@ static struct snd_soc_dai_link smdk2443_dai[] = { | |||
29 | { | 28 | { |
30 | .name = "AC97", | 29 | .name = "AC97", |
31 | .stream_name = "AC97 HiFi", | 30 | .stream_name = "AC97 HiFi", |
32 | .cpu_dai = &s3c_ac97_dai[S3C_AC97_DAI_PCM], | 31 | .cpu_dai_name = "s3c-ac97", |
33 | .codec_dai = &ac97_dai, | 32 | .codec_dai_name = "ac97-hifi", |
33 | .codec_name = "ac97-codec", | ||
34 | .platform_name = "s3c24xx-pcm-audio", | ||
34 | }, | 35 | }, |
35 | }; | 36 | }; |
36 | 37 | ||
37 | static struct snd_soc_card smdk2443 = { | 38 | static struct snd_soc_card smdk2443 = { |
38 | .name = "SMDK2443", | 39 | .name = "SMDK2443", |
39 | .platform = &s3c24xx_soc_platform, | ||
40 | .dai_link = smdk2443_dai, | 40 | .dai_link = smdk2443_dai, |
41 | .num_links = ARRAY_SIZE(smdk2443_dai), | 41 | .num_links = ARRAY_SIZE(smdk2443_dai), |
42 | }; | 42 | }; |
43 | 43 | ||
44 | static struct snd_soc_device smdk2443_snd_ac97_devdata = { | ||
45 | .card = &smdk2443, | ||
46 | .codec_dev = &soc_codec_dev_ac97, | ||
47 | }; | ||
48 | |||
49 | static struct platform_device *smdk2443_snd_ac97_device; | 44 | static struct platform_device *smdk2443_snd_ac97_device; |
50 | 45 | ||
51 | static int __init smdk2443_init(void) | 46 | static int __init smdk2443_init(void) |
@@ -56,9 +51,7 @@ static int __init smdk2443_init(void) | |||
56 | if (!smdk2443_snd_ac97_device) | 51 | if (!smdk2443_snd_ac97_device) |
57 | return -ENOMEM; | 52 | return -ENOMEM; |
58 | 53 | ||
59 | platform_set_drvdata(smdk2443_snd_ac97_device, | 54 | platform_set_drvdata(smdk2443_snd_ac97_device, &smdk2443); |
60 | &smdk2443_snd_ac97_devdata); | ||
61 | smdk2443_snd_ac97_devdata.dev = &smdk2443_snd_ac97_device->dev; | ||
62 | ret = platform_device_add(smdk2443_snd_ac97_device); | 55 | ret = platform_device_add(smdk2443_snd_ac97_device); |
63 | 56 | ||
64 | if (ret) | 57 | if (ret) |
diff --git a/sound/soc/s3c24xx/smdk64xx_wm8580.c b/sound/soc/s3c24xx/smdk64xx_wm8580.c index 07e8e51d10d6..052e499b68d1 100644 --- a/sound/soc/s3c24xx/smdk64xx_wm8580.c +++ b/sound/soc/s3c24xx/smdk64xx_wm8580.c | |||
@@ -22,6 +22,12 @@ | |||
22 | #include "s3c-dma.h" | 22 | #include "s3c-dma.h" |
23 | #include "s3c64xx-i2s.h" | 23 | #include "s3c64xx-i2s.h" |
24 | 24 | ||
25 | /* | ||
26 | * Default CFG switch settings to use this driver: | ||
27 | * | ||
28 | * SMDK6410: Set CFG1 1-3 Off, CFG2 1-4 On | ||
29 | */ | ||
30 | |||
25 | /* SMDK64XX has a 12MHZ crystal attached to WM8580 */ | 31 | /* SMDK64XX has a 12MHZ crystal attached to WM8580 */ |
26 | #define SMDK64XX_WM8580_FREQ 12000000 | 32 | #define SMDK64XX_WM8580_FREQ 12000000 |
27 | 33 | ||
@@ -29,8 +35,8 @@ static int smdk64xx_hw_params(struct snd_pcm_substream *substream, | |||
29 | struct snd_pcm_hw_params *params) | 35 | struct snd_pcm_hw_params *params) |
30 | { | 36 | { |
31 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 37 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
32 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 38 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
33 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 39 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
34 | unsigned int pll_out; | 40 | unsigned int pll_out; |
35 | int bfs, rfs, ret; | 41 | int bfs, rfs, ret; |
36 | 42 | ||
@@ -107,14 +113,13 @@ static int smdk64xx_hw_params(struct snd_pcm_substream *substream, | |||
107 | if (ret < 0) | 113 | if (ret < 0) |
108 | return ret; | 114 | return ret; |
109 | 115 | ||
110 | /* Explicitly set WM8580-DAC to source from MCLK */ | 116 | ret = snd_soc_dai_set_pll(codec_dai, WM8580_PLLA, 0, |
111 | ret = snd_soc_dai_set_clkdiv(codec_dai, WM8580_DAC_CLKSEL, | 117 | SMDK64XX_WM8580_FREQ, pll_out); |
112 | WM8580_CLKSRC_MCLK); | ||
113 | if (ret < 0) | 118 | if (ret < 0) |
114 | return ret; | 119 | return ret; |
115 | 120 | ||
116 | ret = snd_soc_dai_set_pll(codec_dai, WM8580_PLLA, 0, | 121 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8580_CLKSRC_PLLA, |
117 | SMDK64XX_WM8580_FREQ, pll_out); | 122 | pll_out, SND_SOC_CLOCK_IN); |
118 | if (ret < 0) | 123 | if (ret < 0) |
119 | return ret; | 124 | return ret; |
120 | 125 | ||
@@ -138,9 +143,9 @@ static struct snd_soc_ops smdk64xx_ops = { | |||
138 | 143 | ||
139 | /* SMDK64xx Playback widgets */ | 144 | /* SMDK64xx Playback widgets */ |
140 | static const struct snd_soc_dapm_widget wm8580_dapm_widgets_pbk[] = { | 145 | static const struct snd_soc_dapm_widget wm8580_dapm_widgets_pbk[] = { |
141 | SND_SOC_DAPM_HP("Front-L/R", NULL), | 146 | SND_SOC_DAPM_HP("Front", NULL), |
142 | SND_SOC_DAPM_HP("Center/Sub", NULL), | 147 | SND_SOC_DAPM_HP("Center+Sub", NULL), |
143 | SND_SOC_DAPM_HP("Rear-L/R", NULL), | 148 | SND_SOC_DAPM_HP("Rear", NULL), |
144 | }; | 149 | }; |
145 | 150 | ||
146 | /* SMDK64xx Capture widgets */ | 151 | /* SMDK64xx Capture widgets */ |
@@ -162,20 +167,22 @@ static const struct snd_soc_dapm_route audio_map_tx[] = { | |||
162 | /* SMDK-PAIFRX connections */ | 167 | /* SMDK-PAIFRX connections */ |
163 | static const struct snd_soc_dapm_route audio_map_rx[] = { | 168 | static const struct snd_soc_dapm_route audio_map_rx[] = { |
164 | /* Front Left/Right are fed VOUT1L/R */ | 169 | /* Front Left/Right are fed VOUT1L/R */ |
165 | {"Front-L/R", NULL, "VOUT1L"}, | 170 | {"Front", NULL, "VOUT1L"}, |
166 | {"Front-L/R", NULL, "VOUT1R"}, | 171 | {"Front", NULL, "VOUT1R"}, |
167 | 172 | ||
168 | /* Center/Sub are fed VOUT2L/R */ | 173 | /* Center/Sub are fed VOUT2L/R */ |
169 | {"Center/Sub", NULL, "VOUT2L"}, | 174 | {"Center+Sub", NULL, "VOUT2L"}, |
170 | {"Center/Sub", NULL, "VOUT2R"}, | 175 | {"Center+Sub", NULL, "VOUT2R"}, |
171 | 176 | ||
172 | /* Rear Left/Right are fed VOUT3L/R */ | 177 | /* Rear Left/Right are fed VOUT3L/R */ |
173 | {"Rear-L/R", NULL, "VOUT3L"}, | 178 | {"Rear", NULL, "VOUT3L"}, |
174 | {"Rear-L/R", NULL, "VOUT3R"}, | 179 | {"Rear", NULL, "VOUT3R"}, |
175 | }; | 180 | }; |
176 | 181 | ||
177 | static int smdk64xx_wm8580_init_paiftx(struct snd_soc_codec *codec) | 182 | static int smdk64xx_wm8580_init_paiftx(struct snd_soc_pcm_runtime *rtd) |
178 | { | 183 | { |
184 | struct snd_soc_codec *codec = rtd->codec; | ||
185 | |||
179 | /* Add smdk64xx specific Capture widgets */ | 186 | /* Add smdk64xx specific Capture widgets */ |
180 | snd_soc_dapm_new_controls(codec, wm8580_dapm_widgets_cpt, | 187 | snd_soc_dapm_new_controls(codec, wm8580_dapm_widgets_cpt, |
181 | ARRAY_SIZE(wm8580_dapm_widgets_cpt)); | 188 | ARRAY_SIZE(wm8580_dapm_widgets_cpt)); |
@@ -194,8 +201,10 @@ static int smdk64xx_wm8580_init_paiftx(struct snd_soc_codec *codec) | |||
194 | return 0; | 201 | return 0; |
195 | } | 202 | } |
196 | 203 | ||
197 | static int smdk64xx_wm8580_init_paifrx(struct snd_soc_codec *codec) | 204 | static int smdk64xx_wm8580_init_paifrx(struct snd_soc_pcm_runtime *rtd) |
198 | { | 205 | { |
206 | struct snd_soc_codec *codec = rtd->codec; | ||
207 | |||
199 | /* Add smdk64xx specific Playback widgets */ | 208 | /* Add smdk64xx specific Playback widgets */ |
200 | snd_soc_dapm_new_controls(codec, wm8580_dapm_widgets_pbk, | 209 | snd_soc_dapm_new_controls(codec, wm8580_dapm_widgets_pbk, |
201 | ARRAY_SIZE(wm8580_dapm_widgets_pbk)); | 210 | ARRAY_SIZE(wm8580_dapm_widgets_pbk)); |
@@ -213,33 +222,31 @@ static struct snd_soc_dai_link smdk64xx_dai[] = { | |||
213 | { /* Primary Playback i/f */ | 222 | { /* Primary Playback i/f */ |
214 | .name = "WM8580 PAIF RX", | 223 | .name = "WM8580 PAIF RX", |
215 | .stream_name = "Playback", | 224 | .stream_name = "Playback", |
216 | .cpu_dai = &s3c64xx_i2s_v4_dai, | 225 | .cpu_dai_name = "s3c64xx-iis-v4", |
217 | .codec_dai = &wm8580_dai[WM8580_DAI_PAIFRX], | 226 | .codec_dai_name = "wm8580-hifi-playback", |
227 | .platform_name = "s3c24xx-pcm-audio", | ||
228 | .codec_name = "wm8580-codec.0-001b", | ||
218 | .init = smdk64xx_wm8580_init_paifrx, | 229 | .init = smdk64xx_wm8580_init_paifrx, |
219 | .ops = &smdk64xx_ops, | 230 | .ops = &smdk64xx_ops, |
220 | }, | 231 | }, |
221 | { /* Primary Capture i/f */ | 232 | { /* Primary Capture i/f */ |
222 | .name = "WM8580 PAIF TX", | 233 | .name = "WM8580 PAIF TX", |
223 | .stream_name = "Capture", | 234 | .stream_name = "Capture", |
224 | .cpu_dai = &s3c64xx_i2s_v4_dai, | 235 | .cpu_dai_name = "s3c64xx-iis-v4", |
225 | .codec_dai = &wm8580_dai[WM8580_DAI_PAIFTX], | 236 | .codec_dai_name = "wm8580-hifi-capture", |
237 | .platform_name = "s3c24xx-pcm-audio", | ||
238 | .codec_name = "wm8580-codec.0-001b", | ||
226 | .init = smdk64xx_wm8580_init_paiftx, | 239 | .init = smdk64xx_wm8580_init_paiftx, |
227 | .ops = &smdk64xx_ops, | 240 | .ops = &smdk64xx_ops, |
228 | }, | 241 | }, |
229 | }; | 242 | }; |
230 | 243 | ||
231 | static struct snd_soc_card smdk64xx = { | 244 | static struct snd_soc_card smdk64xx = { |
232 | .name = "smdk64xx", | 245 | .name = "SMDK64xx 5.1", |
233 | .platform = &s3c24xx_soc_platform, | ||
234 | .dai_link = smdk64xx_dai, | 246 | .dai_link = smdk64xx_dai, |
235 | .num_links = ARRAY_SIZE(smdk64xx_dai), | 247 | .num_links = ARRAY_SIZE(smdk64xx_dai), |
236 | }; | 248 | }; |
237 | 249 | ||
238 | static struct snd_soc_device smdk64xx_snd_devdata = { | ||
239 | .card = &smdk64xx, | ||
240 | .codec_dev = &soc_codec_dev_wm8580, | ||
241 | }; | ||
242 | |||
243 | static struct platform_device *smdk64xx_snd_device; | 250 | static struct platform_device *smdk64xx_snd_device; |
244 | 251 | ||
245 | static int __init smdk64xx_audio_init(void) | 252 | static int __init smdk64xx_audio_init(void) |
@@ -250,8 +257,7 @@ static int __init smdk64xx_audio_init(void) | |||
250 | if (!smdk64xx_snd_device) | 257 | if (!smdk64xx_snd_device) |
251 | return -ENOMEM; | 258 | return -ENOMEM; |
252 | 259 | ||
253 | platform_set_drvdata(smdk64xx_snd_device, &smdk64xx_snd_devdata); | 260 | platform_set_drvdata(smdk64xx_snd_device, &smdk64xx); |
254 | smdk64xx_snd_devdata.dev = &smdk64xx_snd_device->dev; | ||
255 | ret = platform_device_add(smdk64xx_snd_device); | 261 | ret = platform_device_add(smdk64xx_snd_device); |
256 | 262 | ||
257 | if (ret) | 263 | if (ret) |
diff --git a/sound/soc/s3c24xx/smdk_spdif.c b/sound/soc/s3c24xx/smdk_spdif.c new file mode 100644 index 000000000000..f31d22ad7c88 --- /dev/null +++ b/sound/soc/s3c24xx/smdk_spdif.c | |||
@@ -0,0 +1,223 @@ | |||
1 | /* | ||
2 | * smdk_spdif.c -- S/PDIF audio for SMDK | ||
3 | * | ||
4 | * Copyright 2010 Samsung Electronics Co. Ltd. | ||
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 as | ||
8 | * published by the Free Software Foundation; either version 2 of the | ||
9 | * License, or (at your option) any later version. | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/device.h> | ||
15 | #include <linux/clk.h> | ||
16 | |||
17 | #include <plat/devs.h> | ||
18 | |||
19 | #include <sound/soc.h> | ||
20 | |||
21 | #include "s3c-dma.h" | ||
22 | #include "spdif.h" | ||
23 | |||
24 | /* Audio clock settings are belonged to board specific part. Every | ||
25 | * board can set audio source clock setting which is matched with H/W | ||
26 | * like this function-'set_audio_clock_heirachy'. | ||
27 | */ | ||
28 | static int set_audio_clock_heirachy(struct platform_device *pdev) | ||
29 | { | ||
30 | struct clk *fout_epll, *mout_epll, *sclk_audio0, *sclk_spdif; | ||
31 | int ret; | ||
32 | |||
33 | fout_epll = clk_get(NULL, "fout_epll"); | ||
34 | if (IS_ERR(fout_epll)) { | ||
35 | printk(KERN_WARNING "%s: Cannot find fout_epll.\n", | ||
36 | __func__); | ||
37 | return -EINVAL; | ||
38 | } | ||
39 | |||
40 | mout_epll = clk_get(NULL, "mout_epll"); | ||
41 | if (IS_ERR(fout_epll)) { | ||
42 | printk(KERN_WARNING "%s: Cannot find mout_epll.\n", | ||
43 | __func__); | ||
44 | ret = -EINVAL; | ||
45 | goto out1; | ||
46 | } | ||
47 | |||
48 | sclk_audio0 = clk_get(&pdev->dev, "sclk_audio"); | ||
49 | if (IS_ERR(sclk_audio0)) { | ||
50 | printk(KERN_WARNING "%s: Cannot find sclk_audio.\n", | ||
51 | __func__); | ||
52 | ret = -EINVAL; | ||
53 | goto out2; | ||
54 | } | ||
55 | |||
56 | sclk_spdif = clk_get(NULL, "sclk_spdif"); | ||
57 | if (IS_ERR(fout_epll)) { | ||
58 | printk(KERN_WARNING "%s: Cannot find sclk_spdif.\n", | ||
59 | __func__); | ||
60 | ret = -EINVAL; | ||
61 | goto out3; | ||
62 | } | ||
63 | |||
64 | /* Set audio clock heirachy for S/PDIF */ | ||
65 | clk_set_parent(mout_epll, fout_epll); | ||
66 | clk_set_parent(sclk_audio0, mout_epll); | ||
67 | clk_set_parent(sclk_spdif, sclk_audio0); | ||
68 | |||
69 | clk_put(sclk_spdif); | ||
70 | out3: | ||
71 | clk_put(sclk_audio0); | ||
72 | out2: | ||
73 | clk_put(mout_epll); | ||
74 | out1: | ||
75 | clk_put(fout_epll); | ||
76 | |||
77 | return ret; | ||
78 | } | ||
79 | |||
80 | /* We should haved to set clock directly on this part because of clock | ||
81 | * scheme of Samsudng SoCs did not support to set rates from abstrct | ||
82 | * clock of it's heirachy. | ||
83 | */ | ||
84 | static int set_audio_clock_rate(unsigned long epll_rate, | ||
85 | unsigned long audio_rate) | ||
86 | { | ||
87 | struct clk *fout_epll, *sclk_spdif; | ||
88 | |||
89 | fout_epll = clk_get(NULL, "fout_epll"); | ||
90 | if (IS_ERR(fout_epll)) { | ||
91 | printk(KERN_ERR "%s: failed to get fout_epll\n", __func__); | ||
92 | return -ENOENT; | ||
93 | } | ||
94 | |||
95 | clk_set_rate(fout_epll, epll_rate); | ||
96 | clk_put(fout_epll); | ||
97 | |||
98 | sclk_spdif = clk_get(NULL, "sclk_spdif"); | ||
99 | if (IS_ERR(sclk_spdif)) { | ||
100 | printk(KERN_ERR "%s: failed to get sclk_spdif\n", __func__); | ||
101 | return -ENOENT; | ||
102 | } | ||
103 | |||
104 | clk_set_rate(sclk_spdif, audio_rate); | ||
105 | clk_put(sclk_spdif); | ||
106 | |||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | static int smdk_hw_params(struct snd_pcm_substream *substream, | ||
111 | struct snd_pcm_hw_params *params) | ||
112 | { | ||
113 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
114 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
115 | unsigned long pll_out, rclk_rate; | ||
116 | int ret, ratio; | ||
117 | |||
118 | switch (params_rate(params)) { | ||
119 | case 44100: | ||
120 | pll_out = 45158400; | ||
121 | break; | ||
122 | case 32000: | ||
123 | case 48000: | ||
124 | case 96000: | ||
125 | pll_out = 49152000; | ||
126 | break; | ||
127 | default: | ||
128 | return -EINVAL; | ||
129 | } | ||
130 | |||
131 | /* Setting ratio to 512fs helps to use S/PDIF with HDMI without | ||
132 | * modify S/PDIF ASoC machine driver. | ||
133 | */ | ||
134 | ratio = 512; | ||
135 | rclk_rate = params_rate(params) * ratio; | ||
136 | |||
137 | /* Set audio source clock rates */ | ||
138 | ret = set_audio_clock_rate(pll_out, rclk_rate); | ||
139 | if (ret < 0) | ||
140 | return ret; | ||
141 | |||
142 | /* Set S/PDIF uses internal source clock */ | ||
143 | ret = snd_soc_dai_set_sysclk(cpu_dai, SND_SOC_SPDIF_INT_MCLK, | ||
144 | rclk_rate, SND_SOC_CLOCK_IN); | ||
145 | if (ret < 0) | ||
146 | return ret; | ||
147 | |||
148 | return ret; | ||
149 | } | ||
150 | |||
151 | static struct snd_soc_ops smdk_spdif_ops = { | ||
152 | .hw_params = smdk_hw_params, | ||
153 | }; | ||
154 | |||
155 | static struct snd_soc_card smdk; | ||
156 | |||
157 | static struct snd_soc_dai_link smdk_dai = { | ||
158 | .name = "S/PDIF", | ||
159 | .stream_name = "S/PDIF PCM Playback", | ||
160 | .platform_name = "s3c24xx-pcm-audio", | ||
161 | .cpu_dai_name = "samsung-spdif", | ||
162 | .codec_dai_name = "dit-hifi", | ||
163 | .codec_name = "spdif-dit", | ||
164 | .ops = &smdk_spdif_ops, | ||
165 | }; | ||
166 | |||
167 | static struct snd_soc_card smdk = { | ||
168 | .name = "SMDK-S/PDIF", | ||
169 | .dai_link = &smdk_dai, | ||
170 | .num_links = 1, | ||
171 | }; | ||
172 | |||
173 | static struct platform_device *smdk_snd_spdif_dit_device; | ||
174 | static struct platform_device *smdk_snd_spdif_device; | ||
175 | |||
176 | static int __init smdk_init(void) | ||
177 | { | ||
178 | int ret; | ||
179 | |||
180 | smdk_snd_spdif_dit_device = platform_device_alloc("spdif-dit", -1); | ||
181 | if (!smdk_snd_spdif_dit_device) | ||
182 | return -ENOMEM; | ||
183 | |||
184 | ret = platform_device_add(smdk_snd_spdif_dit_device); | ||
185 | if (ret) | ||
186 | goto err2; | ||
187 | |||
188 | smdk_snd_spdif_device = platform_device_alloc("soc-audio", -1); | ||
189 | if (!smdk_snd_spdif_device) { | ||
190 | ret = -ENOMEM; | ||
191 | goto err2; | ||
192 | } | ||
193 | |||
194 | platform_set_drvdata(smdk_snd_spdif_device, &smdk); | ||
195 | |||
196 | ret = platform_device_add(smdk_snd_spdif_device); | ||
197 | if (ret) | ||
198 | goto err1; | ||
199 | |||
200 | /* Set audio clock heirachy manually */ | ||
201 | ret = set_audio_clock_heirachy(smdk_snd_spdif_device); | ||
202 | if (ret) | ||
203 | goto err1; | ||
204 | |||
205 | return 0; | ||
206 | err1: | ||
207 | platform_device_put(smdk_snd_spdif_device); | ||
208 | err2: | ||
209 | platform_device_put(smdk_snd_spdif_dit_device); | ||
210 | return ret; | ||
211 | } | ||
212 | |||
213 | static void __exit smdk_exit(void) | ||
214 | { | ||
215 | platform_device_unregister(smdk_snd_spdif_device); | ||
216 | } | ||
217 | |||
218 | module_init(smdk_init); | ||
219 | module_exit(smdk_exit); | ||
220 | |||
221 | MODULE_AUTHOR("Seungwhan Youn, <sw.youn@samsung.com>"); | ||
222 | MODULE_DESCRIPTION("ALSA SoC SMDK+S/PDIF"); | ||
223 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/s3c24xx/smdk_wm9713.c b/sound/soc/s3c24xx/smdk_wm9713.c index 5527b9e88c98..33ba8fdbcf07 100644 --- a/sound/soc/s3c24xx/smdk_wm9713.c +++ b/sound/soc/s3c24xx/smdk_wm9713.c | |||
@@ -15,7 +15,6 @@ | |||
15 | #include <linux/device.h> | 15 | #include <linux/device.h> |
16 | #include <sound/soc.h> | 16 | #include <sound/soc.h> |
17 | 17 | ||
18 | #include "../codecs/wm9713.h" | ||
19 | #include "s3c-dma.h" | 18 | #include "s3c-dma.h" |
20 | #include "s3c-ac97.h" | 19 | #include "s3c-ac97.h" |
21 | 20 | ||
@@ -46,46 +45,57 @@ static struct snd_soc_card smdk; | |||
46 | static struct snd_soc_dai_link smdk_dai = { | 45 | static struct snd_soc_dai_link smdk_dai = { |
47 | .name = "AC97", | 46 | .name = "AC97", |
48 | .stream_name = "AC97 PCM", | 47 | .stream_name = "AC97 PCM", |
49 | .cpu_dai = &s3c_ac97_dai[S3C_AC97_DAI_PCM], | 48 | .platform_name = "s3c24xx-pcm-audio", |
50 | .codec_dai = &wm9713_dai[WM9713_DAI_AC97_HIFI], | 49 | .cpu_dai_name = "s3c-ac97", |
50 | .codec_dai_name = "wm9713-hifi", | ||
51 | .codec_name = "wm9713-codec", | ||
51 | }; | 52 | }; |
52 | 53 | ||
53 | static struct snd_soc_card smdk = { | 54 | static struct snd_soc_card smdk = { |
54 | .name = "SMDK", | 55 | .name = "SMDK WM9713", |
55 | .platform = &s3c24xx_soc_platform, | ||
56 | .dai_link = &smdk_dai, | 56 | .dai_link = &smdk_dai, |
57 | .num_links = 1, | 57 | .num_links = 1, |
58 | }; | 58 | }; |
59 | 59 | ||
60 | static struct snd_soc_device smdk_snd_ac97_devdata = { | 60 | static struct platform_device *smdk_snd_wm9713_device; |
61 | .card = &smdk, | ||
62 | .codec_dev = &soc_codec_dev_wm9713, | ||
63 | }; | ||
64 | |||
65 | static struct platform_device *smdk_snd_ac97_device; | 61 | static struct platform_device *smdk_snd_ac97_device; |
66 | 62 | ||
67 | static int __init smdk_init(void) | 63 | static int __init smdk_init(void) |
68 | { | 64 | { |
69 | int ret; | 65 | int ret; |
70 | 66 | ||
71 | smdk_snd_ac97_device = platform_device_alloc("soc-audio", -1); | 67 | smdk_snd_wm9713_device = platform_device_alloc("wm9713-codec", -1); |
72 | if (!smdk_snd_ac97_device) | 68 | if (!smdk_snd_wm9713_device) |
73 | return -ENOMEM; | 69 | return -ENOMEM; |
74 | 70 | ||
75 | platform_set_drvdata(smdk_snd_ac97_device, | 71 | ret = platform_device_add(smdk_snd_wm9713_device); |
76 | &smdk_snd_ac97_devdata); | 72 | if (ret) |
77 | smdk_snd_ac97_devdata.dev = &smdk_snd_ac97_device->dev; | 73 | goto err; |
74 | |||
75 | smdk_snd_ac97_device = platform_device_alloc("soc-audio", -1); | ||
76 | if (!smdk_snd_ac97_device) { | ||
77 | ret = -ENOMEM; | ||
78 | goto err; | ||
79 | } | ||
80 | |||
81 | platform_set_drvdata(smdk_snd_ac97_device, &smdk); | ||
78 | 82 | ||
79 | ret = platform_device_add(smdk_snd_ac97_device); | 83 | ret = platform_device_add(smdk_snd_ac97_device); |
80 | if (ret) | 84 | if (ret) { |
81 | platform_device_put(smdk_snd_ac97_device); | 85 | platform_device_put(smdk_snd_ac97_device); |
86 | goto err; | ||
87 | } | ||
82 | 88 | ||
89 | return 0; | ||
90 | err: | ||
91 | platform_device_put(smdk_snd_wm9713_device); | ||
83 | return ret; | 92 | return ret; |
84 | } | 93 | } |
85 | 94 | ||
86 | static void __exit smdk_exit(void) | 95 | static void __exit smdk_exit(void) |
87 | { | 96 | { |
88 | platform_device_unregister(smdk_snd_ac97_device); | 97 | platform_device_unregister(smdk_snd_ac97_device); |
98 | platform_device_unregister(smdk_snd_wm9713_device); | ||
89 | } | 99 | } |
90 | 100 | ||
91 | module_init(smdk_init); | 101 | module_init(smdk_init); |
diff --git a/sound/soc/s3c24xx/spdif.c b/sound/soc/s3c24xx/spdif.c new file mode 100644 index 000000000000..ce554e9cabcc --- /dev/null +++ b/sound/soc/s3c24xx/spdif.c | |||
@@ -0,0 +1,501 @@ | |||
1 | /* sound/soc/s3c24xx/spdif.c | ||
2 | * | ||
3 | * ALSA SoC Audio Layer - Samsung S/PDIF Controller driver | ||
4 | * | ||
5 | * Copyright (c) 2010 Samsung Electronics Co. Ltd | ||
6 | * http://www.samsung.com/ | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/clk.h> | ||
14 | #include <linux/io.h> | ||
15 | |||
16 | #include <sound/pcm.h> | ||
17 | #include <sound/pcm_params.h> | ||
18 | #include <sound/soc.h> | ||
19 | |||
20 | #include <plat/audio.h> | ||
21 | #include <mach/dma.h> | ||
22 | |||
23 | #include "s3c-dma.h" | ||
24 | #include "spdif.h" | ||
25 | |||
26 | /* Registers */ | ||
27 | #define CLKCON 0x00 | ||
28 | #define CON 0x04 | ||
29 | #define BSTAS 0x08 | ||
30 | #define CSTAS 0x0C | ||
31 | #define DATA_OUTBUF 0x10 | ||
32 | #define DCNT 0x14 | ||
33 | #define BSTAS_S 0x18 | ||
34 | #define DCNT_S 0x1C | ||
35 | |||
36 | #define CLKCTL_MASK 0x7 | ||
37 | #define CLKCTL_MCLK_EXT (0x1 << 2) | ||
38 | #define CLKCTL_PWR_ON (0x1 << 0) | ||
39 | |||
40 | #define CON_MASK 0x3ffffff | ||
41 | #define CON_FIFO_TH_SHIFT 19 | ||
42 | #define CON_FIFO_TH_MASK (0x7 << 19) | ||
43 | #define CON_USERDATA_23RDBIT (0x1 << 12) | ||
44 | |||
45 | #define CON_SW_RESET (0x1 << 5) | ||
46 | |||
47 | #define CON_MCLKDIV_MASK (0x3 << 3) | ||
48 | #define CON_MCLKDIV_256FS (0x0 << 3) | ||
49 | #define CON_MCLKDIV_384FS (0x1 << 3) | ||
50 | #define CON_MCLKDIV_512FS (0x2 << 3) | ||
51 | |||
52 | #define CON_PCM_MASK (0x3 << 1) | ||
53 | #define CON_PCM_16BIT (0x0 << 1) | ||
54 | #define CON_PCM_20BIT (0x1 << 1) | ||
55 | #define CON_PCM_24BIT (0x2 << 1) | ||
56 | |||
57 | #define CON_PCM_DATA (0x1 << 0) | ||
58 | |||
59 | #define CSTAS_MASK 0x3fffffff | ||
60 | #define CSTAS_SAMP_FREQ_MASK (0xF << 24) | ||
61 | #define CSTAS_SAMP_FREQ_44 (0x0 << 24) | ||
62 | #define CSTAS_SAMP_FREQ_48 (0x2 << 24) | ||
63 | #define CSTAS_SAMP_FREQ_32 (0x3 << 24) | ||
64 | #define CSTAS_SAMP_FREQ_96 (0xA << 24) | ||
65 | |||
66 | #define CSTAS_CATEGORY_MASK (0xFF << 8) | ||
67 | #define CSTAS_CATEGORY_CODE_CDP (0x01 << 8) | ||
68 | |||
69 | #define CSTAS_NO_COPYRIGHT (0x1 << 2) | ||
70 | |||
71 | /** | ||
72 | * struct samsung_spdif_info - Samsung S/PDIF Controller information | ||
73 | * @lock: Spin lock for S/PDIF. | ||
74 | * @dev: The parent device passed to use from the probe. | ||
75 | * @regs: The pointer to the device register block. | ||
76 | * @clk_rate: Current clock rate for calcurate ratio. | ||
77 | * @pclk: The peri-clock pointer for spdif master operation. | ||
78 | * @sclk: The source clock pointer for making sync signals. | ||
79 | * @save_clkcon: Backup clkcon reg. in suspend. | ||
80 | * @save_con: Backup con reg. in suspend. | ||
81 | * @save_cstas: Backup cstas reg. in suspend. | ||
82 | * @dma_playback: DMA information for playback channel. | ||
83 | */ | ||
84 | struct samsung_spdif_info { | ||
85 | spinlock_t lock; | ||
86 | struct device *dev; | ||
87 | void __iomem *regs; | ||
88 | unsigned long clk_rate; | ||
89 | struct clk *pclk; | ||
90 | struct clk *sclk; | ||
91 | u32 saved_clkcon; | ||
92 | u32 saved_con; | ||
93 | u32 saved_cstas; | ||
94 | struct s3c_dma_params *dma_playback; | ||
95 | }; | ||
96 | |||
97 | static struct s3c2410_dma_client spdif_dma_client_out = { | ||
98 | .name = "S/PDIF Stereo out", | ||
99 | }; | ||
100 | |||
101 | static struct s3c_dma_params spdif_stereo_out; | ||
102 | static struct samsung_spdif_info spdif_info; | ||
103 | |||
104 | static inline struct samsung_spdif_info *to_info(struct snd_soc_dai *cpu_dai) | ||
105 | { | ||
106 | return snd_soc_dai_get_drvdata(cpu_dai); | ||
107 | } | ||
108 | |||
109 | static void spdif_snd_txctrl(struct samsung_spdif_info *spdif, int on) | ||
110 | { | ||
111 | void __iomem *regs = spdif->regs; | ||
112 | u32 clkcon; | ||
113 | |||
114 | dev_dbg(spdif->dev, "Entered %s\n", __func__); | ||
115 | |||
116 | clkcon = readl(regs + CLKCON) & CLKCTL_MASK; | ||
117 | if (on) | ||
118 | writel(clkcon | CLKCTL_PWR_ON, regs + CLKCON); | ||
119 | else | ||
120 | writel(clkcon & ~CLKCTL_PWR_ON, regs + CLKCON); | ||
121 | } | ||
122 | |||
123 | static int spdif_set_sysclk(struct snd_soc_dai *cpu_dai, | ||
124 | int clk_id, unsigned int freq, int dir) | ||
125 | { | ||
126 | struct samsung_spdif_info *spdif = to_info(cpu_dai); | ||
127 | u32 clkcon; | ||
128 | |||
129 | dev_dbg(spdif->dev, "Entered %s\n", __func__); | ||
130 | |||
131 | clkcon = readl(spdif->regs + CLKCON); | ||
132 | |||
133 | if (clk_id == SND_SOC_SPDIF_INT_MCLK) | ||
134 | clkcon &= ~CLKCTL_MCLK_EXT; | ||
135 | else | ||
136 | clkcon |= CLKCTL_MCLK_EXT; | ||
137 | |||
138 | writel(clkcon, spdif->regs + CLKCON); | ||
139 | |||
140 | spdif->clk_rate = freq; | ||
141 | |||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | static int spdif_trigger(struct snd_pcm_substream *substream, int cmd, | ||
146 | struct snd_soc_dai *dai) | ||
147 | { | ||
148 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
149 | struct samsung_spdif_info *spdif = to_info(rtd->cpu_dai); | ||
150 | unsigned long flags; | ||
151 | |||
152 | dev_dbg(spdif->dev, "Entered %s\n", __func__); | ||
153 | |||
154 | switch (cmd) { | ||
155 | case SNDRV_PCM_TRIGGER_START: | ||
156 | case SNDRV_PCM_TRIGGER_RESUME: | ||
157 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
158 | spin_lock_irqsave(&spdif->lock, flags); | ||
159 | spdif_snd_txctrl(spdif, 1); | ||
160 | spin_unlock_irqrestore(&spdif->lock, flags); | ||
161 | break; | ||
162 | case SNDRV_PCM_TRIGGER_STOP: | ||
163 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
164 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
165 | spin_lock_irqsave(&spdif->lock, flags); | ||
166 | spdif_snd_txctrl(spdif, 0); | ||
167 | spin_unlock_irqrestore(&spdif->lock, flags); | ||
168 | break; | ||
169 | default: | ||
170 | return -EINVAL; | ||
171 | } | ||
172 | |||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | static int spdif_sysclk_ratios[] = { | ||
177 | 512, 384, 256, | ||
178 | }; | ||
179 | |||
180 | static int spdif_hw_params(struct snd_pcm_substream *substream, | ||
181 | struct snd_pcm_hw_params *params, | ||
182 | struct snd_soc_dai *socdai) | ||
183 | { | ||
184 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
185 | struct samsung_spdif_info *spdif = to_info(rtd->cpu_dai); | ||
186 | void __iomem *regs = spdif->regs; | ||
187 | struct s3c_dma_params *dma_data; | ||
188 | u32 con, clkcon, cstas; | ||
189 | unsigned long flags; | ||
190 | int i, ratio; | ||
191 | |||
192 | dev_dbg(spdif->dev, "Entered %s\n", __func__); | ||
193 | |||
194 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
195 | dma_data = spdif->dma_playback; | ||
196 | else { | ||
197 | dev_err(spdif->dev, "Capture is not supported\n"); | ||
198 | return -EINVAL; | ||
199 | } | ||
200 | |||
201 | snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_data); | ||
202 | |||
203 | spin_lock_irqsave(&spdif->lock, flags); | ||
204 | |||
205 | con = readl(regs + CON) & CON_MASK; | ||
206 | cstas = readl(regs + CSTAS) & CSTAS_MASK; | ||
207 | clkcon = readl(regs + CLKCON) & CLKCTL_MASK; | ||
208 | |||
209 | con &= ~CON_FIFO_TH_MASK; | ||
210 | con |= (0x7 << CON_FIFO_TH_SHIFT); | ||
211 | con |= CON_USERDATA_23RDBIT; | ||
212 | con |= CON_PCM_DATA; | ||
213 | |||
214 | con &= ~CON_PCM_MASK; | ||
215 | switch (params_format(params)) { | ||
216 | case SNDRV_PCM_FORMAT_S16_LE: | ||
217 | con |= CON_PCM_16BIT; | ||
218 | break; | ||
219 | default: | ||
220 | dev_err(spdif->dev, "Unsupported data size.\n"); | ||
221 | goto err; | ||
222 | } | ||
223 | |||
224 | ratio = spdif->clk_rate / params_rate(params); | ||
225 | for (i = 0; i < ARRAY_SIZE(spdif_sysclk_ratios); i++) | ||
226 | if (ratio == spdif_sysclk_ratios[i]) | ||
227 | break; | ||
228 | if (i == ARRAY_SIZE(spdif_sysclk_ratios)) { | ||
229 | dev_err(spdif->dev, "Invalid clock ratio %ld/%d\n", | ||
230 | spdif->clk_rate, params_rate(params)); | ||
231 | goto err; | ||
232 | } | ||
233 | |||
234 | con &= ~CON_MCLKDIV_MASK; | ||
235 | switch (ratio) { | ||
236 | case 256: | ||
237 | con |= CON_MCLKDIV_256FS; | ||
238 | break; | ||
239 | case 384: | ||
240 | con |= CON_MCLKDIV_384FS; | ||
241 | break; | ||
242 | case 512: | ||
243 | con |= CON_MCLKDIV_512FS; | ||
244 | break; | ||
245 | } | ||
246 | |||
247 | cstas &= ~CSTAS_SAMP_FREQ_MASK; | ||
248 | switch (params_rate(params)) { | ||
249 | case 44100: | ||
250 | cstas |= CSTAS_SAMP_FREQ_44; | ||
251 | break; | ||
252 | case 48000: | ||
253 | cstas |= CSTAS_SAMP_FREQ_48; | ||
254 | break; | ||
255 | case 32000: | ||
256 | cstas |= CSTAS_SAMP_FREQ_32; | ||
257 | break; | ||
258 | case 96000: | ||
259 | cstas |= CSTAS_SAMP_FREQ_96; | ||
260 | break; | ||
261 | default: | ||
262 | dev_err(spdif->dev, "Invalid sampling rate %d\n", | ||
263 | params_rate(params)); | ||
264 | goto err; | ||
265 | } | ||
266 | |||
267 | cstas &= ~CSTAS_CATEGORY_MASK; | ||
268 | cstas |= CSTAS_CATEGORY_CODE_CDP; | ||
269 | cstas |= CSTAS_NO_COPYRIGHT; | ||
270 | |||
271 | writel(con, regs + CON); | ||
272 | writel(cstas, regs + CSTAS); | ||
273 | writel(clkcon, regs + CLKCON); | ||
274 | |||
275 | spin_unlock_irqrestore(&spdif->lock, flags); | ||
276 | |||
277 | return 0; | ||
278 | err: | ||
279 | spin_unlock_irqrestore(&spdif->lock, flags); | ||
280 | return -EINVAL; | ||
281 | } | ||
282 | |||
283 | static void spdif_shutdown(struct snd_pcm_substream *substream, | ||
284 | struct snd_soc_dai *dai) | ||
285 | { | ||
286 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
287 | struct samsung_spdif_info *spdif = to_info(rtd->cpu_dai); | ||
288 | void __iomem *regs = spdif->regs; | ||
289 | u32 con, clkcon; | ||
290 | |||
291 | dev_dbg(spdif->dev, "Entered %s\n", __func__); | ||
292 | |||
293 | con = readl(regs + CON) & CON_MASK; | ||
294 | clkcon = readl(regs + CLKCON) & CLKCTL_MASK; | ||
295 | |||
296 | writel(con | CON_SW_RESET, regs + CON); | ||
297 | cpu_relax(); | ||
298 | |||
299 | writel(clkcon & ~CLKCTL_PWR_ON, regs + CLKCON); | ||
300 | } | ||
301 | |||
302 | #ifdef CONFIG_PM | ||
303 | static int spdif_suspend(struct snd_soc_dai *cpu_dai) | ||
304 | { | ||
305 | struct samsung_spdif_info *spdif = to_info(cpu_dai); | ||
306 | u32 con = spdif->saved_con; | ||
307 | |||
308 | dev_dbg(spdif->dev, "Entered %s\n", __func__); | ||
309 | |||
310 | spdif->saved_clkcon = readl(spdif->regs + CLKCON) & CLKCTL_MASK; | ||
311 | spdif->saved_con = readl(spdif->regs + CON) & CON_MASK; | ||
312 | spdif->saved_cstas = readl(spdif->regs + CSTAS) & CSTAS_MASK; | ||
313 | |||
314 | writel(con | CON_SW_RESET, spdif->regs + CON); | ||
315 | cpu_relax(); | ||
316 | |||
317 | return 0; | ||
318 | } | ||
319 | |||
320 | static int spdif_resume(struct snd_soc_dai *cpu_dai) | ||
321 | { | ||
322 | struct samsung_spdif_info *spdif = to_info(cpu_dai); | ||
323 | |||
324 | dev_dbg(spdif->dev, "Entered %s\n", __func__); | ||
325 | |||
326 | writel(spdif->saved_clkcon, spdif->regs + CLKCON); | ||
327 | writel(spdif->saved_con, spdif->regs + CON); | ||
328 | writel(spdif->saved_cstas, spdif->regs + CSTAS); | ||
329 | |||
330 | return 0; | ||
331 | } | ||
332 | #else | ||
333 | #define spdif_suspend NULL | ||
334 | #define spdif_resume NULL | ||
335 | #endif | ||
336 | |||
337 | static struct snd_soc_dai_ops spdif_dai_ops = { | ||
338 | .set_sysclk = spdif_set_sysclk, | ||
339 | .trigger = spdif_trigger, | ||
340 | .hw_params = spdif_hw_params, | ||
341 | .shutdown = spdif_shutdown, | ||
342 | }; | ||
343 | |||
344 | struct snd_soc_dai_driver samsung_spdif_dai = { | ||
345 | .name = "samsung-spdif", | ||
346 | .playback = { | ||
347 | .stream_name = "S/PDIF Playback", | ||
348 | .channels_min = 2, | ||
349 | .channels_max = 2, | ||
350 | .rates = (SNDRV_PCM_RATE_32000 | | ||
351 | SNDRV_PCM_RATE_44100 | | ||
352 | SNDRV_PCM_RATE_48000 | | ||
353 | SNDRV_PCM_RATE_96000), | ||
354 | .formats = SNDRV_PCM_FMTBIT_S16_LE, }, | ||
355 | .ops = &spdif_dai_ops, | ||
356 | .suspend = spdif_suspend, | ||
357 | .resume = spdif_resume, | ||
358 | }; | ||
359 | |||
360 | static __devinit int spdif_probe(struct platform_device *pdev) | ||
361 | { | ||
362 | struct s3c_audio_pdata *spdif_pdata; | ||
363 | struct resource *mem_res, *dma_res; | ||
364 | struct samsung_spdif_info *spdif; | ||
365 | int ret; | ||
366 | |||
367 | spdif_pdata = pdev->dev.platform_data; | ||
368 | |||
369 | dev_dbg(&pdev->dev, "Entered %s\n", __func__); | ||
370 | |||
371 | dma_res = platform_get_resource(pdev, IORESOURCE_DMA, 0); | ||
372 | if (!dma_res) { | ||
373 | dev_err(&pdev->dev, "Unable to get dma resource.\n"); | ||
374 | return -ENXIO; | ||
375 | } | ||
376 | |||
377 | mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
378 | if (!mem_res) { | ||
379 | dev_err(&pdev->dev, "Unable to get register resource.\n"); | ||
380 | return -ENXIO; | ||
381 | } | ||
382 | |||
383 | if (spdif_pdata && spdif_pdata->cfg_gpio | ||
384 | && spdif_pdata->cfg_gpio(pdev)) { | ||
385 | dev_err(&pdev->dev, "Unable to configure GPIO pins\n"); | ||
386 | return -EINVAL; | ||
387 | } | ||
388 | |||
389 | spdif = &spdif_info; | ||
390 | spdif->dev = &pdev->dev; | ||
391 | |||
392 | spin_lock_init(&spdif->lock); | ||
393 | |||
394 | spdif->pclk = clk_get(&pdev->dev, "spdif"); | ||
395 | if (IS_ERR(spdif->pclk)) { | ||
396 | dev_err(&pdev->dev, "failed to get peri-clock\n"); | ||
397 | ret = -ENOENT; | ||
398 | goto err0; | ||
399 | } | ||
400 | clk_enable(spdif->pclk); | ||
401 | |||
402 | spdif->sclk = clk_get(&pdev->dev, "sclk_spdif"); | ||
403 | if (IS_ERR(spdif->sclk)) { | ||
404 | dev_err(&pdev->dev, "failed to get internal source clock\n"); | ||
405 | ret = -ENOENT; | ||
406 | goto err1; | ||
407 | } | ||
408 | clk_enable(spdif->sclk); | ||
409 | |||
410 | /* Request S/PDIF Register's memory region */ | ||
411 | if (!request_mem_region(mem_res->start, | ||
412 | resource_size(mem_res), "samsung-spdif")) { | ||
413 | dev_err(&pdev->dev, "Unable to request register region\n"); | ||
414 | ret = -EBUSY; | ||
415 | goto err2; | ||
416 | } | ||
417 | |||
418 | spdif->regs = ioremap(mem_res->start, 0x100); | ||
419 | if (spdif->regs == NULL) { | ||
420 | dev_err(&pdev->dev, "Cannot ioremap registers\n"); | ||
421 | ret = -ENXIO; | ||
422 | goto err3; | ||
423 | } | ||
424 | |||
425 | dev_set_drvdata(&pdev->dev, spdif); | ||
426 | |||
427 | ret = snd_soc_register_dai(&pdev->dev, &samsung_spdif_dai); | ||
428 | if (ret != 0) { | ||
429 | dev_err(&pdev->dev, "fail to register dai\n"); | ||
430 | goto err4; | ||
431 | } | ||
432 | |||
433 | spdif_stereo_out.dma_size = 2; | ||
434 | spdif_stereo_out.client = &spdif_dma_client_out; | ||
435 | spdif_stereo_out.dma_addr = mem_res->start + DATA_OUTBUF; | ||
436 | spdif_stereo_out.channel = dma_res->start; | ||
437 | |||
438 | spdif->dma_playback = &spdif_stereo_out; | ||
439 | |||
440 | return 0; | ||
441 | |||
442 | err4: | ||
443 | iounmap(spdif->regs); | ||
444 | err3: | ||
445 | release_mem_region(mem_res->start, resource_size(mem_res)); | ||
446 | err2: | ||
447 | clk_disable(spdif->sclk); | ||
448 | clk_put(spdif->sclk); | ||
449 | err1: | ||
450 | clk_disable(spdif->pclk); | ||
451 | clk_put(spdif->pclk); | ||
452 | err0: | ||
453 | return ret; | ||
454 | } | ||
455 | |||
456 | static __devexit int spdif_remove(struct platform_device *pdev) | ||
457 | { | ||
458 | struct samsung_spdif_info *spdif = &spdif_info; | ||
459 | struct resource *mem_res; | ||
460 | |||
461 | snd_soc_unregister_dai(&pdev->dev); | ||
462 | |||
463 | iounmap(spdif->regs); | ||
464 | |||
465 | mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
466 | if (mem_res) | ||
467 | release_mem_region(mem_res->start, resource_size(mem_res)); | ||
468 | |||
469 | clk_disable(spdif->sclk); | ||
470 | clk_put(spdif->sclk); | ||
471 | clk_disable(spdif->pclk); | ||
472 | clk_put(spdif->pclk); | ||
473 | |||
474 | return 0; | ||
475 | } | ||
476 | |||
477 | static struct platform_driver samsung_spdif_driver = { | ||
478 | .probe = spdif_probe, | ||
479 | .remove = spdif_remove, | ||
480 | .driver = { | ||
481 | .name = "samsung-spdif", | ||
482 | .owner = THIS_MODULE, | ||
483 | }, | ||
484 | }; | ||
485 | |||
486 | static int __init spdif_init(void) | ||
487 | { | ||
488 | return platform_driver_register(&samsung_spdif_driver); | ||
489 | } | ||
490 | module_init(spdif_init); | ||
491 | |||
492 | static void __exit spdif_exit(void) | ||
493 | { | ||
494 | platform_driver_unregister(&samsung_spdif_driver); | ||
495 | } | ||
496 | module_exit(spdif_exit); | ||
497 | |||
498 | MODULE_AUTHOR("Seungwhan Youn, <sw.youn@samsung.com>"); | ||
499 | MODULE_DESCRIPTION("Samsung S/PDIF Controller Driver"); | ||
500 | MODULE_LICENSE("GPL"); | ||
501 | MODULE_ALIAS("platform:samsung-spdif"); | ||
diff --git a/sound/soc/s3c24xx/spdif.h b/sound/soc/s3c24xx/spdif.h new file mode 100644 index 000000000000..3ed55592710f --- /dev/null +++ b/sound/soc/s3c24xx/spdif.h | |||
@@ -0,0 +1,19 @@ | |||
1 | /* sound/soc/s3c24xx/spdif.h | ||
2 | * | ||
3 | * ALSA SoC Audio Layer - Samsung S/PDIF Controller driver | ||
4 | * | ||
5 | * Copyright (c) 2010 Samsung Electronics Co. Ltd | ||
6 | * http://www.samsung.com/ | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #ifndef __SND_SOC_SAMSUNG_SPDIF_H | ||
14 | #define __SND_SOC_SAMSUNG_SPDIF_H __FILE__ | ||
15 | |||
16 | #define SND_SOC_SPDIF_INT_MCLK 0 | ||
17 | #define SND_SOC_SPDIF_EXT_MCLK 1 | ||
18 | |||
19 | #endif /* __SND_SOC_SAMSUNG_SPDIF_H */ | ||