4 * Copyright (C) 2011 Samsung Electronics Co.Ltd
5 * Author: Chanwoo Choi <cw00.choi@samsung.com>
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
14 #include <linux/module.h>
15 #include <linux/moduleparam.h>
17 #include <linux/platform_device.h>
18 #include <linux/jack.h>
19 #include <linux/pm_runtime.h>
20 #include <sound/soc.h>
21 #include <sound/soc-dapm.h>
22 #include <sound/jack.h>
23 #include <sound/mc1n2/mc1n2_priv.h>
25 #include <asm/mach-types.h>
26 #include <mach/gpio.h>
27 #include <plat/gpio-cfg.h>
30 #include "../codecs/mc1n2/mc1n2.h"
31 #include "mc1n2_path.h"
33 #include "s3c64xx-i2s.h"
34 #include "../../../arch/arm/mach-s5pv310/gpio-mobile.h"
35 #include "../../../arch/arm/mach-s5pv310/gpio-slp7.h"
37 #define MC1N2_HIFI_DAI 0 /* I2S Interface */
38 #define MC1N2_VOICE_DAI 3 /* PCM interface */
39 #define MC1N2_BT_DAI 5 /* PCM interface */
40 #define MC1N2_DAI_NUM 6
42 #define MC1N2_VOICE_STREAM_NAME "Voice"
43 #define MC1N2_BT_VOICE_STREAM_NAME "BT Voice"
46 * XXX Don't include the gpio directly at drivers
47 * Use the mobile gpio function
49 #define SLP7_MICBIAS_EN MOBILE_GPIO(MICBIAS_EN)
50 #define SLP7_DET_3_5 MOBILE_GPIO(DET_3_5)
51 #define SLP7_EAR_MICBIAS_EN MOBILE_GPIO(EAR_MICBIAS_EN)
52 #define SLP7_EAR_SEND_END MOBILE_GPIO(EAR_SEND_END)
54 #define IS_JACK(val, idx) ( \
55 ((val >= jack_tbl[idx].adc_start1) && \
56 (val <= (jack_tbl[idx].adc_start1 + \
57 jack_tbl[idx].adc_length1))) \
58 || ((val >= jack_tbl[idx].adc_start2) && \
59 (val <= (jack_tbl[idx].adc_start2 + \
60 jack_tbl[idx].adc_length2))) \
62 #define JACK_DETECT(val) (!val)
64 #define JACK_UEVENT_NAME "earjack"
65 #define JACK_KEY_UEVENT_NAME "earkey"
66 #define SND_JACK_NONE 0x00
67 #define ADC_LOOP_COUNT 5
68 #define ADC_CHANNEL_EAR_ADC_3_5 3
70 extern struct snd_soc_platform s3c_dma_wrapper;
72 extern void s5pv310_enable_on_suspend(unsigned int);
74 static struct snd_soc_card slp7;
75 static struct platform_device *slp7_snd_device;
77 static int slp7_jack_status_check(void);
79 static struct s3c_adc_request slp7_jack_adc_request;
82 static struct snd_soc_jack slp7_jack;
84 /* 3.5 pie jack detection DAPM pins */
85 static struct snd_soc_jack_pin slp7_jack_pins[] = {
88 .mask = SND_JACK_MICROPHONE,
90 .pin = "Headset Stereophone",
91 .mask = SND_JACK_HEADPHONE,
95 /* 3.5 pie jack detection gpios */
96 static struct snd_soc_jack_gpio slp7_jack_gpios[] = {
98 /* .gpio filled below */
100 .report = SND_JACK_HEADSET,
102 .jack_status_check = slp7_jack_status_check,
116 const static struct {
117 /* The scope of ADC value according to jack type */
126 {-1, -1, -1, -1, SND_JACK_NONE},
127 {0, 10, -1, -1, SND_JACK_HEADPHONE},
128 {30, 300, -1, -1, SND_JACK_HEADSET},
131 {-1, -1, -1, -1, SND_JACK_BTN_0},
132 {-1, -1, -1, -1, SND_JACK_BTN_1},
133 {-1, -1, -1, -1, SND_JACK_BTN_2},
136 struct jack_key_data {
137 struct work_struct work;
145 static int slp7_jack_get_adc(void)
149 /* Read EAR_ADC_3.5 */
150 for (i = 0; i < ADC_LOOP_COUNT; i++)
151 adc = s3c_adc_get(&slp7_jack_adc_request);
156 * Get the state of jack when irq is happened
157 * - DET_3.5 : Jack is attatched/detached
158 * - EAR_SEND_END : Key is pressed
160 static int slp7_jack_status_get(void)
163 int jack_status = SND_JACK_HEADSET;
165 /* check jact status */
166 adc = slp7_jack_get_adc();
167 det = JACK_DETECT(gpio_get_value(SLP7_DET_3_5));
169 printk(KERN_DEBUG "ADC : %d, DET_3.5 : %d\n", adc, det);
172 for (i = 0 ; i < JACK_TYPE_NUM ; i++ ) {
173 if (IS_JACK(adc, i)) {
174 jack_status = jack_tbl[i].jack_type;
179 jack_status = jack_tbl[JACK_NONE].jack_type;
185 * Set the state of jack when irq is happened
186 * - DET_3.5 : Jack is attatched/detached
187 * - EAR_SEND_END : Key is pressed
189 static void slp7_jack_status_set(int jack) {
192 if (jack < SND_JACK_BTN_0) {
196 printk(KERN_NOTICE "Jack is detached\n");
199 case SND_JACK_HEADPHONE:
200 printk(KERN_NOTICE "Jack is Earjack3\n");
201 idx = JACK_HEADPHONE;
203 case SND_JACK_HEADSET:
204 printk(KERN_NOTICE "Jack is Earjack4\n");
208 printk(KERN_NOTICE "Jack is unknown\n");
211 jack_event_handler(JACK_UEVENT_NAME, jack_tbl[idx].jack_type);
217 printk(KERN_NOTICE "EAR_SEND_END is pressed\n");
218 idx = JACK_EAR_SEND_END;
223 printk(KERN_NOTICE "The key is unknown\n");
226 jack_event_handler(JACK_KEY_UEVENT_NAME, jack_tbl[idx].jack_type);
231 * Callback function for "DET_3.5"
233 static int slp7_jack_status_check(void)
237 jack_status = slp7_jack_status_get();
238 slp7_jack_status_set(jack_status);
243 * Sysfs to set/get the state of jack on user-space
245 static ssize_t slp7_jack_show(struct device *dev,
246 struct device_attribute *attr, char *buf)
248 return sprintf(buf, "%d\n", slp7_jack_status_get());
251 static ssize_t slp7_jack_store(struct device *dev,
252 struct device_attribute *attr, const char *buf, size_t count)
256 strict_strtoul(buf, 10, (unsigned long *)&value);
257 slp7_jack_status_set(value);
258 snd_soc_jack_report(&slp7_jack, value, slp7_jack_gpios[0].report);
262 static DEVICE_ATTR(jack_status, 0664, slp7_jack_show, slp7_jack_store);
265 * Callback function of jack key
266 * - EAR_SEND_END : SND_JACK_BTN_0
267 * - NONE_KEY : SND_JACK_BTN_1
268 * - NONE_KEY : SND_JACK_BTN_2
270 static void slp7_jack_key_work(struct work_struct *work)
274 static irqreturn_t slp7_jack_key_handler(int irq, void *dev_id)
276 struct jack_key_data *data = dev_id;
278 schedule_work(&data->work);
286 static int slp7_jack_init(void)
290 /* - MICBIAS_EN is low */
291 gpio = SLP7_MICBIAS_EN;
292 gpio_request(gpio, "MICBIAS_EN"); /* XMDMADDR_4 */
293 gpio_direction_output(gpio, 0);
294 gpio_export(gpio, 0);
296 /* - EAR_MICBIAS_EN is low */
297 gpio = SLP7_EAR_MICBIAS_EN;
298 gpio_request(gpio, "EAR_MICBIAS_EN"); /* XMDMADDR_12 */
299 gpio_direction_output(gpio, 0);
300 gpio_export(gpio, 0);
303 ret = device_create_file(&slp7_snd_device->dev,
304 &dev_attr_jack_status);
306 dev_warn(&slp7_snd_device->dev,
307 "Failed to add jack_status sysfs files\n");
313 /* FIXME: When DET_3.5 is high, EAR_SEND_END irq happened.
314 But, the state of DET_3.5 is low with earjack,
315 so EAR_SEND_END irq haven't happened. */
316 INIT_WORK(&slp7_jack_key.work, slp7_jack_key_work);
318 slp7_jack_key.gpio = SLP7_EAR_SEND_END;
319 gpio = slp7_jack_key.gpio;
320 gpio_request(gpio, "EAR_SEND_END");
321 gpio_direction_input(gpio);
323 ret = request_irq(gpio_to_irq(gpio), slp7_jack_key_handler,
324 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
325 "EAR_SEND_END", &slp7_jack_key);
326 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
328 dev_warn(&slp7_snd_device->dev,
329 "Failed to request hadndler of EAR_SEND_END\n");
333 /* Set ADC channel for reading value */
334 slp7_jack_adc_request.channel = ADC_CHANNEL_EAR_ADC_3_5;
339 gpio_free(slp7_jack_key.gpio);
342 gpio_free(SLP7_MICBIAS_EN);
343 gpio_free(SLP7_EAR_MICBIAS_EN);
348 static struct mc1n2_setup s5pv310_mc1n2_setup = {
349 { /* MCDRV_INIT_INFO */
350 MCDRV_CKSEL_CMOS, /* bCkSel */
351 28, /* bDivR0 20MHz*/ //28 for 24, 19 for 20
352 86, /* bDivF0 20MHz*/ //86 for 24, 70 for 20
358 MCDRV_DAHIZ_LOW, /* bDioSdo0Hiz */
359 MCDRV_DAHIZ_LOW, /* bDioSdo1Hiz */
360 MCDRV_DAHIZ_LOW, /* bDioSdo2Hiz */
361 MCDRV_DAHIZ_LOW, /* bDioClk0Hiz */
362 MCDRV_DAHIZ_LOW, /* bDioClk1Hiz */
363 MCDRV_DAHIZ_LOW, /* bDioClk2Hiz */
364 MCDRV_PCMHIZ_HIZ, /* bPcmHiz */
365 MCDRV_LINE_STEREO,/* bLineIn1Dif */
367 MCDRV_LINE_STEREO,/* bLineOut1Dif */
368 MCDRV_LINE_STEREO,/* bLineOUt2Dif */
369 MCDRV_SPMN_ON, /* bSpmn */
370 MCDRV_MIC_DIF, /* bMic1Sng */
371 MCDRV_MIC_DIF, /* bMic2Sng */
372 MCDRV_MIC_DIF, /* bMic3Sng */
373 MCDRV_POWMODE_NORMAL, /* bPowerMode */
374 MCDRV_SPHIZ_PULLDOWN, /* bSpHiz */
375 MCDRV_LDO_ON, /* bLdo */
376 MCDRV_PAD_GPIO, /* bPad0Func */
377 MCDRV_PAD_GPIO, /* bPad1Func */
378 MCDRV_PAD_GPIO, /* bPad2Func */
379 MCDRV_OUTLEV_4, /* bAvddLev */
381 MCDRV_DCLGAIN_12, /* bDclGain */
382 MCDRV_DCLLIMIT_0, /* bDclLimit */
391 25000, /* dMic1Cin */
392 25000, /* dMic2Cin */
393 25000, /* dMic3Cin */
394 25000, /* dLine1Cin */
395 25000, /* dLine2Cin */
396 5000, /* dVrefRdy1 */
397 15000, /* dVrefRdy2 */
401 1000, /* dAnaRdyInterval */
402 1000, /* dSvolInterval */
403 1000, /* dAnaRdyTimeOut */
404 1000 /* dSvolTimeOut */
406 }, /* MCDRV_INIT_INFO end */
409 }, /* pcm_extend end */
410 { /* pcm_hiz_redge */
411 MCDRV_PCMHIZTIM_FALLING, MCDRV_PCMHIZTIM_FALLING, MCDRV_PCMHIZTIM_FALLING
412 }, /* pcm_hiz_redge end */
415 }, /* pcm_hperiod end */
423 static int slp7_get_enable_on_suspend(struct snd_kcontrol *kcontrol,
424 struct snd_ctl_elem_value *ucontrol)
426 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
428 ucontrol->value.integer.value[0] = codec->enable_on_suspend;
432 static int slp7_set_enable_on_suspend(struct snd_kcontrol *kcontrol,
433 struct snd_ctl_elem_value *ucontrol)
435 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
437 if (codec->enable_on_suspend == ucontrol->value.integer.value[0])
440 codec->enable_on_suspend = ucontrol->value.integer.value[0];
441 s5pv310_enable_on_suspend(ucontrol->value.integer.value[0]);
446 /* Enable sound codec to support setting of sound-path in user-space */
447 static int slp7_get_enable_codec(struct snd_kcontrol *kcontrol,
448 struct snd_ctl_elem_value *ucontrol)
452 suspended = pm_runtime_suspended(mc1n2_dai[0].dev);
453 ucontrol->value.integer.value[0] = !suspended;
457 static int slp7_set_enable_codec(struct snd_kcontrol *kcontrol,
458 struct snd_ctl_elem_value *ucontrol)
460 pm_runtime_get_sync(mc1n2_dai[0].dev);
465 /* Disable sound codec to support setting of sound-path in user-space */
466 static int slp7_get_disable_codec(struct snd_kcontrol *kcontrol,
467 struct snd_ctl_elem_value *ucontrol)
471 suspended = pm_runtime_suspended(mc1n2_dai[0].dev);
472 ucontrol->value.integer.value[0] = !suspended;
476 static int slp7_set_disable_codec(struct snd_kcontrol *kcontrol,
477 struct snd_ctl_elem_value *ucontrol)
479 if (pm_runtime_suspended(mc1n2_dai[0].dev)) {
480 WARN(true, "%s: The power state of sound is suspended.", __func__);
484 pm_runtime_put(mc1n2_dai[0].dev);
489 /* FIXME: Add debug kcontrol to show codec registers */
490 static int set_codec_reg(struct snd_kcontrol *kcontrol,
491 struct snd_ctl_elem_value *ucontrol)
493 struct snd_soc_codec *codec = kcontrol->private_data;
495 mc1n2_show_reg(codec);
500 static const struct snd_kcontrol_new slp7_controls[] = {
501 /* This kcontrol controls the operation state of codec during sleep.
502 * If this kcontrol is enabled, its function must be correctly
503 * operated on sleep. */
504 SOC_SINGLE_BOOL_EXT("Enable on Suspend", 0,
505 slp7_get_enable_on_suspend,
506 slp7_set_enable_on_suspend),
507 /* This kcontrol controls the power of codec. */
508 SOC_SINGLE_BOOL_EXT("Enable Codec", 0,
509 slp7_get_enable_codec,
510 slp7_set_enable_codec),
511 SOC_SINGLE_BOOL_EXT("Disable Codec", 0,
512 slp7_get_disable_codec,
513 slp7_set_disable_codec),
514 /* FIXME: This kcontrol displays the register dump of codec to user in user-space,
515 * this kcontrol should be removed to kcontrol list. */
516 SOC_SINGLE_BOOL_EXT("codec_reg", 0,
517 NULL, set_codec_reg),
520 static const struct snd_soc_dapm_widget slp7_dapm_widgets[] = {
521 SND_SOC_DAPM_SPK("Left Speaker", NULL),
522 SND_SOC_DAPM_SPK("Right Speaker", NULL),
523 SND_SOC_DAPM_SPK("Receiver", NULL),
524 SND_SOC_DAPM_HP("Headset Stereophone", NULL),
525 SND_SOC_DAPM_MIC("Headset Mic", NULL),
526 SND_SOC_DAPM_MIC("Main Mic", NULL),
527 SND_SOC_DAPM_MIC("2nd Mic", NULL),
528 SND_SOC_DAPM_LINE("Radio In", NULL),
531 static const struct snd_soc_dapm_route slp7_dapm_routes[] = {
532 {"Left Speaker", NULL, "SPOUTLN"},
533 {"Left Speaker", NULL, "SPOUTLP"},
534 {"Right Speaker", NULL, "SPOUTRN"},
535 {"Right Speaker", NULL, "SPOUTRP"},
537 {"Receiver", NULL, "RCOUTN"},
538 {"Receiver", NULL, "RCOUTP"},
540 {"Headset Stereophone", NULL, "HPOUTL"},
541 {"Headset Stereophone", NULL, "HPOUTR"},
543 {"MIC1", NULL, "Main Mic"},
544 {"MIC2", NULL, "Headset Mic"},
545 {"MIC3", NULL, "2nd Mic"},
546 {"LINEIN", NULL, "Radio In"},
549 static int slp7_mc1n2_init(struct snd_soc_codec *codec)
553 /* add slp7 specific kcontorls */
554 ret = snd_soc_add_controls(codec, slp7_controls,
555 ARRAY_SIZE(slp7_controls));
560 /* add slp7 specific widgets */
561 snd_soc_dapm_new_controls(codec, slp7_dapm_widgets,
562 ARRAY_SIZE(slp7_dapm_widgets));
564 /* set up slp7 specific audio routes */
565 snd_soc_dapm_add_routes(codec, slp7_dapm_routes,
566 ARRAY_SIZE(slp7_dapm_routes));
568 snd_soc_dapm_sync(codec);
570 /* Init jack and key */
571 ret = slp7_jack_init();
575 /* Headset jack detection */
576 ret = snd_soc_jack_new(&slp7, "Headset Jack",
577 SND_JACK_HEADSET, &slp7_jack);
581 ret = snd_soc_jack_add_pins(&slp7_jack, ARRAY_SIZE(slp7_jack_pins),
586 slp7_jack_gpios[0].gpio = SLP7_DET_3_5;
587 ret = snd_soc_jack_add_gpios(&slp7_jack, ARRAY_SIZE(slp7_jack_gpios),
592 /* FIXME: I don't completely remove following code which set default
593 * sound path(ap_to_speaker) to test local rootfs on party server.
594 * If you want to listen booting music, you executes "set_sound_path()"
596 set_sound_path(codec, CODEC_START, DAPM_ON);
601 int slp7_startup(struct snd_pcm_substream *substream)
603 pm_runtime_get_sync(mc1n2_dai[0].dev);
608 void slp7_shutdown(struct snd_pcm_substream *substream)
610 if (pm_runtime_suspended(mc1n2_dai[0].dev)) {
611 WARN(true, "%s: The power state of sound is suspended.", __func__);
614 pm_runtime_put(mc1n2_dai[0].dev);
617 static int slp7_hifi_hw_params(struct snd_pcm_substream *substream,
618 struct snd_pcm_hw_params *params)
620 struct snd_soc_pcm_runtime *rtd = substream->private_data;
621 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
622 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
625 /* set the cpu DAI configuration */
626 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
627 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
631 /* set the cpu system clock
632 * - Use audio-bus clock instead of I2S clock from AudioSS
633 * as the source clock of I2S*/
634 ret = snd_soc_dai_set_sysclk(cpu_dai, S3C64XX_CLKSRC_PCLK, 0,
639 /* set codec DAI configuration */
640 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
641 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
645 /* set the codec clock divide */
646 ret = snd_soc_dai_set_clkdiv(codec_dai,
647 MC1N2_BCLK_MULT, MC1N2_LRCK_X64);
654 static struct snd_soc_ops slp7_hifi_ops = {
655 .startup = slp7_startup,
656 .shutdown = slp7_shutdown,
657 .hw_params = slp7_hifi_hw_params,
660 static int slp7_voice_hw_params(struct snd_pcm_substream *substream,
661 struct snd_pcm_hw_params *params)
663 struct snd_soc_pcm_runtime *rtd = substream->private_data;
664 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
667 if (params_rate(params) != 8000)
670 /* set codec DAI configuration */
671 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A |
672 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
676 /* set the codec clock divide */
677 ret = snd_soc_dai_set_clkdiv(codec_dai,
678 MC1N2_BCLK_MULT, MCDRV_BCKFS_32);
685 static struct snd_soc_ops slp7_voice_ops = {
686 .startup = slp7_startup,
687 .shutdown = slp7_shutdown,
688 .hw_params = slp7_voice_hw_params,
691 static int slp7_bt_voice_hw_params(struct snd_pcm_substream *substream,
692 struct snd_pcm_hw_params *params)
694 struct snd_soc_pcm_runtime *rtd = substream->private_data;
695 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
698 if (params_rate(params) != 8000)
701 /* set codec DAI configuration */
702 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A |
703 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
707 /* set the codec clock divide */
708 ret = snd_soc_dai_set_clkdiv(codec_dai,
709 MC1N2_BCLK_MULT, MCDRV_BCKFS_32);
716 static struct snd_soc_ops slp7_bt_voice_ops = {
717 .startup = slp7_startup,
718 .shutdown = slp7_shutdown,
719 .hw_params = slp7_bt_voice_hw_params,
722 static int slp7_hwmixing_hw_params(struct snd_pcm_substream *substream,
723 struct snd_pcm_hw_params *params)
725 struct snd_soc_pcm_runtime *rtd = substream->private_data;
726 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
727 struct snd_soc_dai *cpu_dai = &s3c64xx_i2s_v4_dai;
730 /* set the cpu DAI configuration */
731 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
732 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
736 /* set the cpu system clock */
737 ret = snd_soc_dai_set_sysclk(cpu_dai, S3C64XX_CLKSRC_PCLK, 0,
742 /* set codec DAI configuration */
743 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
744 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
748 /* set the codec clock divide */
749 ret = snd_soc_dai_set_clkdiv(codec_dai,
750 MC1N2_BCLK_MULT, MC1N2_LRCK_X64);
757 static struct snd_soc_ops slp7_hwmixing_ops = {
758 .startup = slp7_startup,
759 .shutdown = slp7_shutdown,
760 .hw_params = slp7_hwmixing_hw_params,
763 #define MC1N2_PCM_RATE (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000)
764 #define MC1N2_PCM_FORMATS \
765 (SNDRV_PCM_FMTBIT_S8 | \
766 SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \
767 SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_MU_LAW)
769 static struct snd_soc_dai voice_dai = {
770 .name = "MC1N2 Voice",
775 .rates = MC1N2_PCM_RATE,
776 .formats = MC1N2_PCM_FORMATS,},
780 .rates = MC1N2_PCM_RATE,
781 .formats = MC1N2_PCM_FORMATS,},
784 static struct snd_soc_dai_link slp7_dai[] = {
786 .name = "MC1N2 HiFi",
787 .stream_name = MC1N2_HIFI_STREAM_NAME,
788 .cpu_dai = &s3c64xx_i2s_v4_dai,
789 .codec_dai = &mc1n2_dai[MC1N2_HIFI_DAI],
790 .init = slp7_mc1n2_init,
791 .ops = &slp7_hifi_ops,
793 .name = "MC1N2 Voice",
794 .stream_name = MC1N2_VOICE_STREAM_NAME,
795 .cpu_dai = &voice_dai,
796 .codec_dai = &mc1n2_dai[MC1N2_VOICE_DAI],
797 .ops = &slp7_voice_ops,
799 .name = "MC1N2 HiFi Secondary",
800 .stream_name = MC1N2_HIFI_SEC_STREAM_NAME,
801 .cpu_dai = &s3c64xx_i2s_v4_dai,
802 .codec_dai = &mc1n2_dai[MC1N2_HIFI_DAI],
803 .ops = &slp7_hwmixing_ops,
805 .name = "MC1N2 Bluetooth",
806 .stream_name = MC1N2_BT_VOICE_STREAM_NAME,
807 .cpu_dai = &voice_dai,
808 .codec_dai = &mc1n2_dai[MC1N2_BT_DAI],
809 .ops = &slp7_bt_voice_ops,
813 static struct snd_soc_card slp7 = {
815 .platform = &s3c_dma_wrapper,
816 .dai_link = slp7_dai,
817 .num_links = ARRAY_SIZE(slp7_dai),
820 static struct snd_soc_device slp7_snd_devdata = {
822 .codec_dev = &soc_codec_dev_mc1n2,
823 .codec_data = &s5pv310_mc1n2_setup,
826 static int __init slp7_init(void)
830 if (!machine_is_slp7_c210() && !machine_is_slp10_c210() && !machine_is_nuri())
833 /* register voice DAI here */
834 ret = snd_soc_register_dai(&voice_dai);
838 slp7_snd_device = platform_device_alloc("soc-audio", -1);
839 if (!slp7_snd_device)
842 platform_set_drvdata(slp7_snd_device, &slp7_snd_devdata);
843 slp7_snd_devdata.dev = &slp7_snd_device->dev;
844 ret = platform_device_add(slp7_snd_device);
847 platform_device_put(slp7_snd_device);
853 static void __exit slp7_exit(void)
855 platform_device_unregister(slp7_snd_device);
858 module_init(slp7_init);
859 module_exit(slp7_exit);
861 /* Module information */
862 MODULE_DESCRIPTION("ALSA SoC MC1N2 SLP7(C210)");
863 MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>");
864 MODULE_LICENSE("GPL");