blob: f23a6a0b2e5126937e08e10dc1f89c47de8453c7 [file] [log] [blame]
Kiran Kandi9db678b2012-01-15 14:25:59 -08001/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/init.h>
14#include <linux/module.h>
15#include <linux/device.h>
16#include <linux/platform_device.h>
17#include <linux/mfd/wcd9310/core.h>
18#include <linux/bitops.h>
19#include <linux/slab.h>
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -070020#include <linux/clk.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070021#include <sound/core.h>
22#include <sound/pcm.h>
23#include <sound/soc.h>
24#include <sound/apr_audio.h>
25#include <sound/q6afe.h>
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -070026#include <sound/msm-dai-q6.h>
27#include <mach/clk.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070028
29enum {
30 STATUS_PORT_STARTED, /* track if AFE port has started */
31 STATUS_MAX
32};
33
34struct msm_dai_q6_dai_data {
35 DECLARE_BITMAP(status_mask, STATUS_MAX);
36 u32 rate;
37 u32 channels;
38 union afe_port_config port_config;
39};
40
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -070041static struct clk *pcm_clk;
42
Kuirong Wang274f21a2011-12-15 21:29:08 -080043static u8 num_of_bits_set(u8 sd_line_mask)
44{
45 u8 num_bits_set = 0;
46
47 while (sd_line_mask) {
48 num_bits_set++;
49 sd_line_mask = sd_line_mask & (sd_line_mask - 1);
50 }
51 return num_bits_set;
52}
53
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070054static int msm_dai_q6_cdc_hw_params(struct snd_pcm_hw_params *params,
55 struct snd_soc_dai *dai, int stream)
56{
57 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
58
59 dai_data->channels = params_channels(params);
60 switch (dai_data->channels) {
61 case 2:
62 dai_data->port_config.mi2s.channel = MSM_AFE_STEREO;
63 break;
64 case 1:
65 dai_data->port_config.mi2s.channel = MSM_AFE_MONO;
66 break;
67 default:
68 return -EINVAL;
69 break;
70 }
71 dai_data->rate = params_rate(params);
72
73 dev_dbg(dai->dev, " channel %d sample rate %d entered\n",
74 dai_data->channels, dai_data->rate);
75
76 /* Q6 only supports 16 as now */
77 dai_data->port_config.mi2s.bitwidth = 16;
78 dai_data->port_config.mi2s.line = 1;
Kuirong Wang274f21a2011-12-15 21:29:08 -080079 return 0;
80}
81
82static int msm_dai_q6_mi2s_hw_params(struct snd_pcm_hw_params *params,
83 struct snd_soc_dai *dai, int stream)
84{
85 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
86 struct msm_mi2s_data *mi2s_pdata =
87 (struct msm_mi2s_data *) dai->dev->platform_data;
88
89 dai_data->channels = params_channels(params);
90 if (num_of_bits_set(mi2s_pdata->sd_lines) == 1) {
91 switch (dai_data->channels) {
92 case 2:
93 dai_data->port_config.mi2s.channel = MSM_AFE_STEREO;
94 break;
95 case 1:
96 dai_data->port_config.mi2s.channel = MSM_AFE_MONO;
97 break;
98 default:
99 pr_warn("greater than stereo has not been validated");
100 break;
101 }
102 }
103 /* Q6 only supports 16 as now */
104 dai_data->port_config.mi2s.bitwidth = 16;
Lei Zhou157c1842011-08-19 13:05:04 -0400105
106 return 0;
107}
108
Kuirong Wang274f21a2011-12-15 21:29:08 -0800109static int msm_dai_q6_mi2s_platform_data_validation(
110 struct snd_soc_dai *dai)
111{
112 u8 num_of_sd_lines;
113 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
114 struct msm_mi2s_data *mi2s_pdata =
115 (struct msm_mi2s_data *)dai->dev->platform_data;
116 struct snd_soc_dai_driver *dai_driver =
117 (struct snd_soc_dai_driver *)dai->driver;
118
119 num_of_sd_lines = num_of_bits_set(mi2s_pdata->sd_lines);
120
121 switch (num_of_sd_lines) {
122 case 1:
123 switch (mi2s_pdata->sd_lines) {
124 case MSM_MI2S_SD0:
125 dai_data->port_config.mi2s.line = AFE_I2S_SD0;
126 break;
127 case MSM_MI2S_SD1:
128 dai_data->port_config.mi2s.line = AFE_I2S_SD1;
129 break;
130 case MSM_MI2S_SD2:
131 dai_data->port_config.mi2s.line = AFE_I2S_SD2;
132 break;
133 case MSM_MI2S_SD3:
134 dai_data->port_config.mi2s.line = AFE_I2S_SD3;
135 break;
136 default:
137 pr_err("%s: invalid SD line\n",
138 __func__);
139 goto error_invalid_data;
140 }
141 break;
142 case 2:
143 switch (mi2s_pdata->sd_lines) {
144 case MSM_MI2S_SD0 | MSM_MI2S_SD1:
145 dai_data->port_config.mi2s.line = AFE_I2S_QUAD01;
146 break;
147 case MSM_MI2S_SD2 | MSM_MI2S_SD3:
148 dai_data->port_config.mi2s.line = AFE_I2S_QUAD23;
149 break;
150 default:
151 pr_err("%s: invalid SD line\n",
152 __func__);
153 goto error_invalid_data;
154 }
155 break;
156 case 3:
157 switch (mi2s_pdata->sd_lines) {
158 case MSM_MI2S_SD0 | MSM_MI2S_SD1 | MSM_MI2S_SD2:
159 dai_data->port_config.mi2s.line = AFE_I2S_6CHS;
160 break;
161 default:
162 pr_err("%s: invalid SD lines\n",
163 __func__);
164 goto error_invalid_data;
165 }
166 break;
167 case 4:
168 switch (mi2s_pdata->sd_lines) {
169 case MSM_MI2S_SD0 | MSM_MI2S_SD1 | MSM_MI2S_SD2 | MSM_MI2S_SD3:
170 dai_data->port_config.mi2s.line = AFE_I2S_8CHS;
171 break;
172 default:
173 pr_err("%s: invalid SD lines\n",
174 __func__);
175 goto error_invalid_data;
176 }
177 break;
178 default:
179 pr_err("%s: invalid SD lines\n", __func__);
180 goto error_invalid_data;
181 }
182 if (mi2s_pdata->capability == MSM_MI2S_CAP_RX)
183 dai_driver->playback.channels_max = num_of_sd_lines << 1;
184
185 return 0;
186
187error_invalid_data:
188 return -EINVAL;
189}
190
Lei Zhou157c1842011-08-19 13:05:04 -0400191static int msm_dai_q6_cdc_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
192{
193 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
194
195 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
196 case SND_SOC_DAIFMT_CBS_CFS:
197 dai_data->port_config.mi2s.ws = 1; /* CPU is master */
198 break;
199 case SND_SOC_DAIFMT_CBM_CFM:
200 dai_data->port_config.mi2s.ws = 0; /* CPU is slave */
201 break;
202 default:
203 return -EINVAL;
204 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700205
206 return 0;
207}
208
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700209
210static int msm_dai_q6_slim_bus_hw_params(struct snd_pcm_hw_params *params,
211 struct snd_soc_dai *dai, int stream)
212{
213 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700214
215 dai_data->channels = params_channels(params);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700216 dai_data->rate = params_rate(params);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700217
218 dai_data->port_config.slimbus.slimbus_dev_id = AFE_SLIMBUS_DEVICE_1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700219 /* Q6 only supports 16 as now */
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800220 dai_data->port_config.slim_sch.bit_width = 16;
221 dai_data->port_config.slim_sch.data_format = 0;
222 dai_data->port_config.slim_sch.num_channels = dai_data->channels;
223 dai_data->port_config.slim_sch.reserved = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700224
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800225 dev_dbg(dai->dev, "%s:slimbus_dev_id[%hu] bit_wd[%hu] format[%hu]\n"
226 "num_channel %hu slave_ch_mapping[0] %hu\n"
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700227 "slave_port_mapping[1] %hu slave_port_mapping[2] %hu\n"
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800228 "sample_rate %d\n", __func__,
229 dai_data->port_config.slim_sch.slimbus_dev_id,
230 dai_data->port_config.slim_sch.bit_width,
231 dai_data->port_config.slim_sch.data_format,
232 dai_data->port_config.slim_sch.num_channels,
233 dai_data->port_config.slim_sch.slave_ch_mapping[0],
234 dai_data->port_config.slim_sch.slave_ch_mapping[1],
235 dai_data->port_config.slim_sch.slave_ch_mapping[2],
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700236 dai_data->rate);
237
238 return 0;
239}
240
241static int msm_dai_q6_bt_fm_hw_params(struct snd_pcm_hw_params *params,
242 struct snd_soc_dai *dai, int stream)
243{
244 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
245
246 dai_data->channels = params_channels(params);
247 dai_data->rate = params_rate(params);
248
249 dev_dbg(dai->dev, "channels %d sample rate %d entered\n",
250 dai_data->channels, dai_data->rate);
251
252 memset(&dai_data->port_config, 0, sizeof(dai_data->port_config));
253
254 return 0;
255}
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700256static int msm_dai_q6_auxpcm_hw_params(
257 struct snd_pcm_substream *substream,
258 struct snd_pcm_hw_params *params,
259 struct snd_soc_dai *dai)
260{
261 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
262 struct msm_dai_auxpcm_pdata *auxpcm_pdata =
263 (struct msm_dai_auxpcm_pdata *) dai->dev->platform_data;
264
265 if (params_channels(params) != 1) {
266 dev_err(dai->dev, "AUX PCM supports only mono stream\n");
267 return -EINVAL;
268 }
269 dai_data->channels = params_channels(params);
270
271 if (params_rate(params) != 8000) {
272 dev_err(dai->dev, "AUX PCM supports only 8KHz sampling rate\n");
273 return -EINVAL;
274 }
275 dai_data->rate = params_rate(params);
276 dai_data->port_config.pcm.mode = auxpcm_pdata->mode;
277 dai_data->port_config.pcm.sync = auxpcm_pdata->sync;
278 dai_data->port_config.pcm.frame = auxpcm_pdata->frame;
279 dai_data->port_config.pcm.quant = auxpcm_pdata->quant;
280 dai_data->port_config.pcm.slot = auxpcm_pdata->slot;
281 dai_data->port_config.pcm.data = auxpcm_pdata->data;
282
283 return 0;
284}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700285
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530286static int get_frame_size(u16 rate, u16 ch)
287{
288 if (rate == 8000) {
289 if (ch == 1)
290 return 128 * 2;
291 else
292 return 128 * 2 * 2;
293 } else if (rate == 16000) {
294 if (ch == 1)
295 return 128 * 2 * 2;
296 else
297 return 128 * 2 * 4;
298 } else if (rate == 48000) {
299 if (ch == 1)
300 return 128 * 2 * 6;
301 else
302 return 128 * 2 * 12;
303 } else
304 return 128 * 2 * 12;
305}
306
307static int msm_dai_q6_afe_rtproxy_hw_params(struct snd_pcm_hw_params *params,
308 struct snd_soc_dai *dai)
309{
310 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
311
312 dai_data->rate = params_rate(params);
313 dai_data->port_config.rtproxy.num_ch =
314 params_channels(params);
315
316 pr_debug("channel %d entered,dai_id: %d,rate: %d\n",
317 dai_data->port_config.rtproxy.num_ch, dai->id, dai_data->rate);
318
319 dai_data->port_config.rtproxy.bitwidth = 16; /* Q6 only supports 16 */
320 dai_data->port_config.rtproxy.interleaved = 1;
321 dai_data->port_config.rtproxy.frame_sz = get_frame_size(dai_data->rate,
322 dai_data->port_config.rtproxy.num_ch);
323 dai_data->port_config.rtproxy.jitter =
324 dai_data->port_config.rtproxy.frame_sz/2;
325 dai_data->port_config.rtproxy.lw_mark = 0;
326 dai_data->port_config.rtproxy.hw_mark = 0;
327 dai_data->port_config.rtproxy.rsvd = 0;
328
329 return 0;
330}
331
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700332/* Current implementation assumes hw_param is called once
333 * This may not be the case but what to do when ADM and AFE
334 * port are already opened and parameter changes
335 */
336static int msm_dai_q6_hw_params(struct snd_pcm_substream *substream,
337 struct snd_pcm_hw_params *params,
338 struct snd_soc_dai *dai)
339{
340 int rc = 0;
341
342 switch (dai->id) {
343 case PRIMARY_I2S_TX:
344 case PRIMARY_I2S_RX:
Kuirong Wang9bbf6132012-01-10 18:28:49 -0800345 case SECONDARY_I2S_RX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700346 rc = msm_dai_q6_cdc_hw_params(params, dai, substream->stream);
347 break;
Kuirong Wang274f21a2011-12-15 21:29:08 -0800348 case MI2S_RX:
349 rc = msm_dai_q6_mi2s_hw_params(params, dai, substream->stream);
350 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700351 case SLIMBUS_0_RX:
352 case SLIMBUS_0_TX:
353 rc = msm_dai_q6_slim_bus_hw_params(params, dai,
354 substream->stream);
355 break;
356 case INT_BT_SCO_RX:
357 case INT_BT_SCO_TX:
358 case INT_FM_RX:
359 case INT_FM_TX:
360 rc = msm_dai_q6_bt_fm_hw_params(params, dai, substream->stream);
361 break;
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530362 case RT_PROXY_DAI_001_TX:
363 case RT_PROXY_DAI_001_RX:
364 case RT_PROXY_DAI_002_TX:
365 case RT_PROXY_DAI_002_RX:
366 rc = msm_dai_q6_afe_rtproxy_hw_params(params, dai);
367 break;
Helen Zeng0705a5f2011-10-14 15:29:52 -0700368 case VOICE_PLAYBACK_TX:
Helen Zenge3d716a2011-10-14 16:32:16 -0700369 case VOICE_RECORD_RX:
370 case VOICE_RECORD_TX:
Helen Zeng0705a5f2011-10-14 15:29:52 -0700371 rc = 0;
372 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700373 default:
374 dev_err(dai->dev, "invalid AFE port ID\n");
375 rc = -EINVAL;
376 break;
377 }
378
379 return rc;
380}
381
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700382static void msm_dai_q6_auxpcm_shutdown(struct snd_pcm_substream *substream,
383 struct snd_soc_dai *dai)
384{
385 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
386 int rc = 0;
387
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700388 pr_debug("%s: dai->id = %d", __func__, dai->id);
389
390 if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
391 clk_disable(pcm_clk);
392 rc = afe_close(dai->id); /* can block */
393 if (IS_ERR_VALUE(rc))
394 dev_err(dai->dev, "fail to close AFE port\n");
395 pr_debug("%s: dai_data->status_mask = %ld\n", __func__,
396 *dai_data->status_mask);
397 clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
398
399 rc = afe_close(PCM_TX);
400 if (IS_ERR_VALUE(rc))
401 dev_err(dai->dev, "fail to close AUX PCM TX port\n");
402 }
403}
404
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700405static void msm_dai_q6_shutdown(struct snd_pcm_substream *substream,
406 struct snd_soc_dai *dai)
407{
408 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530409 int rc = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700410
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700411 if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
Helen Zeng0705a5f2011-10-14 15:29:52 -0700412 switch (dai->id) {
413 case VOICE_PLAYBACK_TX:
Helen Zenge3d716a2011-10-14 16:32:16 -0700414 case VOICE_RECORD_TX:
415 case VOICE_RECORD_RX:
Helen Zeng0705a5f2011-10-14 15:29:52 -0700416 pr_debug("%s, stop pseudo port:%d\n",
417 __func__, dai->id);
418 rc = afe_stop_pseudo_port(dai->id);
419 break;
420 default:
421 rc = afe_close(dai->id); /* can block */
422 break;
423 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700424 if (IS_ERR_VALUE(rc))
425 dev_err(dai->dev, "fail to close AFE port\n");
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530426 pr_debug("%s: dai_data->status_mask = %ld\n", __func__,
427 *dai_data->status_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700428 clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
429 }
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700430}
431
432static int msm_dai_q6_auxpcm_prepare(struct snd_pcm_substream *substream,
433 struct snd_soc_dai *dai)
434{
435 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
436 int rc = 0;
437
438 struct msm_dai_auxpcm_pdata *auxpcm_pdata =
439 (struct msm_dai_auxpcm_pdata *) dai->dev->platform_data;
440
441 if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
Patrick Laicf999112011-08-23 11:27:20 -0700442 rc = afe_q6_interface_prepare();
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700443 if (IS_ERR_VALUE(rc))
Patrick Laicf999112011-08-23 11:27:20 -0700444 dev_err(dai->dev, "fail to open AFE APR\n");
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700445
Patrick Laicf999112011-08-23 11:27:20 -0700446 rc = afe_q6_interface_prepare();
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700447 if (IS_ERR_VALUE(rc))
Patrick Laicf999112011-08-23 11:27:20 -0700448 dev_err(dai->dev, "fail to open AFE APR\n");
449
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700450 pr_debug("%s:dai->id:%d dai_data->status_mask = %ld\n",
451 __func__, dai->id, *dai_data->status_mask);
452
453 /*
454 * For AUX PCM Interface the below sequence of clk
455 * settings and afe_open is a strict requirement.
456 *
457 * Also using afe_open instead of afe_port_start_nowait
458 * to make sure the port is open before deasserting the
459 * clock line. This is required because pcm register is
460 * not written before clock deassert. Hence the hw does
461 * not get updated with new setting if the below clock
462 * assert/deasset and afe_open sequence is not followed.
463 */
464
465 clk_reset(pcm_clk, CLK_RESET_ASSERT);
466
467 afe_open(dai->id, &dai_data->port_config,
468 dai_data->rate);
469 set_bit(STATUS_PORT_STARTED,
470 dai_data->status_mask);
471
472 afe_open(PCM_TX, &dai_data->port_config, dai_data->rate);
473
474 rc = clk_set_rate(pcm_clk, auxpcm_pdata->pcm_clk_rate);
475 if (rc < 0) {
476 pr_err("%s: clk_set_rate failed\n", __func__);
477 return rc;
478 }
479
480 clk_enable(pcm_clk);
481 clk_reset(pcm_clk, CLK_RESET_DEASSERT);
482
483 }
484 return rc;
485}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700486
487static int msm_dai_q6_prepare(struct snd_pcm_substream *substream,
488 struct snd_soc_dai *dai)
489{
490 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
491 int rc = 0;
492
Patrick Lai831561e2011-07-26 22:51:27 -0700493 if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
Patrick Laicf999112011-08-23 11:27:20 -0700494 /* PORT START should be set if prepare called in active state */
495 rc = afe_q6_interface_prepare();
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700496 if (IS_ERR_VALUE(rc))
Patrick Laicf999112011-08-23 11:27:20 -0700497 dev_err(dai->dev, "fail to open AFE APR\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700498 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700499 return rc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700500}
501
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700502static int msm_dai_q6_auxpcm_trigger(struct snd_pcm_substream *substream,
503 int cmd, struct snd_soc_dai *dai)
504{
505 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
506 int rc = 0;
507
508 pr_debug("%s:port:%d cmd:%d dai_data->status_mask = %ld",
509 __func__, dai->id, cmd, *dai_data->status_mask);
510
511 switch (cmd) {
512
513 case SNDRV_PCM_TRIGGER_START:
514 case SNDRV_PCM_TRIGGER_RESUME:
515 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
516 /* afe_open will be called from prepare */
517 return 0;
518
519 case SNDRV_PCM_TRIGGER_STOP:
520 case SNDRV_PCM_TRIGGER_SUSPEND:
521 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
522 if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
523
524 clk_disable(pcm_clk);
525 afe_port_stop_nowait(dai->id);
526 clear_bit(STATUS_PORT_STARTED,
527 dai_data->status_mask);
528
529 afe_port_stop_nowait(PCM_TX);
530 }
531 break;
532
533 default:
534 rc = -EINVAL;
535 }
536
537 return rc;
538
539}
540
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700541static int msm_dai_q6_trigger(struct snd_pcm_substream *substream, int cmd,
542 struct snd_soc_dai *dai)
543{
544 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
545 int rc = 0;
546
547 /* Start/stop port without waiting for Q6 AFE response. Need to have
548 * native q6 AFE driver propagates AFE response in order to handle
549 * port start/stop command error properly if error does arise.
550 */
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530551 pr_debug("%s:port:%d cmd:%d dai_data->status_mask = %ld",
552 __func__, dai->id, cmd, *dai_data->status_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700553 switch (cmd) {
554 case SNDRV_PCM_TRIGGER_START:
555 case SNDRV_PCM_TRIGGER_RESUME:
556 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
557 if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
Helen Zeng0705a5f2011-10-14 15:29:52 -0700558 switch (dai->id) {
559 case VOICE_PLAYBACK_TX:
Helen Zenge3d716a2011-10-14 16:32:16 -0700560 case VOICE_RECORD_TX:
561 case VOICE_RECORD_RX:
Helen Zeng0705a5f2011-10-14 15:29:52 -0700562 afe_pseudo_port_start_nowait(dai->id);
563 break;
564 default:
565 afe_port_start_nowait(dai->id,
566 &dai_data->port_config, dai_data->rate);
567 break;
568 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700569 set_bit(STATUS_PORT_STARTED,
570 dai_data->status_mask);
571 }
572 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700573 case SNDRV_PCM_TRIGGER_STOP:
574 case SNDRV_PCM_TRIGGER_SUSPEND:
575 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
576 if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
Helen Zeng0705a5f2011-10-14 15:29:52 -0700577 switch (dai->id) {
578 case VOICE_PLAYBACK_TX:
Helen Zenge3d716a2011-10-14 16:32:16 -0700579 case VOICE_RECORD_TX:
580 case VOICE_RECORD_RX:
Helen Zeng0705a5f2011-10-14 15:29:52 -0700581 afe_pseudo_port_stop_nowait(dai->id);
582 break;
583 default:
584 afe_port_stop_nowait(dai->id);
585 break;
586 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700587 clear_bit(STATUS_PORT_STARTED,
588 dai_data->status_mask);
589 }
590 break;
591
592 default:
593 rc = -EINVAL;
594 }
595
596 return rc;
597}
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700598static int msm_dai_q6_dai_auxpcm_probe(struct snd_soc_dai *dai)
599{
600 struct msm_dai_q6_dai_data *dai_data;
601 int rc = 0;
602
603 struct msm_dai_auxpcm_pdata *auxpcm_pdata =
604 (struct msm_dai_auxpcm_pdata *) dai->dev->platform_data;
605
606 dai_data = kzalloc(sizeof(struct msm_dai_q6_dai_data),
607 GFP_KERNEL);
608
609 if (!dai_data) {
610 dev_err(dai->dev, "DAI-%d: fail to allocate dai data\n",
611 dai->id);
612 rc = -ENOMEM;
613 } else
614 dev_set_drvdata(dai->dev, dai_data);
615
616 /*
617 * The clk name for AUX PCM operation is passed as platform
618 * data to the cpu driver, since cpu drive is unaware of any
619 * boarc specific configuration.
620 */
Kuirong Wanga9c3acc2012-02-09 17:00:45 -0800621 pcm_clk = clk_get(dai->dev, auxpcm_pdata->clk);
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700622 if (IS_ERR(pcm_clk)) {
623 pr_err("%s: could not get pcm_clk\n", __func__);
624 return PTR_ERR(pcm_clk);
625 kfree(dai_data);
626 }
627
628 return rc;
629}
630
631static int msm_dai_q6_dai_auxpcm_remove(struct snd_soc_dai *dai)
632{
633 struct msm_dai_q6_dai_data *dai_data;
634 int rc;
635
636 dai_data = dev_get_drvdata(dai->dev);
637
638 /* If AFE port is still up, close it */
639 if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
640 rc = afe_close(dai->id); /* can block */
641 if (IS_ERR_VALUE(rc))
642 dev_err(dai->dev, "fail to close AFE port\n");
643 clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
644
645 rc = afe_close(PCM_TX);
646 if (IS_ERR_VALUE(rc))
647 dev_err(dai->dev, "fail to close AUX PCM TX port\n");
648 }
649
650
651 kfree(dai_data);
652 snd_soc_unregister_dai(dai->dev);
653
654 return 0;
655}
Kuirong Wang274f21a2011-12-15 21:29:08 -0800656static int msm_dai_q6_dai_mi2s_probe(struct snd_soc_dai *dai)
657{
658 struct msm_dai_q6_dai_data *dai_data;
659 int rc = 0;
660
661 dai_data = kzalloc(sizeof(struct msm_dai_q6_dai_data),
662 GFP_KERNEL);
663
664 if (!dai_data) {
665 dev_err(dai->dev, "DAI-%d: fail to allocate dai data\n",
666 dai->id);
667 rc = -ENOMEM;
668 goto rtn;
669 } else
670 dev_set_drvdata(dai->dev, dai_data);
671
672 rc = msm_dai_q6_mi2s_platform_data_validation(dai);
673 if (rc != 0) {
674 pr_err("%s: The msm_dai_q6_mi2s_platform_data_validation failed\n",
675 __func__);
676 kfree(dai_data);
677 }
678rtn:
679 return rc;
680}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700681
682static int msm_dai_q6_dai_probe(struct snd_soc_dai *dai)
683{
684 struct msm_dai_q6_dai_data *dai_data;
685 int rc = 0;
686
687 dai_data = kzalloc(sizeof(struct msm_dai_q6_dai_data),
688 GFP_KERNEL);
689
690 if (!dai_data) {
691 dev_err(dai->dev, "DAI-%d: fail to allocate dai data\n",
692 dai->id);
693 rc = -ENOMEM;
694 } else
695 dev_set_drvdata(dai->dev, dai_data);
696
697 return rc;
698}
699
700static int msm_dai_q6_dai_remove(struct snd_soc_dai *dai)
701{
702 struct msm_dai_q6_dai_data *dai_data;
703 int rc;
704
705 dai_data = dev_get_drvdata(dai->dev);
706
707 /* If AFE port is still up, close it */
708 if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
Helen Zeng0705a5f2011-10-14 15:29:52 -0700709 switch (dai->id) {
710 case VOICE_PLAYBACK_TX:
Helen Zenge3d716a2011-10-14 16:32:16 -0700711 case VOICE_RECORD_TX:
712 case VOICE_RECORD_RX:
Helen Zeng0705a5f2011-10-14 15:29:52 -0700713 pr_debug("%s, stop pseudo port:%d\n",
714 __func__, dai->id);
715 rc = afe_stop_pseudo_port(dai->id);
716 break;
717 default:
718 rc = afe_close(dai->id); /* can block */
719 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700720 if (IS_ERR_VALUE(rc))
721 dev_err(dai->dev, "fail to close AFE port\n");
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530722 clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700723 }
724 kfree(dai_data);
725 snd_soc_unregister_dai(dai->dev);
726
727 return 0;
728}
729
Lei Zhou157c1842011-08-19 13:05:04 -0400730static int msm_dai_q6_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
731{
732 int rc = 0;
733
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800734 dev_dbg(dai->dev, "enter %s, id = %d fmt[%d]\n", __func__,
735 dai->id, fmt);
Lei Zhou157c1842011-08-19 13:05:04 -0400736 switch (dai->id) {
737 case PRIMARY_I2S_TX:
738 case PRIMARY_I2S_RX:
Kuirong Wang274f21a2011-12-15 21:29:08 -0800739 case MI2S_RX:
Kuirong Wang9bbf6132012-01-10 18:28:49 -0800740 case SECONDARY_I2S_RX:
Lei Zhou157c1842011-08-19 13:05:04 -0400741 rc = msm_dai_q6_cdc_set_fmt(dai, fmt);
742 break;
743 default:
744 dev_err(dai->dev, "invalid cpu_dai set_fmt\n");
745 rc = -EINVAL;
746 break;
747 }
748
749 return rc;
750}
751
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800752static int msm_dai_q6_set_channel_map(struct snd_soc_dai *dai,
753 unsigned int tx_num, unsigned int *tx_slot,
754 unsigned int rx_num, unsigned int *rx_slot)
755
756{
757 int rc = 0;
758 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
759 unsigned int i = 0;
760
761 dev_dbg(dai->dev, "enter %s, id = %d\n", __func__,
762 dai->id);
763 if (!tx_slot && !rx_slot)
764 return -EINVAL;
765 switch (dai->id) {
766 case SLIMBUS_0_RX:
767 /* channel number to be between 128 and 255. For RX port
768 * use channel numbers from 138 to 144, for TX port
769 * use channel numbers from 128 to 137
770 */
771 for (i = 0; i < rx_num; i++) {
772 dai_data->port_config.slim_sch.slave_ch_mapping[i] =
773 rx_slot[i];
774 pr_debug("%s: find number of channels[%d] ch[%d]\n",
775 __func__, i,
776 rx_slot[i]);
777 }
778 dai_data->port_config.slim_sch.num_channels = rx_num;
779 pr_debug("%s:SLIMBUS_0_RX cnt[%d] ch[%d %d]\n", __func__,
780 rx_num, dai_data->port_config.slim_sch.slave_ch_mapping[0],
781 dai_data->port_config.slim_sch.slave_ch_mapping[1]);
782
783 break;
784 case SLIMBUS_0_TX:
785 /* channel number to be between 128 and 255. For RX port
786 * use channel numbers from 138 to 144, for TX port
787 * use channel numbers from 128 to 137
788 */
789 for (i = 0; i < tx_num; i++) {
790 dai_data->port_config.slim_sch.slave_ch_mapping[i] =
791 tx_slot[i];
792 pr_debug("%s: find number of channels[%d] ch[%d]\n",
793 __func__, i, tx_slot[i]);
794 }
795 dai_data->port_config.slim_sch.num_channels = tx_num;
796 pr_debug("%s:SLIMBUS_0_TX cnt[%d] ch[%d %d]\n", __func__,
797 tx_num, dai_data->port_config.slim_sch.slave_ch_mapping[0],
798 dai_data->port_config.slim_sch.slave_ch_mapping[1]);
799 break;
800 default:
801 dev_err(dai->dev, "invalid cpu_dai set_fmt\n");
802 rc = -EINVAL;
803 break;
804 }
805 return rc;
806}
807
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700808static struct snd_soc_dai_ops msm_dai_q6_ops = {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700809 .prepare = msm_dai_q6_prepare,
810 .trigger = msm_dai_q6_trigger,
811 .hw_params = msm_dai_q6_hw_params,
812 .shutdown = msm_dai_q6_shutdown,
Lei Zhou157c1842011-08-19 13:05:04 -0400813 .set_fmt = msm_dai_q6_set_fmt,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800814 .set_channel_map = msm_dai_q6_set_channel_map,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700815};
816
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700817static struct snd_soc_dai_ops msm_dai_q6_auxpcm_ops = {
818 .prepare = msm_dai_q6_auxpcm_prepare,
819 .trigger = msm_dai_q6_auxpcm_trigger,
820 .hw_params = msm_dai_q6_auxpcm_hw_params,
821 .shutdown = msm_dai_q6_auxpcm_shutdown,
822};
823
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700824static struct snd_soc_dai_driver msm_dai_q6_i2s_rx_dai = {
825 .playback = {
826 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
827 SNDRV_PCM_RATE_16000,
828 .formats = SNDRV_PCM_FMTBIT_S16_LE,
829 .channels_min = 1,
Kiran Kandi9db678b2012-01-15 14:25:59 -0800830 .channels_max = 4,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700831 .rate_min = 8000,
832 .rate_max = 48000,
833 },
834 .ops = &msm_dai_q6_ops,
835 .probe = msm_dai_q6_dai_probe,
836 .remove = msm_dai_q6_dai_remove,
837};
838
839static struct snd_soc_dai_driver msm_dai_q6_i2s_tx_dai = {
840 .capture = {
841 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
842 SNDRV_PCM_RATE_16000,
843 .formats = SNDRV_PCM_FMTBIT_S16_LE,
844 .channels_min = 1,
845 .channels_max = 2,
846 .rate_min = 8000,
847 .rate_max = 48000,
848 },
849 .ops = &msm_dai_q6_ops,
850 .probe = msm_dai_q6_dai_probe,
851 .remove = msm_dai_q6_dai_remove,
852};
853
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530854static struct snd_soc_dai_driver msm_dai_q6_afe_rx_dai = {
855 .playback = {
856 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
857 SNDRV_PCM_RATE_16000,
858 .formats = SNDRV_PCM_FMTBIT_S16_LE,
859 .channels_min = 1,
860 .channels_max = 2,
861 .rate_min = 8000,
862 .rate_max = 48000,
863 },
864 .ops = &msm_dai_q6_ops,
865 .probe = msm_dai_q6_dai_probe,
866 .remove = msm_dai_q6_dai_remove,
867};
868
869static struct snd_soc_dai_driver msm_dai_q6_afe_tx_dai = {
870 .capture = {
871 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
872 SNDRV_PCM_RATE_16000,
873 .formats = SNDRV_PCM_FMTBIT_S16_LE,
874 .channels_min = 1,
875 .channels_max = 2,
876 .rate_min = 8000,
877 .rate_max = 48000,
878 },
879 .ops = &msm_dai_q6_ops,
880 .probe = msm_dai_q6_dai_probe,
881 .remove = msm_dai_q6_dai_remove,
882};
883
Helen Zeng0705a5f2011-10-14 15:29:52 -0700884static struct snd_soc_dai_driver msm_dai_q6_voice_playback_tx_dai = {
885 .playback = {
886 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
887 SNDRV_PCM_RATE_16000,
888 .formats = SNDRV_PCM_FMTBIT_S16_LE,
889 .channels_min = 1,
890 .channels_max = 2,
891 .rate_max = 48000,
892 .rate_min = 8000,
893 },
894 .ops = &msm_dai_q6_ops,
895 .probe = msm_dai_q6_dai_probe,
896 .remove = msm_dai_q6_dai_remove,
897};
898
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700899static struct snd_soc_dai_driver msm_dai_q6_slimbus_rx_dai = {
900 .playback = {
901 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
902 SNDRV_PCM_RATE_16000,
903 .formats = SNDRV_PCM_FMTBIT_S16_LE,
904 .channels_min = 1,
905 .channels_max = 2,
906 .rate_min = 8000,
907 .rate_max = 48000,
908 },
909 .ops = &msm_dai_q6_ops,
910 .probe = msm_dai_q6_dai_probe,
911 .remove = msm_dai_q6_dai_remove,
912};
913
914static struct snd_soc_dai_driver msm_dai_q6_slimbus_tx_dai = {
915 .capture = {
916 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
917 SNDRV_PCM_RATE_16000,
918 .formats = SNDRV_PCM_FMTBIT_S16_LE,
919 .channels_min = 1,
920 .channels_max = 2,
921 .rate_min = 8000,
922 .rate_max = 48000,
923 },
924 .ops = &msm_dai_q6_ops,
925 .probe = msm_dai_q6_dai_probe,
926 .remove = msm_dai_q6_dai_remove,
927};
928
Helen Zenge3d716a2011-10-14 16:32:16 -0700929static struct snd_soc_dai_driver msm_dai_q6_incall_record_dai = {
930 .capture = {
931 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
932 SNDRV_PCM_RATE_16000,
933 .formats = SNDRV_PCM_FMTBIT_S16_LE,
934 .channels_min = 1,
935 .channels_max = 2,
936 .rate_min = 8000,
937 .rate_max = 48000,
938 },
939 .ops = &msm_dai_q6_ops,
940 .probe = msm_dai_q6_dai_probe,
941 .remove = msm_dai_q6_dai_remove,
942};
943
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700944static struct snd_soc_dai_driver msm_dai_q6_bt_sco_rx_dai = {
945 .playback = {
946 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
947 .formats = SNDRV_PCM_FMTBIT_S16_LE,
948 .channels_min = 1,
949 .channels_max = 1,
950 .rate_max = 16000,
951 .rate_min = 8000,
952 },
953 .ops = &msm_dai_q6_ops,
954 .probe = msm_dai_q6_dai_probe,
955 .remove = msm_dai_q6_dai_remove,
956};
957
958static struct snd_soc_dai_driver msm_dai_q6_bt_sco_tx_dai = {
959 .playback = {
960 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
961 .formats = SNDRV_PCM_FMTBIT_S16_LE,
962 .channels_min = 1,
963 .channels_max = 1,
964 .rate_max = 16000,
965 .rate_min = 8000,
966 },
967 .ops = &msm_dai_q6_ops,
968 .probe = msm_dai_q6_dai_probe,
969 .remove = msm_dai_q6_dai_remove,
970};
971
972static struct snd_soc_dai_driver msm_dai_q6_fm_rx_dai = {
973 .playback = {
974 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
975 SNDRV_PCM_RATE_16000,
976 .formats = SNDRV_PCM_FMTBIT_S16_LE,
977 .channels_min = 2,
978 .channels_max = 2,
979 .rate_max = 48000,
980 .rate_min = 8000,
981 },
982 .ops = &msm_dai_q6_ops,
983 .probe = msm_dai_q6_dai_probe,
984 .remove = msm_dai_q6_dai_remove,
985};
986
987static struct snd_soc_dai_driver msm_dai_q6_fm_tx_dai = {
988 .playback = {
989 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
990 SNDRV_PCM_RATE_16000,
991 .formats = SNDRV_PCM_FMTBIT_S16_LE,
992 .channels_min = 2,
993 .channels_max = 2,
994 .rate_max = 48000,
995 .rate_min = 8000,
996 },
997 .ops = &msm_dai_q6_ops,
998 .probe = msm_dai_q6_dai_probe,
999 .remove = msm_dai_q6_dai_remove,
1000};
1001
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001002static struct snd_soc_dai_driver msm_dai_q6_aux_pcm_rx_dai = {
1003 .playback = {
1004 .rates = SNDRV_PCM_RATE_8000,
1005 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1006 .channels_min = 1,
1007 .channels_max = 1,
1008 .rate_max = 8000,
1009 .rate_min = 8000,
1010 },
1011 .ops = &msm_dai_q6_auxpcm_ops,
1012 .probe = msm_dai_q6_dai_auxpcm_probe,
1013 .remove = msm_dai_q6_dai_auxpcm_remove,
1014};
1015
1016static struct snd_soc_dai_driver msm_dai_q6_aux_pcm_tx_dai = {
1017 .capture = {
1018 .rates = SNDRV_PCM_RATE_8000,
1019 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1020 .channels_min = 1,
1021 .channels_max = 1,
1022 .rate_max = 8000,
1023 .rate_min = 8000,
1024 },
1025};
1026
Kuirong Wang274f21a2011-12-15 21:29:08 -08001027static struct snd_soc_dai_driver msm_dai_q6_mi2s_rx_dai = {
1028 .playback = {
1029 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1030 SNDRV_PCM_RATE_16000,
1031 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1032 .channels_min = 1,
1033 .rate_min = 8000,
1034 .rate_max = 48000,
1035 },
1036 .ops = &msm_dai_q6_ops,
1037 .probe = msm_dai_q6_dai_mi2s_probe,
1038 .remove = msm_dai_q6_dai_probe,
1039};
1040
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001041/* To do: change to register DAIs as batch */
1042static __devinit int msm_dai_q6_dev_probe(struct platform_device *pdev)
1043{
1044 int rc = 0;
1045
1046 dev_dbg(&pdev->dev, "dev name %s\n", dev_name(&pdev->dev));
1047
1048 switch (pdev->id) {
1049 case PRIMARY_I2S_RX:
Kuirong Wang9bbf6132012-01-10 18:28:49 -08001050 case SECONDARY_I2S_RX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001051 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_i2s_rx_dai);
1052 break;
1053 case PRIMARY_I2S_TX:
1054 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_i2s_tx_dai);
1055 break;
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001056 case PCM_RX:
1057 rc = snd_soc_register_dai(&pdev->dev,
1058 &msm_dai_q6_aux_pcm_rx_dai);
1059 break;
1060 case PCM_TX:
1061 rc = snd_soc_register_dai(&pdev->dev,
1062 &msm_dai_q6_aux_pcm_tx_dai);
1063 break;
Kuirong Wang274f21a2011-12-15 21:29:08 -08001064 case MI2S_RX:
1065 rc = snd_soc_register_dai(&pdev->dev,
1066 &msm_dai_q6_mi2s_rx_dai);
1067 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001068 case SLIMBUS_0_RX:
1069 rc = snd_soc_register_dai(&pdev->dev,
1070 &msm_dai_q6_slimbus_rx_dai);
1071 break;
1072 case SLIMBUS_0_TX:
1073 rc = snd_soc_register_dai(&pdev->dev,
1074 &msm_dai_q6_slimbus_tx_dai);
1075 case INT_BT_SCO_RX:
1076 rc = snd_soc_register_dai(&pdev->dev,
1077 &msm_dai_q6_bt_sco_rx_dai);
1078 break;
1079 case INT_BT_SCO_TX:
1080 rc = snd_soc_register_dai(&pdev->dev,
1081 &msm_dai_q6_bt_sco_tx_dai);
1082 break;
1083 case INT_FM_RX:
1084 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_fm_rx_dai);
1085 break;
1086 case INT_FM_TX:
1087 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_fm_tx_dai);
1088 break;
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301089 case RT_PROXY_DAI_001_RX:
1090 case RT_PROXY_DAI_002_RX:
1091 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_afe_rx_dai);
1092 break;
1093 case RT_PROXY_DAI_001_TX:
1094 case RT_PROXY_DAI_002_TX:
1095 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_afe_tx_dai);
1096 break;
Helen Zeng0705a5f2011-10-14 15:29:52 -07001097 case VOICE_PLAYBACK_TX:
1098 rc = snd_soc_register_dai(&pdev->dev,
1099 &msm_dai_q6_voice_playback_tx_dai);
1100 break;
Helen Zenge3d716a2011-10-14 16:32:16 -07001101 case VOICE_RECORD_RX:
1102 case VOICE_RECORD_TX:
1103 rc = snd_soc_register_dai(&pdev->dev,
1104 &msm_dai_q6_incall_record_dai);
1105 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001106 default:
1107 rc = -ENODEV;
1108 break;
1109 }
1110 return rc;
1111}
1112
1113static __devexit int msm_dai_q6_dev_remove(struct platform_device *pdev)
1114{
1115 snd_soc_unregister_dai(&pdev->dev);
1116 return 0;
1117}
1118
1119static struct platform_driver msm_dai_q6_driver = {
1120 .probe = msm_dai_q6_dev_probe,
1121 .remove = msm_dai_q6_dev_remove,
1122 .driver = {
1123 .name = "msm-dai-q6",
1124 .owner = THIS_MODULE,
1125 },
1126};
1127
1128static int __init msm_dai_q6_init(void)
1129{
1130 return platform_driver_register(&msm_dai_q6_driver);
1131}
1132module_init(msm_dai_q6_init);
1133
1134static void __exit msm_dai_q6_exit(void)
1135{
1136 platform_driver_unregister(&msm_dai_q6_driver);
1137}
1138module_exit(msm_dai_q6_exit);
1139
1140/* Module information */
1141MODULE_DESCRIPTION("MSM DSP DAI driver");
1142MODULE_LICENSE("GPL v2");