blob: c8c2e1067e02da6d3604601906e046b4a659db4e [file] [log] [blame]
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -05001/*
2 * sdp4430.c -- SoC audio for TI OMAP4430 SDP
3 *
4 * Author: Misael Lopez Cruz <x0052729@ti.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18 * 02110-1301 USA
19 *
20 */
21
22#include <linux/clk.h>
23#include <linux/platform_device.h>
Misael Lopez Cruzf4b3dc32011-05-01 21:27:00 -050024#include <linux/mfd/twl6040.h>
25
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -050026#include <sound/core.h>
27#include <sound/pcm.h>
Liam Girdwoodede6aa92011-02-07 21:07:48 +000028#include <sound/pcm_params.h>
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -050029#include <sound/soc.h>
Liam Girdwoodede6aa92011-02-07 21:07:48 +000030#include <sound/soc-dapm.h>
Jorge Eduardo Candelaria96dc2272010-12-10 20:45:19 -060031#include <sound/jack.h>
Liam Girdwoodede6aa92011-02-07 21:07:48 +000032#include <sound/soc-dsp.h>
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -050033
34#include <asm/mach-types.h>
35#include <plat/hardware.h>
36#include <plat/mux.h>
37
Liam Girdwoodede6aa92011-02-07 21:07:48 +000038#include "omap-mcpdm.h"
39#include "omap-abe.h"
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -050040#include "omap-pcm.h"
Liam Girdwoodede6aa92011-02-07 21:07:48 +000041#include "omap-mcbsp.h"
42#include "omap-dmic.h"
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -050043#include "../codecs/twl6040.h"
44
45static int twl6040_power_mode;
Liam Girdwoodede6aa92011-02-07 21:07:48 +000046static int mcbsp_cfg;
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -050047
Liam Girdwoodede6aa92011-02-07 21:07:48 +000048static int sdp4430_mcpdm_hw_params(struct snd_pcm_substream *substream,
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -050049 struct snd_pcm_hw_params *params)
50{
51 struct snd_soc_pcm_runtime *rtd = substream->private_data;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +000052 struct snd_soc_dai *codec_dai = rtd->codec_dai;
Liam Girdwoodede6aa92011-02-07 21:07:48 +000053 struct snd_soc_pcm_runtime *modem_rtd;
54 struct snd_pcm_substream *modem_substream[2];
55 struct snd_soc_dsp_params *dsp_params;
56 int clk_id, freq, ret, stream = substream->stream;
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -050057
58 if (twl6040_power_mode) {
59 clk_id = TWL6040_SYSCLK_SEL_HPPLL;
60 freq = 38400000;
61 } else {
62 clk_id = TWL6040_SYSCLK_SEL_LPPLL;
63 freq = 32768;
64 }
65
66 /* set the codec mclk */
67 ret = snd_soc_dai_set_sysclk(codec_dai, clk_id, freq,
68 SND_SOC_CLOCK_IN);
69 if (ret) {
70 printk(KERN_ERR "can't set codec system clock\n");
71 return ret;
72 }
Liam Girdwoodede6aa92011-02-07 21:07:48 +000073 list_for_each_entry(dsp_params, &rtd->dsp[stream].fe_clients, list_fe) {
74
75 if (dsp_params->fe->cpu_dai->id != ABE_FRONTEND_DAI_MODEM)
76 continue;
77
78 if (!mcbsp_cfg) {
79 modem_substream[stream] =
80 snd_soc_get_dai_substream(rtd->card,
81 OMAP_ABE_BE_MM_EXT1,
82 substream->stream);
83 if (modem_substream[stream] == NULL)
84 return -ENODEV;
85
86 modem_rtd = modem_substream[stream]->private_data;
87
88 /* Set cpu DAI configuration */
89 ret = snd_soc_dai_set_fmt(modem_rtd->cpu_dai,
90 SND_SOC_DAIFMT_I2S |
91 SND_SOC_DAIFMT_NB_NF |
92 SND_SOC_DAIFMT_CBM_CFM);
93 mcbsp_cfg = 1;
94 }
95 if (ret < 0) {
96 printk(KERN_ERR "can't set Modem cpu DAI configuration\n");
97 return ret;
98 }
99 }
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000100 return ret;
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500101}
102
Liam Girdwoodede6aa92011-02-07 21:07:48 +0000103static struct snd_soc_ops sdp4430_mcpdm_ops = {
104 .hw_params = sdp4430_mcpdm_hw_params,
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500105};
106
Liam Girdwoodede6aa92011-02-07 21:07:48 +0000107static int sdp4430_mcbsp_hw_params(struct snd_pcm_substream *substream,
108 struct snd_pcm_hw_params *params)
109{
110 struct snd_soc_pcm_runtime *rtd = substream->private_data;
111 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
112 int ret = 0;
113 unsigned int be_id;
114
115 be_id = rtd->dai_link->be_id;
116
117 if (be_id == OMAP_ABE_DAI_MM_FM) {
118 /* Set cpu DAI configuration */
119 ret = snd_soc_dai_set_fmt(cpu_dai,
120 SND_SOC_DAIFMT_I2S |
121 SND_SOC_DAIFMT_NB_NF |
122 SND_SOC_DAIFMT_CBM_CFM);
123 } else if (be_id == OMAP_ABE_DAI_BT_VX) {
124 ret = snd_soc_dai_set_fmt(cpu_dai,
125 SND_SOC_DAIFMT_DSP_B |
126 SND_SOC_DAIFMT_NB_IF |
127 SND_SOC_DAIFMT_CBM_CFM);
128 }
129
130 if (ret < 0) {
131 printk(KERN_ERR "can't set cpu DAI configuration\n");
132 return ret;
133 }
134
135 /*
136 * TODO: where does this clock come from (external source??) -
137 * do we need to enable it.
138 */
139 /* Set McBSP clock to external */
140 ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_SYSCLK_CLKS_FCLK,
141 64 * params_rate(params),
142 SND_SOC_CLOCK_IN);
143 if (ret < 0) {
144 printk(KERN_ERR "can't set cpu system clock\n");
145 return ret;
146 }
147 return 0;
148}
149
150static struct snd_soc_ops sdp4430_mcbsp_ops = {
151 .hw_params = sdp4430_mcbsp_hw_params,
152};
153
154static int sdp4430_dmic_hw_params(struct snd_pcm_substream *substream,
155 struct snd_pcm_hw_params *params)
156{
157 struct snd_soc_pcm_runtime *rtd = substream->private_data;
158 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
159 int ret = 0;
160
161 ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_DMIC_SYSCLK_PAD_CLKS,
162 19200000, SND_SOC_CLOCK_IN);
163 if (ret < 0) {
164 printk(KERN_ERR "can't set DMIC cpu system clock\n");
165 return ret;
166 }
167 ret = snd_soc_dai_set_clkdiv(cpu_dai, OMAP_DMIC_CLKDIV, 8);
168 if (ret < 0) {
169 printk(KERN_ERR "can't set DMIC cpu clock divider\n");
170 return ret;
171 }
172 return 0;
173}
174
175static struct snd_soc_ops sdp4430_dmic_ops = {
176 .hw_params = sdp4430_dmic_hw_params,
177};
178
179static int mcbsp_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
180 struct snd_pcm_hw_params *params)
181{
182 struct snd_interval *channels = hw_param_interval(params,
183 SNDRV_PCM_HW_PARAM_CHANNELS);
184 unsigned int be_id = rtd->dai_link->be_id;
185
186 if (be_id == OMAP_ABE_DAI_MM_FM)
187 channels->min = 2;
188 else if (be_id == OMAP_ABE_DAI_BT_VX)
189 channels->min = 1;
190 snd_mask_set(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT -
191 SNDRV_PCM_HW_PARAM_FIRST_MASK],
192 SNDRV_PCM_FORMAT_S16_LE);
193 return 0;
194}
195
196static int dmic_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
197 struct snd_pcm_hw_params *params)
198{
199 struct snd_interval *rate = hw_param_interval(params,
200 SNDRV_PCM_HW_PARAM_RATE);
201
202 /* The ABE will covert the FE rate to 96k */
203 rate->min = rate->max = 96000;
204
205 snd_mask_set(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT -
206 SNDRV_PCM_HW_PARAM_FIRST_MASK],
207 SNDRV_PCM_FORMAT_S32_LE);
208 return 0;
209}
210
Jorge Eduardo Candelaria96dc2272010-12-10 20:45:19 -0600211/* Headset jack */
212static struct snd_soc_jack hs_jack;
213
214/*Headset jack detection DAPM pins */
215static struct snd_soc_jack_pin hs_jack_pins[] = {
216 {
217 .pin = "Headset Mic",
218 .mask = SND_JACK_MICROPHONE,
219 },
220 {
221 .pin = "Headset Stereophone",
222 .mask = SND_JACK_HEADPHONE,
223 },
224};
225
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500226static int sdp4430_get_power_mode(struct snd_kcontrol *kcontrol,
227 struct snd_ctl_elem_value *ucontrol)
228{
229 ucontrol->value.integer.value[0] = twl6040_power_mode;
230 return 0;
231}
232
233static int sdp4430_set_power_mode(struct snd_kcontrol *kcontrol,
234 struct snd_ctl_elem_value *ucontrol)
235{
236 if (twl6040_power_mode == ucontrol->value.integer.value[0])
237 return 0;
238
239 twl6040_power_mode = ucontrol->value.integer.value[0];
240
241 return 1;
242}
243
244static const char *power_texts[] = {"Low-Power", "High-Performance"};
245
246static const struct soc_enum sdp4430_enum[] = {
247 SOC_ENUM_SINGLE_EXT(2, power_texts),
248};
249
250static const struct snd_kcontrol_new sdp4430_controls[] = {
251 SOC_ENUM_EXT("TWL6040 Power Mode", sdp4430_enum[0],
252 sdp4430_get_power_mode, sdp4430_set_power_mode),
253};
254
255/* SDP4430 machine DAPM */
256static const struct snd_soc_dapm_widget sdp4430_twl6040_dapm_widgets[] = {
257 SND_SOC_DAPM_MIC("Ext Mic", NULL),
258 SND_SOC_DAPM_SPK("Ext Spk", NULL),
259 SND_SOC_DAPM_MIC("Headset Mic", NULL),
260 SND_SOC_DAPM_HP("Headset Stereophone", NULL),
Jorge Eduardo Candelaria7254e2b2010-05-18 12:44:17 -0500261 SND_SOC_DAPM_SPK("Earphone Spk", NULL),
Jorge Eduardo Candelaria23ac3b62010-12-08 10:55:05 -0600262 SND_SOC_DAPM_INPUT("Aux/FM Stereo In"),
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500263};
264
265static const struct snd_soc_dapm_route audio_map[] = {
266 /* External Mics: MAINMIC, SUBMIC with bias*/
267 {"MAINMIC", NULL, "Main Mic Bias"},
268 {"SUBMIC", NULL, "Main Mic Bias"},
269 {"Main Mic Bias", NULL, "Ext Mic"},
270
271 /* External Speakers: HFL, HFR */
272 {"Ext Spk", NULL, "HFL"},
273 {"Ext Spk", NULL, "HFR"},
274
275 /* Headset Mic: HSMIC with bias */
276 {"HSMIC", NULL, "Headset Mic Bias"},
277 {"Headset Mic Bias", NULL, "Headset Mic"},
278
279 /* Headset Stereophone (Headphone): HSOL, HSOR */
280 {"Headset Stereophone", NULL, "HSOL"},
281 {"Headset Stereophone", NULL, "HSOR"},
Jorge Eduardo Candelaria7254e2b2010-05-18 12:44:17 -0500282
283 /* Earphone speaker */
284 {"Earphone Spk", NULL, "EP"},
Jorge Eduardo Candelaria23ac3b62010-12-08 10:55:05 -0600285
286 /* Aux/FM Stereo In: AFML, AFMR */
287 {"AFML", NULL, "Aux/FM Stereo In"},
288 {"AFMR", NULL, "Aux/FM Stereo In"},
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500289};
290
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000291static int sdp4430_twl6040_init(struct snd_soc_pcm_runtime *rtd)
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500292{
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000293 struct snd_soc_codec *codec = rtd->codec;
Liam Girdwoodce6120c2010-11-05 15:53:46 +0200294 struct snd_soc_dapm_context *dapm = &codec->dapm;
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500295 int ret;
296
297 /* Add SDP4430 specific controls */
298 ret = snd_soc_add_controls(codec, sdp4430_controls,
299 ARRAY_SIZE(sdp4430_controls));
300 if (ret)
301 return ret;
302
303 /* Add SDP4430 specific widgets */
Liam Girdwoodce6120c2010-11-05 15:53:46 +0200304 ret = snd_soc_dapm_new_controls(dapm, sdp4430_twl6040_dapm_widgets,
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500305 ARRAY_SIZE(sdp4430_twl6040_dapm_widgets));
306 if (ret)
307 return ret;
308
309 /* Set up SDP4430 specific audio path audio_map */
Liam Girdwoodce6120c2010-11-05 15:53:46 +0200310 snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500311
312 /* SDP4430 connected pins */
Liam Girdwoodce6120c2010-11-05 15:53:46 +0200313 snd_soc_dapm_enable_pin(dapm, "Ext Mic");
314 snd_soc_dapm_enable_pin(dapm, "Ext Spk");
Jorge Eduardo Candelaria23ac3b62010-12-08 10:55:05 -0600315 snd_soc_dapm_enable_pin(dapm, "AFML");
316 snd_soc_dapm_enable_pin(dapm, "AFMR");
Liam Girdwoodce6120c2010-11-05 15:53:46 +0200317 snd_soc_dapm_enable_pin(dapm, "Headset Mic");
318 snd_soc_dapm_enable_pin(dapm, "Headset Stereophone");
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500319
Liam Girdwoodede6aa92011-02-07 21:07:48 +0000320 /* allow audio paths from the audio modem to run during suspend */
321 snd_soc_dapm_ignore_suspend(dapm, "Ext Mic");
322 snd_soc_dapm_ignore_suspend(dapm, "Ext Spk");
323 snd_soc_dapm_ignore_suspend(dapm, "AFML");
324 snd_soc_dapm_ignore_suspend(dapm, "AFMR");
325 snd_soc_dapm_ignore_suspend(dapm, "Headset Mic");
326 snd_soc_dapm_ignore_suspend(dapm, "Headset Stereophone");
327
Liam Girdwoodce6120c2010-11-05 15:53:46 +0200328 ret = snd_soc_dapm_sync(dapm);
Jorge Eduardo Candelaria96dc2272010-12-10 20:45:19 -0600329 if (ret)
330 return ret;
331
332 /* Headset jack detection */
333 ret = snd_soc_jack_new(codec, "Headset Jack",
334 SND_JACK_HEADSET, &hs_jack);
335 if (ret)
336 return ret;
337
338 ret = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins),
339 hs_jack_pins);
340
341 if (machine_is_omap_4430sdp())
342 twl6040_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADSET);
343 else
344 snd_soc_jack_report(&hs_jack, SND_JACK_HEADSET, SND_JACK_HEADSET);
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500345
346 return ret;
347}
348
Liam Girdwoodede6aa92011-02-07 21:07:48 +0000349/* TODO: make this a separate BT CODEC driver or DUMMY */
350static struct snd_soc_dai_driver dai[] = {
351{
352 .name = "Bluetooth",
353 .playback = {
354 .stream_name = "Playback",
355 .channels_min = 1,
356 .channels_max = 2,
357 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
358 SNDRV_PCM_RATE_48000,
359 .formats = SNDRV_PCM_FMTBIT_S16_LE,
360 },
361 .capture = {
362 .stream_name = "Capture",
363 .channels_min = 1,
364 .channels_max = 2,
365 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
366 SNDRV_PCM_RATE_48000,
367 .formats = SNDRV_PCM_FMTBIT_S16_LE,
368 },
369},
370/* TODO: make this a separate FM CODEC driver or DUMMY */
371{
372 .name = "FM Digital",
373 .playback = {
374 .stream_name = "Playback",
375 .channels_min = 1,
376 .channels_max = 2,
377 .rates = SNDRV_PCM_RATE_48000,
378 .formats = SNDRV_PCM_FMTBIT_S16_LE,
379 },
380 .capture = {
381 .stream_name = "Capture",
382 .channels_min = 1,
383 .channels_max = 2,
384 .rates = SNDRV_PCM_RATE_48000,
385 .formats = SNDRV_PCM_FMTBIT_S16_LE,
386 },
387},
388{
389 .name = "HDMI",
390 .playback = {
391 .stream_name = "Playback",
392 .channels_min = 2,
393 .channels_max = 8,
394 .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
395 SNDRV_PCM_RATE_48000,
396 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
397 },
398},
399};
400
401static const char *mm1_be[] = {
402 OMAP_ABE_BE_PDM_DL1,
403 OMAP_ABE_BE_PDM_UL1,
404 OMAP_ABE_BE_PDM_DL2,
405 OMAP_ABE_BE_BT_VX,
406 OMAP_ABE_BE_MM_EXT0,
407 OMAP_ABE_BE_DMIC0,
408 OMAP_ABE_BE_DMIC1,
409 OMAP_ABE_BE_DMIC2,
410};
411
412struct snd_soc_dsp_link fe_media = {
413 .supported_be = mm1_be,
414 .num_be = ARRAY_SIZE(mm1_be),
415 .fe_playback_channels = 2,
416 .fe_capture_channels = 8,
417 .trigger =
418 {SND_SOC_DSP_TRIGGER_BESPOKE, SND_SOC_DSP_TRIGGER_BESPOKE},
419};
420
421static const char *mm2_be[] = {
422 OMAP_ABE_BE_PDM_UL1,
423 OMAP_ABE_BE_BT_VX,
424 OMAP_ABE_BE_MM_EXT0,
425 OMAP_ABE_BE_DMIC0,
426 OMAP_ABE_BE_DMIC1,
427 OMAP_ABE_BE_DMIC2,
428};
429
430struct snd_soc_dsp_link fe_media_capture = {
431 .supported_be = mm2_be,
432 .num_be = ARRAY_SIZE(mm2_be),
433 .fe_capture_channels = 8,
434 .trigger =
435 {SND_SOC_DSP_TRIGGER_BESPOKE, SND_SOC_DSP_TRIGGER_BESPOKE},
436};
437
438static const char *tones_be[] = {
439 OMAP_ABE_BE_PDM_DL1,
440 OMAP_ABE_BE_PDM_DL2,
441 OMAP_ABE_BE_BT_VX,
442 OMAP_ABE_BE_MM_EXT0,
443};
444
445struct snd_soc_dsp_link fe_tones = {
446 .supported_be = tones_be,
447 .num_be = ARRAY_SIZE(tones_be),
448 .fe_playback_channels = 2,
449 .trigger =
450 {SND_SOC_DSP_TRIGGER_BESPOKE, SND_SOC_DSP_TRIGGER_BESPOKE},
451};
452
453static const char *vib_be[] = {
454 OMAP_ABE_BE_PDM_VIB,
455};
456
457struct snd_soc_dsp_link fe_vib = {
458 .supported_be = vib_be,
459 .num_be = ARRAY_SIZE(vib_be),
460 .fe_playback_channels = 2,
461 .trigger =
462 {SND_SOC_DSP_TRIGGER_BESPOKE, SND_SOC_DSP_TRIGGER_BESPOKE},
463};
464
465static const char *modem_be[] = {
466 OMAP_ABE_BE_PDM_DL1,
467 OMAP_ABE_BE_PDM_UL1,
468 OMAP_ABE_BE_PDM_DL2,
469 OMAP_ABE_BE_BT_VX,
470 OMAP_ABE_BE_DMIC0,
471 OMAP_ABE_BE_DMIC1,
472 OMAP_ABE_BE_DMIC2,
473};
474
475struct snd_soc_dsp_link fe_modem = {
476 .supported_be = modem_be,
477 .num_be = ARRAY_SIZE(modem_be),
478 .fe_playback_channels = 2,
479 .fe_capture_channels = 2,
480 .trigger =
481 {SND_SOC_DSP_TRIGGER_BESPOKE, SND_SOC_DSP_TRIGGER_BESPOKE},
482};
483
484static const char *mm_lp_be[] = {
485 OMAP_ABE_BE_PDM_DL1,
486 OMAP_ABE_BE_PDM_DL2,
487 OMAP_ABE_BE_BT_VX,
488 OMAP_ABE_BE_MM_EXT0,
489};
490
491struct snd_soc_dsp_link fe_lp_media = {
492 .supported_be = mm_lp_be,
493 .num_be = ARRAY_SIZE(mm_lp_be),
494 .fe_playback_channels = 2,
495 .trigger =
496 {SND_SOC_DSP_TRIGGER_BESPOKE, SND_SOC_DSP_TRIGGER_BESPOKE},
497};
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500498/* Digital audio interface glue - connects codec <--> CPU */
Liam Girdwoodede6aa92011-02-07 21:07:48 +0000499static struct snd_soc_dai_link sdp4430_dai[] = {
500
501/*
502 * Frontend DAIs - i.e. userspace visible interfaces (ALSA PCMs)
503 */
504
505 {
506 .name = "SDP4430 Media",
507 .stream_name = "Multimedia",
508
509 /* ABE components - MM-UL & MM_DL */
510 .cpu_dai_name = "MultiMedia1",
511 .platform_name = "omap-pcm-audio",
512
513 .dynamic = 1, /* BE is dynamic */
514 .dsp_link = &fe_media,
515 },
516 {
517 .name = "SDP4430 Media Capture",
518 .stream_name = "Multimedia Capture",
519
520 /* ABE components - MM-UL2 */
521 .cpu_dai_name = "MultiMedia2",
522 .platform_name = "omap-pcm-audio",
523
524 .dynamic = 1, /* BE is dynamic */
525 .dsp_link = &fe_media_capture,
526 },
527 {
528 .name = "SDP4430 Voice",
529 .stream_name = "Voice",
530
531 /* ABE components - VX-UL & VX-DL */
532 .cpu_dai_name = "Voice",
533 .platform_name = "omap-pcm-audio",
534
535 .dynamic = 1, /* BE is dynamic */
536 .dsp_link = &fe_media,
537 .no_host_mode = SND_SOC_DAI_LINK_OPT_HOST,
538 },
539 {
540 .name = "SDP4430 Tones Playback",
541 .stream_name = "Tone Playback",
542
543 /* ABE components - TONES_DL */
544 .cpu_dai_name = "Tones",
545 .platform_name = "omap-pcm-audio",
546
547 .dynamic = 1, /* BE is dynamic */
548 .dsp_link = &fe_tones,
549 },
550 {
551 .name = "SDP4430 Vibra Playback",
552 .stream_name = "VIB-DL",
553
554 /* ABE components - DMIC UL 2 */
555 .cpu_dai_name = "Vibra",
556 .platform_name = "omap-pcm-audio",
557
558 .dynamic = 1, /* BE is dynamic */
559 .dsp_link = &fe_vib,
560 },
561 {
562 .name = "SDP4430 MODEM",
563 .stream_name = "MODEM",
564
565 /* ABE components - MODEM <-> McBSP2 */
566 .cpu_dai_name = "MODEM",
567 .platform_name = "aess",
568
569 .dynamic = 1, /* BE is dynamic */
570 .dsp_link = &fe_modem,
571 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
572 .ignore_suspend = 1,
573 },
574 {
575 .name = "SDP4430 Media LP",
576 .stream_name = "Multimedia",
577
578 /* ABE components - MM-DL (mmap) */
579 .cpu_dai_name = "MultiMedia1 LP",
580 .platform_name = "aess",
581
582 .dynamic = 1, /* BE is dynamic */
583 .dsp_link = &fe_lp_media,
584 },
585 {
586 .name = "Legacy McBSP",
587 .stream_name = "Multimedia",
588
589 /* ABE components - MCBSP2 - MM-EXT */
590 .cpu_dai_name = "omap-mcbsp-dai.1",
591 .platform_name = "omap-pcm-audio",
592
593 /* FM */
594 .codec_dai_name = "FM Digital",
595
596 .no_codec = 1, /* TODO: have a dummy CODEC */
597 .ops = &sdp4430_mcbsp_ops,
598 },
599 {
600 .name = "Legacy McPDM",
601 .stream_name = "Headset Playback",
602
603 /* ABE components - DL1 */
604 .cpu_dai_name = "mcpdm-dl",
605 .platform_name = "omap-pcm-audio",
606
607 /* Phoenix - DL1 DAC */
608 .codec_dai_name = "twl6040-dl1",
609 .codec_name = "twl6040-codec",
610
611 .ops = &sdp4430_mcpdm_ops,
612 },
613 {
614 .name = "Legacy DMIC",
615 .stream_name = "DMIC Capture",
616
617 /* ABE components - DMIC0 */
618 .cpu_dai_name = "omap-dmic-dai-0",
619 .platform_name = "omap-pcm-audio",
620
621 /* DMIC codec */
622 .codec_dai_name = "dmic-hifi",
623 .codec_name = "dmic-codec.0",
624
625 .ops = &sdp4430_dmic_ops,
626 },
627
628/*
629 * Backend DAIs - i.e. dynamically matched interfaces, invisible to userspace.
630 * Matched to above interfaces at runtime, based upon use case.
631 */
632
633 {
634 .name = OMAP_ABE_BE_PDM_DL1,
635 .stream_name = "HS Playback",
636
637 /* ABE components - DL1 */
638 .cpu_dai_name = "mcpdm-dl1",
639 .platform_name = "aess",
640
641 /* Phoenix - DL1 DAC */
642 .codec_dai_name = "twl6040-dl1",
643 .codec_name = "twl6040-codec",
644
645 .no_pcm = 1, /* don't create ALSA pcm for this */
646 .init = sdp4430_twl6040_init,
647 .ops = &sdp4430_mcpdm_ops,
648 .be_id = OMAP_ABE_DAI_PDM_DL1,
649 },
650 {
651 .name = OMAP_ABE_BE_PDM_UL1,
652 .stream_name = "Analog Capture",
653
654 /* ABE components - UL1 */
655 .cpu_dai_name = "mcpdm-ul1",
656 .platform_name = "aess",
657
658 /* Phoenix - UL ADC */
659 .codec_dai_name = "twl6040-ul",
660 .codec_name = "twl6040-codec",
661
662 .no_pcm = 1, /* don't create ALSA pcm for this */
663 .ops = &sdp4430_mcpdm_ops,
664 .be_id = OMAP_ABE_DAI_PDM_UL,
665 },
666 {
667 .name = OMAP_ABE_BE_PDM_DL2,
668 .stream_name = "HF Playback",
669
670 /* ABE components - DL2 */
671 .cpu_dai_name = "mcpdm-dl2",
672 .platform_name = "aess",
673
674 /* Phoenix - DL2 DAC */
675 .codec_dai_name = "twl6040-dl2",
676 .codec_name = "twl6040-codec",
677
678 .no_pcm = 1, /* don't create ALSA pcm for this */
679 .ops = &sdp4430_mcpdm_ops,
680 .be_id = OMAP_ABE_DAI_PDM_DL2,
681 },
682 {
683 .name = OMAP_ABE_BE_PDM_VIB,
684 .stream_name = "Vibra",
685
686 /* ABE components - VIB1 DL */
687 .cpu_dai_name = "mcpdm-vib",
688 .platform_name = "aess",
689
690 /* Phoenix - PDM to PWM */
691 .codec_dai_name = "twl6040-vib",
692 .codec_name = "twl6040-codec",
693
694 .no_pcm = 1, /* don't create ALSA pcm for this */
695 .ops = &sdp4430_mcpdm_ops,
696 .be_id = OMAP_ABE_DAI_PDM_VIB,
697 },
698 {
699 .name = OMAP_ABE_BE_BT_VX,
700 .stream_name = "BT",
701
702 /* ABE components - MCBSP1 - BT-VX */
703 .cpu_dai_name = "omap-mcbsp-dai.0",
704 .platform_name = "aess",
705
706 /* Bluetooth */
707 .codec_dai_name = "Bluetooth",
708
709 .no_pcm = 1, /* don't create ALSA pcm for this */
710 .no_codec = 1, /* TODO: have a dummy CODEC */
711 .be_hw_params_fixup = mcbsp_be_hw_params_fixup,
712 .ops = &sdp4430_mcbsp_ops,
713 .be_id = OMAP_ABE_DAI_BT_VX,
714 },
715 {
716 .name = OMAP_ABE_BE_MM_EXT0,
717 .stream_name = "FM",
718
719 /* ABE components - MCBSP2 - MM-EXT */
720 .cpu_dai_name = "omap-mcbsp-dai.1",
721 .platform_name = "aess",
722
723 /* FM */
724 .codec_dai_name = "FM Digital",
725
726 .no_pcm = 1, /* don't create ALSA pcm for this */
727 .no_codec = 1, /* TODO: have a dummy CODEC */
728 .be_hw_params_fixup = mcbsp_be_hw_params_fixup,
729 .ops = &sdp4430_mcbsp_ops,
730 .be_id = OMAP_ABE_DAI_MM_FM,
731 },
732 {
733 .name = OMAP_ABE_BE_MM_EXT1,
734 .stream_name = "MODEM",
735
736 /* ABE components - MCBSP2 - MM-EXT */
737 .cpu_dai_name = "omap-mcbsp-dai.1",
738 .platform_name = "aess",
739
740 /* MODEM */
741 .codec_dai_name = "MODEM",
742
743 .no_pcm = 1, /* don't create ALSA pcm for this */
744 .no_codec = 1, /* TODO: have a dummy CODEC */
745 .be_hw_params_fixup = mcbsp_be_hw_params_fixup,
746 .ops = &sdp4430_mcbsp_ops,
747 .be_id = OMAP_ABE_DAI_MODEM,
748 .ignore_suspend = 1,
749 },
750 {
751 .name = OMAP_ABE_BE_DMIC0,
752 .stream_name = "DMIC0",
753
754 /* ABE components - DMIC UL 1 */
755 .cpu_dai_name = "omap-dmic-abe-dai-0",
756 .platform_name = "aess",
757
758 /* DMIC 0 */
759 .codec_dai_name = "dmic-hifi",
760 .codec_name = "dmic-codec.0",
761 .ops = &sdp4430_dmic_ops,
762
763 .no_pcm = 1, /* don't create ALSA pcm for this */
764 .be_hw_params_fixup = dmic_be_hw_params_fixup,
765 .be_id = OMAP_ABE_DAI_DMIC0,
766 },
767 {
768 .name = OMAP_ABE_BE_DMIC1,
769 .stream_name = "DMIC1",
770
771 /* ABE components - DMIC UL 1 */
772 .cpu_dai_name = "omap-dmic-abe-dai-1",
773 .platform_name = "aess",
774
775 /* DMIC 1 */
776 .codec_dai_name = "dmic-hifi",
777 .codec_name = "dmic-codec.1",
778 .ops = &sdp4430_dmic_ops,
779
780 .no_pcm = 1, /* don't create ALSA pcm for this */
781 .be_hw_params_fixup = dmic_be_hw_params_fixup,
782 .be_id = OMAP_ABE_DAI_DMIC1,
783 },
784 {
785 .name = OMAP_ABE_BE_DMIC2,
786 .stream_name = "DMIC2",
787
788 /* ABE components - DMIC UL 2 */
789 .cpu_dai_name = "omap-dmic-abe-dai-2",
790 .platform_name = "aess",
791
792 /* DMIC 2 */
793 .codec_dai_name = "dmic-hifi",
794 .codec_name = "dmic-codec.2",
795 .ops = &sdp4430_dmic_ops,
796
797 .no_pcm = 1, /* don't create ALSA pcm for this */
798 .be_hw_params_fixup = dmic_be_hw_params_fixup,
799 .be_id = OMAP_ABE_DAI_DMIC2,
800 },
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500801};
802
803/* Audio machine driver */
804static struct snd_soc_card snd_soc_sdp4430 = {
805 .name = "SDP4430",
Liam Girdwoodede6aa92011-02-07 21:07:48 +0000806 .dai_link = sdp4430_dai,
807 .num_links = ARRAY_SIZE(sdp4430_dai),
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500808};
809
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500810static struct platform_device *sdp4430_snd_device;
Liam Girdwoodede6aa92011-02-07 21:07:48 +0000811struct i2c_adapter *adapter;
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500812
813static int __init sdp4430_soc_init(void)
814{
815 int ret;
816
Jarkko Nikulaec588ae2010-10-06 16:47:26 +0300817 if (!machine_is_omap_4430sdp())
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500818 return -ENODEV;
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500819 printk(KERN_INFO "SDP4430 SoC init\n");
820
821 sdp4430_snd_device = platform_device_alloc("soc-audio", -1);
822 if (!sdp4430_snd_device) {
823 printk(KERN_ERR "Platform device allocation failed\n");
824 return -ENOMEM;
825 }
826
Liam Girdwoodede6aa92011-02-07 21:07:48 +0000827 ret = snd_soc_register_dais(&sdp4430_snd_device->dev, dai, ARRAY_SIZE(dai));
828 if (ret < 0)
829 goto err;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000830 platform_set_drvdata(sdp4430_snd_device, &snd_soc_sdp4430);
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500831
832 ret = platform_device_add(sdp4430_snd_device);
833 if (ret)
834 goto err;
835
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500836 return 0;
837
838err:
839 printk(KERN_ERR "Unable to add platform device\n");
840 platform_device_put(sdp4430_snd_device);
841 return ret;
842}
843module_init(sdp4430_soc_init);
844
845static void __exit sdp4430_soc_exit(void)
846{
847 platform_device_unregister(sdp4430_snd_device);
848}
849module_exit(sdp4430_soc_exit);
850
851MODULE_AUTHOR("Misael Lopez Cruz <x0052729@ti.com>");
852MODULE_DESCRIPTION("ALSA SoC SDP4430");
853MODULE_LICENSE("GPL");
854