2 * tavorevb3.c -- SoC audio for Tavor EVB3
4 * Copyright (C) 2010 Marvell International Ltd.
5 * Haojian Zhuang <haojian.zhuang@marvell.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
12 #include <linux/module.h>
13 #include <linux/moduleparam.h>
14 #include <linux/device.h>
15 #include <linux/clk.h>
16 #include <linux/i2c.h>
17 #include <sound/core.h>
18 #include <sound/pcm.h>
19 #include <sound/pcm_params.h>
20 #include <sound/soc.h>
21 #include <sound/jack.h>
23 #include <asm/mach-types.h>
25 #include "../codecs/88pm860x-codec.h"
28 static int evb3_pm860x_init(struct snd_soc_pcm_runtime
*rtd
);
30 static struct platform_device
*evb3_snd_device
;
32 static struct snd_soc_jack hs_jack
, mic_jack
;
34 static struct snd_soc_jack_pin hs_jack_pins
[] = {
35 { .pin
= "Headset Stereophone", .mask
= SND_JACK_HEADPHONE
, },
38 static struct snd_soc_jack_pin mic_jack_pins
[] = {
39 { .pin
= "Headset Mic 2", .mask
= SND_JACK_MICROPHONE
, },
42 /* tavorevb3 machine dapm widgets */
43 static const struct snd_soc_dapm_widget evb3_dapm_widgets
[] = {
44 SND_SOC_DAPM_HP("Headset Stereophone", NULL
),
45 SND_SOC_DAPM_LINE("Lineout Out 1", NULL
),
46 SND_SOC_DAPM_LINE("Lineout Out 2", NULL
),
47 SND_SOC_DAPM_SPK("Ext Speaker", NULL
),
48 SND_SOC_DAPM_MIC("Ext Mic 1", NULL
),
49 SND_SOC_DAPM_MIC("Headset Mic 2", NULL
),
50 SND_SOC_DAPM_MIC("Ext Mic 3", NULL
),
53 /* tavorevb3 machine audio map */
54 static const struct snd_soc_dapm_route audio_map
[] = {
55 {"Headset Stereophone", NULL
, "HS1"},
56 {"Headset Stereophone", NULL
, "HS2"},
58 {"Ext Speaker", NULL
, "LSP"},
59 {"Ext Speaker", NULL
, "LSN"},
61 {"Lineout Out 1", NULL
, "LINEOUT1"},
62 {"Lineout Out 2", NULL
, "LINEOUT2"},
64 {"MIC1P", NULL
, "Mic1 Bias"},
65 {"MIC1N", NULL
, "Mic1 Bias"},
66 {"Mic1 Bias", NULL
, "Ext Mic 1"},
68 {"MIC2P", NULL
, "Mic1 Bias"},
69 {"MIC2N", NULL
, "Mic1 Bias"},
70 {"Mic1 Bias", NULL
, "Headset Mic 2"},
72 {"MIC3P", NULL
, "Mic3 Bias"},
73 {"MIC3N", NULL
, "Mic3 Bias"},
74 {"Mic3 Bias", NULL
, "Ext Mic 3"},
77 static int evb3_i2s_hw_params(struct snd_pcm_substream
*substream
,
78 struct snd_pcm_hw_params
*params
)
80 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
81 struct snd_soc_dai
*codec_dai
= rtd
->codec_dai
;
82 struct snd_soc_dai
*cpu_dai
= rtd
->cpu_dai
;
83 int width
= snd_pcm_format_physical_width(params_format(params
));
86 ret
= snd_soc_dai_set_sysclk(cpu_dai
, PXA_SSP_CLK_NET_PLL
, 0,
91 ret
= snd_soc_dai_set_sysclk(codec_dai
, 0, 0, PM860X_CLK_DIR_OUT
);
95 ret
= snd_soc_dai_set_fmt(cpu_dai
, SND_SOC_DAIFMT_I2S
|
96 SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBM_CFM
);
100 ret
= snd_soc_dai_set_fmt(codec_dai
, SND_SOC_DAIFMT_I2S
|
101 SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBM_CFM
);
105 ret
= snd_soc_dai_set_tdm_slot(cpu_dai
, 3, 3, 2, width
);
109 static struct snd_soc_ops evb3_i2s_ops
= {
110 .hw_params
= evb3_i2s_hw_params
,
113 static struct snd_soc_dai_link evb3_dai
[] = {
115 .name
= "88PM860x I2S",
116 .stream_name
= "I2S Audio",
117 .cpu_dai_name
= "pxa-ssp-dai.1",
118 .codec_dai_name
= "88pm860x-i2s",
119 .platform_name
= "pxa-pcm-audio",
120 .codec_name
= "88pm860x-codec",
121 .init
= evb3_pm860x_init
,
122 .ops
= &evb3_i2s_ops
,
126 static struct snd_soc_card snd_soc_card_evb3
= {
127 .name
= "Tavor EVB3",
128 .dai_link
= evb3_dai
,
129 .num_links
= ARRAY_SIZE(evb3_dai
),
132 static int evb3_pm860x_init(struct snd_soc_pcm_runtime
*rtd
)
134 struct snd_soc_codec
*codec
= rtd
->codec
;
135 struct snd_soc_dapm_context
*dapm
= &codec
->dapm
;
138 snd_soc_dapm_new_controls(dapm
, evb3_dapm_widgets
,
139 ARRAY_SIZE(evb3_dapm_widgets
));
140 snd_soc_dapm_add_routes(dapm
, audio_map
, ARRAY_SIZE(audio_map
));
143 snd_soc_dapm_enable_pin(dapm
, "Ext Speaker");
144 snd_soc_dapm_enable_pin(dapm
, "Ext Mic 1");
145 snd_soc_dapm_enable_pin(dapm
, "Ext Mic 3");
146 snd_soc_dapm_disable_pin(dapm
, "Headset Mic 2");
147 snd_soc_dapm_disable_pin(dapm
, "Headset Stereophone");
149 ret
= snd_soc_dapm_sync(dapm
);
153 /* Headset jack detection */
154 snd_soc_jack_new(codec
, "Headphone Jack", SND_JACK_HEADPHONE
155 | SND_JACK_BTN_0
| SND_JACK_BTN_1
| SND_JACK_BTN_2
,
157 snd_soc_jack_add_pins(&hs_jack
, ARRAY_SIZE(hs_jack_pins
),
159 snd_soc_jack_new(codec
, "Microphone Jack", SND_JACK_MICROPHONE
,
161 snd_soc_jack_add_pins(&mic_jack
, ARRAY_SIZE(mic_jack_pins
),
164 /* headphone, microphone detection & headset short detection */
165 pm860x_hs_jack_detect(codec
, &hs_jack
, SND_JACK_HEADPHONE
,
166 SND_JACK_BTN_0
, SND_JACK_BTN_1
, SND_JACK_BTN_2
);
167 pm860x_mic_jack_detect(codec
, &hs_jack
, SND_JACK_MICROPHONE
);
171 static int __init
tavorevb3_init(void)
175 if (!machine_is_tavorevb3())
177 evb3_snd_device
= platform_device_alloc("soc-audio", -1);
178 if (!evb3_snd_device
)
181 platform_set_drvdata(evb3_snd_device
, &snd_soc_card_evb3
);
183 ret
= platform_device_add(evb3_snd_device
);
185 platform_device_put(evb3_snd_device
);
190 static void __exit
tavorevb3_exit(void)
192 platform_device_unregister(evb3_snd_device
);
195 module_init(tavorevb3_init
);
196 module_exit(tavorevb3_exit
);
198 MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
199 MODULE_DESCRIPTION("ALSA SoC 88PM860x Tavor EVB3");
200 MODULE_LICENSE("GPL");