Merge tag 'reset-for-v5.3' of git://git.pengutronix.de/git/pza/linux into arm/drivers
[sfrench/cifs-2.6.git] / sound / soc / ti / n810.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * n810.c  --  SoC audio for Nokia N810
4  *
5  * Copyright (C) 2008 Nokia Corporation
6  *
7  * Contact: Jarkko Nikula <jarkko.nikula@bitmer.com>
8  */
9
10 #include <linux/clk.h>
11 #include <linux/i2c.h>
12 #include <linux/platform_device.h>
13 #include <sound/core.h>
14 #include <sound/pcm.h>
15 #include <sound/soc.h>
16
17 #include <asm/mach-types.h>
18 #include <linux/gpio.h>
19 #include <linux/module.h>
20 #include <linux/platform_data/asoc-ti-mcbsp.h>
21
22 #include "omap-mcbsp.h"
23
24 #define N810_HEADSET_AMP_GPIO   10
25 #define N810_SPEAKER_AMP_GPIO   101
26
27 enum {
28         N810_JACK_DISABLED,
29         N810_JACK_HP,
30         N810_JACK_HS,
31         N810_JACK_MIC,
32 };
33
34 static struct clk *sys_clkout2;
35 static struct clk *sys_clkout2_src;
36 static struct clk *func96m_clk;
37
38 static int n810_spk_func;
39 static int n810_jack_func;
40 static int n810_dmic_func;
41
42 static void n810_ext_control(struct snd_soc_dapm_context *dapm)
43 {
44         int hp = 0, line1l = 0;
45
46         switch (n810_jack_func) {
47         case N810_JACK_HS:
48                 line1l = 1;
49         case N810_JACK_HP:
50                 hp = 1;
51                 break;
52         case N810_JACK_MIC:
53                 line1l = 1;
54                 break;
55         }
56
57         snd_soc_dapm_mutex_lock(dapm);
58
59         if (n810_spk_func)
60                 snd_soc_dapm_enable_pin_unlocked(dapm, "Ext Spk");
61         else
62                 snd_soc_dapm_disable_pin_unlocked(dapm, "Ext Spk");
63
64         if (hp)
65                 snd_soc_dapm_enable_pin_unlocked(dapm, "Headphone Jack");
66         else
67                 snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack");
68         if (line1l)
69                 snd_soc_dapm_enable_pin_unlocked(dapm, "HS Mic");
70         else
71                 snd_soc_dapm_disable_pin_unlocked(dapm, "HS Mic");
72
73         if (n810_dmic_func)
74                 snd_soc_dapm_enable_pin_unlocked(dapm, "DMic");
75         else
76                 snd_soc_dapm_disable_pin_unlocked(dapm, "DMic");
77
78         snd_soc_dapm_sync_unlocked(dapm);
79
80         snd_soc_dapm_mutex_unlock(dapm);
81 }
82
83 static int n810_startup(struct snd_pcm_substream *substream)
84 {
85         struct snd_pcm_runtime *runtime = substream->runtime;
86         struct snd_soc_pcm_runtime *rtd = substream->private_data;
87
88         snd_pcm_hw_constraint_single(runtime, SNDRV_PCM_HW_PARAM_CHANNELS, 2);
89
90         n810_ext_control(&rtd->card->dapm);
91         return clk_prepare_enable(sys_clkout2);
92 }
93
94 static void n810_shutdown(struct snd_pcm_substream *substream)
95 {
96         clk_disable_unprepare(sys_clkout2);
97 }
98
99 static int n810_hw_params(struct snd_pcm_substream *substream,
100         struct snd_pcm_hw_params *params)
101 {
102         struct snd_soc_pcm_runtime *rtd = substream->private_data;
103         struct snd_soc_dai *codec_dai = rtd->codec_dai;
104         int err;
105
106         /* Set the codec system clock for DAC and ADC */
107         err = snd_soc_dai_set_sysclk(codec_dai, 0, 12000000,
108                                             SND_SOC_CLOCK_IN);
109
110         return err;
111 }
112
113 static const struct snd_soc_ops n810_ops = {
114         .startup = n810_startup,
115         .hw_params = n810_hw_params,
116         .shutdown = n810_shutdown,
117 };
118
119 static int n810_get_spk(struct snd_kcontrol *kcontrol,
120                         struct snd_ctl_elem_value *ucontrol)
121 {
122         ucontrol->value.enumerated.item[0] = n810_spk_func;
123
124         return 0;
125 }
126
127 static int n810_set_spk(struct snd_kcontrol *kcontrol,
128                         struct snd_ctl_elem_value *ucontrol)
129 {
130         struct snd_soc_card *card =  snd_kcontrol_chip(kcontrol);
131
132         if (n810_spk_func == ucontrol->value.enumerated.item[0])
133                 return 0;
134
135         n810_spk_func = ucontrol->value.enumerated.item[0];
136         n810_ext_control(&card->dapm);
137
138         return 1;
139 }
140
141 static int n810_get_jack(struct snd_kcontrol *kcontrol,
142                          struct snd_ctl_elem_value *ucontrol)
143 {
144         ucontrol->value.enumerated.item[0] = n810_jack_func;
145
146         return 0;
147 }
148
149 static int n810_set_jack(struct snd_kcontrol *kcontrol,
150                          struct snd_ctl_elem_value *ucontrol)
151 {
152         struct snd_soc_card *card =  snd_kcontrol_chip(kcontrol);
153
154         if (n810_jack_func == ucontrol->value.enumerated.item[0])
155                 return 0;
156
157         n810_jack_func = ucontrol->value.enumerated.item[0];
158         n810_ext_control(&card->dapm);
159
160         return 1;
161 }
162
163 static int n810_get_input(struct snd_kcontrol *kcontrol,
164                           struct snd_ctl_elem_value *ucontrol)
165 {
166         ucontrol->value.enumerated.item[0] = n810_dmic_func;
167
168         return 0;
169 }
170
171 static int n810_set_input(struct snd_kcontrol *kcontrol,
172                           struct snd_ctl_elem_value *ucontrol)
173 {
174         struct snd_soc_card *card =  snd_kcontrol_chip(kcontrol);
175
176         if (n810_dmic_func == ucontrol->value.enumerated.item[0])
177                 return 0;
178
179         n810_dmic_func = ucontrol->value.enumerated.item[0];
180         n810_ext_control(&card->dapm);
181
182         return 1;
183 }
184
185 static int n810_spk_event(struct snd_soc_dapm_widget *w,
186                           struct snd_kcontrol *k, int event)
187 {
188         if (SND_SOC_DAPM_EVENT_ON(event))
189                 gpio_set_value(N810_SPEAKER_AMP_GPIO, 1);
190         else
191                 gpio_set_value(N810_SPEAKER_AMP_GPIO, 0);
192
193         return 0;
194 }
195
196 static int n810_jack_event(struct snd_soc_dapm_widget *w,
197                            struct snd_kcontrol *k, int event)
198 {
199         if (SND_SOC_DAPM_EVENT_ON(event))
200                 gpio_set_value(N810_HEADSET_AMP_GPIO, 1);
201         else
202                 gpio_set_value(N810_HEADSET_AMP_GPIO, 0);
203
204         return 0;
205 }
206
207 static const struct snd_soc_dapm_widget aic33_dapm_widgets[] = {
208         SND_SOC_DAPM_SPK("Ext Spk", n810_spk_event),
209         SND_SOC_DAPM_HP("Headphone Jack", n810_jack_event),
210         SND_SOC_DAPM_MIC("DMic", NULL),
211         SND_SOC_DAPM_MIC("HS Mic", NULL),
212 };
213
214 static const struct snd_soc_dapm_route audio_map[] = {
215         {"Headphone Jack", NULL, "HPLOUT"},
216         {"Headphone Jack", NULL, "HPROUT"},
217
218         {"Ext Spk", NULL, "LLOUT"},
219         {"Ext Spk", NULL, "RLOUT"},
220
221         {"DMic Rate 64", NULL, "DMic"},
222         {"DMic", NULL, "Mic Bias"},
223
224         /*
225          * Note that the mic bias is coming from Retu/Vilma and we don't have
226          * control over it atm. The analog HS mic is not working. <- TODO
227          */
228         {"LINE1L", NULL, "HS Mic"},
229 };
230
231 static const char *spk_function[] = {"Off", "On"};
232 static const char *jack_function[] = {"Off", "Headphone", "Headset", "Mic"};
233 static const char *input_function[] = {"ADC", "Digital Mic"};
234 static const struct soc_enum n810_enum[] = {
235         SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spk_function), spk_function),
236         SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(jack_function), jack_function),
237         SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(input_function), input_function),
238 };
239
240 static const struct snd_kcontrol_new aic33_n810_controls[] = {
241         SOC_ENUM_EXT("Speaker Function", n810_enum[0],
242                      n810_get_spk, n810_set_spk),
243         SOC_ENUM_EXT("Jack Function", n810_enum[1],
244                      n810_get_jack, n810_set_jack),
245         SOC_ENUM_EXT("Input Select",  n810_enum[2],
246                      n810_get_input, n810_set_input),
247 };
248
249 /* Digital audio interface glue - connects codec <--> CPU */
250 static struct snd_soc_dai_link n810_dai = {
251         .name = "TLV320AIC33",
252         .stream_name = "AIC33",
253         .cpu_dai_name = "48076000.mcbsp",
254         .platform_name = "48076000.mcbsp",
255         .codec_name = "tlv320aic3x-codec.1-0018",
256         .codec_dai_name = "tlv320aic3x-hifi",
257         .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
258                    SND_SOC_DAIFMT_CBM_CFM,
259         .ops = &n810_ops,
260 };
261
262 /* Audio machine driver */
263 static struct snd_soc_card snd_soc_n810 = {
264         .name = "N810",
265         .owner = THIS_MODULE,
266         .dai_link = &n810_dai,
267         .num_links = 1,
268
269         .controls = aic33_n810_controls,
270         .num_controls = ARRAY_SIZE(aic33_n810_controls),
271         .dapm_widgets = aic33_dapm_widgets,
272         .num_dapm_widgets = ARRAY_SIZE(aic33_dapm_widgets),
273         .dapm_routes = audio_map,
274         .num_dapm_routes = ARRAY_SIZE(audio_map),
275         .fully_routed = true,
276 };
277
278 static struct platform_device *n810_snd_device;
279
280 static int __init n810_soc_init(void)
281 {
282         int err;
283         struct device *dev;
284
285         if (!of_have_populated_dt() ||
286             (!of_machine_is_compatible("nokia,n810") &&
287              !of_machine_is_compatible("nokia,n810-wimax")))
288                 return -ENODEV;
289
290         n810_snd_device = platform_device_alloc("soc-audio", -1);
291         if (!n810_snd_device)
292                 return -ENOMEM;
293
294         platform_set_drvdata(n810_snd_device, &snd_soc_n810);
295         err = platform_device_add(n810_snd_device);
296         if (err)
297                 goto err1;
298
299         dev = &n810_snd_device->dev;
300
301         sys_clkout2_src = clk_get(dev, "sys_clkout2_src");
302         if (IS_ERR(sys_clkout2_src)) {
303                 dev_err(dev, "Could not get sys_clkout2_src clock\n");
304                 err = PTR_ERR(sys_clkout2_src);
305                 goto err2;
306         }
307         sys_clkout2 = clk_get(dev, "sys_clkout2");
308         if (IS_ERR(sys_clkout2)) {
309                 dev_err(dev, "Could not get sys_clkout2\n");
310                 err = PTR_ERR(sys_clkout2);
311                 goto err3;
312         }
313         /*
314          * Configure 12 MHz output on SYS_CLKOUT2. Therefore we must use
315          * 96 MHz as its parent in order to get 12 MHz
316          */
317         func96m_clk = clk_get(dev, "func_96m_ck");
318         if (IS_ERR(func96m_clk)) {
319                 dev_err(dev, "Could not get func 96M clock\n");
320                 err = PTR_ERR(func96m_clk);
321                 goto err4;
322         }
323         clk_set_parent(sys_clkout2_src, func96m_clk);
324         clk_set_rate(sys_clkout2, 12000000);
325
326         if (WARN_ON((gpio_request(N810_HEADSET_AMP_GPIO, "hs_amp") < 0) ||
327                     (gpio_request(N810_SPEAKER_AMP_GPIO, "spk_amp") < 0))) {
328                 err = -EINVAL;
329                 goto err4;
330         }
331
332         gpio_direction_output(N810_HEADSET_AMP_GPIO, 0);
333         gpio_direction_output(N810_SPEAKER_AMP_GPIO, 0);
334
335         return 0;
336 err4:
337         clk_put(sys_clkout2);
338 err3:
339         clk_put(sys_clkout2_src);
340 err2:
341         platform_device_del(n810_snd_device);
342 err1:
343         platform_device_put(n810_snd_device);
344
345         return err;
346 }
347
348 static void __exit n810_soc_exit(void)
349 {
350         gpio_free(N810_SPEAKER_AMP_GPIO);
351         gpio_free(N810_HEADSET_AMP_GPIO);
352         clk_put(sys_clkout2_src);
353         clk_put(sys_clkout2);
354         clk_put(func96m_clk);
355
356         platform_device_unregister(n810_snd_device);
357 }
358
359 module_init(n810_soc_init);
360 module_exit(n810_soc_exit);
361
362 MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@bitmer.com>");
363 MODULE_DESCRIPTION("ALSA SoC Nokia N810");
364 MODULE_LICENSE("GPL");