]> Pileus Git - ~andy/linux/blob - sound/soc/tegra/tegra_wm8903.c
Merge branch 'topic/misc' into for-linus
[~andy/linux] / sound / soc / tegra / tegra_wm8903.c
1 /*
2  * tegra_wm8903.c - Tegra machine ASoC driver for boards using WM8903 codec.
3  *
4  * Author: Stephen Warren <swarren@nvidia.com>
5  * Copyright (C) 2010-2011 - NVIDIA, Inc.
6  *
7  * Based on code copyright/by:
8  *
9  * (c) 2009, 2010 Nvidia Graphics Pvt. Ltd.
10  *
11  * Copyright 2007 Wolfson Microelectronics PLC.
12  * Author: Graeme Gregory
13  *         graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
14  *
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * version 2 as published by the Free Software Foundation.
18  *
19  * This program is distributed in the hope that it will be useful, but
20  * WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
27  * 02110-1301 USA
28  *
29  */
30
31 #include <asm/mach-types.h>
32
33 #include <linux/module.h>
34 #include <linux/platform_device.h>
35 #include <linux/slab.h>
36 #include <linux/gpio.h>
37 #include <linux/of_gpio.h>
38
39 #include <mach/tegra_wm8903_pdata.h>
40
41 #include <sound/core.h>
42 #include <sound/jack.h>
43 #include <sound/pcm.h>
44 #include <sound/pcm_params.h>
45 #include <sound/soc.h>
46
47 #include "../codecs/wm8903.h"
48
49 #include "tegra_das.h"
50 #include "tegra_i2s.h"
51 #include "tegra_pcm.h"
52 #include "tegra_asoc_utils.h"
53
54 #define DRV_NAME "tegra-snd-wm8903"
55
56 #define GPIO_SPKR_EN    BIT(0)
57 #define GPIO_HP_MUTE    BIT(1)
58 #define GPIO_INT_MIC_EN BIT(2)
59 #define GPIO_EXT_MIC_EN BIT(3)
60 #define GPIO_HP_DET     BIT(4)
61
62 struct tegra_wm8903 {
63         struct tegra_wm8903_platform_data pdata;
64         struct platform_device *pcm_dev;
65         struct tegra_asoc_utils_data util_data;
66         int gpio_requested;
67 };
68
69 static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream,
70                                         struct snd_pcm_hw_params *params)
71 {
72         struct snd_soc_pcm_runtime *rtd = substream->private_data;
73         struct snd_soc_dai *codec_dai = rtd->codec_dai;
74         struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
75         struct snd_soc_codec *codec = rtd->codec;
76         struct snd_soc_card *card = codec->card;
77         struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
78         int srate, mclk;
79         int err;
80
81         srate = params_rate(params);
82         switch (srate) {
83         case 64000:
84         case 88200:
85         case 96000:
86                 mclk = 128 * srate;
87                 break;
88         default:
89                 mclk = 256 * srate;
90                 break;
91         }
92         /* FIXME: Codec only requires >= 3MHz if OSR==0 */
93         while (mclk < 6000000)
94                 mclk *= 2;
95
96         err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
97         if (err < 0) {
98                 dev_err(card->dev, "Can't configure clocks\n");
99                 return err;
100         }
101
102         err = snd_soc_dai_set_fmt(codec_dai,
103                                         SND_SOC_DAIFMT_I2S |
104                                         SND_SOC_DAIFMT_NB_NF |
105                                         SND_SOC_DAIFMT_CBS_CFS);
106         if (err < 0) {
107                 dev_err(card->dev, "codec_dai fmt not set\n");
108                 return err;
109         }
110
111         err = snd_soc_dai_set_fmt(cpu_dai,
112                                         SND_SOC_DAIFMT_I2S |
113                                         SND_SOC_DAIFMT_NB_NF |
114                                         SND_SOC_DAIFMT_CBS_CFS);
115         if (err < 0) {
116                 dev_err(card->dev, "cpu_dai fmt not set\n");
117                 return err;
118         }
119
120         err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
121                                         SND_SOC_CLOCK_IN);
122         if (err < 0) {
123                 dev_err(card->dev, "codec_dai clock not set\n");
124                 return err;
125         }
126
127         return 0;
128 }
129
130 static struct snd_soc_ops tegra_wm8903_ops = {
131         .hw_params = tegra_wm8903_hw_params,
132 };
133
134 static struct snd_soc_jack tegra_wm8903_hp_jack;
135
136 static struct snd_soc_jack_pin tegra_wm8903_hp_jack_pins[] = {
137         {
138                 .pin = "Headphone Jack",
139                 .mask = SND_JACK_HEADPHONE,
140         },
141 };
142
143 static struct snd_soc_jack_gpio tegra_wm8903_hp_jack_gpio = {
144         .name = "headphone detect",
145         .report = SND_JACK_HEADPHONE,
146         .debounce_time = 150,
147         .invert = 1,
148 };
149
150 static struct snd_soc_jack tegra_wm8903_mic_jack;
151
152 static struct snd_soc_jack_pin tegra_wm8903_mic_jack_pins[] = {
153         {
154                 .pin = "Mic Jack",
155                 .mask = SND_JACK_MICROPHONE,
156         },
157 };
158
159 static int tegra_wm8903_event_int_spk(struct snd_soc_dapm_widget *w,
160                                         struct snd_kcontrol *k, int event)
161 {
162         struct snd_soc_dapm_context *dapm = w->dapm;
163         struct snd_soc_card *card = dapm->card;
164         struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
165         struct tegra_wm8903_platform_data *pdata = &machine->pdata;
166
167         if (!(machine->gpio_requested & GPIO_SPKR_EN))
168                 return 0;
169
170         gpio_set_value_cansleep(pdata->gpio_spkr_en,
171                                 SND_SOC_DAPM_EVENT_ON(event));
172
173         return 0;
174 }
175
176 static int tegra_wm8903_event_hp(struct snd_soc_dapm_widget *w,
177                                         struct snd_kcontrol *k, int event)
178 {
179         struct snd_soc_dapm_context *dapm = w->dapm;
180         struct snd_soc_card *card = dapm->card;
181         struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
182         struct tegra_wm8903_platform_data *pdata = &machine->pdata;
183
184         if (!(machine->gpio_requested & GPIO_HP_MUTE))
185                 return 0;
186
187         gpio_set_value_cansleep(pdata->gpio_hp_mute,
188                                 !SND_SOC_DAPM_EVENT_ON(event));
189
190         return 0;
191 }
192
193 static const struct snd_soc_dapm_widget tegra_wm8903_dapm_widgets[] = {
194         SND_SOC_DAPM_SPK("Int Spk", tegra_wm8903_event_int_spk),
195         SND_SOC_DAPM_HP("Headphone Jack", tegra_wm8903_event_hp),
196         SND_SOC_DAPM_MIC("Mic Jack", NULL),
197 };
198
199 static const struct snd_soc_dapm_route harmony_audio_map[] = {
200         {"Headphone Jack", NULL, "HPOUTR"},
201         {"Headphone Jack", NULL, "HPOUTL"},
202         {"Int Spk", NULL, "ROP"},
203         {"Int Spk", NULL, "RON"},
204         {"Int Spk", NULL, "LOP"},
205         {"Int Spk", NULL, "LON"},
206         {"Mic Jack", NULL, "MICBIAS"},
207         {"IN1L", NULL, "Mic Jack"},
208 };
209
210 static const struct snd_soc_dapm_route seaboard_audio_map[] = {
211         {"Headphone Jack", NULL, "HPOUTR"},
212         {"Headphone Jack", NULL, "HPOUTL"},
213         {"Int Spk", NULL, "ROP"},
214         {"Int Spk", NULL, "RON"},
215         {"Int Spk", NULL, "LOP"},
216         {"Int Spk", NULL, "LON"},
217         {"Mic Jack", NULL, "MICBIAS"},
218         {"IN1R", NULL, "Mic Jack"},
219 };
220
221 static const struct snd_soc_dapm_route kaen_audio_map[] = {
222         {"Headphone Jack", NULL, "HPOUTR"},
223         {"Headphone Jack", NULL, "HPOUTL"},
224         {"Int Spk", NULL, "ROP"},
225         {"Int Spk", NULL, "RON"},
226         {"Int Spk", NULL, "LOP"},
227         {"Int Spk", NULL, "LON"},
228         {"Mic Jack", NULL, "MICBIAS"},
229         {"IN2R", NULL, "Mic Jack"},
230 };
231
232 static const struct snd_soc_dapm_route aebl_audio_map[] = {
233         {"Headphone Jack", NULL, "HPOUTR"},
234         {"Headphone Jack", NULL, "HPOUTL"},
235         {"Int Spk", NULL, "LINEOUTR"},
236         {"Int Spk", NULL, "LINEOUTL"},
237         {"Mic Jack", NULL, "MICBIAS"},
238         {"IN1R", NULL, "Mic Jack"},
239 };
240
241 static const struct snd_kcontrol_new tegra_wm8903_controls[] = {
242         SOC_DAPM_PIN_SWITCH("Int Spk"),
243 };
244
245 static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd)
246 {
247         struct snd_soc_codec *codec = rtd->codec;
248         struct snd_soc_dapm_context *dapm = &codec->dapm;
249         struct snd_soc_card *card = codec->card;
250         struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
251         struct tegra_wm8903_platform_data *pdata = &machine->pdata;
252         struct device_node *np = card->dev->of_node;
253         int ret;
254
255         if (card->dev->platform_data) {
256                 memcpy(pdata, card->dev->platform_data, sizeof(*pdata));
257         } else if (np) {
258                 /*
259                  * This part must be in init() rather than probe() in order to
260                  * guarantee that the WM8903 has been probed, and hence its
261                  * GPIO controller registered, which is a pre-condition for
262                  * of_get_named_gpio() to be able to map the phandles in the
263                  * properties to the controller node. Given this, all
264                  * pdata handling is in init() for consistency.
265                  */
266                 pdata->gpio_spkr_en = of_get_named_gpio(np,
267                                                 "nvidia,spkr-en-gpios", 0);
268                 pdata->gpio_hp_mute = of_get_named_gpio(np,
269                                                 "nvidia,hp-mute-gpios", 0);
270                 pdata->gpio_hp_det = of_get_named_gpio(np,
271                                                 "nvidia,hp-det-gpios", 0);
272                 pdata->gpio_int_mic_en = of_get_named_gpio(np,
273                                                 "nvidia,int-mic-en-gpios", 0);
274                 pdata->gpio_ext_mic_en = of_get_named_gpio(np,
275                                                 "nvidia,ext-mic-en-gpios", 0);
276         } else {
277                 dev_err(card->dev, "No platform data supplied\n");
278                 return -EINVAL;
279         }
280
281         if (gpio_is_valid(pdata->gpio_spkr_en)) {
282                 ret = gpio_request(pdata->gpio_spkr_en, "spkr_en");
283                 if (ret) {
284                         dev_err(card->dev, "cannot get spkr_en gpio\n");
285                         return ret;
286                 }
287                 machine->gpio_requested |= GPIO_SPKR_EN;
288
289                 gpio_direction_output(pdata->gpio_spkr_en, 0);
290         }
291
292         if (gpio_is_valid(pdata->gpio_hp_mute)) {
293                 ret = gpio_request(pdata->gpio_hp_mute, "hp_mute");
294                 if (ret) {
295                         dev_err(card->dev, "cannot get hp_mute gpio\n");
296                         return ret;
297                 }
298                 machine->gpio_requested |= GPIO_HP_MUTE;
299
300                 gpio_direction_output(pdata->gpio_hp_mute, 1);
301         }
302
303         if (gpio_is_valid(pdata->gpio_int_mic_en)) {
304                 ret = gpio_request(pdata->gpio_int_mic_en, "int_mic_en");
305                 if (ret) {
306                         dev_err(card->dev, "cannot get int_mic_en gpio\n");
307                         return ret;
308                 }
309                 machine->gpio_requested |= GPIO_INT_MIC_EN;
310
311                 /* Disable int mic; enable signal is active-high */
312                 gpio_direction_output(pdata->gpio_int_mic_en, 0);
313         }
314
315         if (gpio_is_valid(pdata->gpio_ext_mic_en)) {
316                 ret = gpio_request(pdata->gpio_ext_mic_en, "ext_mic_en");
317                 if (ret) {
318                         dev_err(card->dev, "cannot get ext_mic_en gpio\n");
319                         return ret;
320                 }
321                 machine->gpio_requested |= GPIO_EXT_MIC_EN;
322
323                 /* Enable ext mic; enable signal is active-low */
324                 gpio_direction_output(pdata->gpio_ext_mic_en, 0);
325         }
326
327         if (gpio_is_valid(pdata->gpio_hp_det)) {
328                 tegra_wm8903_hp_jack_gpio.gpio = pdata->gpio_hp_det;
329                 snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE,
330                                 &tegra_wm8903_hp_jack);
331                 snd_soc_jack_add_pins(&tegra_wm8903_hp_jack,
332                                         ARRAY_SIZE(tegra_wm8903_hp_jack_pins),
333                                         tegra_wm8903_hp_jack_pins);
334                 snd_soc_jack_add_gpios(&tegra_wm8903_hp_jack,
335                                         1,
336                                         &tegra_wm8903_hp_jack_gpio);
337                 machine->gpio_requested |= GPIO_HP_DET;
338         }
339
340         snd_soc_jack_new(codec, "Mic Jack", SND_JACK_MICROPHONE,
341                          &tegra_wm8903_mic_jack);
342         snd_soc_jack_add_pins(&tegra_wm8903_mic_jack,
343                               ARRAY_SIZE(tegra_wm8903_mic_jack_pins),
344                               tegra_wm8903_mic_jack_pins);
345         wm8903_mic_detect(codec, &tegra_wm8903_mic_jack, SND_JACK_MICROPHONE,
346                                 0);
347
348         snd_soc_dapm_force_enable_pin(dapm, "MICBIAS");
349
350         return 0;
351 }
352
353 static struct snd_soc_dai_link tegra_wm8903_dai = {
354         .name = "WM8903",
355         .stream_name = "WM8903 PCM",
356         .codec_name = "wm8903.0-001a",
357         .platform_name = "tegra-pcm-audio",
358         .cpu_dai_name = "tegra-i2s.0",
359         .codec_dai_name = "wm8903-hifi",
360         .init = tegra_wm8903_init,
361         .ops = &tegra_wm8903_ops,
362 };
363
364 static struct snd_soc_card snd_soc_tegra_wm8903 = {
365         .name = "tegra-wm8903",
366         .owner = THIS_MODULE,
367         .dai_link = &tegra_wm8903_dai,
368         .num_links = 1,
369
370         .controls = tegra_wm8903_controls,
371         .num_controls = ARRAY_SIZE(tegra_wm8903_controls),
372         .dapm_widgets = tegra_wm8903_dapm_widgets,
373         .num_dapm_widgets = ARRAY_SIZE(tegra_wm8903_dapm_widgets),
374         .fully_routed = true,
375 };
376
377 static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev)
378 {
379         struct snd_soc_card *card = &snd_soc_tegra_wm8903;
380         struct tegra_wm8903 *machine;
381         int ret;
382
383         if (!pdev->dev.platform_data && !pdev->dev.of_node) {
384                 dev_err(&pdev->dev, "No platform data supplied\n");
385                 return -EINVAL;
386         }
387
388         machine = devm_kzalloc(&pdev->dev, sizeof(struct tegra_wm8903),
389                                GFP_KERNEL);
390         if (!machine) {
391                 dev_err(&pdev->dev, "Can't allocate tegra_wm8903 struct\n");
392                 ret = -ENOMEM;
393                 goto err;
394         }
395         machine->pcm_dev = ERR_PTR(-EINVAL);
396
397         card->dev = &pdev->dev;
398         platform_set_drvdata(pdev, card);
399         snd_soc_card_set_drvdata(card, machine);
400
401         if (pdev->dev.of_node) {
402                 ret = snd_soc_of_parse_card_name(card, "nvidia,model");
403                 if (ret)
404                         goto err;
405
406                 ret = snd_soc_of_parse_audio_routing(card,
407                                                      "nvidia,audio-routing");
408                 if (ret)
409                         goto err;
410
411                 tegra_wm8903_dai.codec_name = NULL;
412                 tegra_wm8903_dai.codec_of_node = of_parse_phandle(
413                                 pdev->dev.of_node, "nvidia,audio-codec", 0);
414                 if (!tegra_wm8903_dai.codec_of_node) {
415                         dev_err(&pdev->dev,
416                                 "Property 'nvidia,audio-codec' missing or invalid\n");
417                         ret = -EINVAL;
418                         goto err;
419                 }
420
421                 tegra_wm8903_dai.cpu_dai_name = NULL;
422                 tegra_wm8903_dai.cpu_dai_of_node = of_parse_phandle(
423                                 pdev->dev.of_node, "nvidia,i2s-controller", 0);
424                 if (!tegra_wm8903_dai.cpu_dai_of_node) {
425                         dev_err(&pdev->dev,
426                                 "Property 'nvidia,i2s-controller' missing or invalid\n");
427                         ret = -EINVAL;
428                         goto err;
429                 }
430
431                 machine->pcm_dev = platform_device_register_simple(
432                                         "tegra-pcm-audio", -1, NULL, 0);
433                 if (IS_ERR(machine->pcm_dev)) {
434                         dev_err(&pdev->dev,
435                                 "Can't instantiate tegra-pcm-audio\n");
436                         ret = PTR_ERR(machine->pcm_dev);
437                         goto err;
438                 }
439         } else {
440                 if (machine_is_harmony()) {
441                         card->dapm_routes = harmony_audio_map;
442                         card->num_dapm_routes = ARRAY_SIZE(harmony_audio_map);
443                 } else if (machine_is_seaboard()) {
444                         card->dapm_routes = seaboard_audio_map;
445                         card->num_dapm_routes = ARRAY_SIZE(seaboard_audio_map);
446                 } else if (machine_is_kaen()) {
447                         card->dapm_routes = kaen_audio_map;
448                         card->num_dapm_routes = ARRAY_SIZE(kaen_audio_map);
449                 } else {
450                         card->dapm_routes = aebl_audio_map;
451                         card->num_dapm_routes = ARRAY_SIZE(aebl_audio_map);
452                 }
453         }
454
455         ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev);
456         if (ret)
457                 goto err_unregister;
458
459         ret = snd_soc_register_card(card);
460         if (ret) {
461                 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
462                         ret);
463                 goto err_fini_utils;
464         }
465
466         return 0;
467
468 err_fini_utils:
469         tegra_asoc_utils_fini(&machine->util_data);
470 err_unregister:
471         if (!IS_ERR(machine->pcm_dev))
472                 platform_device_unregister(machine->pcm_dev);
473 err:
474         return ret;
475 }
476
477 static int __devexit tegra_wm8903_driver_remove(struct platform_device *pdev)
478 {
479         struct snd_soc_card *card = platform_get_drvdata(pdev);
480         struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
481         struct tegra_wm8903_platform_data *pdata = &machine->pdata;
482
483         if (machine->gpio_requested & GPIO_HP_DET)
484                 snd_soc_jack_free_gpios(&tegra_wm8903_hp_jack,
485                                         1,
486                                         &tegra_wm8903_hp_jack_gpio);
487         if (machine->gpio_requested & GPIO_EXT_MIC_EN)
488                 gpio_free(pdata->gpio_ext_mic_en);
489         if (machine->gpio_requested & GPIO_INT_MIC_EN)
490                 gpio_free(pdata->gpio_int_mic_en);
491         if (machine->gpio_requested & GPIO_HP_MUTE)
492                 gpio_free(pdata->gpio_hp_mute);
493         if (machine->gpio_requested & GPIO_SPKR_EN)
494                 gpio_free(pdata->gpio_spkr_en);
495         machine->gpio_requested = 0;
496
497         snd_soc_unregister_card(card);
498
499         tegra_asoc_utils_fini(&machine->util_data);
500         if (!IS_ERR(machine->pcm_dev))
501                 platform_device_unregister(machine->pcm_dev);
502
503         return 0;
504 }
505
506 static const struct of_device_id tegra_wm8903_of_match[] __devinitconst = {
507         { .compatible = "nvidia,tegra-audio-wm8903", },
508         {},
509 };
510
511 static struct platform_driver tegra_wm8903_driver = {
512         .driver = {
513                 .name = DRV_NAME,
514                 .owner = THIS_MODULE,
515                 .pm = &snd_soc_pm_ops,
516                 .of_match_table = tegra_wm8903_of_match,
517         },
518         .probe = tegra_wm8903_driver_probe,
519         .remove = __devexit_p(tegra_wm8903_driver_remove),
520 };
521 module_platform_driver(tegra_wm8903_driver);
522
523 MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
524 MODULE_DESCRIPTION("Tegra+WM8903 machine ASoC driver");
525 MODULE_LICENSE("GPL");
526 MODULE_ALIAS("platform:" DRV_NAME);
527 MODULE_DEVICE_TABLE(of, tegra_wm8903_of_match);