treewide: remove redundant IS_ERR() before error code check
[linux/fpc-iii.git] / sound / soc / samsung / neo1973_wm8753.c
blob1339e41e986072744a98083bb045a3ef69400904
1 // SPDX-License-Identifier: GPL-2.0+
2 //
3 // neo1973_wm8753.c - SoC audio for Openmoko Neo1973 and Freerunner devices
4 //
5 // Copyright 2007 Openmoko Inc
6 // Author: Graeme Gregory <graeme@openmoko.org>
7 // Copyright 2007 Wolfson Microelectronics PLC.
8 // Author: Graeme Gregory
9 // graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
10 // Copyright 2009 Wolfson Microelectronics
12 #include <linux/module.h>
13 #include <linux/platform_device.h>
14 #include <linux/gpio.h>
16 #include <sound/soc.h>
18 #include <mach/gpio-samsung.h>
19 #include <asm/mach-types.h>
20 #include "regs-iis.h"
22 #include "../codecs/wm8753.h"
23 #include "s3c24xx-i2s.h"
25 static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream,
26 struct snd_pcm_hw_params *params)
28 struct snd_soc_pcm_runtime *rtd = substream->private_data;
29 struct snd_soc_dai *codec_dai = rtd->codec_dai;
30 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
31 unsigned int pll_out = 0, bclk = 0;
32 int ret = 0;
33 unsigned long iis_clkrate;
35 iis_clkrate = s3c24xx_i2s_get_clockrate();
37 switch (params_rate(params)) {
38 case 8000:
39 case 16000:
40 pll_out = 12288000;
41 break;
42 case 48000:
43 bclk = WM8753_BCLK_DIV_4;
44 pll_out = 12288000;
45 break;
46 case 96000:
47 bclk = WM8753_BCLK_DIV_2;
48 pll_out = 12288000;
49 break;
50 case 11025:
51 bclk = WM8753_BCLK_DIV_16;
52 pll_out = 11289600;
53 break;
54 case 22050:
55 bclk = WM8753_BCLK_DIV_8;
56 pll_out = 11289600;
57 break;
58 case 44100:
59 bclk = WM8753_BCLK_DIV_4;
60 pll_out = 11289600;
61 break;
62 case 88200:
63 bclk = WM8753_BCLK_DIV_2;
64 pll_out = 11289600;
65 break;
68 /* set the codec system clock for DAC and ADC */
69 ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_MCLK, pll_out,
70 SND_SOC_CLOCK_IN);
71 if (ret < 0)
72 return ret;
74 /* set MCLK division for sample rate */
75 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK,
76 S3C2410_IISMOD_32FS);
77 if (ret < 0)
78 return ret;
80 /* set codec BCLK division for sample rate */
81 ret = snd_soc_dai_set_clkdiv(codec_dai, WM8753_BCLKDIV, bclk);
82 if (ret < 0)
83 return ret;
85 /* set prescaler division for sample rate */
86 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER,
87 S3C24XX_PRESCALE(4, 4));
88 if (ret < 0)
89 return ret;
91 /* codec PLL input is PCLK/4 */
92 ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0,
93 iis_clkrate / 4, pll_out);
94 if (ret < 0)
95 return ret;
97 return 0;
100 static int neo1973_hifi_hw_free(struct snd_pcm_substream *substream)
102 struct snd_soc_pcm_runtime *rtd = substream->private_data;
103 struct snd_soc_dai *codec_dai = rtd->codec_dai;
105 /* disable the PLL */
106 return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0, 0);
110 * Neo1973 WM8753 HiFi DAI opserations.
112 static struct snd_soc_ops neo1973_hifi_ops = {
113 .hw_params = neo1973_hifi_hw_params,
114 .hw_free = neo1973_hifi_hw_free,
117 static int neo1973_voice_hw_params(struct snd_pcm_substream *substream,
118 struct snd_pcm_hw_params *params)
120 struct snd_soc_pcm_runtime *rtd = substream->private_data;
121 struct snd_soc_dai *codec_dai = rtd->codec_dai;
122 unsigned int pcmdiv = 0;
123 int ret = 0;
124 unsigned long iis_clkrate;
126 iis_clkrate = s3c24xx_i2s_get_clockrate();
128 if (params_rate(params) != 8000)
129 return -EINVAL;
130 if (params_channels(params) != 1)
131 return -EINVAL;
133 pcmdiv = WM8753_PCM_DIV_6; /* 2.048 MHz */
135 /* set the codec system clock for DAC and ADC */
136 ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_PCMCLK, 12288000,
137 SND_SOC_CLOCK_IN);
138 if (ret < 0)
139 return ret;
141 /* set codec PCM division for sample rate */
142 ret = snd_soc_dai_set_clkdiv(codec_dai, WM8753_PCMDIV, pcmdiv);
143 if (ret < 0)
144 return ret;
146 /* configure and enable PLL for 12.288MHz output */
147 ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0,
148 iis_clkrate / 4, 12288000);
149 if (ret < 0)
150 return ret;
152 return 0;
155 static int neo1973_voice_hw_free(struct snd_pcm_substream *substream)
157 struct snd_soc_pcm_runtime *rtd = substream->private_data;
158 struct snd_soc_dai *codec_dai = rtd->codec_dai;
160 /* disable the PLL */
161 return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0, 0);
164 static struct snd_soc_ops neo1973_voice_ops = {
165 .hw_params = neo1973_voice_hw_params,
166 .hw_free = neo1973_voice_hw_free,
169 static int gta02_speaker_enabled;
171 static int lm4853_set_spk(struct snd_kcontrol *kcontrol,
172 struct snd_ctl_elem_value *ucontrol)
174 gta02_speaker_enabled = ucontrol->value.integer.value[0];
176 gpio_set_value(S3C2410_GPJ(2), !gta02_speaker_enabled);
178 return 0;
181 static int lm4853_get_spk(struct snd_kcontrol *kcontrol,
182 struct snd_ctl_elem_value *ucontrol)
184 ucontrol->value.integer.value[0] = gta02_speaker_enabled;
185 return 0;
188 static int lm4853_event(struct snd_soc_dapm_widget *w,
189 struct snd_kcontrol *k, int event)
191 gpio_set_value(S3C2410_GPJ(1), SND_SOC_DAPM_EVENT_OFF(event));
193 return 0;
196 static const struct snd_soc_dapm_widget neo1973_wm8753_dapm_widgets[] = {
197 SND_SOC_DAPM_LINE("GSM Line Out", NULL),
198 SND_SOC_DAPM_LINE("GSM Line In", NULL),
199 SND_SOC_DAPM_MIC("Headset Mic", NULL),
200 SND_SOC_DAPM_MIC("Handset Mic", NULL),
201 SND_SOC_DAPM_SPK("Handset Spk", NULL),
202 SND_SOC_DAPM_SPK("Stereo Out", lm4853_event),
205 static const struct snd_soc_dapm_route neo1973_wm8753_routes[] = {
206 /* Connections to the GSM Module */
207 {"GSM Line Out", NULL, "MONO1"},
208 {"GSM Line Out", NULL, "MONO2"},
209 {"RXP", NULL, "GSM Line In"},
210 {"RXN", NULL, "GSM Line In"},
212 /* Connections to Headset */
213 {"MIC1", NULL, "Mic Bias"},
214 {"Mic Bias", NULL, "Headset Mic"},
216 /* Call Mic */
217 {"MIC2", NULL, "Mic Bias"},
218 {"MIC2N", NULL, "Mic Bias"},
219 {"Mic Bias", NULL, "Handset Mic"},
221 /* Connect the ALC pins */
222 {"ACIN", NULL, "ACOP"},
224 /* Connections to the amp */
225 {"Stereo Out", NULL, "LOUT1"},
226 {"Stereo Out", NULL, "ROUT1"},
228 /* Call Speaker */
229 {"Handset Spk", NULL, "LOUT2"},
230 {"Handset Spk", NULL, "ROUT2"},
233 static const struct snd_kcontrol_new neo1973_wm8753_controls[] = {
234 SOC_DAPM_PIN_SWITCH("GSM Line Out"),
235 SOC_DAPM_PIN_SWITCH("GSM Line In"),
236 SOC_DAPM_PIN_SWITCH("Headset Mic"),
237 SOC_DAPM_PIN_SWITCH("Handset Mic"),
238 SOC_DAPM_PIN_SWITCH("Handset Spk"),
239 SOC_DAPM_PIN_SWITCH("Stereo Out"),
241 SOC_SINGLE_BOOL_EXT("Amp Spk Switch", 0,
242 lm4853_get_spk,
243 lm4853_set_spk),
246 static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd)
248 struct snd_soc_card *card = rtd->card;
250 /* set endpoints to default off mode */
251 snd_soc_dapm_disable_pin(&card->dapm, "GSM Line Out");
252 snd_soc_dapm_disable_pin(&card->dapm, "GSM Line In");
253 snd_soc_dapm_disable_pin(&card->dapm, "Headset Mic");
254 snd_soc_dapm_disable_pin(&card->dapm, "Handset Mic");
255 snd_soc_dapm_disable_pin(&card->dapm, "Stereo Out");
256 snd_soc_dapm_disable_pin(&card->dapm, "Handset Spk");
258 /* allow audio paths from the GSM modem to run during suspend */
259 snd_soc_dapm_ignore_suspend(&card->dapm, "GSM Line Out");
260 snd_soc_dapm_ignore_suspend(&card->dapm, "GSM Line In");
261 snd_soc_dapm_ignore_suspend(&card->dapm, "Headset Mic");
262 snd_soc_dapm_ignore_suspend(&card->dapm, "Handset Mic");
263 snd_soc_dapm_ignore_suspend(&card->dapm, "Stereo Out");
264 snd_soc_dapm_ignore_suspend(&card->dapm, "Handset Spk");
266 return 0;
269 SND_SOC_DAILINK_DEFS(wm8753,
270 DAILINK_COMP_ARRAY(COMP_CPU("s3c24xx-iis")),
271 DAILINK_COMP_ARRAY(COMP_CODEC("wm8753.0-001a", "wm8753-hifi")),
272 DAILINK_COMP_ARRAY(COMP_PLATFORM("s3c24xx-iis")));
274 SND_SOC_DAILINK_DEFS(bluetooth,
275 DAILINK_COMP_ARRAY(COMP_CPU("bt-sco-pcm")),
276 DAILINK_COMP_ARRAY(COMP_CODEC("wm8753.0-001a", "wm8753-voice")));
278 static struct snd_soc_dai_link neo1973_dai[] = {
279 { /* Hifi Playback - for similatious use with voice below */
280 .name = "WM8753",
281 .stream_name = "WM8753 HiFi",
282 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
283 SND_SOC_DAIFMT_CBM_CFM,
284 .init = neo1973_wm8753_init,
285 .ops = &neo1973_hifi_ops,
286 SND_SOC_DAILINK_REG(wm8753),
288 { /* Voice via BT */
289 .name = "Bluetooth",
290 .stream_name = "Voice",
291 .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF |
292 SND_SOC_DAIFMT_CBS_CFS,
293 .ops = &neo1973_voice_ops,
294 SND_SOC_DAILINK_REG(bluetooth),
298 static struct snd_soc_aux_dev neo1973_aux_devs[] = {
300 .dlc = COMP_AUX("dfbmcs320.0"),
304 static struct snd_soc_codec_conf neo1973_codec_conf[] = {
306 .dlc = COMP_CODEC_CONF("lm4857.0-007c"),
307 .name_prefix = "Amp",
311 static const struct gpio neo1973_gta02_gpios[] = {
312 { S3C2410_GPJ(2), GPIOF_OUT_INIT_HIGH, "GTA02_HP_IN" },
313 { S3C2410_GPJ(1), GPIOF_OUT_INIT_HIGH, "GTA02_AMP_SHUT" },
316 static struct snd_soc_card neo1973 = {
317 .name = "neo1973",
318 .owner = THIS_MODULE,
319 .dai_link = neo1973_dai,
320 .num_links = ARRAY_SIZE(neo1973_dai),
321 .aux_dev = neo1973_aux_devs,
322 .num_aux_devs = ARRAY_SIZE(neo1973_aux_devs),
323 .codec_conf = neo1973_codec_conf,
324 .num_configs = ARRAY_SIZE(neo1973_codec_conf),
326 .controls = neo1973_wm8753_controls,
327 .num_controls = ARRAY_SIZE(neo1973_wm8753_controls),
328 .dapm_widgets = neo1973_wm8753_dapm_widgets,
329 .num_dapm_widgets = ARRAY_SIZE(neo1973_wm8753_dapm_widgets),
330 .dapm_routes = neo1973_wm8753_routes,
331 .num_dapm_routes = ARRAY_SIZE(neo1973_wm8753_routes),
332 .fully_routed = true,
335 static struct platform_device *neo1973_snd_device;
337 static int __init neo1973_init(void)
339 int ret;
341 if (!machine_is_neo1973_gta02())
342 return -ENODEV;
344 if (machine_is_neo1973_gta02()) {
345 neo1973.name = "neo1973gta02";
346 neo1973.num_aux_devs = 1;
348 ret = gpio_request_array(neo1973_gta02_gpios,
349 ARRAY_SIZE(neo1973_gta02_gpios));
350 if (ret)
351 return ret;
354 neo1973_snd_device = platform_device_alloc("soc-audio", -1);
355 if (!neo1973_snd_device) {
356 ret = -ENOMEM;
357 goto err_gpio_free;
360 platform_set_drvdata(neo1973_snd_device, &neo1973);
361 ret = platform_device_add(neo1973_snd_device);
363 if (ret)
364 goto err_put_device;
366 return 0;
368 err_put_device:
369 platform_device_put(neo1973_snd_device);
370 err_gpio_free:
371 if (machine_is_neo1973_gta02()) {
372 gpio_free_array(neo1973_gta02_gpios,
373 ARRAY_SIZE(neo1973_gta02_gpios));
375 return ret;
377 module_init(neo1973_init);
379 static void __exit neo1973_exit(void)
381 platform_device_unregister(neo1973_snd_device);
383 if (machine_is_neo1973_gta02()) {
384 gpio_free_array(neo1973_gta02_gpios,
385 ARRAY_SIZE(neo1973_gta02_gpios));
388 module_exit(neo1973_exit);
390 /* Module information */
391 MODULE_AUTHOR("Graeme Gregory, graeme@openmoko.org, www.openmoko.org");
392 MODULE_DESCRIPTION("ALSA SoC WM8753 Neo1973 and Frerunner");
393 MODULE_LICENSE("GPL");