blob: 168087f478ff384b11181cd7da62445fe6403c40 [file] [log] [blame]
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -05001/*
2 * sdp4430.c -- SoC audio for TI OMAP4430 SDP
3 *
Liam Girdwood63a06702011-05-01 13:45:18 +01004 * Author: Misael Lopez Cruz <misael.lopez@ti.com>
5 * Liam Girdwood <lrg@ti.com>
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -05006 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * version 2 as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
19 * 02110-1301 USA
20 *
21 */
22
23#include <linux/clk.h>
24#include <linux/platform_device.h>
Misael Lopez Cruzf4b3dc32011-05-01 21:27:00 -050025#include <linux/mfd/twl6040.h>
26
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -050027#include <sound/core.h>
28#include <sound/pcm.h>
Liam Girdwoodede6aa92011-02-07 21:07:48 +000029#include <sound/pcm_params.h>
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -050030#include <sound/soc.h>
Liam Girdwoodede6aa92011-02-07 21:07:48 +000031#include <sound/soc-dapm.h>
Jorge Eduardo Candelaria96dc2272010-12-10 20:45:19 -060032#include <sound/jack.h>
Liam Girdwoodede6aa92011-02-07 21:07:48 +000033#include <sound/soc-dsp.h>
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -050034
35#include <asm/mach-types.h>
36#include <plat/hardware.h>
37#include <plat/mux.h>
38
Liam Girdwoodede6aa92011-02-07 21:07:48 +000039#include "omap-mcpdm.h"
40#include "omap-abe.h"
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -050041#include "omap-pcm.h"
Liam Girdwoodede6aa92011-02-07 21:07:48 +000042#include "omap-mcbsp.h"
43#include "omap-dmic.h"
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -050044#include "../codecs/twl6040.h"
45
46static int twl6040_power_mode;
Liam Girdwoodede6aa92011-02-07 21:07:48 +000047static int mcbsp_cfg;
Liam Girdwood8cc57052011-02-07 21:18:06 +000048static struct i2c_client *tps6130x_client;
49static struct i2c_board_info tps6130x_hwmon_info = {
50 I2C_BOARD_INFO("tps6130x", 0x33),
51};
52
53/* configure the TPS6130x Handsfree Boost Converter */
54static int sdp4430_tps6130x_configure(void)
55{
56 u8 data[2];
57
58 data[0] = 0x01;
59 data[1] = 0x60;
60 if (i2c_master_send(tps6130x_client, data, 2) != 2)
61 printk(KERN_ERR "I2C write to TPS6130x failed\n");
62
63 data[0] = 0x02;
64 if (i2c_master_send(tps6130x_client, data, 2) != 2)
65 printk(KERN_ERR "I2C write to TPS6130x failed\n");
66
67 return 0;
68}
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -050069
Liam Girdwoodede6aa92011-02-07 21:07:48 +000070static int sdp4430_mcpdm_hw_params(struct snd_pcm_substream *substream,
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -050071 struct snd_pcm_hw_params *params)
72{
73 struct snd_soc_pcm_runtime *rtd = substream->private_data;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +000074 struct snd_soc_dai *codec_dai = rtd->codec_dai;
Liam Girdwoodede6aa92011-02-07 21:07:48 +000075 struct snd_soc_pcm_runtime *modem_rtd;
76 struct snd_pcm_substream *modem_substream[2];
77 struct snd_soc_dsp_params *dsp_params;
78 int clk_id, freq, ret, stream = substream->stream;
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -050079
80 if (twl6040_power_mode) {
81 clk_id = TWL6040_SYSCLK_SEL_HPPLL;
82 freq = 38400000;
83 } else {
84 clk_id = TWL6040_SYSCLK_SEL_LPPLL;
85 freq = 32768;
86 }
87
88 /* set the codec mclk */
89 ret = snd_soc_dai_set_sysclk(codec_dai, clk_id, freq,
90 SND_SOC_CLOCK_IN);
91 if (ret) {
92 printk(KERN_ERR "can't set codec system clock\n");
93 return ret;
94 }
Liam Girdwoodede6aa92011-02-07 21:07:48 +000095 list_for_each_entry(dsp_params, &rtd->dsp[stream].fe_clients, list_fe) {
96
97 if (dsp_params->fe->cpu_dai->id != ABE_FRONTEND_DAI_MODEM)
98 continue;
99
100 if (!mcbsp_cfg) {
101 modem_substream[stream] =
102 snd_soc_get_dai_substream(rtd->card,
103 OMAP_ABE_BE_MM_EXT1,
104 substream->stream);
105 if (modem_substream[stream] == NULL)
106 return -ENODEV;
107
108 modem_rtd = modem_substream[stream]->private_data;
109
110 /* Set cpu DAI configuration */
111 ret = snd_soc_dai_set_fmt(modem_rtd->cpu_dai,
112 SND_SOC_DAIFMT_I2S |
113 SND_SOC_DAIFMT_NB_NF |
114 SND_SOC_DAIFMT_CBM_CFM);
115 mcbsp_cfg = 1;
116 }
117 if (ret < 0) {
118 printk(KERN_ERR "can't set Modem cpu DAI configuration\n");
119 return ret;
120 }
121 }
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000122 return ret;
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500123}
124
Liam Girdwoodede6aa92011-02-07 21:07:48 +0000125static struct snd_soc_ops sdp4430_mcpdm_ops = {
126 .hw_params = sdp4430_mcpdm_hw_params,
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500127};
128
Liam Girdwoodede6aa92011-02-07 21:07:48 +0000129static int sdp4430_mcbsp_hw_params(struct snd_pcm_substream *substream,
130 struct snd_pcm_hw_params *params)
131{
132 struct snd_soc_pcm_runtime *rtd = substream->private_data;
133 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
134 int ret = 0;
135 unsigned int be_id;
136
137 be_id = rtd->dai_link->be_id;
138
139 if (be_id == OMAP_ABE_DAI_MM_FM) {
140 /* Set cpu DAI configuration */
141 ret = snd_soc_dai_set_fmt(cpu_dai,
142 SND_SOC_DAIFMT_I2S |
143 SND_SOC_DAIFMT_NB_NF |
144 SND_SOC_DAIFMT_CBM_CFM);
145 } else if (be_id == OMAP_ABE_DAI_BT_VX) {
146 ret = snd_soc_dai_set_fmt(cpu_dai,
147 SND_SOC_DAIFMT_DSP_B |
148 SND_SOC_DAIFMT_NB_IF |
149 SND_SOC_DAIFMT_CBM_CFM);
150 }
151
152 if (ret < 0) {
153 printk(KERN_ERR "can't set cpu DAI configuration\n");
154 return ret;
155 }
156
157 /*
158 * TODO: where does this clock come from (external source??) -
159 * do we need to enable it.
160 */
161 /* Set McBSP clock to external */
162 ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_SYSCLK_CLKS_FCLK,
163 64 * params_rate(params),
164 SND_SOC_CLOCK_IN);
165 if (ret < 0) {
166 printk(KERN_ERR "can't set cpu system clock\n");
167 return ret;
168 }
169 return 0;
170}
171
172static struct snd_soc_ops sdp4430_mcbsp_ops = {
173 .hw_params = sdp4430_mcbsp_hw_params,
174};
175
176static int sdp4430_dmic_hw_params(struct snd_pcm_substream *substream,
177 struct snd_pcm_hw_params *params)
178{
179 struct snd_soc_pcm_runtime *rtd = substream->private_data;
180 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
181 int ret = 0;
182
183 ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_DMIC_SYSCLK_PAD_CLKS,
184 19200000, SND_SOC_CLOCK_IN);
185 if (ret < 0) {
186 printk(KERN_ERR "can't set DMIC cpu system clock\n");
187 return ret;
188 }
189 ret = snd_soc_dai_set_clkdiv(cpu_dai, OMAP_DMIC_CLKDIV, 8);
190 if (ret < 0) {
191 printk(KERN_ERR "can't set DMIC cpu clock divider\n");
192 return ret;
193 }
194 return 0;
195}
196
197static struct snd_soc_ops sdp4430_dmic_ops = {
198 .hw_params = sdp4430_dmic_hw_params,
199};
200
201static int mcbsp_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
202 struct snd_pcm_hw_params *params)
203{
204 struct snd_interval *channels = hw_param_interval(params,
205 SNDRV_PCM_HW_PARAM_CHANNELS);
206 unsigned int be_id = rtd->dai_link->be_id;
207
208 if (be_id == OMAP_ABE_DAI_MM_FM)
209 channels->min = 2;
210 else if (be_id == OMAP_ABE_DAI_BT_VX)
211 channels->min = 1;
212 snd_mask_set(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT -
213 SNDRV_PCM_HW_PARAM_FIRST_MASK],
214 SNDRV_PCM_FORMAT_S16_LE);
215 return 0;
216}
217
218static int dmic_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
219 struct snd_pcm_hw_params *params)
220{
221 struct snd_interval *rate = hw_param_interval(params,
222 SNDRV_PCM_HW_PARAM_RATE);
223
224 /* The ABE will covert the FE rate to 96k */
225 rate->min = rate->max = 96000;
226
227 snd_mask_set(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT -
228 SNDRV_PCM_HW_PARAM_FIRST_MASK],
229 SNDRV_PCM_FORMAT_S32_LE);
230 return 0;
231}
232
Jorge Eduardo Candelaria96dc2272010-12-10 20:45:19 -0600233/* Headset jack */
234static struct snd_soc_jack hs_jack;
235
236/*Headset jack detection DAPM pins */
237static struct snd_soc_jack_pin hs_jack_pins[] = {
238 {
239 .pin = "Headset Mic",
240 .mask = SND_JACK_MICROPHONE,
241 },
242 {
243 .pin = "Headset Stereophone",
244 .mask = SND_JACK_HEADPHONE,
245 },
246};
247
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500248static int sdp4430_get_power_mode(struct snd_kcontrol *kcontrol,
249 struct snd_ctl_elem_value *ucontrol)
250{
251 ucontrol->value.integer.value[0] = twl6040_power_mode;
252 return 0;
253}
254
255static int sdp4430_set_power_mode(struct snd_kcontrol *kcontrol,
256 struct snd_ctl_elem_value *ucontrol)
257{
258 if (twl6040_power_mode == ucontrol->value.integer.value[0])
259 return 0;
260
261 twl6040_power_mode = ucontrol->value.integer.value[0];
262
263 return 1;
264}
265
266static const char *power_texts[] = {"Low-Power", "High-Performance"};
267
268static const struct soc_enum sdp4430_enum[] = {
269 SOC_ENUM_SINGLE_EXT(2, power_texts),
270};
271
272static const struct snd_kcontrol_new sdp4430_controls[] = {
273 SOC_ENUM_EXT("TWL6040 Power Mode", sdp4430_enum[0],
274 sdp4430_get_power_mode, sdp4430_set_power_mode),
275};
276
277/* SDP4430 machine DAPM */
278static const struct snd_soc_dapm_widget sdp4430_twl6040_dapm_widgets[] = {
279 SND_SOC_DAPM_MIC("Ext Mic", NULL),
280 SND_SOC_DAPM_SPK("Ext Spk", NULL),
281 SND_SOC_DAPM_MIC("Headset Mic", NULL),
282 SND_SOC_DAPM_HP("Headset Stereophone", NULL),
Jorge Eduardo Candelaria7254e2b2010-05-18 12:44:17 -0500283 SND_SOC_DAPM_SPK("Earphone Spk", NULL),
Jorge Eduardo Candelaria23ac3b62010-12-08 10:55:05 -0600284 SND_SOC_DAPM_INPUT("Aux/FM Stereo In"),
Misael Lopez Cruz685a4732011-04-25 20:23:20 -0500285 SND_SOC_DAPM_MIC("Digital Mic 0", NULL),
286 SND_SOC_DAPM_MIC("Digital Mic 1", NULL),
287 SND_SOC_DAPM_MIC("Digital Mic 2", NULL),
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500288};
289
290static const struct snd_soc_dapm_route audio_map[] = {
291 /* External Mics: MAINMIC, SUBMIC with bias*/
292 {"MAINMIC", NULL, "Main Mic Bias"},
293 {"SUBMIC", NULL, "Main Mic Bias"},
294 {"Main Mic Bias", NULL, "Ext Mic"},
295
296 /* External Speakers: HFL, HFR */
297 {"Ext Spk", NULL, "HFL"},
298 {"Ext Spk", NULL, "HFR"},
299
300 /* Headset Mic: HSMIC with bias */
301 {"HSMIC", NULL, "Headset Mic Bias"},
302 {"Headset Mic Bias", NULL, "Headset Mic"},
303
304 /* Headset Stereophone (Headphone): HSOL, HSOR */
305 {"Headset Stereophone", NULL, "HSOL"},
306 {"Headset Stereophone", NULL, "HSOR"},
Jorge Eduardo Candelaria7254e2b2010-05-18 12:44:17 -0500307
308 /* Earphone speaker */
309 {"Earphone Spk", NULL, "EP"},
Jorge Eduardo Candelaria23ac3b62010-12-08 10:55:05 -0600310
311 /* Aux/FM Stereo In: AFML, AFMR */
312 {"AFML", NULL, "Aux/FM Stereo In"},
313 {"AFMR", NULL, "Aux/FM Stereo In"},
Misael Lopez Cruz685a4732011-04-25 20:23:20 -0500314
315 /* Digital Mics: DMic0, DMic1, DMic2 with bias */
316 {"DMIC0", NULL, "Digital Mic1 Bias"},
317 {"Digital Mic1 Bias", NULL, "Digital Mic 0"},
318
319 {"DMIC1", NULL, "Digital Mic1 Bias"},
320 {"Digital Mic1 Bias", NULL, "Digital Mic 1"},
321
322 {"DMIC2", NULL, "Digital Mic1 Bias"},
323 {"Digital Mic1 Bias", NULL, "Digital Mic 2"},
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500324};
325
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000326static int sdp4430_twl6040_init(struct snd_soc_pcm_runtime *rtd)
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500327{
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000328 struct snd_soc_codec *codec = rtd->codec;
Liam Girdwoodce6120c2010-11-05 15:53:46 +0200329 struct snd_soc_dapm_context *dapm = &codec->dapm;
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500330 int ret;
331
332 /* Add SDP4430 specific controls */
333 ret = snd_soc_add_controls(codec, sdp4430_controls,
334 ARRAY_SIZE(sdp4430_controls));
335 if (ret)
336 return ret;
337
338 /* Add SDP4430 specific widgets */
Liam Girdwoodce6120c2010-11-05 15:53:46 +0200339 ret = snd_soc_dapm_new_controls(dapm, sdp4430_twl6040_dapm_widgets,
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500340 ARRAY_SIZE(sdp4430_twl6040_dapm_widgets));
341 if (ret)
342 return ret;
343
344 /* Set up SDP4430 specific audio path audio_map */
Liam Girdwoodce6120c2010-11-05 15:53:46 +0200345 snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500346
347 /* SDP4430 connected pins */
Liam Girdwoodce6120c2010-11-05 15:53:46 +0200348 snd_soc_dapm_enable_pin(dapm, "Ext Mic");
349 snd_soc_dapm_enable_pin(dapm, "Ext Spk");
Jorge Eduardo Candelaria23ac3b62010-12-08 10:55:05 -0600350 snd_soc_dapm_enable_pin(dapm, "AFML");
351 snd_soc_dapm_enable_pin(dapm, "AFMR");
Liam Girdwoodce6120c2010-11-05 15:53:46 +0200352 snd_soc_dapm_enable_pin(dapm, "Headset Mic");
353 snd_soc_dapm_enable_pin(dapm, "Headset Stereophone");
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500354
Liam Girdwoodede6aa92011-02-07 21:07:48 +0000355 /* allow audio paths from the audio modem to run during suspend */
356 snd_soc_dapm_ignore_suspend(dapm, "Ext Mic");
357 snd_soc_dapm_ignore_suspend(dapm, "Ext Spk");
358 snd_soc_dapm_ignore_suspend(dapm, "AFML");
359 snd_soc_dapm_ignore_suspend(dapm, "AFMR");
360 snd_soc_dapm_ignore_suspend(dapm, "Headset Mic");
361 snd_soc_dapm_ignore_suspend(dapm, "Headset Stereophone");
Misael Lopez Cruz685a4732011-04-25 20:23:20 -0500362 snd_soc_dapm_ignore_suspend(dapm, "Digital Mic 0");
363 snd_soc_dapm_ignore_suspend(dapm, "Digital Mic 1");
364 snd_soc_dapm_ignore_suspend(dapm, "Digital Mic 2");
Liam Girdwoodede6aa92011-02-07 21:07:48 +0000365
Liam Girdwoodce6120c2010-11-05 15:53:46 +0200366 ret = snd_soc_dapm_sync(dapm);
Jorge Eduardo Candelaria96dc2272010-12-10 20:45:19 -0600367 if (ret)
368 return ret;
369
370 /* Headset jack detection */
371 ret = snd_soc_jack_new(codec, "Headset Jack",
372 SND_JACK_HEADSET, &hs_jack);
373 if (ret)
374 return ret;
375
376 ret = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins),
377 hs_jack_pins);
378
379 if (machine_is_omap_4430sdp())
380 twl6040_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADSET);
381 else
382 snd_soc_jack_report(&hs_jack, SND_JACK_HEADSET, SND_JACK_HEADSET);
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500383
Misael Lopez Cruzae141a22011-04-29 01:52:45 -0500384 /* wait 500 ms before switching of HS power */
385 rtd->pmdown_time = 500;
386
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500387 return ret;
388}
389
Misael Lopez Cruzae141a22011-04-29 01:52:45 -0500390static int sdp4430_twl6040_dl2_init(struct snd_soc_pcm_runtime *rtd)
391{
392 /* wait 500 ms before switching of HF power */
393 rtd->pmdown_time = 500;
394
395 return 0;
396}
397
Misael Lopez Cruz47415f02011-04-27 23:56:32 -0500398/* SDP4430 digital microphones DAPM */
399static const struct snd_soc_dapm_widget sdp4430_dmic_dapm_widgets[] = {
400 SND_SOC_DAPM_MIC("Digital Mic Legacy", NULL),
401};
402
403static const struct snd_soc_dapm_route dmic_audio_map[] = {
404 {"DMic", NULL, "Digital Mic1 Bias"},
405 {"Digital Mic1 Bias", NULL, "Digital Mic Legacy"},
406};
407
408static int sdp4430_dmic_init(struct snd_soc_pcm_runtime *rtd)
409{
410 struct snd_soc_codec *codec = rtd->codec;
411 struct snd_soc_dapm_context *dapm = &codec->dapm;
412 int ret;
413
414 ret = snd_soc_dapm_new_controls(dapm, sdp4430_dmic_dapm_widgets,
415 ARRAY_SIZE(sdp4430_dmic_dapm_widgets));
416 if (ret)
417 return ret;
418
419 ret = snd_soc_dapm_add_routes(dapm, dmic_audio_map,
420 ARRAY_SIZE(dmic_audio_map));
421 if (ret)
422 return ret;
423
424 snd_soc_dapm_enable_pin(dapm, "Digital Mic Legacy");
425
426 ret = snd_soc_dapm_sync(dapm);
427
428 return ret;
429}
430
Liam Girdwoodede6aa92011-02-07 21:07:48 +0000431/* TODO: make this a separate BT CODEC driver or DUMMY */
432static struct snd_soc_dai_driver dai[] = {
433{
434 .name = "Bluetooth",
435 .playback = {
436 .stream_name = "Playback",
437 .channels_min = 1,
438 .channels_max = 2,
439 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
440 SNDRV_PCM_RATE_48000,
441 .formats = SNDRV_PCM_FMTBIT_S16_LE,
442 },
443 .capture = {
444 .stream_name = "Capture",
445 .channels_min = 1,
446 .channels_max = 2,
447 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
448 SNDRV_PCM_RATE_48000,
449 .formats = SNDRV_PCM_FMTBIT_S16_LE,
450 },
451},
452/* TODO: make this a separate FM CODEC driver or DUMMY */
453{
454 .name = "FM Digital",
455 .playback = {
456 .stream_name = "Playback",
457 .channels_min = 1,
458 .channels_max = 2,
459 .rates = SNDRV_PCM_RATE_48000,
460 .formats = SNDRV_PCM_FMTBIT_S16_LE,
461 },
462 .capture = {
463 .stream_name = "Capture",
464 .channels_min = 1,
465 .channels_max = 2,
466 .rates = SNDRV_PCM_RATE_48000,
467 .formats = SNDRV_PCM_FMTBIT_S16_LE,
468 },
469},
470{
471 .name = "HDMI",
472 .playback = {
473 .stream_name = "Playback",
474 .channels_min = 2,
475 .channels_max = 8,
476 .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
477 SNDRV_PCM_RATE_48000,
478 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
479 },
480},
481};
482
Liam Girdwoodede6aa92011-02-07 21:07:48 +0000483struct snd_soc_dsp_link fe_media = {
Liam Girdwood767dfac2011-06-03 14:26:23 +0100484 .playback = true,
485 .capture = true,
Liam Girdwoodede6aa92011-02-07 21:07:48 +0000486 .trigger =
487 {SND_SOC_DSP_TRIGGER_BESPOKE, SND_SOC_DSP_TRIGGER_BESPOKE},
488};
489
Liam Girdwoodede6aa92011-02-07 21:07:48 +0000490struct snd_soc_dsp_link fe_media_capture = {
Liam Girdwood767dfac2011-06-03 14:26:23 +0100491 .capture = true,
Liam Girdwoodede6aa92011-02-07 21:07:48 +0000492 .trigger =
493 {SND_SOC_DSP_TRIGGER_BESPOKE, SND_SOC_DSP_TRIGGER_BESPOKE},
494};
495
Liam Girdwoodede6aa92011-02-07 21:07:48 +0000496struct snd_soc_dsp_link fe_tones = {
Liam Girdwood767dfac2011-06-03 14:26:23 +0100497 .playback = true,
Liam Girdwoodede6aa92011-02-07 21:07:48 +0000498 .trigger =
499 {SND_SOC_DSP_TRIGGER_BESPOKE, SND_SOC_DSP_TRIGGER_BESPOKE},
500};
501
Liam Girdwoodede6aa92011-02-07 21:07:48 +0000502struct snd_soc_dsp_link fe_vib = {
Liam Girdwood767dfac2011-06-03 14:26:23 +0100503 .playback = true,
Liam Girdwoodede6aa92011-02-07 21:07:48 +0000504 .trigger =
505 {SND_SOC_DSP_TRIGGER_BESPOKE, SND_SOC_DSP_TRIGGER_BESPOKE},
506};
507
Liam Girdwoodede6aa92011-02-07 21:07:48 +0000508struct snd_soc_dsp_link fe_modem = {
Liam Girdwood767dfac2011-06-03 14:26:23 +0100509 .playback = true,
510 .capture = true,
Liam Girdwoodede6aa92011-02-07 21:07:48 +0000511 .trigger =
512 {SND_SOC_DSP_TRIGGER_BESPOKE, SND_SOC_DSP_TRIGGER_BESPOKE},
513};
514
Liam Girdwoodede6aa92011-02-07 21:07:48 +0000515struct snd_soc_dsp_link fe_lp_media = {
Liam Girdwood767dfac2011-06-03 14:26:23 +0100516 .playback = true,
Liam Girdwoodede6aa92011-02-07 21:07:48 +0000517 .trigger =
518 {SND_SOC_DSP_TRIGGER_BESPOKE, SND_SOC_DSP_TRIGGER_BESPOKE},
519};
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500520/* Digital audio interface glue - connects codec <--> CPU */
Liam Girdwoodede6aa92011-02-07 21:07:48 +0000521static struct snd_soc_dai_link sdp4430_dai[] = {
522
523/*
524 * Frontend DAIs - i.e. userspace visible interfaces (ALSA PCMs)
525 */
526
527 {
528 .name = "SDP4430 Media",
529 .stream_name = "Multimedia",
530
531 /* ABE components - MM-UL & MM_DL */
532 .cpu_dai_name = "MultiMedia1",
533 .platform_name = "omap-pcm-audio",
534
535 .dynamic = 1, /* BE is dynamic */
536 .dsp_link = &fe_media,
537 },
538 {
539 .name = "SDP4430 Media Capture",
540 .stream_name = "Multimedia Capture",
541
542 /* ABE components - MM-UL2 */
543 .cpu_dai_name = "MultiMedia2",
544 .platform_name = "omap-pcm-audio",
545
546 .dynamic = 1, /* BE is dynamic */
547 .dsp_link = &fe_media_capture,
548 },
549 {
550 .name = "SDP4430 Voice",
551 .stream_name = "Voice",
552
553 /* ABE components - VX-UL & VX-DL */
554 .cpu_dai_name = "Voice",
555 .platform_name = "omap-pcm-audio",
556
557 .dynamic = 1, /* BE is dynamic */
558 .dsp_link = &fe_media,
559 .no_host_mode = SND_SOC_DAI_LINK_OPT_HOST,
560 },
561 {
562 .name = "SDP4430 Tones Playback",
563 .stream_name = "Tone Playback",
564
565 /* ABE components - TONES_DL */
566 .cpu_dai_name = "Tones",
567 .platform_name = "omap-pcm-audio",
568
569 .dynamic = 1, /* BE is dynamic */
570 .dsp_link = &fe_tones,
571 },
572 {
573 .name = "SDP4430 Vibra Playback",
574 .stream_name = "VIB-DL",
575
576 /* ABE components - DMIC UL 2 */
577 .cpu_dai_name = "Vibra",
578 .platform_name = "omap-pcm-audio",
579
580 .dynamic = 1, /* BE is dynamic */
581 .dsp_link = &fe_vib,
582 },
583 {
584 .name = "SDP4430 MODEM",
585 .stream_name = "MODEM",
586
587 /* ABE components - MODEM <-> McBSP2 */
588 .cpu_dai_name = "MODEM",
589 .platform_name = "aess",
590
591 .dynamic = 1, /* BE is dynamic */
592 .dsp_link = &fe_modem,
593 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
594 .ignore_suspend = 1,
595 },
596 {
597 .name = "SDP4430 Media LP",
598 .stream_name = "Multimedia",
599
600 /* ABE components - MM-DL (mmap) */
601 .cpu_dai_name = "MultiMedia1 LP",
602 .platform_name = "aess",
603
604 .dynamic = 1, /* BE is dynamic */
605 .dsp_link = &fe_lp_media,
606 },
607 {
608 .name = "Legacy McBSP",
609 .stream_name = "Multimedia",
610
611 /* ABE components - MCBSP2 - MM-EXT */
612 .cpu_dai_name = "omap-mcbsp-dai.1",
613 .platform_name = "omap-pcm-audio",
614
615 /* FM */
616 .codec_dai_name = "FM Digital",
617
618 .no_codec = 1, /* TODO: have a dummy CODEC */
619 .ops = &sdp4430_mcbsp_ops,
620 },
621 {
622 .name = "Legacy McPDM",
623 .stream_name = "Headset Playback",
624
625 /* ABE components - DL1 */
626 .cpu_dai_name = "mcpdm-dl",
627 .platform_name = "omap-pcm-audio",
628
629 /* Phoenix - DL1 DAC */
630 .codec_dai_name = "twl6040-dl1",
631 .codec_name = "twl6040-codec",
632
633 .ops = &sdp4430_mcpdm_ops,
634 },
635 {
636 .name = "Legacy DMIC",
637 .stream_name = "DMIC Capture",
638
639 /* ABE components - DMIC0 */
640 .cpu_dai_name = "omap-dmic-dai-0",
641 .platform_name = "omap-pcm-audio",
642
643 /* DMIC codec */
644 .codec_dai_name = "dmic-hifi",
645 .codec_name = "dmic-codec.0",
646
Misael Lopez Cruz47415f02011-04-27 23:56:32 -0500647 .init = sdp4430_dmic_init,
Liam Girdwoodede6aa92011-02-07 21:07:48 +0000648 .ops = &sdp4430_dmic_ops,
649 },
650
651/*
652 * Backend DAIs - i.e. dynamically matched interfaces, invisible to userspace.
653 * Matched to above interfaces at runtime, based upon use case.
654 */
655
656 {
657 .name = OMAP_ABE_BE_PDM_DL1,
658 .stream_name = "HS Playback",
659
660 /* ABE components - DL1 */
661 .cpu_dai_name = "mcpdm-dl1",
662 .platform_name = "aess",
663
664 /* Phoenix - DL1 DAC */
665 .codec_dai_name = "twl6040-dl1",
666 .codec_name = "twl6040-codec",
667
668 .no_pcm = 1, /* don't create ALSA pcm for this */
669 .init = sdp4430_twl6040_init,
670 .ops = &sdp4430_mcpdm_ops,
671 .be_id = OMAP_ABE_DAI_PDM_DL1,
672 },
673 {
674 .name = OMAP_ABE_BE_PDM_UL1,
675 .stream_name = "Analog Capture",
676
677 /* ABE components - UL1 */
678 .cpu_dai_name = "mcpdm-ul1",
679 .platform_name = "aess",
680
681 /* Phoenix - UL ADC */
682 .codec_dai_name = "twl6040-ul",
683 .codec_name = "twl6040-codec",
684
685 .no_pcm = 1, /* don't create ALSA pcm for this */
686 .ops = &sdp4430_mcpdm_ops,
687 .be_id = OMAP_ABE_DAI_PDM_UL,
688 },
689 {
690 .name = OMAP_ABE_BE_PDM_DL2,
691 .stream_name = "HF Playback",
692
693 /* ABE components - DL2 */
694 .cpu_dai_name = "mcpdm-dl2",
695 .platform_name = "aess",
696
697 /* Phoenix - DL2 DAC */
698 .codec_dai_name = "twl6040-dl2",
699 .codec_name = "twl6040-codec",
700
701 .no_pcm = 1, /* don't create ALSA pcm for this */
Misael Lopez Cruzae141a22011-04-29 01:52:45 -0500702 .init = sdp4430_twl6040_dl2_init,
Liam Girdwoodede6aa92011-02-07 21:07:48 +0000703 .ops = &sdp4430_mcpdm_ops,
704 .be_id = OMAP_ABE_DAI_PDM_DL2,
705 },
706 {
707 .name = OMAP_ABE_BE_PDM_VIB,
708 .stream_name = "Vibra",
709
710 /* ABE components - VIB1 DL */
711 .cpu_dai_name = "mcpdm-vib",
712 .platform_name = "aess",
713
714 /* Phoenix - PDM to PWM */
715 .codec_dai_name = "twl6040-vib",
716 .codec_name = "twl6040-codec",
717
718 .no_pcm = 1, /* don't create ALSA pcm for this */
719 .ops = &sdp4430_mcpdm_ops,
720 .be_id = OMAP_ABE_DAI_PDM_VIB,
721 },
722 {
723 .name = OMAP_ABE_BE_BT_VX,
724 .stream_name = "BT",
725
726 /* ABE components - MCBSP1 - BT-VX */
727 .cpu_dai_name = "omap-mcbsp-dai.0",
728 .platform_name = "aess",
729
730 /* Bluetooth */
731 .codec_dai_name = "Bluetooth",
732
733 .no_pcm = 1, /* don't create ALSA pcm for this */
734 .no_codec = 1, /* TODO: have a dummy CODEC */
735 .be_hw_params_fixup = mcbsp_be_hw_params_fixup,
736 .ops = &sdp4430_mcbsp_ops,
737 .be_id = OMAP_ABE_DAI_BT_VX,
738 },
739 {
740 .name = OMAP_ABE_BE_MM_EXT0,
741 .stream_name = "FM",
742
743 /* ABE components - MCBSP2 - MM-EXT */
744 .cpu_dai_name = "omap-mcbsp-dai.1",
745 .platform_name = "aess",
746
747 /* FM */
748 .codec_dai_name = "FM Digital",
749
750 .no_pcm = 1, /* don't create ALSA pcm for this */
751 .no_codec = 1, /* TODO: have a dummy CODEC */
752 .be_hw_params_fixup = mcbsp_be_hw_params_fixup,
753 .ops = &sdp4430_mcbsp_ops,
754 .be_id = OMAP_ABE_DAI_MM_FM,
755 },
756 {
757 .name = OMAP_ABE_BE_MM_EXT1,
758 .stream_name = "MODEM",
759
760 /* ABE components - MCBSP2 - MM-EXT */
761 .cpu_dai_name = "omap-mcbsp-dai.1",
762 .platform_name = "aess",
763
764 /* MODEM */
765 .codec_dai_name = "MODEM",
766
767 .no_pcm = 1, /* don't create ALSA pcm for this */
768 .no_codec = 1, /* TODO: have a dummy CODEC */
769 .be_hw_params_fixup = mcbsp_be_hw_params_fixup,
770 .ops = &sdp4430_mcbsp_ops,
771 .be_id = OMAP_ABE_DAI_MODEM,
772 .ignore_suspend = 1,
773 },
774 {
775 .name = OMAP_ABE_BE_DMIC0,
776 .stream_name = "DMIC0",
777
778 /* ABE components - DMIC UL 1 */
779 .cpu_dai_name = "omap-dmic-abe-dai-0",
780 .platform_name = "aess",
781
782 /* DMIC 0 */
783 .codec_dai_name = "dmic-hifi",
784 .codec_name = "dmic-codec.0",
785 .ops = &sdp4430_dmic_ops,
786
787 .no_pcm = 1, /* don't create ALSA pcm for this */
788 .be_hw_params_fixup = dmic_be_hw_params_fixup,
789 .be_id = OMAP_ABE_DAI_DMIC0,
790 },
791 {
792 .name = OMAP_ABE_BE_DMIC1,
793 .stream_name = "DMIC1",
794
795 /* ABE components - DMIC UL 1 */
796 .cpu_dai_name = "omap-dmic-abe-dai-1",
797 .platform_name = "aess",
798
799 /* DMIC 1 */
800 .codec_dai_name = "dmic-hifi",
801 .codec_name = "dmic-codec.1",
802 .ops = &sdp4430_dmic_ops,
803
804 .no_pcm = 1, /* don't create ALSA pcm for this */
805 .be_hw_params_fixup = dmic_be_hw_params_fixup,
806 .be_id = OMAP_ABE_DAI_DMIC1,
807 },
808 {
809 .name = OMAP_ABE_BE_DMIC2,
810 .stream_name = "DMIC2",
811
812 /* ABE components - DMIC UL 2 */
813 .cpu_dai_name = "omap-dmic-abe-dai-2",
814 .platform_name = "aess",
815
816 /* DMIC 2 */
817 .codec_dai_name = "dmic-hifi",
818 .codec_name = "dmic-codec.2",
819 .ops = &sdp4430_dmic_ops,
820
821 .no_pcm = 1, /* don't create ALSA pcm for this */
822 .be_hw_params_fixup = dmic_be_hw_params_fixup,
823 .be_id = OMAP_ABE_DAI_DMIC2,
824 },
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500825};
826
827/* Audio machine driver */
828static struct snd_soc_card snd_soc_sdp4430 = {
Liam Girdwood62e16e82011-02-07 21:09:59 +0000829 .driver_name = "OMAP4",
830 .long_name = "TI OMAP4 Board",
Liam Girdwoodede6aa92011-02-07 21:07:48 +0000831 .dai_link = sdp4430_dai,
832 .num_links = ARRAY_SIZE(sdp4430_dai),
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500833};
834
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500835static struct platform_device *sdp4430_snd_device;
Liam Girdwood8cc57052011-02-07 21:18:06 +0000836static struct i2c_adapter *adapter;
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500837
838static int __init sdp4430_soc_init(void)
839{
840 int ret;
841
Liam Girdwood62e16e82011-02-07 21:09:59 +0000842 if (!machine_is_omap_4430sdp() && !machine_is_omap4_panda()) {
843 pr_debug("Not SDP4430 or PandaBoard!\n");
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500844 return -ENODEV;
Liam Girdwood62e16e82011-02-07 21:09:59 +0000845 }
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500846 printk(KERN_INFO "SDP4430 SoC init\n");
Liam Girdwood62e16e82011-02-07 21:09:59 +0000847 if (machine_is_omap_4430sdp())
848 snd_soc_sdp4430.name = "SDP4430";
849 else if (machine_is_omap4_panda())
850 snd_soc_sdp4430.name = "Panda";
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500851
852 sdp4430_snd_device = platform_device_alloc("soc-audio", -1);
853 if (!sdp4430_snd_device) {
854 printk(KERN_ERR "Platform device allocation failed\n");
855 return -ENOMEM;
856 }
857
Liam Girdwoodede6aa92011-02-07 21:07:48 +0000858 ret = snd_soc_register_dais(&sdp4430_snd_device->dev, dai, ARRAY_SIZE(dai));
859 if (ret < 0)
Liam Girdwood8cc57052011-02-07 21:18:06 +0000860 goto err_dai;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000861 platform_set_drvdata(sdp4430_snd_device, &snd_soc_sdp4430);
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500862
863 ret = platform_device_add(sdp4430_snd_device);
864 if (ret)
Liam Girdwood8cc57052011-02-07 21:18:06 +0000865 goto err_dev;
866
867 adapter = i2c_get_adapter(1);
868 if (!adapter) {
869 printk(KERN_ERR "can't get i2c adapter\n");
870 ret = -ENODEV;
871 goto err_adap;
872 }
873
874 tps6130x_client = i2c_new_device(adapter, &tps6130x_hwmon_info);
875 if (!tps6130x_client) {
876 printk(KERN_ERR "can't add i2c device\n");
877 ret = -ENODEV;
878 goto err_i2c;
879 }
880
881 /* Only configure the TPS6130x on SDP4430 */
882 if (machine_is_omap_4430sdp())
883 sdp4430_tps6130x_configure();
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500884
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500885 return 0;
886
Liam Girdwood8cc57052011-02-07 21:18:06 +0000887err_i2c:
888 i2c_put_adapter(adapter);
889err_adap:
890 platform_device_del(sdp4430_snd_device);
891err_dev:
892 snd_soc_unregister_dais(&sdp4430_snd_device->dev, ARRAY_SIZE(dai));
893err_dai:
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500894 platform_device_put(sdp4430_snd_device);
895 return ret;
896}
897module_init(sdp4430_soc_init);
898
899static void __exit sdp4430_soc_exit(void)
900{
901 platform_device_unregister(sdp4430_snd_device);
Liam Girdwood8cc57052011-02-07 21:18:06 +0000902 snd_soc_unregister_dais(&sdp4430_snd_device->dev, ARRAY_SIZE(dai));
903 i2c_unregister_device(tps6130x_client);
904 i2c_put_adapter(adapter);
Misael Lopez Cruz5e64d6a2010-05-17 19:53:10 -0500905}
906module_exit(sdp4430_soc_exit);
907
908MODULE_AUTHOR("Misael Lopez Cruz <x0052729@ti.com>");
909MODULE_DESCRIPTION("ALSA SoC SDP4430");
910MODULE_LICENSE("GPL");
911