blob: 07a7e770fc7ed74865067a417d333920ad5e4eb5 [file] [log] [blame]
Liam Girdwoodc60eacc2011-02-03 15:12:22 +00001/*
2 * omap-abe.c -- OMAP ALSA SoC DAI driver using Audio Backend
3 *
4 * Copyright (C) 2010 Texas Instruments
5 *
Liam Girdwoode708bea2011-02-03 15:17:26 +00006 * Contact: Liam Girdwood <lrg@ti.com>
7 * Misael Lopez Cruz <misael.lopez@ti.com>
8 * Sebastien Guiriec <s-guiriec@ti.com>
Liam Girdwoodc60eacc2011-02-03 15:12:22 +00009 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * version 2 as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22 * 02110-1301 USA
23 *
24 */
25
26#define DEBUG
27
28#include <linux/init.h>
29#include <linux/module.h>
30#include <linux/device.h>
31#include <linux/slab.h>
32#include <linux/platform_device.h>
33#include <linux/delay.h>
34#include <sound/core.h>
35#include <sound/pcm.h>
36#include <sound/pcm_params.h>
37#include <sound/initval.h>
38#include <sound/soc.h>
39#include <sound/soc-dapm.h>
40#include <sound/soc-dsp.h>
41
Liam Girdwoodc60eacc2011-02-03 15:12:22 +000042#include <plat/dma-44xx.h>
43#include <plat/dma.h>
44#include "omap-pcm.h"
45#include "omap-abe.h"
46#include "omap-abe-dsp.h"
47#include "abe/abe_main.h"
48#include "abe/port_mgr.h"
49
50#define OMAP_ABE_FORMATS SNDRV_PCM_FMTBIT_S32_LE
51
52struct omap_abe_data {
53 /* MODEM FE*/
54 struct snd_pcm_substream *modem_substream[2];
55 struct snd_soc_dai *modem_dai;
56
57 struct abe *abe;
58
59 /* BE & FE Ports */
60 struct omap_abe_port *port[OMAP_ABE_MAX_PORT_ID + 1];
61};
62
63/*
64 * Stream DMA parameters
65 */
66static struct omap_pcm_dma_data omap_abe_dai_dma_params[7][2] = {
67{
68 {
69 .name = "Media Playback",
70 .dma_req = OMAP44XX_DMA_ABE_REQ_0,
71 .data_type = OMAP_DMA_DATA_TYPE_S32,
72 .sync_mode = OMAP_DMA_SYNC_PACKET,
73 },
74 {
75 .name = "Media Capture1",
76 .dma_req = OMAP44XX_DMA_ABE_REQ_3,
77 .data_type = OMAP_DMA_DATA_TYPE_S32,
78 .sync_mode = OMAP_DMA_SYNC_PACKET,
79 },
80},
81{
82 {},
83 {
84 .name = "Media Capture2",
85 .dma_req = OMAP44XX_DMA_ABE_REQ_4,
86 .data_type = OMAP_DMA_DATA_TYPE_S32,
87 .sync_mode = OMAP_DMA_SYNC_PACKET,
88 },
89},
90{
91 {
92 .name = "Voice Playback",
93 .dma_req = OMAP44XX_DMA_ABE_REQ_1,
94 .data_type = OMAP_DMA_DATA_TYPE_S32,
95 .sync_mode = OMAP_DMA_SYNC_PACKET,
96 },
97 {
98 .name = "Voice Capture",
99 .dma_req = OMAP44XX_DMA_ABE_REQ_2,
100 .data_type = OMAP_DMA_DATA_TYPE_S32,
101 .sync_mode = OMAP_DMA_SYNC_PACKET,
102 },
103},
104{
105 {
106 .name = "Tones Playback",
107 .dma_req = OMAP44XX_DMA_ABE_REQ_5,
108 .data_type = OMAP_DMA_DATA_TYPE_S32,
109 .sync_mode = OMAP_DMA_SYNC_PACKET,
110 },{},
111},
112{
113 {
114 .name = "Vibra Playback",
115 .dma_req = OMAP44XX_DMA_ABE_REQ_6,
116 .data_type = OMAP_DMA_DATA_TYPE_S32,
117 .sync_mode = OMAP_DMA_SYNC_PACKET,
118 },{},
119},
120{
121 {
122 .name = "MODEM Playback",
123 .dma_req = OMAP44XX_DMA_ABE_REQ_1,
124 .data_type = OMAP_DMA_DATA_TYPE_S32,
125 .sync_mode = OMAP_DMA_SYNC_PACKET,
126 },
127 {
128 .name = "MODEM Capture",
129 .dma_req = OMAP44XX_DMA_ABE_REQ_2,
130 .data_type = OMAP_DMA_DATA_TYPE_S32,
131 .sync_mode = OMAP_DMA_SYNC_PACKET,
132 },
133},
134{
135 {
136 .name = "Low Power Playback",
137 .dma_req = OMAP44XX_DMA_ABE_REQ_0,
138 .data_type = OMAP_DMA_DATA_TYPE_S32,
139 .sync_mode = OMAP_DMA_SYNC_PACKET,
140 },{},
141},};
142
143static int modem_get_dai(struct snd_pcm_substream *substream,
144 struct snd_soc_dai *dai)
145{
146 struct snd_soc_pcm_runtime *rtd = substream->private_data;
147 struct omap_abe_data *abe_priv = snd_soc_dai_get_drvdata(dai);
148 struct snd_soc_pcm_runtime *modem_rtd;
149
150 abe_priv->modem_substream[substream->stream] =
151 snd_soc_get_dai_substream(rtd->card,
152 OMAP_ABE_BE_MM_EXT1, substream->stream);
153
154 if (abe_priv->modem_substream[substream->stream] == NULL)
155 return -ENODEV;
156
157 modem_rtd = abe_priv->modem_substream[substream->stream]->private_data;
158 abe_priv->modem_substream[substream->stream]->runtime = substream->runtime;
159 abe_priv->modem_dai = modem_rtd->cpu_dai;
160
161 return 0;
162}
163
164static void mute_be(struct snd_soc_pcm_runtime *be,
165 struct snd_soc_dai *dai, int stream)
166{
167 dev_dbg(&be->dev, "%s: %s %d\n", __func__, be->cpu_dai->name, stream);
168
169 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
170 switch (be->dai_link->be_id) {
171 case OMAP_ABE_DAI_PDM_DL1:
172 abe_write_gain(GAINS_DL1, MUTE_GAIN, RAMP_5MS,
173 GAIN_LEFT_OFFSET);
174 abe_write_gain(GAINS_DL1, MUTE_GAIN, RAMP_5MS,
175 GAIN_RIGHT_OFFSET);
176 break;
177 case OMAP_ABE_DAI_PDM_DL2:
178 abe_write_gain(GAINS_DL2, MUTE_GAIN, RAMP_5MS,
179 GAIN_LEFT_OFFSET);
180 abe_write_gain(GAINS_DL2, MUTE_GAIN, RAMP_5MS,
181 GAIN_RIGHT_OFFSET);
182 break;
183 case OMAP_ABE_DAI_PDM_VIB:
184 case OMAP_ABE_DAI_BT_VX:
185 case OMAP_ABE_DAI_MM_FM:
186 case OMAP_ABE_DAI_MODEM:
187 break;
188 }
189 } else {
190 switch (be->dai_link->be_id) {
191 case OMAP_ABE_DAI_PDM_UL:
192 break;
193 case OMAP_ABE_DAI_BT_VX:
194 case OMAP_ABE_DAI_MM_FM:
195 case OMAP_ABE_DAI_MODEM:
196 case OMAP_ABE_DAI_DMIC0:
197 case OMAP_ABE_DAI_DMIC1:
198 case OMAP_ABE_DAI_DMIC2:
199 break;
200 }
201 }
202}
203
204static void unmute_be(struct snd_soc_pcm_runtime *be,
205 struct snd_soc_dai *dai, int stream)
206{
207 dev_dbg(&be->dev, "%s: %s %d\n", __func__, be->cpu_dai->name, stream);
208
209 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
210 switch (be->dai_link->be_id) {
211 case OMAP_ABE_DAI_PDM_DL1:
212 abe_write_gain(GAINS_DL1, GAIN_0dB, RAMP_5MS,
213 GAIN_LEFT_OFFSET);
214 abe_write_gain(GAINS_DL1, GAIN_0dB, RAMP_5MS,
215 GAIN_RIGHT_OFFSET);
216 break;
217 case OMAP_ABE_DAI_PDM_DL2:
218 abe_write_gain(GAINS_DL2, GAIN_0dB, RAMP_5MS,
219 GAIN_LEFT_OFFSET);
220 abe_write_gain(GAINS_DL2, GAIN_0dB, RAMP_5MS,
221 GAIN_RIGHT_OFFSET);
222 break;
223 case OMAP_ABE_DAI_PDM_VIB:
224 case OMAP_ABE_DAI_BT_VX:
225 case OMAP_ABE_DAI_MM_FM:
226 case OMAP_ABE_DAI_MODEM:
227 break;
228 }
229 } else {
230
231 switch (be->dai_link->be_id) {
232 case OMAP_ABE_DAI_PDM_UL:
233 break;
234 case OMAP_ABE_DAI_BT_VX:
235 case OMAP_ABE_DAI_MM_FM:
236 case OMAP_ABE_DAI_MODEM:
237 case OMAP_ABE_DAI_DMIC0:
238 case OMAP_ABE_DAI_DMIC1:
239 case OMAP_ABE_DAI_DMIC2:
240 break;
241 }
242 }
243}
244
245static void enable_be_port(struct snd_soc_pcm_runtime *be,
246 struct snd_soc_dai *dai, int stream)
247{
248 struct omap_abe_data *abe_priv = snd_soc_dai_get_drvdata(dai);
249 abe_data_format_t format;
250
251 dev_dbg(&be->dev, "%s: %s %d\n", __func__, be->cpu_dai->name, stream);
252
253 switch (be->dai_link->be_id) {
254 /* McPDM Downlink is special case and handled by McPDM driver */
255 case OMAP_ABE_DAI_PDM_DL1:
256 case OMAP_ABE_DAI_PDM_DL2:
257 case OMAP_ABE_DAI_PDM_VIB:
258 break;
259 case OMAP_ABE_DAI_PDM_UL:
260 omap_abe_port_enable(abe_priv->abe,
261 abe_priv->port[OMAP_ABE_BE_PORT_PDM_UL1]);
262 break;
263 case OMAP_ABE_DAI_BT_VX:
264 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
265
266 /* port can only be configured if it's not running */
267 if (omap_abe_port_is_enabled(abe_priv->abe,
268 abe_priv->port[OMAP_ABE_BE_PORT_BT_VX_DL]))
269 return;
270
271 /* BT_DL connection to McBSP 1 ports */
272 format.f = 8000;
273 format.samp_format = MONO_RSHIFTED_16;
274 abe_connect_serial_port(BT_VX_DL_PORT, &format, MCBSP1_TX);
275 omap_abe_port_enable(abe_priv->abe,
276 abe_priv->port[OMAP_ABE_BE_PORT_BT_VX_DL]);
277 } else {
278
279 /* port can only be configured if it's not running */
280 if (omap_abe_port_is_enabled(abe_priv->abe,
281 abe_priv->port[OMAP_ABE_BE_PORT_BT_VX_UL]))
282 return;
283
284 /* BT_UL connection to McBSP 1 ports */
285 format.f = 8000;
286 format.samp_format = MONO_RSHIFTED_16;
287 abe_connect_serial_port(BT_VX_UL_PORT, &format, MCBSP1_RX);
288 omap_abe_port_enable(abe_priv->abe,
289 abe_priv->port[OMAP_ABE_BE_PORT_BT_VX_UL]);
290 }
291 break;
292 case OMAP_ABE_DAI_MM_FM:
293 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
294
295 /* port can only be configured if it's not running */
296 if (omap_abe_port_is_enabled(abe_priv->abe,
297 abe_priv->port[OMAP_ABE_BE_PORT_MM_EXT_DL]))
298 return;
299
300 /* MM_EXT connection to McBSP 2 ports */
301 format.f = 48000;
302 format.samp_format = STEREO_RSHIFTED_16;
303 abe_connect_serial_port(MM_EXT_OUT_PORT, &format, MCBSP2_TX);
304 omap_abe_port_enable(abe_priv->abe,
305 abe_priv->port[OMAP_ABE_BE_PORT_MM_EXT_DL]);
306 } else {
307
308 /* port can only be configured if it's not running */
309 if (omap_abe_port_is_enabled(abe_priv->abe,
310 abe_priv->port[OMAP_ABE_BE_PORT_MM_EXT_UL]))
311 return;
312
313 /* MM_EXT connection to McBSP 2 ports */
314 format.f = 48000;
315 format.samp_format = STEREO_RSHIFTED_16;
316 abe_connect_serial_port(MM_EXT_IN_PORT, &format, MCBSP2_RX);
317 omap_abe_port_enable(abe_priv->abe,
318 abe_priv->port[OMAP_ABE_BE_PORT_MM_EXT_UL]);
319 }
320 break;
321 case OMAP_ABE_DAI_DMIC0:
322 omap_abe_port_enable(abe_priv->abe,
323 abe_priv->port[OMAP_ABE_BE_PORT_DMIC0]);
324 break;
325 case OMAP_ABE_DAI_DMIC1:
326 omap_abe_port_enable(abe_priv->abe,
327 abe_priv->port[OMAP_ABE_BE_PORT_DMIC1]);
328 break;
329 case OMAP_ABE_DAI_DMIC2:
330 omap_abe_port_enable(abe_priv->abe,
331 abe_priv->port[OMAP_ABE_BE_PORT_DMIC2]);
332 break;
333 }
334}
335
336static void enable_fe_port(struct snd_pcm_substream *substream,
337 struct snd_soc_dai *dai, int stream)
338{
339 struct snd_soc_pcm_runtime *fe = substream->private_data;
340 struct omap_abe_data *abe_priv = snd_soc_dai_get_drvdata(dai);
341
342 dev_dbg(&fe->dev, "%s: %s %d\n", __func__, dai->name, stream);
343
344 switch(dai->id) {
345 case ABE_FRONTEND_DAI_MEDIA:
346 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
347 omap_abe_port_enable(abe_priv->abe,
348 abe_priv->port[OMAP_ABE_FE_PORT_MM_DL1]);
349 else
350 omap_abe_port_enable(abe_priv->abe,
351 abe_priv->port[OMAP_ABE_FE_PORT_MM_UL1]);
352 break;
353 case ABE_FRONTEND_DAI_LP_MEDIA:
354 abe_enable_data_transfer(MM_DL_PORT);
355 break;
356 case ABE_FRONTEND_DAI_MEDIA_CAPTURE:
357 if (stream == SNDRV_PCM_STREAM_CAPTURE)
358 omap_abe_port_enable(abe_priv->abe,
359 abe_priv->port[OMAP_ABE_FE_PORT_MM_UL2]);
360 break;
361 case ABE_FRONTEND_DAI_MODEM:
362 case ABE_FRONTEND_DAI_VOICE:
363 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
364 omap_abe_port_enable(abe_priv->abe,
365 abe_priv->port[OMAP_ABE_FE_PORT_VX_DL]);
366 else
367 omap_abe_port_enable(abe_priv->abe,
368 abe_priv->port[OMAP_ABE_FE_PORT_VX_UL]);
369 break;
370 case ABE_FRONTEND_DAI_TONES:
371 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
372 omap_abe_port_enable(abe_priv->abe,
373 abe_priv->port[OMAP_ABE_FE_PORT_TONES]);
374 break;
375 case ABE_FRONTEND_DAI_VIBRA:
376 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
377 omap_abe_port_enable(abe_priv->abe,
378 abe_priv->port[OMAP_ABE_FE_PORT_VIB]);
379 break;
380 }
381}
382
383static void disable_be_port(struct snd_soc_pcm_runtime *be,
384 struct snd_soc_dai *dai, int stream)
385{
386 struct omap_abe_data *abe_priv = snd_soc_dai_get_drvdata(dai);
387
388 dev_dbg(&be->dev, "%s: %s %d\n", __func__, be->cpu_dai->name, stream);
389
390 switch (be->dai_link->be_id) {
391 /* McPDM Downlink is special case and handled by McPDM driver */
392 case OMAP_ABE_DAI_PDM_DL1:
393 case OMAP_ABE_DAI_PDM_DL2:
394 case OMAP_ABE_DAI_PDM_VIB:
395 break;
396 case OMAP_ABE_DAI_PDM_UL:
397 omap_abe_port_disable(abe_priv->abe,
398 abe_priv->port[OMAP_ABE_BE_PORT_PDM_UL1]);
399 break;
400 case OMAP_ABE_DAI_BT_VX:
401 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
402 omap_abe_port_disable(abe_priv->abe,
403 abe_priv->port[OMAP_ABE_BE_PORT_BT_VX_DL]);
404 else
405 omap_abe_port_disable(abe_priv->abe,
406 abe_priv->port[OMAP_ABE_BE_PORT_BT_VX_UL]);
407 break;
408 case OMAP_ABE_DAI_MM_FM:
409 case OMAP_ABE_DAI_MODEM:
410 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
411 omap_abe_port_disable(abe_priv->abe,
412 abe_priv->port[OMAP_ABE_BE_PORT_MM_EXT_DL]);
413 else
414 omap_abe_port_disable(abe_priv->abe,
415 abe_priv->port[OMAP_ABE_BE_PORT_MM_EXT_UL]);
416 break;
417 case OMAP_ABE_DAI_DMIC0:
418 omap_abe_port_disable(abe_priv->abe,
419 abe_priv->port[OMAP_ABE_BE_PORT_DMIC0]);
420 break;
421 case OMAP_ABE_DAI_DMIC1:
422 omap_abe_port_disable(abe_priv->abe,
423 abe_priv->port[OMAP_ABE_BE_PORT_DMIC1]);
424 break;
425 case OMAP_ABE_DAI_DMIC2:
426 omap_abe_port_disable(abe_priv->abe,
427 abe_priv->port[OMAP_ABE_BE_PORT_DMIC2]);
428 break;
429 }
430}
431
432static void disable_fe_port(struct snd_pcm_substream *substream,
433 struct snd_soc_dai *dai, int stream)
434{
435 struct snd_soc_pcm_runtime *fe = substream->private_data;
436 struct omap_abe_data *abe_priv = snd_soc_dai_get_drvdata(dai);
437
438 dev_dbg(&fe->dev, "%s: %s %d\n", __func__, dai->name, stream);
439
440 switch(dai->id) {
441 case ABE_FRONTEND_DAI_MEDIA:
442 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
443 omap_abe_port_disable(abe_priv->abe,
444 abe_priv->port[OMAP_ABE_FE_PORT_MM_DL1]);
445 else
446 omap_abe_port_disable(abe_priv->abe,
447 abe_priv->port[OMAP_ABE_FE_PORT_MM_UL1]);
448 break;
449 case ABE_FRONTEND_DAI_LP_MEDIA:
450 abe_disable_data_transfer(MM_DL_PORT);
451 break;
452 case ABE_FRONTEND_DAI_MEDIA_CAPTURE:
453 if (stream == SNDRV_PCM_STREAM_CAPTURE)
454 omap_abe_port_disable(abe_priv->abe,
455 abe_priv->port[OMAP_ABE_FE_PORT_MM_UL2]);
456 break;
457 case ABE_FRONTEND_DAI_MODEM:
458 case ABE_FRONTEND_DAI_VOICE:
459 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
460 omap_abe_port_disable(abe_priv->abe,
461 abe_priv->port[OMAP_ABE_FE_PORT_VX_DL]);
462 else
463 omap_abe_port_disable(abe_priv->abe,
464 abe_priv->port[OMAP_ABE_FE_PORT_VX_UL]);
465 break;
466 case ABE_FRONTEND_DAI_TONES:
467 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
468 omap_abe_port_disable(abe_priv->abe,
469 abe_priv->port[OMAP_ABE_FE_PORT_TONES]);
470 break;
471 case ABE_FRONTEND_DAI_VIBRA:
472 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
473 omap_abe_port_disable(abe_priv->abe,
474 abe_priv->port[OMAP_ABE_FE_PORT_VIB]);
475 break;
476 }
477}
478
479static void mute_fe_port(struct snd_pcm_substream *substream,
480 struct snd_soc_dai *dai, int stream)
481{
482 struct snd_soc_pcm_runtime *fe = substream->private_data;
483 struct omap_abe_data *abe_priv = snd_soc_dai_get_drvdata(dai);
484
485 dev_dbg(&fe->dev, "%s: %s %d\n", __func__, dai->name, stream);
486
487 switch(dai->id) {
488 case ABE_FRONTEND_DAI_MEDIA:
489 case ABE_FRONTEND_DAI_LP_MEDIA:
490 if (omap_abe_port_is_enabled(abe_priv->abe,
491 abe_priv->port[OMAP_ABE_BE_PORT_PDM_DL2]))
492 abe_mute_gain(MIXDL2, MIX_DL2_INPUT_MM_DL);
493 if (omap_abe_port_is_enabled(abe_priv->abe,
494 abe_priv->port[OMAP_ABE_BE_PORT_PDM_DL1]))
495 abe_mute_gain(MIXDL1, MIX_DL1_INPUT_MM_DL);
496 break;
497 case ABE_FRONTEND_DAI_VOICE:
498 if (omap_abe_port_is_enabled(abe_priv->abe,
499 abe_priv->port[OMAP_ABE_BE_PORT_PDM_DL2]))
500 abe_mute_gain(MIXDL2, MIX_DL2_INPUT_VX_DL);
501 if (omap_abe_port_is_enabled(abe_priv->abe,
502 abe_priv->port[OMAP_ABE_BE_PORT_PDM_DL1]))
503 abe_mute_gain(MIXDL1, MIX_DL1_INPUT_VX_DL);
504 break;
505 case ABE_FRONTEND_DAI_TONES:
506 if (omap_abe_port_is_enabled(abe_priv->abe,
507 abe_priv->port[OMAP_ABE_BE_PORT_PDM_DL2]))
508 abe_mute_gain(MIXDL2, MIX_DL2_INPUT_TONES);
509 if (omap_abe_port_is_enabled(abe_priv->abe,
510 abe_priv->port[OMAP_ABE_BE_PORT_PDM_DL1]))
511 abe_mute_gain(MIXDL1, MIX_DL1_INPUT_TONES);
512 break;
513 case ABE_FRONTEND_DAI_VIBRA:
514 case ABE_FRONTEND_DAI_MEDIA_CAPTURE:
515 break;
516 }
517}
518
519static void unmute_fe_port(struct snd_pcm_substream *substream,
520 struct snd_soc_dai *dai, int stream)
521{
522 struct snd_soc_pcm_runtime *fe = substream->private_data;
523 struct omap_abe_data *abe_priv = snd_soc_dai_get_drvdata(dai);
524
525 dev_dbg(&fe->dev, "%s: %s %d\n", __func__, dai->name, stream);
526
527 switch(dai->id) {
528 case ABE_FRONTEND_DAI_MEDIA:
529 case ABE_FRONTEND_DAI_LP_MEDIA:
530 if (omap_abe_port_is_enabled(abe_priv->abe,
531 abe_priv->port[OMAP_ABE_BE_PORT_PDM_DL2]))
532 abe_unmute_gain(MIXDL2, MIX_DL2_INPUT_MM_DL);
533 if (omap_abe_port_is_enabled(abe_priv->abe,
534 abe_priv->port[OMAP_ABE_BE_PORT_PDM_DL1]))
535 abe_unmute_gain(MIXDL1, MIX_DL1_INPUT_MM_DL);
536 break;
537 case ABE_FRONTEND_DAI_VOICE:
538 if (omap_abe_port_is_enabled(abe_priv->abe,
539 abe_priv->port[OMAP_ABE_BE_PORT_PDM_DL2]))
540 abe_unmute_gain(MIXDL2, MIX_DL2_INPUT_VX_DL);
541 if (omap_abe_port_is_enabled(abe_priv->abe,
542 abe_priv->port[OMAP_ABE_BE_PORT_PDM_DL1]))
543 abe_unmute_gain(MIXDL1, MIX_DL1_INPUT_VX_DL);
544 break;
545 case ABE_FRONTEND_DAI_TONES:
546 if (omap_abe_port_is_enabled(abe_priv->abe,
547 abe_priv->port[OMAP_ABE_BE_PORT_PDM_DL2]))
548 abe_unmute_gain(MIXDL2, MIX_DL2_INPUT_TONES);
549 if (omap_abe_port_is_enabled(abe_priv->abe,
550 abe_priv->port[OMAP_ABE_BE_PORT_PDM_DL1]))
551 abe_unmute_gain(MIXDL1, MIX_DL1_INPUT_TONES);
552 break;
553 case ABE_FRONTEND_DAI_VIBRA:
554 case ABE_FRONTEND_DAI_MEDIA_CAPTURE:
555 break;
556 }
557}
558
559static void capture_trigger(struct snd_pcm_substream *substream,
560 struct snd_soc_dai *dai, int cmd)
561{
562 struct snd_soc_pcm_runtime *fe = substream->private_data;
563 struct snd_soc_dsp_params *dsp_params;
564 struct snd_pcm_substream *be_substream;
565 int stream = substream->stream;
566
567 dev_dbg(&fe->dev, "%s: %s %d\n", __func__, fe->cpu_dai->name, stream);
568
569 switch (cmd) {
570 case SNDRV_PCM_TRIGGER_START:
571
572 /* mute and enable BE ports */
573 list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be) {
574 struct snd_soc_pcm_runtime *be = dsp_params->be;
575
576 /* does this trigger() apply to this BE and stream ? */
577 if (!snd_soc_dsp_is_trigger_for_be(fe, be, stream))
578 continue;
579
580 /* is the BE already in the trigger START state ? */
581 if (dsp_params->state == SND_SOC_DSP_LINK_STATE_START)
582 continue;
583
584 be_substream = snd_soc_dsp_get_substream(dsp_params->be, stream);
585
586 /* mute the BE port */
587 mute_be(be, dai, stream);
588
589 /* enable the BE port */
590 enable_be_port(be, dai, stream);
591
592 /* DAI work must be started/stopped at least 250us after ABE */
593 udelay(250);
594
595 /* trigger the BE port */
596 snd_soc_dai_trigger(be_substream, cmd, be->cpu_dai);
597 }
598
599 /* does this trigger() apply to the FE ? */
600 if (snd_soc_dsp_is_trigger_for_fe(fe, stream)) {
601 /* Enable Frontend sDMA */
602 snd_soc_dsp_platform_trigger(substream, cmd, fe->platform);
603 enable_fe_port(substream, dai, stream);
604 }
605
606 /* Restore ABE GAINS AMIC */
607 list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be) {
608 struct snd_soc_pcm_runtime *be = dsp_params->be;
609
610 /* does this trigger() apply to this BE and stream ? */
611 if (!snd_soc_dsp_is_trigger_for_be(fe, be, stream))
612 continue;
613
614 /* unmute this BE port */
615 unmute_be(be, dai, stream);
616 }
617 break;
618 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
619 /* Enable sDMA */
620 snd_soc_dsp_platform_trigger(substream, cmd, fe->platform);
621 enable_fe_port(substream, dai, stream);
622 break;
623 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
624 /* Disable sDMA */
625 disable_fe_port(substream, dai, stream);
626 snd_soc_dsp_platform_trigger(substream, cmd, fe->platform);
627 break;
628 case SNDRV_PCM_TRIGGER_STOP:
629
630 /* does this trigger() apply to the FE ? */
631 if (snd_soc_dsp_is_trigger_for_fe(fe, stream)) {
632 /* Disable sDMA */
633 disable_fe_port(substream, dai, stream);
634 snd_soc_dsp_platform_trigger(substream, cmd, fe->platform);
635 }
636
637 /* disable BE ports */
638 list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be) {
639 struct snd_soc_pcm_runtime *be = dsp_params->be;
640
641 /* does this trigger() apply to this BE and stream ? */
642 if (!snd_soc_dsp_is_trigger_for_be(fe, be, stream))
643 continue;
644
645 /* only STOP BE in FREE state */
646 /* REVISIT: Investigate the appropriate state to check against */
647 //if (dsp_params->state != SND_SOC_DSP_LINK_STATE_FREE)
648 // continue;
649
650 be_substream = snd_soc_dsp_get_substream(dsp_params->be, stream);
651
652 /* disable the BE port */
653 disable_be_port(be, dai, stream);
654
655 /* DAI work must be started/stopped at least 250us after ABE */
656 udelay(250);
657
658 /* trigger BE port */
659 snd_soc_dai_trigger(be_substream, cmd, be->cpu_dai);
660 }
661 break;
662 default:
663 break;
664 }
665}
666
667static void playback_trigger(struct snd_pcm_substream *substream,
668 struct snd_soc_dai *dai, int cmd)
669{
670 struct snd_soc_pcm_runtime *fe = substream->private_data;
671 struct snd_soc_dsp_params *dsp_params;
672 struct snd_pcm_substream *be_substream;
673 int stream = substream->stream;
674
675 dev_dbg(&fe->dev, "%s: %s %d\n", __func__, fe->cpu_dai->name, stream);
676
677 switch (cmd) {
678 case SNDRV_PCM_TRIGGER_START:
679
680 /* mute and enable ports */
681 list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be) {
682 struct snd_soc_pcm_runtime *be = dsp_params->be;
683
684 /* does this trigger() apply to the FE ? */
685 if (!snd_soc_dsp_is_trigger_for_be(fe, be, stream))
686 continue;
687
688 /* is the BE already in the trigger START state ? */
689 if (dsp_params->state == SND_SOC_DSP_LINK_STATE_START)
690 continue;
691
692 be_substream = snd_soc_dsp_get_substream(dsp_params->be, stream);
693
694 /* mute BE port */
695 mute_be(be, dai, stream);
696
697 /* enabled BE port */
698 enable_be_port(be, dai, stream);
699
700 /* DAI work must be started/stopped at least 250us after ABE */
701 udelay(250);
702
703 /* trigger BE port */
704 snd_soc_dai_trigger(be_substream, cmd, be->cpu_dai);
705
706 /* unmute the BE port */
707 unmute_be(be, dai, stream);
708 }
709
710 /* does this trigger() apply to the FE ? */
711 if (snd_soc_dsp_is_trigger_for_fe(fe, stream)) {
712
713 /* Enable Frontend sDMA */
714 snd_soc_dsp_platform_trigger(substream, cmd, fe->platform);
715 enable_fe_port(substream, dai, stream);
716
717 /* unmute FE port */
718 unmute_fe_port(substream, dai, stream);
719 }
720 break;
721 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
722 /* Enable Frontend sDMA */
723 snd_soc_dsp_platform_trigger(substream, cmd, fe->platform);
724 enable_fe_port(substream, dai, stream);
725
726 /* unmute FE port */
727 unmute_fe_port(substream, dai, stream);
728 break;
729 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
730 /* disable Frontend sDMA */
731 disable_fe_port(substream, dai, stream);
732 snd_soc_dsp_platform_trigger(substream, cmd, fe->platform);
733
734 /* mute FE port */
735 mute_fe_port(substream, dai, stream);
736 break;
737 case SNDRV_PCM_TRIGGER_STOP:
738
739 /* does this trigger() apply to the FE ? */
740 if (snd_soc_dsp_is_trigger_for_fe(fe, stream)) {
741
742 /* disable the transfer */
743 disable_fe_port(substream, dai, stream);
744 snd_soc_dsp_platform_trigger(substream, cmd, fe->platform);
745
746 /* mute FE port */
747 mute_fe_port(substream, dai, stream);
748 }
749
750 /* disable BE ports */
751 list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be) {
752 struct snd_soc_pcm_runtime *be = dsp_params->be;
753
754 /* does this trigger() apply to this BE and stream ? */
755 if (!snd_soc_dsp_is_trigger_for_be(fe, be, stream))
756 continue;
757
758 /* only STOP BE in FREE state */
759 if (dsp_params->state != SND_SOC_DSP_LINK_STATE_FREE)
760 continue;
761
762 be_substream = snd_soc_dsp_get_substream(dsp_params->be, stream);
763
764 /* disable the BE */
765 disable_be_port(be, dai, stream);
766
767 /* DAI work must be started/stopped at least 250us after ABE */
768 udelay(250);
769
770 /* trigger the BE port */
771 snd_soc_dai_trigger(be_substream, cmd, be->cpu_dai);
772 }
773 break;
774 default:
775 break;
776 }
777}
778
779static int omap_abe_dai_startup(struct snd_pcm_substream *substream,
780 struct snd_soc_dai *dai)
781{
782 struct omap_abe_data *abe_priv = snd_soc_dai_get_drvdata(dai);
783 int ret = 0;
784
785 dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
786
787 if (dai->id == ABE_FRONTEND_DAI_MODEM) {
788
789 ret = modem_get_dai(substream, dai);
790 if (ret < 0) {
791 dev_err(dai->dev, "failed to get MODEM DAI\n");
792 return ret;
793 }
794 dev_dbg(abe_priv->modem_dai->dev, "%s: MODEM stream %d\n",
795 __func__, substream->stream);
796
797 ret = snd_soc_dai_startup(abe_priv->modem_substream[substream->stream],
798 abe_priv->modem_dai);
799 if (ret < 0) {
800 dev_err(abe_priv->modem_dai->dev, "failed to open DAI %d\n", ret);
801 return ret;
802 }
803 }
804
805 return ret;
806}
807
808static int omap_abe_dai_hw_params(struct snd_pcm_substream *substream,
809 struct snd_pcm_hw_params *params,
810 struct snd_soc_dai *dai)
811{
812 struct omap_abe_data *abe_priv = snd_soc_dai_get_drvdata(dai);
813 abe_data_format_t format;
814 abe_dma_t dma_sink;
815 abe_dma_t dma_params;
816 int ret;
817
818 dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
819
820 switch (params_channels(params)) {
821 case 1:
822 if (params_format(params) == SNDRV_PCM_FORMAT_S16_LE)
823 format.samp_format = MONO_RSHIFTED_16;
824 else
825 format.samp_format = MONO_MSB;
826 break;
827 case 2:
828 if (params_format(params) == SNDRV_PCM_FORMAT_S16_LE)
829 format.samp_format = STEREO_16_16;
830 else
831 format.samp_format = STEREO_MSB;
832 break;
833 case 3:
834 format.samp_format = THREE_MSB;
835 break;
836 case 4:
837 format.samp_format = FOUR_MSB;
838 break;
839 case 5:
840 format.samp_format = FIVE_MSB;
841 break;
842 case 6 :
843 format.samp_format = SIX_MSB;
844 break;
845 case 7 :
846 format.samp_format = SEVEN_MSB;
847 break;
848 case 8:
849 format.samp_format = EIGHT_MSB;
850 break;
851 default:
852 dev_err(dai->dev, "%d channels not supported",
853 params_channels(params));
854 return -EINVAL;
855 }
856
857 format.f = params_rate(params);
858
859 switch (dai->id) {
860 case ABE_FRONTEND_DAI_MEDIA:
861 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
862 abe_connect_cbpr_dmareq_port(MM_DL_PORT, &format, ABE_CBPR0_IDX,
863 &dma_sink);
864 abe_read_port_address(MM_DL_PORT, &dma_params);
865 } else {
866 abe_connect_cbpr_dmareq_port(MM_UL_PORT, &format, ABE_CBPR3_IDX,
867 &dma_sink);
868 abe_read_port_address(MM_UL_PORT, &dma_params);
869 }
870 break;
871 case ABE_FRONTEND_DAI_LP_MEDIA:
872 return 0;
873 break;
874 case ABE_FRONTEND_DAI_MEDIA_CAPTURE:
875 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
876 return -EINVAL;
877 else {
878 abe_connect_cbpr_dmareq_port(MM_UL2_PORT, &format, ABE_CBPR4_IDX,
879 &dma_sink);
880 abe_read_port_address(MM_UL2_PORT, &dma_params);
881 }
882 break;
883 case ABE_FRONTEND_DAI_VOICE:
884 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
885 abe_connect_cbpr_dmareq_port(VX_DL_PORT, &format, ABE_CBPR1_IDX,
886 &dma_sink);
887 abe_read_port_address(VX_DL_PORT, &dma_params);
888 } else {
889 abe_connect_cbpr_dmareq_port(VX_UL_PORT, &format, ABE_CBPR2_IDX,
890 &dma_sink);
891 abe_read_port_address(VX_UL_PORT, &dma_params);
892 }
893 break;
894 case ABE_FRONTEND_DAI_TONES:
895 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
896 abe_connect_cbpr_dmareq_port(TONES_DL_PORT, &format, ABE_CBPR5_IDX,
897 &dma_sink);
898 abe_read_port_address(TONES_DL_PORT, &dma_params);
899 } else
900 return -EINVAL;
901 break;
902 case ABE_FRONTEND_DAI_VIBRA:
903 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
904 abe_connect_cbpr_dmareq_port(VIB_DL_PORT, &format, ABE_CBPR6_IDX,
905 &dma_sink);
906 abe_read_port_address(VIB_DL_PORT, &dma_params);
907 } else
908 return -EINVAL;
909 break;
910 case ABE_FRONTEND_DAI_MODEM:
911 /* MODEM is special case where data IO is performed by McBSP2
912 * directly onto VX_DL and VX_UL (instead of SDMA).
913 */
914 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
915 /* Vx_DL connection to McBSP 2 ports */
916 format.samp_format = STEREO_RSHIFTED_16;
917 abe_connect_serial_port(VX_DL_PORT, &format, MCBSP2_RX);
918 abe_read_port_address(VX_DL_PORT, &dma_params);
919 } else {
920 /* Vx_UL connection to McBSP 2 ports */
921 format.samp_format = STEREO_RSHIFTED_16;
922 abe_connect_serial_port(VX_UL_PORT, &format, MCBSP2_TX);
923 abe_read_port_address(VX_UL_PORT, &dma_params);
924 }
925 break;
926 }
927
928 /* configure frontend SDMA data */
929 omap_abe_dai_dma_params[dai->id][substream->stream].port_addr =
930 (unsigned long)dma_params.data;
931 omap_abe_dai_dma_params[dai->id][substream->stream].packet_size =
932 dma_params.iter;
933
934 if (dai->id == ABE_FRONTEND_DAI_MODEM) {
935 /* call hw_params on McBSP with correct DMA data */
936 snd_soc_dai_set_dma_data(abe_priv->modem_dai, substream,
937 &omap_abe_dai_dma_params[dai->id][substream->stream]);
938
939 dev_dbg(abe_priv->modem_dai->dev, "%s: MODEM stream %d\n",
940 __func__, substream->stream);
941
942 ret = snd_soc_dai_hw_params(abe_priv->modem_substream[substream->stream],
943 params, abe_priv->modem_dai);
944 if (ret < 0)
945 dev_err(abe_priv->modem_dai->dev, "MODEM hw_params failed\n");
946 return ret;
947 }
948
949 snd_soc_dai_set_dma_data(dai, substream,
950 &omap_abe_dai_dma_params[dai->id][substream->stream]);
951
952 return 0;
953}
954
955static int omap_abe_dai_prepare(struct snd_pcm_substream *substream,
956 struct snd_soc_dai *dai)
957{
958 struct omap_abe_data *abe_priv = snd_soc_dai_get_drvdata(dai);
959 int ret = 0;
960
961 dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
962
963 if (dai->id == ABE_FRONTEND_DAI_MODEM) {
964 ret = snd_soc_dai_prepare(abe_priv->modem_substream[substream->stream],
965 abe_priv->modem_dai);
966
967 dev_dbg(abe_priv->modem_dai->dev, "%s: MODEM stream %d\n",
968 __func__, substream->stream);
969
970 if (ret < 0) {
971 dev_err(abe_priv->modem_dai->dev, "MODEM prepare failed\n");
972 return ret;
973 }
974 }
975 return ret;
976}
977
978static int omap_abe_dai_trigger(struct snd_pcm_substream *substream,
979 int cmd, struct snd_soc_dai *dai)
980{
981 struct omap_abe_data *abe_priv = snd_soc_dai_get_drvdata(dai);
982 int ret = 0;
983
984 dev_dbg(dai->dev, "%s: %s cmd %d\n", __func__, dai->name, cmd);
985
986 if (dai->id == ABE_FRONTEND_DAI_MODEM) {
987
988 dev_dbg(abe_priv->modem_dai->dev, "%s: MODEM stream %d cmd %d\n",
989 __func__, substream->stream, cmd);
990
991 ret = snd_soc_dai_trigger(abe_priv->modem_substream[substream->stream],
992 cmd, abe_priv->modem_dai);
993 if (ret < 0) {
994 dev_err(abe_priv->modem_dai->dev, "MODEM trigger failed\n");
995 return ret;
996 }
997 }
998
999 return ret;
1000}
1001
1002static int omap_abe_dai_bespoke_trigger(struct snd_pcm_substream *substream,
1003 int cmd, struct snd_soc_dai *dai)
1004{
Misael Lopez Cruza3168ef2011-06-17 18:32:11 -05001005 struct omap_abe_data *abe_priv = snd_soc_dai_get_drvdata(dai);
1006 int ret = 0;
1007
Liam Girdwoodc60eacc2011-02-03 15:12:22 +00001008 dev_dbg(dai->dev, "%s: %s cmd %d\n", __func__, dai->name, cmd);
1009
Misael Lopez Cruza3168ef2011-06-17 18:32:11 -05001010 if (dai->id == ABE_FRONTEND_DAI_MODEM) {
1011
1012 dev_dbg(abe_priv->modem_dai->dev, "%s: MODEM stream %d cmd %d\n",
1013 __func__, substream->stream, cmd);
1014
1015 ret = snd_soc_dai_trigger(abe_priv->modem_substream[substream->stream],
1016 cmd, abe_priv->modem_dai);
1017 if (ret < 0) {
1018 dev_err(abe_priv->modem_dai->dev, "MODEM trigger failed\n");
1019 return ret;
1020 }
1021 }
1022
Liam Girdwoodc60eacc2011-02-03 15:12:22 +00001023 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
1024 playback_trigger(substream, dai, cmd);
1025 else
1026 capture_trigger(substream, dai, cmd);
1027
Misael Lopez Cruza3168ef2011-06-17 18:32:11 -05001028 return ret;
Liam Girdwoodc60eacc2011-02-03 15:12:22 +00001029}
1030
1031static int omap_abe_dai_hw_free(struct snd_pcm_substream *substream,
1032 struct snd_soc_dai *dai)
1033{
1034 struct omap_abe_data *abe_priv = snd_soc_dai_get_drvdata(dai);
1035 int ret = 0;
1036
1037 dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
1038
1039 if (dai->id == ABE_FRONTEND_DAI_MODEM) {
1040
1041 dev_dbg(abe_priv->modem_dai->dev, "%s: MODEM stream %d\n",
1042 __func__, substream->stream);
1043
1044 ret = snd_soc_dai_hw_free(abe_priv->modem_substream[substream->stream],
1045 abe_priv->modem_dai);
1046 if (ret < 0) {
1047 dev_err(abe_priv->modem_dai->dev, "MODEM hw_free failed\n");
1048 return ret;
1049 }
1050 }
1051 return ret;
1052}
1053
1054static void omap_abe_dai_shutdown(struct snd_pcm_substream *substream,
1055 struct snd_soc_dai *dai)
1056{
1057 struct omap_abe_data *abe_priv = snd_soc_dai_get_drvdata(dai);
1058
1059 dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
1060
1061 if (dai->id == ABE_FRONTEND_DAI_MODEM) {
1062 dev_dbg(abe_priv->modem_dai->dev, "%s: MODEM stream %d\n",
1063 __func__, substream->stream);
1064
1065 snd_soc_dai_shutdown(abe_priv->modem_substream[substream->stream],
1066 abe_priv->modem_dai);
1067 }
1068}
1069
1070static int omap_abe_dai_probe(struct snd_soc_dai *dai)
1071{
1072 struct omap_abe_data *abe_priv;
1073 int i;
1074
1075 abe_priv = kzalloc(sizeof(struct omap_abe_data), GFP_KERNEL);
1076 if (abe_priv == NULL)
1077 return -ENOMEM;
1078
1079 abe_priv->abe = omap_abe_port_mgr_get();
1080 if (!abe_priv->abe)
1081 goto err;
1082
1083 for (i = 0; i <= OMAP_ABE_MAX_PORT_ID; i++) {
1084
1085 abe_priv->port[i] = omap_abe_port_open(abe_priv->abe, i);
1086 if (abe_priv->port[i] == NULL) {
1087 for (--i; i >= 0; i--)
1088 omap_abe_port_close(abe_priv->abe, abe_priv->port[i]);
1089
1090 goto err_port;
1091 }
1092 }
1093
1094 snd_soc_dai_set_drvdata(dai, abe_priv);
1095 return 0;
1096
1097err_port:
1098 omap_abe_port_mgr_put(abe_priv->abe);
1099err:
1100 kfree(abe_priv);
1101 return -ENOMEM;
1102}
1103
1104static int omap_abe_dai_remove(struct snd_soc_dai *dai)
1105{
1106 struct omap_abe_data *abe_priv = snd_soc_dai_get_drvdata(dai);
1107
1108 omap_abe_port_mgr_put(abe_priv->abe);
1109 kfree(abe_priv);
1110 return 0;
1111}
1112
1113static struct snd_soc_dai_ops omap_abe_dai_ops = {
1114 .startup = omap_abe_dai_startup,
1115 .shutdown = omap_abe_dai_shutdown,
1116 .hw_params = omap_abe_dai_hw_params,
1117 .hw_free = omap_abe_dai_hw_free,
1118 .prepare = omap_abe_dai_prepare,
1119 .trigger = omap_abe_dai_trigger,
1120 .bespoke_trigger = omap_abe_dai_bespoke_trigger,
1121};
1122
1123static struct snd_soc_dai_driver omap_abe_dai[] = {
1124 { /* Multimedia Playback and Capture */
1125 .name = "MultiMedia1",
1126 .probe = omap_abe_dai_probe,
1127 .remove = omap_abe_dai_remove,
1128 .playback = {
1129 .stream_name = "MultiMedia1 Playback",
1130 .channels_min = 1,
1131 .channels_max = 2,
1132 .rates = SNDRV_PCM_RATE_48000,
1133 .formats = OMAP_ABE_FORMATS,
1134 },
1135 .capture = {
1136 .stream_name = "MultiMedia1 Capture",
1137 .channels_min = 2,
1138 .channels_max = 8,
1139 .rates = SNDRV_PCM_RATE_48000,
1140 .formats = OMAP_ABE_FORMATS,
1141 },
1142 .ops = &omap_abe_dai_ops,
1143 },
1144 { /* Multimedia Capture */
1145 .name = "MultiMedia2",
1146 .capture = {
1147 .stream_name = "MultiMedia2 Capture",
1148 .channels_min = 1,
1149 .channels_max = 2,
1150 .rates = SNDRV_PCM_RATE_48000,
1151 .formats = OMAP_ABE_FORMATS,
1152 },
1153 .ops = &omap_abe_dai_ops,
1154 },
1155 { /* Voice Playback and Capture */
1156 .name = "Voice",
1157 .playback = {
1158 .stream_name = "Voice Playback",
1159 .channels_min = 1,
1160 .channels_max = 2,
1161 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
1162 .formats = OMAP_ABE_FORMATS,
1163 },
1164 .capture = {
1165 .stream_name = "Voice Capture",
1166 .channels_min = 1,
1167 .channels_max = 2,
1168 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
1169 .formats = OMAP_ABE_FORMATS,
1170 },
1171 .ops = &omap_abe_dai_ops,
1172 },
1173 { /* Tones Playback */
1174 .name = "Tones",
1175 .playback = {
1176 .stream_name = "Tones Playback",
1177 .channels_min = 1,
1178 .channels_max = 2,
1179 .rates = SNDRV_PCM_RATE_48000,
1180 .formats = OMAP_ABE_FORMATS,
1181 },
1182 .ops = &omap_abe_dai_ops,
1183 },
1184 { /* Vibra */
1185 .name = "Vibra",
1186 .playback = {
1187 .stream_name = "Vibra Playback",
1188 .channels_min = 2,
1189 .channels_max = 2,
1190 .rates = SNDRV_PCM_RATE_CONTINUOUS,
1191 .formats = OMAP_ABE_FORMATS,
1192 },
1193 .ops = &omap_abe_dai_ops,
1194 },
1195 { /* MODEM Voice Playback and Capture */
1196 .name = "MODEM",
1197 .playback = {
1198 .stream_name = "Voice Playback",
1199 .channels_min = 1,
Francois Mazard0014f452011-06-17 15:07:12 +02001200 .channels_max = 2,
Liam Girdwoodc60eacc2011-02-03 15:12:22 +00001201 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
1202 .formats = OMAP_ABE_FORMATS | SNDRV_PCM_FMTBIT_S16_LE,
1203 },
1204 .capture = {
1205 .stream_name = "Voice Capture",
1206 .channels_min = 1,
Francois Mazard0014f452011-06-17 15:07:12 +02001207 .channels_max = 2,
Liam Girdwoodc60eacc2011-02-03 15:12:22 +00001208 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
1209 .formats = OMAP_ABE_FORMATS | SNDRV_PCM_FMTBIT_S16_LE,
1210 },
1211 .ops = &omap_abe_dai_ops,
1212 },
1213 { /* Low Power HiFi Playback */
1214 .name = "MultiMedia1 LP",
1215 .playback = {
1216 .stream_name = "MultiMedia1 LP Playback",
1217 .channels_min = 2,
1218 .channels_max = 2,
1219 .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
1220 .formats = OMAP_ABE_FORMATS | SNDRV_PCM_FMTBIT_S16_LE,
1221 },
1222 .ops = &omap_abe_dai_ops,
1223 },
1224};
1225
1226static int __devinit omap_abe_probe(struct platform_device *pdev)
1227{
1228 return snd_soc_register_dais(&pdev->dev, omap_abe_dai,
1229 ARRAY_SIZE(omap_abe_dai));
1230}
1231
1232static int __devexit omap_abe_remove(struct platform_device *pdev)
1233{
1234 snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(omap_abe_dai));
1235 return 0;
1236}
1237
1238static struct platform_driver omap_abe_driver = {
1239 .driver = {
1240 .name = "omap-abe-dai",
1241 .owner = THIS_MODULE,
1242 },
1243 .probe = omap_abe_probe,
1244 .remove = __devexit_p(omap_abe_remove),
1245};
1246
1247static int __init omap_abe_init(void)
1248{
1249 return platform_driver_register(&omap_abe_driver);
1250}
1251module_init(omap_abe_init);
1252
1253static void __exit omap_abe_exit(void)
1254{
1255 platform_driver_unregister(&omap_abe_driver);
1256}
1257module_exit(omap_abe_exit);
1258
Liam Girdwoode708bea2011-02-03 15:17:26 +00001259MODULE_AUTHOR("Liam Girdwood <lrg@ti.com>");
Liam Girdwoodc60eacc2011-02-03 15:12:22 +00001260MODULE_DESCRIPTION("OMAP ABE SoC Interface");
1261MODULE_LICENSE("GPL");