Linux-libre 5.3.12-gnu
[librecmc/linux-libre.git] / sound / soc / samsung / neo1973_wm8753.c
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
11
12 #include <linux/module.h>
13 #include <linux/platform_device.h>
14 #include <linux/gpio.h>
15
16 #include <sound/soc.h>
17
18 #include <mach/gpio-samsung.h>
19 #include <asm/mach-types.h>
20 #include "regs-iis.h"
21
22 #include "../codecs/wm8753.h"
23 #include "s3c24xx-i2s.h"
24
25 static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream,
26         struct snd_pcm_hw_params *params)
27 {
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;
34
35         iis_clkrate = s3c24xx_i2s_get_clockrate();
36
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;
66         }
67
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;
73
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;
79
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;
84
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;
90
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;
96
97         return 0;
98 }
99
100 static int neo1973_hifi_hw_free(struct snd_pcm_substream *substream)
101 {
102         struct snd_soc_pcm_runtime *rtd = substream->private_data;
103         struct snd_soc_dai *codec_dai = rtd->codec_dai;
104
105         /* disable the PLL */
106         return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0, 0);
107 }
108
109 /*
110  * Neo1973 WM8753 HiFi DAI opserations.
111  */
112 static struct snd_soc_ops neo1973_hifi_ops = {
113         .hw_params = neo1973_hifi_hw_params,
114         .hw_free = neo1973_hifi_hw_free,
115 };
116
117 static int neo1973_voice_hw_params(struct snd_pcm_substream *substream,
118         struct snd_pcm_hw_params *params)
119 {
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;
125
126         iis_clkrate = s3c24xx_i2s_get_clockrate();
127
128         if (params_rate(params) != 8000)
129                 return -EINVAL;
130         if (params_channels(params) != 1)
131                 return -EINVAL;
132
133         pcmdiv = WM8753_PCM_DIV_6; /* 2.048 MHz */
134
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;
140
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;
145
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;
151
152         return 0;
153 }
154
155 static int neo1973_voice_hw_free(struct snd_pcm_substream *substream)
156 {
157         struct snd_soc_pcm_runtime *rtd = substream->private_data;
158         struct snd_soc_dai *codec_dai = rtd->codec_dai;
159
160         /* disable the PLL */
161         return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0, 0);
162 }
163
164 static struct snd_soc_ops neo1973_voice_ops = {
165         .hw_params = neo1973_voice_hw_params,
166         .hw_free = neo1973_voice_hw_free,
167 };
168
169 static int gta02_speaker_enabled;
170
171 static int lm4853_set_spk(struct snd_kcontrol *kcontrol,
172         struct snd_ctl_elem_value *ucontrol)
173 {
174         gta02_speaker_enabled = ucontrol->value.integer.value[0];
175
176         gpio_set_value(S3C2410_GPJ(2), !gta02_speaker_enabled);
177
178         return 0;
179 }
180
181 static int lm4853_get_spk(struct snd_kcontrol *kcontrol,
182         struct snd_ctl_elem_value *ucontrol)
183 {
184         ucontrol->value.integer.value[0] = gta02_speaker_enabled;
185         return 0;
186 }
187
188 static int lm4853_event(struct snd_soc_dapm_widget *w,
189                         struct snd_kcontrol *k, int event)
190 {
191         gpio_set_value(S3C2410_GPJ(1), SND_SOC_DAPM_EVENT_OFF(event));
192
193         return 0;
194 }
195
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),
203 };
204
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"},
211
212         /* Connections to Headset */
213         {"MIC1", NULL, "Mic Bias"},
214         {"Mic Bias", NULL, "Headset Mic"},
215
216         /* Call Mic */
217         {"MIC2", NULL, "Mic Bias"},
218         {"MIC2N", NULL, "Mic Bias"},
219         {"Mic Bias", NULL, "Handset Mic"},
220
221         /* Connect the ALC pins */
222         {"ACIN", NULL, "ACOP"},
223
224         /* Connections to the amp */
225         {"Stereo Out", NULL, "LOUT1"},
226         {"Stereo Out", NULL, "ROUT1"},
227
228         /* Call Speaker */
229         {"Handset Spk", NULL, "LOUT2"},
230         {"Handset Spk", NULL, "ROUT2"},
231 };
232
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"),
240
241         SOC_SINGLE_BOOL_EXT("Amp Spk Switch", 0,
242                 lm4853_get_spk,
243                 lm4853_set_spk),
244 };
245
246 static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd)
247 {
248         struct snd_soc_card *card = rtd->card;
249
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");
257
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");
265
266         return 0;
267 }
268
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")));
273
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")));
277
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),
287 },
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),
295 },
296 };
297
298 static struct snd_soc_aux_dev neo1973_aux_devs[] = {
299         {
300                 .name = "dfbmcs320",
301                 .codec_name = "dfbmcs320.0",
302         },
303 };
304
305 static struct snd_soc_codec_conf neo1973_codec_conf[] = {
306         {
307                 .dev_name = "lm4857.0-007c",
308                 .name_prefix = "Amp",
309         },
310 };
311
312 static const struct gpio neo1973_gta02_gpios[] = {
313         { S3C2410_GPJ(2), GPIOF_OUT_INIT_HIGH, "GTA02_HP_IN" },
314         { S3C2410_GPJ(1), GPIOF_OUT_INIT_HIGH, "GTA02_AMP_SHUT" },
315 };
316
317 static struct snd_soc_card neo1973 = {
318         .name = "neo1973",
319         .owner = THIS_MODULE,
320         .dai_link = neo1973_dai,
321         .num_links = ARRAY_SIZE(neo1973_dai),
322         .aux_dev = neo1973_aux_devs,
323         .num_aux_devs = ARRAY_SIZE(neo1973_aux_devs),
324         .codec_conf = neo1973_codec_conf,
325         .num_configs = ARRAY_SIZE(neo1973_codec_conf),
326
327         .controls = neo1973_wm8753_controls,
328         .num_controls = ARRAY_SIZE(neo1973_wm8753_controls),
329         .dapm_widgets = neo1973_wm8753_dapm_widgets,
330         .num_dapm_widgets = ARRAY_SIZE(neo1973_wm8753_dapm_widgets),
331         .dapm_routes = neo1973_wm8753_routes,
332         .num_dapm_routes = ARRAY_SIZE(neo1973_wm8753_routes),
333         .fully_routed = true,
334 };
335
336 static struct platform_device *neo1973_snd_device;
337
338 static int __init neo1973_init(void)
339 {
340         int ret;
341
342         if (!machine_is_neo1973_gta02())
343                 return -ENODEV;
344
345         if (machine_is_neo1973_gta02()) {
346                 neo1973.name = "neo1973gta02";
347                 neo1973.num_aux_devs = 1;
348
349                 ret = gpio_request_array(neo1973_gta02_gpios,
350                                 ARRAY_SIZE(neo1973_gta02_gpios));
351                 if (ret)
352                         return ret;
353         }
354
355         neo1973_snd_device = platform_device_alloc("soc-audio", -1);
356         if (!neo1973_snd_device) {
357                 ret = -ENOMEM;
358                 goto err_gpio_free;
359         }
360
361         platform_set_drvdata(neo1973_snd_device, &neo1973);
362         ret = platform_device_add(neo1973_snd_device);
363
364         if (ret)
365                 goto err_put_device;
366
367         return 0;
368
369 err_put_device:
370         platform_device_put(neo1973_snd_device);
371 err_gpio_free:
372         if (machine_is_neo1973_gta02()) {
373                 gpio_free_array(neo1973_gta02_gpios,
374                                 ARRAY_SIZE(neo1973_gta02_gpios));
375         }
376         return ret;
377 }
378 module_init(neo1973_init);
379
380 static void __exit neo1973_exit(void)
381 {
382         platform_device_unregister(neo1973_snd_device);
383
384         if (machine_is_neo1973_gta02()) {
385                 gpio_free_array(neo1973_gta02_gpios,
386                                 ARRAY_SIZE(neo1973_gta02_gpios));
387         }
388 }
389 module_exit(neo1973_exit);
390
391 /* Module information */
392 MODULE_AUTHOR("Graeme Gregory, graeme@openmoko.org, www.openmoko.org");
393 MODULE_DESCRIPTION("ALSA SoC WM8753 Neo1973 and Frerunner");
394 MODULE_LICENSE("GPL");