aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/tegra/tegra_max98095.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/tegra/tegra_max98095.c')
-rw-r--r--sound/soc/tegra/tegra_max98095.c723
1 files changed, 723 insertions, 0 deletions
diff --git a/sound/soc/tegra/tegra_max98095.c b/sound/soc/tegra/tegra_max98095.c
new file mode 100644
index 00000000000..2104ba849cd
--- /dev/null
+++ b/sound/soc/tegra/tegra_max98095.c
@@ -0,0 +1,723 @@
1/*
2 * tegra_max98095.c - Tegra machine ASoC driver for boards using MAX98095 codec.
3 *
4 * Author: Ravindra Lokhande <rlokhande@nvidia.com>
5 * Copyright (C) 2012 - NVIDIA, Inc.
6 *
7 * Based on version from Sumit Bhattacharya <sumitb@nvidia.com>
8 *
9 * Based on code copyright/by:
10 *
11 * (c) 2010, 2011, 2012 Nvidia Graphics Pvt. Ltd.
12 *
13 * Copyright 2007 Wolfson Microelectronics PLC.
14 * Author: Graeme Gregory
15 * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
16 *
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License
19 * version 2 as published by the Free Software Foundation.
20 *
21 * This program is distributed in the hope that it will be useful, but
22 * WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 * General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
29 * 02110-1301 USA
30 *
31 */
32
33#include <asm/mach-types.h>
34
35#include <linux/module.h>
36#include <linux/platform_device.h>
37#include <linux/slab.h>
38#include <linux/gpio.h>
39#include <linux/regulator/consumer.h>
40#ifdef CONFIG_SWITCH
41#include <linux/switch.h>
42#endif
43
44#include <mach/tegra_asoc_pdata.h>
45
46#include <sound/core.h>
47#include <sound/jack.h>
48#include <sound/pcm.h>
49#include <sound/pcm_params.h>
50#include <sound/soc.h>
51
52#include "../codecs/max98095.h"
53
54#include "tegra_pcm.h"
55#include "tegra_asoc_utils.h"
56#ifndef CONFIG_ARCH_TEGRA_2x_SOC
57#include "tegra30_ahub.h"
58#include "tegra30_i2s.h"
59#include "tegra30_dam.h"
60#endif
61
62#define DRV_NAME "tegra-snd-max98095"
63
64#define GPIO_SPKR_EN BIT(0)
65#define GPIO_HP_MUTE BIT(1)
66#define GPIO_INT_MIC_EN BIT(2)
67#define GPIO_EXT_MIC_EN BIT(3)
68
69#ifndef CONFIG_ARCH_TEGRA_2x_SOC
70const char *tegra_max98095_i2s_dai_name[TEGRA30_NR_I2S_IFC] = {
71 "tegra30-i2s.0",
72 "tegra30-i2s.1",
73 "tegra30-i2s.2",
74 "tegra30-i2s.3",
75 "tegra30-i2s.4",
76};
77#endif
78
79struct tegra_max98095 {
80 struct tegra_asoc_utils_data util_data;
81 struct tegra_asoc_platform_data *pdata;
82 int gpio_requested;
83 bool init_done;
84 int is_call_mode;
85 int is_device_bt;
86#ifndef CONFIG_ARCH_TEGRA_2x_SOC
87 struct codec_config codec_info[NUM_I2S_DEVICES];
88#endif
89 enum snd_soc_bias_level bias_level;
90};
91
92
93#ifndef CONFIG_ARCH_TEGRA_2x_SOC
94static int tegra_max98095_set_dam_cif(int dam_ifc, int srate,
95 int channels, int bit_size)
96{
97 tegra30_dam_set_samplerate(dam_ifc, TEGRA30_DAM_CHOUT,
98 srate);
99 tegra30_dam_set_samplerate(dam_ifc, TEGRA30_DAM_CHIN1,
100 srate);
101 tegra30_dam_set_acif(dam_ifc, TEGRA30_DAM_CHIN1,
102 channels, bit_size, channels,
103 bit_size);
104 tegra30_dam_set_acif(dam_ifc, TEGRA30_DAM_CHOUT,
105 channels, bit_size, channels,
106 bit_size);
107
108 return 0;
109}
110#endif
111
112static int tegra_max98095_hw_params(struct snd_pcm_substream *substream,
113 struct snd_pcm_hw_params *params)
114{
115 struct snd_soc_pcm_runtime *rtd = substream->private_data;
116 struct snd_soc_dai *codec_dai = rtd->codec_dai;
117 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
118 struct snd_soc_codec *codec = rtd->codec;
119 struct snd_soc_card *card = codec->card;
120 struct tegra_max98095 *machine = snd_soc_card_get_drvdata(card);
121#ifndef CONFIG_ARCH_TEGRA_2x_SOC
122 struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(cpu_dai);
123#endif
124 unsigned int srate, mclk, sample_size;
125 int err;
126
127 switch (params_format(params)) {
128 case SNDRV_PCM_FORMAT_S16_LE:
129 sample_size = 16;
130 break;
131 default:
132 return -EINVAL;
133 }
134
135 srate = params_rate(params);
136 switch (srate) {
137 case 8000:
138 case 16000:
139 case 24000:
140 case 32000:
141 case 48000:
142 case 64000:
143 case 96000:
144 mclk = 12288000;
145 break;
146 case 11025:
147 case 22050:
148 case 44100:
149 case 88200:
150 mclk = 11289600;
151 break;
152 default:
153 mclk = 12000000;
154 break;
155 }
156
157 err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
158 if (err < 0) {
159 if (!(machine->util_data.set_mclk % mclk))
160 mclk = machine->util_data.set_mclk;
161 else {
162 dev_err(card->dev, "Can't configure clocks\n");
163 return err;
164 }
165 }
166
167 tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
168
169 err = snd_soc_dai_set_fmt(codec_dai,
170 SND_SOC_DAIFMT_I2S |
171 SND_SOC_DAIFMT_NB_NF |
172 SND_SOC_DAIFMT_CBS_CFS);
173 if (err < 0) {
174 dev_err(card->dev, "codec_dai fmt not set\n");
175 return err;
176 }
177
178 err = snd_soc_dai_set_fmt(cpu_dai,
179 SND_SOC_DAIFMT_I2S |
180 SND_SOC_DAIFMT_NB_NF |
181 SND_SOC_DAIFMT_CBS_CFS);
182 if (err < 0) {
183 dev_err(card->dev, "cpu_dai fmt not set\n");
184 return err;
185 }
186
187 err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
188 SND_SOC_CLOCK_IN);
189 if (err < 0) {
190 dev_err(card->dev, "codec_dai clock not set\n");
191 return err;
192 }
193
194#ifndef CONFIG_ARCH_TEGRA_2x_SOC
195 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
196 tegra_max98095_set_dam_cif(i2s->dam_ifc, srate,
197 params_channels(params), sample_size);
198#endif
199
200 return 0;
201}
202
203static int tegra_spdif_hw_params(struct snd_pcm_substream *substream,
204 struct snd_pcm_hw_params *params)
205{
206 struct snd_soc_pcm_runtime *rtd = substream->private_data;
207 struct snd_soc_card *card = rtd->card;
208 struct tegra_max98095 *machine = snd_soc_card_get_drvdata(card);
209 unsigned int srate, mclk, min_mclk;
210 int err;
211
212 srate = params_rate(params);
213 switch (srate) {
214 case 11025:
215 case 22050:
216 case 44100:
217 case 88200:
218 mclk = 11289600;
219 break;
220 case 8000:
221 case 16000:
222 case 32000:
223 case 48000:
224 case 64000:
225 case 96000:
226 mclk = 12288000;
227 break;
228 default:
229 return -EINVAL;
230 }
231 min_mclk = 128 * srate;
232
233 err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
234 if (err < 0) {
235 if (!(machine->util_data.set_mclk % min_mclk))
236 mclk = machine->util_data.set_mclk;
237 else {
238 dev_err(card->dev, "Can't configure clocks\n");
239 return err;
240 }
241 }
242
243 tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
244
245
246
247 return 0;
248}
249
250static int tegra_hw_free(struct snd_pcm_substream *substream)
251{
252 struct snd_soc_pcm_runtime *rtd = substream->private_data;
253 struct tegra_max98095 *machine = snd_soc_card_get_drvdata(rtd->card);
254
255 tegra_asoc_utils_lock_clk_rate(&machine->util_data, 0);
256
257 return 0;
258}
259
260#ifndef CONFIG_ARCH_TEGRA_2x_SOC
261static int tegra_max98095_startup(struct snd_pcm_substream *substream)
262{
263 struct snd_soc_pcm_runtime *rtd = substream->private_data;
264 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
265 struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(cpu_dai);
266
267 if ((substream->stream != SNDRV_PCM_STREAM_PLAYBACK) ||
268 !(i2s->is_dam_used))
269 return 0;
270
271 /*dam configuration*/
272 if (!i2s->dam_ch_refcount)
273 i2s->dam_ifc = tegra30_dam_allocate_controller();
274
275 tegra30_dam_allocate_channel(i2s->dam_ifc, TEGRA30_DAM_CHIN1);
276 i2s->dam_ch_refcount++;
277 tegra30_dam_enable_clock(i2s->dam_ifc);
278 tegra30_dam_set_gain(i2s->dam_ifc, TEGRA30_DAM_CHIN1, 0x1000);
279
280 tegra30_ahub_set_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX1 +
281 (i2s->dam_ifc*2), i2s->txcif);
282
283 /*
284 *make the dam tx to i2s rx connection if this is the only client
285 *using i2s for playback
286 */
287 if (i2s->playback_ref_count == 1)
288 tegra30_ahub_set_rx_cif_source(
289 TEGRA30_AHUB_RXCIF_I2S0_RX0 + i2s->id,
290 TEGRA30_AHUB_TXCIF_DAM0_TX0 + i2s->dam_ifc);
291
292 /* enable the dam*/
293 tegra30_dam_enable(i2s->dam_ifc, TEGRA30_DAM_ENABLE,
294 TEGRA30_DAM_CHIN1);
295
296 return 0;
297}
298
299static void tegra_max98095_shutdown(struct snd_pcm_substream *substream)
300{
301 struct snd_soc_pcm_runtime *rtd = substream->private_data;
302 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
303 struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(cpu_dai);
304
305 if ((substream->stream != SNDRV_PCM_STREAM_PLAYBACK) ||
306 !(i2s->is_dam_used))
307 return;
308
309 /* disable the dam*/
310 tegra30_dam_enable(i2s->dam_ifc, TEGRA30_DAM_DISABLE,
311 TEGRA30_DAM_CHIN1);
312
313 /* disconnect the ahub connections*/
314 tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX1 +
315 (i2s->dam_ifc*2));
316
317 /* disable the dam and free the controller */
318 tegra30_dam_disable_clock(i2s->dam_ifc);
319 tegra30_dam_free_channel(i2s->dam_ifc, TEGRA30_DAM_CHIN1);
320 i2s->dam_ch_refcount--;
321 if (!i2s->dam_ch_refcount)
322 tegra30_dam_free_controller(i2s->dam_ifc);
323
324 return;
325}
326#endif
327
328static struct snd_soc_ops tegra_max98095_ops = {
329 .hw_params = tegra_max98095_hw_params,
330 .hw_free = tegra_hw_free,
331#ifndef CONFIG_ARCH_TEGRA_2x_SOC
332 .startup = tegra_max98095_startup,
333 .shutdown = tegra_max98095_shutdown,
334#endif
335};
336
337static struct snd_soc_ops tegra_spdif_ops = {
338 .hw_params = tegra_spdif_hw_params,
339 .hw_free = tegra_hw_free,
340};
341
342static struct snd_soc_jack tegra_max98095_hp_jack;
343
344#ifdef CONFIG_SWITCH
345static struct switch_dev wired_switch_dev = {
346 .name = "h2w",
347};
348
349/* These values are copied from WiredAccessoryObserver */
350enum headset_state {
351 BIT_NO_HEADSET = 0,
352 BIT_HEADSET = (1 << 0),
353 BIT_HEADSET_NO_MIC = (1 << 1),
354};
355
356static int headset_switch_notify(struct notifier_block *self,
357 unsigned long action, void *dev)
358{
359 int state = 0;
360
361 switch (action) {
362 case SND_JACK_HEADPHONE:
363 state |= BIT_HEADSET_NO_MIC;
364 break;
365 case SND_JACK_HEADSET:
366 state |= BIT_HEADSET;
367 break;
368 default:
369 state |= BIT_NO_HEADSET;
370 }
371
372 switch_set_state(&wired_switch_dev, state);
373
374 return NOTIFY_OK;
375}
376
377static struct notifier_block headset_switch_nb = {
378 .notifier_call = headset_switch_notify,
379};
380#else
381static struct snd_soc_jack_pin tegra_max98095_hp_jack_pins[] = {
382 {
383 .pin = "Headphone Jack",
384 .mask = SND_JACK_HEADPHONE,
385 },
386};
387#endif
388
389static int tegra_max98095_event_int_spk(struct snd_soc_dapm_widget *w,
390 struct snd_kcontrol *k, int event)
391{
392 struct snd_soc_dapm_context *dapm = w->dapm;
393 struct snd_soc_card *card = dapm->card;
394 struct tegra_max98095 *machine = snd_soc_card_get_drvdata(card);
395 struct tegra_asoc_platform_data *pdata = machine->pdata;
396
397 if (!(machine->gpio_requested & GPIO_SPKR_EN))
398 return 0;
399
400 gpio_set_value_cansleep(pdata->gpio_spkr_en,
401 SND_SOC_DAPM_EVENT_ON(event));
402
403 return 0;
404}
405
406static int tegra_max98095_event_hp(struct snd_soc_dapm_widget *w,
407 struct snd_kcontrol *k, int event)
408{
409 struct snd_soc_dapm_context *dapm = w->dapm;
410 struct snd_soc_card *card = dapm->card;
411 struct tegra_max98095 *machine = snd_soc_card_get_drvdata(card);
412 struct tegra_asoc_platform_data *pdata = machine->pdata;
413
414 if (!(machine->gpio_requested & GPIO_HP_MUTE))
415 return 0;
416
417 gpio_set_value_cansleep(pdata->gpio_hp_mute,
418 !SND_SOC_DAPM_EVENT_ON(event));
419
420 return 0;
421}
422
423static const struct snd_soc_dapm_widget tegra_max98095_dapm_widgets[] = {
424 SND_SOC_DAPM_SPK("Int Spk", tegra_max98095_event_int_spk),
425 SND_SOC_DAPM_HP("Headphone Jack", tegra_max98095_event_hp),
426 SND_SOC_DAPM_MIC("Mic Jack", NULL),
427 SND_SOC_DAPM_INPUT("Int Mic"),
428 SND_SOC_DAPM_LINE("Line In", NULL),
429};
430
431static const struct snd_soc_dapm_route enterprise_audio_map[] = {
432 {"Int Spk", NULL, "SPKL"},
433 {"Int Spk", NULL, "SPKR"},
434 {"Headphone Jack", NULL, "HPL"},
435 {"Headphone Jack", NULL, "HPR"},
436 {"MICBIAS2", NULL, "Mic Jack"},
437 {"MIC2", NULL, "MICBIAS2"},
438 {"MIC1", NULL, "Int Mic"},
439 {"MIC1", NULL, "MICBIAS1"},
440 {"INB1", NULL, "Line In"},
441 {"INB2", NULL, "Line In"},
442};
443
444static const struct snd_kcontrol_new tegra_max98095_controls[] = {
445 SOC_DAPM_PIN_SWITCH("Int Spk"),
446 SOC_DAPM_PIN_SWITCH("Headphone Jack"),
447 SOC_DAPM_PIN_SWITCH("Mic Jack"),
448 SOC_DAPM_PIN_SWITCH("Int Mic"),
449 SOC_DAPM_PIN_SWITCH("LineIn"),
450};
451
452static int tegra_max98095_init(struct snd_soc_pcm_runtime *rtd)
453{
454 struct snd_soc_codec *codec = rtd->codec;
455 struct snd_soc_dapm_context *dapm = &codec->dapm;
456 struct snd_soc_card *card = codec->card;
457 struct tegra_max98095 *machine = snd_soc_card_get_drvdata(card);
458 struct tegra_asoc_platform_data *pdata = machine->pdata;
459#ifndef CONFIG_ARCH_TEGRA_2x_SOC
460 struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(rtd->cpu_dai);
461#endif
462 int ret;
463
464#ifndef CONFIG_ARCH_TEGRA_2x_SOC
465 if (machine->codec_info[BASEBAND].i2s_id != -1)
466 i2s->is_dam_used = true;
467#endif
468
469 if (machine->init_done)
470 return 0;
471
472 machine->init_done = true;
473
474 if (gpio_is_valid(pdata->gpio_spkr_en)) {
475 ret = gpio_request(pdata->gpio_spkr_en, "spkr_en");
476 if (ret) {
477 dev_err(card->dev, "cannot get spkr_en gpio\n");
478 return ret;
479 }
480 machine->gpio_requested |= GPIO_SPKR_EN;
481
482 gpio_direction_output(pdata->gpio_spkr_en, 0);
483 }
484
485 if (gpio_is_valid(pdata->gpio_hp_mute)) {
486 ret = gpio_request(pdata->gpio_hp_mute, "hp_mute");
487 if (ret) {
488 dev_err(card->dev, "cannot get hp_mute gpio\n");
489 return ret;
490 }
491 machine->gpio_requested |= GPIO_HP_MUTE;
492
493 gpio_direction_output(pdata->gpio_hp_mute, 0);
494 }
495
496 if (gpio_is_valid(pdata->gpio_int_mic_en)) {
497 ret = gpio_request(pdata->gpio_int_mic_en, "int_mic_en");
498 if (ret) {
499 dev_err(card->dev, "cannot get int_mic_en gpio\n");
500 return ret;
501 }
502 machine->gpio_requested |= GPIO_INT_MIC_EN;
503
504 /* Disable int mic; enable signal is active-high */
505 gpio_direction_output(pdata->gpio_int_mic_en, 0);
506 }
507
508 if (gpio_is_valid(pdata->gpio_ext_mic_en)) {
509 ret = gpio_request(pdata->gpio_ext_mic_en, "ext_mic_en");
510 if (ret) {
511 dev_err(card->dev, "cannot get ext_mic_en gpio\n");
512 return ret;
513 }
514 machine->gpio_requested |= GPIO_EXT_MIC_EN;
515
516 /* Enable ext mic; enable signal is active-low */
517 gpio_direction_output(pdata->gpio_ext_mic_en, 0);
518 }
519
520 ret = snd_soc_add_controls(codec, tegra_max98095_controls,
521 ARRAY_SIZE(tegra_max98095_controls));
522 if (ret < 0)
523 return ret;
524
525 snd_soc_dapm_new_controls(dapm, tegra_max98095_dapm_widgets,
526 ARRAY_SIZE(tegra_max98095_dapm_widgets));
527
528 snd_soc_dapm_add_routes(dapm, enterprise_audio_map,
529 ARRAY_SIZE(enterprise_audio_map));
530
531 ret = snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET,
532 &tegra_max98095_hp_jack);
533 if (ret < 0)
534 return ret;
535
536#ifdef CONFIG_SWITCH
537 snd_soc_jack_notifier_register(&tegra_max98095_hp_jack,
538 &headset_switch_nb);
539#else /*gpio based headset detection*/
540 snd_soc_jack_add_pins(&tegra_max98095_hp_jack,
541 ARRAY_SIZE(tegra_max98095_hp_jack_pins),
542 tegra_max98095_hp_jack_pins);
543#endif
544
545 /* max98095_headset_detect(codec, &tegra_max98095_hp_jack,
546 SND_JACK_HEADSET); */
547
548 snd_soc_dapm_nc_pin(dapm, "INA1");
549 snd_soc_dapm_nc_pin(dapm, "INA2");
550 snd_soc_dapm_nc_pin(dapm, "INB1");
551 snd_soc_dapm_nc_pin(dapm, "INB2");
552 snd_soc_dapm_sync(dapm);
553
554 return 0;
555}
556
557static struct snd_soc_dai_link tegra_max98095_dai[] = {
558 {
559 .name = "MAX98095",
560 .stream_name = "MAX98095 HIFI",
561 .codec_name = "max98095.4-0010",
562 .platform_name = "tegra-pcm-audio",
563 .cpu_dai_name = "tegra30-i2s.1",
564 .codec_dai_name = "HiFi",
565 .init = tegra_max98095_init,
566 .ops = &tegra_max98095_ops,
567 },
568 {
569 .name = "SPDIF",
570 .stream_name = "SPDIF PCM",
571 .codec_name = "spdif-dit.0",
572 .platform_name = "tegra-pcm-audio",
573 .cpu_dai_name = "tegra30-spdif",
574 .codec_dai_name = "dit-hifi",
575 .ops = &tegra_spdif_ops,
576 },
577};
578
579static int tegra30_soc_set_bias_level(struct snd_soc_card *card,
580 enum snd_soc_bias_level level)
581{
582 struct tegra_max98095 *machine = snd_soc_card_get_drvdata(card);
583
584 if (machine->bias_level == SND_SOC_BIAS_OFF &&
585 level != SND_SOC_BIAS_OFF)
586 tegra_asoc_utils_clk_enable(&machine->util_data);
587
588 machine->bias_level = level;
589
590 return 0;
591}
592
593static int tegra30_soc_set_bias_level_post(struct snd_soc_card *card,
594 enum snd_soc_bias_level level)
595{
596 struct tegra_max98095 *machine = snd_soc_card_get_drvdata(card);
597
598 if (level == SND_SOC_BIAS_OFF)
599 tegra_asoc_utils_clk_disable(&machine->util_data);
600
601 return 0 ;
602}
603
604static struct snd_soc_card snd_soc_tegra_max98095 = {
605 .name = "tegra-max98095",
606 .dai_link = tegra_max98095_dai,
607 .num_links = ARRAY_SIZE(tegra_max98095_dai),
608 .set_bias_level = tegra30_soc_set_bias_level,
609 .set_bias_level_post = tegra30_soc_set_bias_level_post,
610};
611
612static __devinit int tegra_max98095_driver_probe(struct platform_device *pdev)
613{
614 struct snd_soc_card *card = &snd_soc_tegra_max98095;
615 struct tegra_max98095 *machine;
616 struct tegra_asoc_platform_data *pdata;
617 int ret;
618
619 pdata = pdev->dev.platform_data;
620 if (!pdata) {
621 dev_err(&pdev->dev, "No platform data supplied\n");
622 return -EINVAL;
623 }
624
625 machine = kzalloc(sizeof(struct tegra_max98095), GFP_KERNEL);
626 if (!machine) {
627 dev_err(&pdev->dev, "Can't allocate tegra_max98095 struct\n");
628 return -ENOMEM;
629 }
630
631 machine->pdata = pdata;
632
633 ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev);
634 if (ret)
635 goto err_free_machine;
636
637 card->dev = &pdev->dev;
638 platform_set_drvdata(pdev, card);
639 snd_soc_card_set_drvdata(card, machine);
640
641#ifdef CONFIG_SWITCH
642 /* Add h2w switch class support */
643 ret = switch_dev_register(&wired_switch_dev);
644 if (ret < 0) {
645 dev_err(&pdev->dev, "not able to register switch device\n");
646 goto err_fini_utils;
647 }
648#endif
649
650 ret = snd_soc_register_card(card);
651 if (ret) {
652 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
653 ret);
654 goto err_switch_unregister;
655 }
656
657 return 0;
658
659err_switch_unregister:
660#ifdef CONFIG_SWITCH
661 switch_dev_unregister(&wired_switch_dev);
662#endif
663err_fini_utils:
664 tegra_asoc_utils_fini(&machine->util_data);
665err_free_machine:
666 kfree(machine);
667 return ret;
668}
669
670static int __devexit tegra_max98095_driver_remove(struct platform_device *pdev)
671{
672 struct snd_soc_card *card = platform_get_drvdata(pdev);
673 struct tegra_max98095 *machine = snd_soc_card_get_drvdata(card);
674 struct tegra_asoc_platform_data *pdata = machine->pdata;
675
676 snd_soc_unregister_card(card);
677
678#ifdef CONFIG_SWITCH
679 switch_dev_unregister(&wired_switch_dev);
680#endif
681
682 tegra_asoc_utils_fini(&machine->util_data);
683
684 if (machine->gpio_requested & GPIO_EXT_MIC_EN)
685 gpio_free(pdata->gpio_ext_mic_en);
686 if (machine->gpio_requested & GPIO_INT_MIC_EN)
687 gpio_free(pdata->gpio_int_mic_en);
688 if (machine->gpio_requested & GPIO_HP_MUTE)
689 gpio_free(pdata->gpio_hp_mute);
690 if (machine->gpio_requested & GPIO_SPKR_EN)
691 gpio_free(pdata->gpio_spkr_en);
692
693 kfree(machine);
694
695 return 0;
696}
697
698static struct platform_driver tegra_max98095_driver = {
699 .driver = {
700 .name = DRV_NAME,
701 .owner = THIS_MODULE,
702 .pm = &snd_soc_pm_ops,
703 },
704 .probe = tegra_max98095_driver_probe,
705 .remove = __devexit_p(tegra_max98095_driver_remove),
706};
707
708static int __init tegra_max98095_modinit(void)
709{
710 return platform_driver_register(&tegra_max98095_driver);
711}
712module_init(tegra_max98095_modinit);
713
714static void __exit tegra_max98095_modexit(void)
715{
716 platform_driver_unregister(&tegra_max98095_driver);
717}
718module_exit(tegra_max98095_modexit);
719
720MODULE_AUTHOR("Ravindra Lokhande <rlokhande@nvidia.com>");
721MODULE_DESCRIPTION("Tegra+MAX98095 machine ASoC driver");
722MODULE_LICENSE("GPL");
723MODULE_ALIAS("platform:" DRV_NAME);