blob: 96260abc8039afd36ef45bf78c6cc2c32223cc83 [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>
26#include <sound/q6adm.h>
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -070027#include <sound/msm-dai-q6.h>
28#include <mach/clk.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070029
30enum {
31 STATUS_PORT_STARTED, /* track if AFE port has started */
32 STATUS_MAX
33};
34
35struct msm_dai_q6_dai_data {
36 DECLARE_BITMAP(status_mask, STATUS_MAX);
37 u32 rate;
38 u32 channels;
39 union afe_port_config port_config;
40};
41
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -070042static struct clk *pcm_clk;
43
Kuirong Wang274f21a2011-12-15 21:29:08 -080044static u8 num_of_bits_set(u8 sd_line_mask)
45{
46 u8 num_bits_set = 0;
47
48 while (sd_line_mask) {
49 num_bits_set++;
50 sd_line_mask = sd_line_mask & (sd_line_mask - 1);
51 }
52 return num_bits_set;
53}
54
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070055static int msm_dai_q6_cdc_hw_params(struct snd_pcm_hw_params *params,
56 struct snd_soc_dai *dai, int stream)
57{
58 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
59
60 dai_data->channels = params_channels(params);
61 switch (dai_data->channels) {
62 case 2:
63 dai_data->port_config.mi2s.channel = MSM_AFE_STEREO;
64 break;
65 case 1:
66 dai_data->port_config.mi2s.channel = MSM_AFE_MONO;
67 break;
68 default:
69 return -EINVAL;
70 break;
71 }
72 dai_data->rate = params_rate(params);
73
74 dev_dbg(dai->dev, " channel %d sample rate %d entered\n",
75 dai_data->channels, dai_data->rate);
76
77 /* Q6 only supports 16 as now */
78 dai_data->port_config.mi2s.bitwidth = 16;
79 dai_data->port_config.mi2s.line = 1;
Kuirong Wang274f21a2011-12-15 21:29:08 -080080 return 0;
81}
82
83static int msm_dai_q6_mi2s_hw_params(struct snd_pcm_hw_params *params,
84 struct snd_soc_dai *dai, int stream)
85{
86 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
87 struct msm_mi2s_data *mi2s_pdata =
88 (struct msm_mi2s_data *) dai->dev->platform_data;
89
90 dai_data->channels = params_channels(params);
91 if (num_of_bits_set(mi2s_pdata->sd_lines) == 1) {
92 switch (dai_data->channels) {
93 case 2:
94 dai_data->port_config.mi2s.channel = MSM_AFE_STEREO;
95 break;
96 case 1:
97 dai_data->port_config.mi2s.channel = MSM_AFE_MONO;
98 break;
99 default:
100 pr_warn("greater than stereo has not been validated");
101 break;
102 }
103 }
104 /* Q6 only supports 16 as now */
105 dai_data->port_config.mi2s.bitwidth = 16;
Lei Zhou157c1842011-08-19 13:05:04 -0400106
107 return 0;
108}
109
Kuirong Wang274f21a2011-12-15 21:29:08 -0800110static int msm_dai_q6_mi2s_platform_data_validation(
111 struct snd_soc_dai *dai)
112{
113 u8 num_of_sd_lines;
114 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
115 struct msm_mi2s_data *mi2s_pdata =
116 (struct msm_mi2s_data *)dai->dev->platform_data;
117 struct snd_soc_dai_driver *dai_driver =
118 (struct snd_soc_dai_driver *)dai->driver;
119
120 num_of_sd_lines = num_of_bits_set(mi2s_pdata->sd_lines);
121
122 switch (num_of_sd_lines) {
123 case 1:
124 switch (mi2s_pdata->sd_lines) {
125 case MSM_MI2S_SD0:
126 dai_data->port_config.mi2s.line = AFE_I2S_SD0;
127 break;
128 case MSM_MI2S_SD1:
129 dai_data->port_config.mi2s.line = AFE_I2S_SD1;
130 break;
131 case MSM_MI2S_SD2:
132 dai_data->port_config.mi2s.line = AFE_I2S_SD2;
133 break;
134 case MSM_MI2S_SD3:
135 dai_data->port_config.mi2s.line = AFE_I2S_SD3;
136 break;
137 default:
138 pr_err("%s: invalid SD line\n",
139 __func__);
140 goto error_invalid_data;
141 }
142 break;
143 case 2:
144 switch (mi2s_pdata->sd_lines) {
145 case MSM_MI2S_SD0 | MSM_MI2S_SD1:
146 dai_data->port_config.mi2s.line = AFE_I2S_QUAD01;
147 break;
148 case MSM_MI2S_SD2 | MSM_MI2S_SD3:
149 dai_data->port_config.mi2s.line = AFE_I2S_QUAD23;
150 break;
151 default:
152 pr_err("%s: invalid SD line\n",
153 __func__);
154 goto error_invalid_data;
155 }
156 break;
157 case 3:
158 switch (mi2s_pdata->sd_lines) {
159 case MSM_MI2S_SD0 | MSM_MI2S_SD1 | MSM_MI2S_SD2:
160 dai_data->port_config.mi2s.line = AFE_I2S_6CHS;
161 break;
162 default:
163 pr_err("%s: invalid SD lines\n",
164 __func__);
165 goto error_invalid_data;
166 }
167 break;
168 case 4:
169 switch (mi2s_pdata->sd_lines) {
170 case MSM_MI2S_SD0 | MSM_MI2S_SD1 | MSM_MI2S_SD2 | MSM_MI2S_SD3:
171 dai_data->port_config.mi2s.line = AFE_I2S_8CHS;
172 break;
173 default:
174 pr_err("%s: invalid SD lines\n",
175 __func__);
176 goto error_invalid_data;
177 }
178 break;
179 default:
180 pr_err("%s: invalid SD lines\n", __func__);
181 goto error_invalid_data;
182 }
183 if (mi2s_pdata->capability == MSM_MI2S_CAP_RX)
184 dai_driver->playback.channels_max = num_of_sd_lines << 1;
185
186 return 0;
187
188error_invalid_data:
189 return -EINVAL;
190}
191
Lei Zhou157c1842011-08-19 13:05:04 -0400192static int msm_dai_q6_cdc_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
193{
194 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
195
196 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
197 case SND_SOC_DAIFMT_CBS_CFS:
198 dai_data->port_config.mi2s.ws = 1; /* CPU is master */
199 break;
200 case SND_SOC_DAIFMT_CBM_CFM:
201 dai_data->port_config.mi2s.ws = 0; /* CPU is slave */
202 break;
203 default:
204 return -EINVAL;
205 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700206
207 return 0;
208}
209
210static int msm_dai_q6_hdmi_hw_params(struct snd_pcm_hw_params *params,
211 struct snd_soc_dai *dai)
212{
213 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
214
215 dev_dbg(dai->dev, "%s start HDMI port\n", __func__);
216
217 dai_data->channels = params_channels(params);
218 switch (dai_data->channels) {
219 case 2:
220 dai_data->port_config.hdmi.channel_mode = 0; /* Put in macro */
221 break;
222 default:
223 return -EINVAL;
224 break;
225 }
226
227 /* Q6 only supports 16 as now */
228 dai_data->port_config.hdmi.bitwidth = 16;
229 dai_data->port_config.hdmi.data_type = 0;
230 dai_data->rate = params_rate(params);
231
232 return 0;
233}
234
235static int msm_dai_q6_slim_bus_hw_params(struct snd_pcm_hw_params *params,
236 struct snd_soc_dai *dai, int stream)
237{
238 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
239 u8 pgd_la, inf_la;
Kiran Kandi9db678b2012-01-15 14:25:59 -0800240 u16 *slave_port_mapping;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700241
242 memset(dai_data->port_config.slimbus.slave_port_mapping, 0,
243 sizeof(dai_data->port_config.slimbus.slave_port_mapping));
244
245 dai_data->channels = params_channels(params);
Kiran Kandi9db678b2012-01-15 14:25:59 -0800246
247 slave_port_mapping = dai_data->port_config.slimbus.slave_port_mapping;
248
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700249 switch (dai_data->channels) {
Kiran Kandi9db678b2012-01-15 14:25:59 -0800250 case 4:
251 if (dai->id == SLIMBUS_0_TX) {
252 slave_port_mapping[0] = 7;
253 slave_port_mapping[1] = 8;
254 slave_port_mapping[2] = 9;
255 slave_port_mapping[3] = 10;
256 } else {
257 return -EINVAL;
258 }
259 break;
260 case 3:
261 if (dai->id == SLIMBUS_0_TX) {
262 slave_port_mapping[0] = 7;
263 slave_port_mapping[1] = 8;
264 slave_port_mapping[2] = 9;
265 } else {
266 return -EINVAL;
267 }
268 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700269 case 2:
270 if (dai->id == SLIMBUS_0_RX) {
Kiran Kandi9db678b2012-01-15 14:25:59 -0800271 slave_port_mapping[0] = 1;
272 slave_port_mapping[1] = 2;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700273 } else {
Kiran Kandi9db678b2012-01-15 14:25:59 -0800274 slave_port_mapping[0] = 7;
275 slave_port_mapping[1] = 8;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700276 }
277 break;
278 case 1:
279 if (dai->id == SLIMBUS_0_RX)
Kiran Kandi9db678b2012-01-15 14:25:59 -0800280 slave_port_mapping[0] = 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700281 else
Kiran Kandi9db678b2012-01-15 14:25:59 -0800282 slave_port_mapping[0] = 7;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700283 break;
284 default:
285 return -EINVAL;
286 break;
287 }
288 dai_data->rate = params_rate(params);
289 tabla_get_logical_addresses(&pgd_la, &inf_la);
290
291 dai_data->port_config.slimbus.slimbus_dev_id = AFE_SLIMBUS_DEVICE_1;
292 dai_data->port_config.slimbus.slave_dev_pgd_la = pgd_la;
293 dai_data->port_config.slimbus.slave_dev_intfdev_la = inf_la;
294 /* Q6 only supports 16 as now */
295 dai_data->port_config.slimbus.bit_width = 16;
296 dai_data->port_config.slimbus.data_format = 0;
297 dai_data->port_config.slimbus.num_channels = dai_data->channels;
298 dai_data->port_config.slimbus.reserved = 0;
299
300 dev_dbg(dai->dev, "slimbus_dev_id %hu slave_dev_pgd_la 0x%hx\n"
301 "slave_dev_intfdev_la 0x%hx bit_width %hu data_format %hu\n"
302 "num_channel %hu slave_port_mapping[0] %hu\n"
303 "slave_port_mapping[1] %hu slave_port_mapping[2] %hu\n"
304 "sample_rate %d\n",
305 dai_data->port_config.slimbus.slimbus_dev_id,
306 dai_data->port_config.slimbus.slave_dev_pgd_la,
307 dai_data->port_config.slimbus.slave_dev_intfdev_la,
308 dai_data->port_config.slimbus.bit_width,
309 dai_data->port_config.slimbus.data_format,
310 dai_data->port_config.slimbus.num_channels,
311 dai_data->port_config.slimbus.slave_port_mapping[0],
312 dai_data->port_config.slimbus.slave_port_mapping[1],
313 dai_data->port_config.slimbus.slave_port_mapping[2],
314 dai_data->rate);
315
316 return 0;
317}
318
319static int msm_dai_q6_bt_fm_hw_params(struct snd_pcm_hw_params *params,
320 struct snd_soc_dai *dai, int stream)
321{
322 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
323
324 dai_data->channels = params_channels(params);
325 dai_data->rate = params_rate(params);
326
327 dev_dbg(dai->dev, "channels %d sample rate %d entered\n",
328 dai_data->channels, dai_data->rate);
329
330 memset(&dai_data->port_config, 0, sizeof(dai_data->port_config));
331
332 return 0;
333}
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700334static int msm_dai_q6_auxpcm_hw_params(
335 struct snd_pcm_substream *substream,
336 struct snd_pcm_hw_params *params,
337 struct snd_soc_dai *dai)
338{
339 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
340 struct msm_dai_auxpcm_pdata *auxpcm_pdata =
341 (struct msm_dai_auxpcm_pdata *) dai->dev->platform_data;
342
343 if (params_channels(params) != 1) {
344 dev_err(dai->dev, "AUX PCM supports only mono stream\n");
345 return -EINVAL;
346 }
347 dai_data->channels = params_channels(params);
348
349 if (params_rate(params) != 8000) {
350 dev_err(dai->dev, "AUX PCM supports only 8KHz sampling rate\n");
351 return -EINVAL;
352 }
353 dai_data->rate = params_rate(params);
354 dai_data->port_config.pcm.mode = auxpcm_pdata->mode;
355 dai_data->port_config.pcm.sync = auxpcm_pdata->sync;
356 dai_data->port_config.pcm.frame = auxpcm_pdata->frame;
357 dai_data->port_config.pcm.quant = auxpcm_pdata->quant;
358 dai_data->port_config.pcm.slot = auxpcm_pdata->slot;
359 dai_data->port_config.pcm.data = auxpcm_pdata->data;
360
361 return 0;
362}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700363
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530364static int get_frame_size(u16 rate, u16 ch)
365{
366 if (rate == 8000) {
367 if (ch == 1)
368 return 128 * 2;
369 else
370 return 128 * 2 * 2;
371 } else if (rate == 16000) {
372 if (ch == 1)
373 return 128 * 2 * 2;
374 else
375 return 128 * 2 * 4;
376 } else if (rate == 48000) {
377 if (ch == 1)
378 return 128 * 2 * 6;
379 else
380 return 128 * 2 * 12;
381 } else
382 return 128 * 2 * 12;
383}
384
385static int msm_dai_q6_afe_rtproxy_hw_params(struct snd_pcm_hw_params *params,
386 struct snd_soc_dai *dai)
387{
388 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
389
390 dai_data->rate = params_rate(params);
391 dai_data->port_config.rtproxy.num_ch =
392 params_channels(params);
393
394 pr_debug("channel %d entered,dai_id: %d,rate: %d\n",
395 dai_data->port_config.rtproxy.num_ch, dai->id, dai_data->rate);
396
397 dai_data->port_config.rtproxy.bitwidth = 16; /* Q6 only supports 16 */
398 dai_data->port_config.rtproxy.interleaved = 1;
399 dai_data->port_config.rtproxy.frame_sz = get_frame_size(dai_data->rate,
400 dai_data->port_config.rtproxy.num_ch);
401 dai_data->port_config.rtproxy.jitter =
402 dai_data->port_config.rtproxy.frame_sz/2;
403 dai_data->port_config.rtproxy.lw_mark = 0;
404 dai_data->port_config.rtproxy.hw_mark = 0;
405 dai_data->port_config.rtproxy.rsvd = 0;
406
407 return 0;
408}
409
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700410/* Current implementation assumes hw_param is called once
411 * This may not be the case but what to do when ADM and AFE
412 * port are already opened and parameter changes
413 */
414static int msm_dai_q6_hw_params(struct snd_pcm_substream *substream,
415 struct snd_pcm_hw_params *params,
416 struct snd_soc_dai *dai)
417{
418 int rc = 0;
419
420 switch (dai->id) {
421 case PRIMARY_I2S_TX:
422 case PRIMARY_I2S_RX:
423 rc = msm_dai_q6_cdc_hw_params(params, dai, substream->stream);
424 break;
Kuirong Wang274f21a2011-12-15 21:29:08 -0800425 case MI2S_RX:
426 rc = msm_dai_q6_mi2s_hw_params(params, dai, substream->stream);
427 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700428 case HDMI_RX:
429 rc = msm_dai_q6_hdmi_hw_params(params, dai);
430 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700431 case SLIMBUS_0_RX:
432 case SLIMBUS_0_TX:
433 rc = msm_dai_q6_slim_bus_hw_params(params, dai,
434 substream->stream);
435 break;
436 case INT_BT_SCO_RX:
437 case INT_BT_SCO_TX:
438 case INT_FM_RX:
439 case INT_FM_TX:
440 rc = msm_dai_q6_bt_fm_hw_params(params, dai, substream->stream);
441 break;
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530442 case RT_PROXY_DAI_001_TX:
443 case RT_PROXY_DAI_001_RX:
444 case RT_PROXY_DAI_002_TX:
445 case RT_PROXY_DAI_002_RX:
446 rc = msm_dai_q6_afe_rtproxy_hw_params(params, dai);
447 break;
Helen Zeng0705a5f2011-10-14 15:29:52 -0700448 case VOICE_PLAYBACK_TX:
Helen Zenge3d716a2011-10-14 16:32:16 -0700449 case VOICE_RECORD_RX:
450 case VOICE_RECORD_TX:
Helen Zeng0705a5f2011-10-14 15:29:52 -0700451 rc = 0;
452 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700453 default:
454 dev_err(dai->dev, "invalid AFE port ID\n");
455 rc = -EINVAL;
456 break;
457 }
458
459 return rc;
460}
461
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700462static void msm_dai_q6_auxpcm_shutdown(struct snd_pcm_substream *substream,
463 struct snd_soc_dai *dai)
464{
465 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
466 int rc = 0;
467
468 rc = adm_close(dai->id);
469 if (IS_ERR_VALUE(rc))
470 dev_err(dai->dev, "fail to close ADM COPP\n");
471
472 pr_debug("%s: dai->id = %d", __func__, dai->id);
473
474 if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
475 clk_disable(pcm_clk);
476 rc = afe_close(dai->id); /* can block */
477 if (IS_ERR_VALUE(rc))
478 dev_err(dai->dev, "fail to close AFE port\n");
479 pr_debug("%s: dai_data->status_mask = %ld\n", __func__,
480 *dai_data->status_mask);
481 clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
482
483 rc = afe_close(PCM_TX);
484 if (IS_ERR_VALUE(rc))
485 dev_err(dai->dev, "fail to close AUX PCM TX port\n");
486 }
487}
488
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700489static void msm_dai_q6_shutdown(struct snd_pcm_substream *substream,
490 struct snd_soc_dai *dai)
491{
492 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530493 int rc = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700494
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700495 if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
Helen Zeng0705a5f2011-10-14 15:29:52 -0700496 switch (dai->id) {
497 case VOICE_PLAYBACK_TX:
Helen Zenge3d716a2011-10-14 16:32:16 -0700498 case VOICE_RECORD_TX:
499 case VOICE_RECORD_RX:
Helen Zeng0705a5f2011-10-14 15:29:52 -0700500 pr_debug("%s, stop pseudo port:%d\n",
501 __func__, dai->id);
502 rc = afe_stop_pseudo_port(dai->id);
503 break;
504 default:
505 rc = afe_close(dai->id); /* can block */
506 break;
507 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700508 if (IS_ERR_VALUE(rc))
509 dev_err(dai->dev, "fail to close AFE port\n");
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530510 pr_debug("%s: dai_data->status_mask = %ld\n", __func__,
511 *dai_data->status_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700512 clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
513 }
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700514}
515
516static int msm_dai_q6_auxpcm_prepare(struct snd_pcm_substream *substream,
517 struct snd_soc_dai *dai)
518{
519 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
520 int rc = 0;
521
522 struct msm_dai_auxpcm_pdata *auxpcm_pdata =
523 (struct msm_dai_auxpcm_pdata *) dai->dev->platform_data;
524
525 if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
Patrick Laicf999112011-08-23 11:27:20 -0700526 rc = afe_q6_interface_prepare();
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700527 if (IS_ERR_VALUE(rc))
Patrick Laicf999112011-08-23 11:27:20 -0700528 dev_err(dai->dev, "fail to open AFE APR\n");
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700529
Patrick Laicf999112011-08-23 11:27:20 -0700530 rc = afe_q6_interface_prepare();
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700531 if (IS_ERR_VALUE(rc))
Patrick Laicf999112011-08-23 11:27:20 -0700532 dev_err(dai->dev, "fail to open AFE APR\n");
533
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700534 pr_debug("%s:dai->id:%d dai_data->status_mask = %ld\n",
535 __func__, dai->id, *dai_data->status_mask);
536
537 /*
538 * For AUX PCM Interface the below sequence of clk
539 * settings and afe_open is a strict requirement.
540 *
541 * Also using afe_open instead of afe_port_start_nowait
542 * to make sure the port is open before deasserting the
543 * clock line. This is required because pcm register is
544 * not written before clock deassert. Hence the hw does
545 * not get updated with new setting if the below clock
546 * assert/deasset and afe_open sequence is not followed.
547 */
548
549 clk_reset(pcm_clk, CLK_RESET_ASSERT);
550
551 afe_open(dai->id, &dai_data->port_config,
552 dai_data->rate);
553 set_bit(STATUS_PORT_STARTED,
554 dai_data->status_mask);
555
556 afe_open(PCM_TX, &dai_data->port_config, dai_data->rate);
557
558 rc = clk_set_rate(pcm_clk, auxpcm_pdata->pcm_clk_rate);
559 if (rc < 0) {
560 pr_err("%s: clk_set_rate failed\n", __func__);
561 return rc;
562 }
563
564 clk_enable(pcm_clk);
565 clk_reset(pcm_clk, CLK_RESET_DEASSERT);
566
567 }
568 return rc;
569}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700570
571static int msm_dai_q6_prepare(struct snd_pcm_substream *substream,
572 struct snd_soc_dai *dai)
573{
574 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
575 int rc = 0;
576
Patrick Lai831561e2011-07-26 22:51:27 -0700577 if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
Patrick Laicf999112011-08-23 11:27:20 -0700578 /* PORT START should be set if prepare called in active state */
579 rc = afe_q6_interface_prepare();
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700580 if (IS_ERR_VALUE(rc))
Patrick Laicf999112011-08-23 11:27:20 -0700581 dev_err(dai->dev, "fail to open AFE APR\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700582 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700583 return rc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700584}
585
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700586static int msm_dai_q6_auxpcm_trigger(struct snd_pcm_substream *substream,
587 int cmd, struct snd_soc_dai *dai)
588{
589 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
590 int rc = 0;
591
592 pr_debug("%s:port:%d cmd:%d dai_data->status_mask = %ld",
593 __func__, dai->id, cmd, *dai_data->status_mask);
594
595 switch (cmd) {
596
597 case SNDRV_PCM_TRIGGER_START:
598 case SNDRV_PCM_TRIGGER_RESUME:
599 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
600 /* afe_open will be called from prepare */
601 return 0;
602
603 case SNDRV_PCM_TRIGGER_STOP:
604 case SNDRV_PCM_TRIGGER_SUSPEND:
605 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
606 if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
607
608 clk_disable(pcm_clk);
609 afe_port_stop_nowait(dai->id);
610 clear_bit(STATUS_PORT_STARTED,
611 dai_data->status_mask);
612
613 afe_port_stop_nowait(PCM_TX);
614 }
615 break;
616
617 default:
618 rc = -EINVAL;
619 }
620
621 return rc;
622
623}
624
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700625static int msm_dai_q6_trigger(struct snd_pcm_substream *substream, int cmd,
626 struct snd_soc_dai *dai)
627{
628 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
629 int rc = 0;
630
631 /* Start/stop port without waiting for Q6 AFE response. Need to have
632 * native q6 AFE driver propagates AFE response in order to handle
633 * port start/stop command error properly if error does arise.
634 */
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530635 pr_debug("%s:port:%d cmd:%d dai_data->status_mask = %ld",
636 __func__, dai->id, cmd, *dai_data->status_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700637 switch (cmd) {
638 case SNDRV_PCM_TRIGGER_START:
639 case SNDRV_PCM_TRIGGER_RESUME:
640 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
641 if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
Helen Zeng0705a5f2011-10-14 15:29:52 -0700642 switch (dai->id) {
643 case VOICE_PLAYBACK_TX:
Helen Zenge3d716a2011-10-14 16:32:16 -0700644 case VOICE_RECORD_TX:
645 case VOICE_RECORD_RX:
Helen Zeng0705a5f2011-10-14 15:29:52 -0700646 afe_pseudo_port_start_nowait(dai->id);
647 break;
648 default:
649 afe_port_start_nowait(dai->id,
650 &dai_data->port_config, dai_data->rate);
651 break;
652 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700653 set_bit(STATUS_PORT_STARTED,
654 dai_data->status_mask);
655 }
656 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700657 case SNDRV_PCM_TRIGGER_STOP:
658 case SNDRV_PCM_TRIGGER_SUSPEND:
659 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
660 if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
Helen Zeng0705a5f2011-10-14 15:29:52 -0700661 switch (dai->id) {
662 case VOICE_PLAYBACK_TX:
Helen Zenge3d716a2011-10-14 16:32:16 -0700663 case VOICE_RECORD_TX:
664 case VOICE_RECORD_RX:
Helen Zeng0705a5f2011-10-14 15:29:52 -0700665 afe_pseudo_port_stop_nowait(dai->id);
666 break;
667 default:
668 afe_port_stop_nowait(dai->id);
669 break;
670 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700671 clear_bit(STATUS_PORT_STARTED,
672 dai_data->status_mask);
673 }
674 break;
675
676 default:
677 rc = -EINVAL;
678 }
679
680 return rc;
681}
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700682static int msm_dai_q6_dai_auxpcm_probe(struct snd_soc_dai *dai)
683{
684 struct msm_dai_q6_dai_data *dai_data;
685 int rc = 0;
686
687 struct msm_dai_auxpcm_pdata *auxpcm_pdata =
688 (struct msm_dai_auxpcm_pdata *) dai->dev->platform_data;
689
690 dai_data = kzalloc(sizeof(struct msm_dai_q6_dai_data),
691 GFP_KERNEL);
692
693 if (!dai_data) {
694 dev_err(dai->dev, "DAI-%d: fail to allocate dai data\n",
695 dai->id);
696 rc = -ENOMEM;
697 } else
698 dev_set_drvdata(dai->dev, dai_data);
699
700 /*
701 * The clk name for AUX PCM operation is passed as platform
702 * data to the cpu driver, since cpu drive is unaware of any
703 * boarc specific configuration.
704 */
705 pcm_clk = clk_get(NULL, auxpcm_pdata->clk);
706 if (IS_ERR(pcm_clk)) {
707 pr_err("%s: could not get pcm_clk\n", __func__);
708 return PTR_ERR(pcm_clk);
709 kfree(dai_data);
710 }
711
712 return rc;
713}
714
715static int msm_dai_q6_dai_auxpcm_remove(struct snd_soc_dai *dai)
716{
717 struct msm_dai_q6_dai_data *dai_data;
718 int rc;
719
720 dai_data = dev_get_drvdata(dai->dev);
721
722 /* If AFE port is still up, close it */
723 if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
724 rc = afe_close(dai->id); /* can block */
725 if (IS_ERR_VALUE(rc))
726 dev_err(dai->dev, "fail to close AFE port\n");
727 clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
728
729 rc = afe_close(PCM_TX);
730 if (IS_ERR_VALUE(rc))
731 dev_err(dai->dev, "fail to close AUX PCM TX port\n");
732 }
733
734
735 kfree(dai_data);
736 snd_soc_unregister_dai(dai->dev);
737
738 return 0;
739}
Kuirong Wang274f21a2011-12-15 21:29:08 -0800740static int msm_dai_q6_dai_mi2s_probe(struct snd_soc_dai *dai)
741{
742 struct msm_dai_q6_dai_data *dai_data;
743 int rc = 0;
744
745 dai_data = kzalloc(sizeof(struct msm_dai_q6_dai_data),
746 GFP_KERNEL);
747
748 if (!dai_data) {
749 dev_err(dai->dev, "DAI-%d: fail to allocate dai data\n",
750 dai->id);
751 rc = -ENOMEM;
752 goto rtn;
753 } else
754 dev_set_drvdata(dai->dev, dai_data);
755
756 rc = msm_dai_q6_mi2s_platform_data_validation(dai);
757 if (rc != 0) {
758 pr_err("%s: The msm_dai_q6_mi2s_platform_data_validation failed\n",
759 __func__);
760 kfree(dai_data);
761 }
762rtn:
763 return rc;
764}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700765
766static int msm_dai_q6_dai_probe(struct snd_soc_dai *dai)
767{
768 struct msm_dai_q6_dai_data *dai_data;
769 int rc = 0;
770
771 dai_data = kzalloc(sizeof(struct msm_dai_q6_dai_data),
772 GFP_KERNEL);
773
774 if (!dai_data) {
775 dev_err(dai->dev, "DAI-%d: fail to allocate dai data\n",
776 dai->id);
777 rc = -ENOMEM;
778 } else
779 dev_set_drvdata(dai->dev, dai_data);
780
781 return rc;
782}
783
784static int msm_dai_q6_dai_remove(struct snd_soc_dai *dai)
785{
786 struct msm_dai_q6_dai_data *dai_data;
787 int rc;
788
789 dai_data = dev_get_drvdata(dai->dev);
790
791 /* If AFE port is still up, close it */
792 if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
Helen Zeng0705a5f2011-10-14 15:29:52 -0700793 switch (dai->id) {
794 case VOICE_PLAYBACK_TX:
Helen Zenge3d716a2011-10-14 16:32:16 -0700795 case VOICE_RECORD_TX:
796 case VOICE_RECORD_RX:
Helen Zeng0705a5f2011-10-14 15:29:52 -0700797 pr_debug("%s, stop pseudo port:%d\n",
798 __func__, dai->id);
799 rc = afe_stop_pseudo_port(dai->id);
800 break;
801 default:
802 rc = afe_close(dai->id); /* can block */
803 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700804 if (IS_ERR_VALUE(rc))
805 dev_err(dai->dev, "fail to close AFE port\n");
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530806 clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700807 }
808 kfree(dai_data);
809 snd_soc_unregister_dai(dai->dev);
810
811 return 0;
812}
813
Lei Zhou157c1842011-08-19 13:05:04 -0400814static int msm_dai_q6_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
815{
816 int rc = 0;
817
818 dev_dbg(dai->dev, "enter %s, id = %d\n", __func__, dai->id);
819 switch (dai->id) {
820 case PRIMARY_I2S_TX:
821 case PRIMARY_I2S_RX:
Kuirong Wang274f21a2011-12-15 21:29:08 -0800822 case MI2S_RX:
Lei Zhou157c1842011-08-19 13:05:04 -0400823 rc = msm_dai_q6_cdc_set_fmt(dai, fmt);
824 break;
825 default:
826 dev_err(dai->dev, "invalid cpu_dai set_fmt\n");
827 rc = -EINVAL;
828 break;
829 }
830
831 return rc;
832}
833
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700834static struct snd_soc_dai_ops msm_dai_q6_ops = {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700835 .prepare = msm_dai_q6_prepare,
836 .trigger = msm_dai_q6_trigger,
837 .hw_params = msm_dai_q6_hw_params,
838 .shutdown = msm_dai_q6_shutdown,
Lei Zhou157c1842011-08-19 13:05:04 -0400839 .set_fmt = msm_dai_q6_set_fmt,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700840};
841
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700842static struct snd_soc_dai_ops msm_dai_q6_auxpcm_ops = {
843 .prepare = msm_dai_q6_auxpcm_prepare,
844 .trigger = msm_dai_q6_auxpcm_trigger,
845 .hw_params = msm_dai_q6_auxpcm_hw_params,
846 .shutdown = msm_dai_q6_auxpcm_shutdown,
847};
848
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700849static struct snd_soc_dai_driver msm_dai_q6_i2s_rx_dai = {
850 .playback = {
851 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
852 SNDRV_PCM_RATE_16000,
853 .formats = SNDRV_PCM_FMTBIT_S16_LE,
854 .channels_min = 1,
Kiran Kandi9db678b2012-01-15 14:25:59 -0800855 .channels_max = 4,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700856 .rate_min = 8000,
857 .rate_max = 48000,
858 },
859 .ops = &msm_dai_q6_ops,
860 .probe = msm_dai_q6_dai_probe,
861 .remove = msm_dai_q6_dai_remove,
862};
863
864static struct snd_soc_dai_driver msm_dai_q6_i2s_tx_dai = {
865 .capture = {
866 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
867 SNDRV_PCM_RATE_16000,
868 .formats = SNDRV_PCM_FMTBIT_S16_LE,
869 .channels_min = 1,
870 .channels_max = 2,
871 .rate_min = 8000,
872 .rate_max = 48000,
873 },
874 .ops = &msm_dai_q6_ops,
875 .probe = msm_dai_q6_dai_probe,
876 .remove = msm_dai_q6_dai_remove,
877};
878
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530879static struct snd_soc_dai_driver msm_dai_q6_afe_rx_dai = {
880 .playback = {
881 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
882 SNDRV_PCM_RATE_16000,
883 .formats = SNDRV_PCM_FMTBIT_S16_LE,
884 .channels_min = 1,
885 .channels_max = 2,
886 .rate_min = 8000,
887 .rate_max = 48000,
888 },
889 .ops = &msm_dai_q6_ops,
890 .probe = msm_dai_q6_dai_probe,
891 .remove = msm_dai_q6_dai_remove,
892};
893
894static struct snd_soc_dai_driver msm_dai_q6_afe_tx_dai = {
895 .capture = {
896 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
897 SNDRV_PCM_RATE_16000,
898 .formats = SNDRV_PCM_FMTBIT_S16_LE,
899 .channels_min = 1,
900 .channels_max = 2,
901 .rate_min = 8000,
902 .rate_max = 48000,
903 },
904 .ops = &msm_dai_q6_ops,
905 .probe = msm_dai_q6_dai_probe,
906 .remove = msm_dai_q6_dai_remove,
907};
908
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700909static struct snd_soc_dai_driver msm_dai_q6_hdmi_rx_dai = {
910 .playback = {
911 .rates = SNDRV_PCM_RATE_48000,
912 .formats = SNDRV_PCM_FMTBIT_S16_LE,
913 .channels_min = 2,
914 .channels_max = 2,
915 .rate_max = 48000,
916 .rate_min = 48000,
917 },
918 .ops = &msm_dai_q6_ops,
919 .probe = msm_dai_q6_dai_probe,
920 .remove = msm_dai_q6_dai_remove,
921};
922
Helen Zeng0705a5f2011-10-14 15:29:52 -0700923static struct snd_soc_dai_driver msm_dai_q6_voice_playback_tx_dai = {
924 .playback = {
925 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
926 SNDRV_PCM_RATE_16000,
927 .formats = SNDRV_PCM_FMTBIT_S16_LE,
928 .channels_min = 1,
929 .channels_max = 2,
930 .rate_max = 48000,
931 .rate_min = 8000,
932 },
933 .ops = &msm_dai_q6_ops,
934 .probe = msm_dai_q6_dai_probe,
935 .remove = msm_dai_q6_dai_remove,
936};
937
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700938static struct snd_soc_dai_driver msm_dai_q6_slimbus_rx_dai = {
939 .playback = {
940 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
941 SNDRV_PCM_RATE_16000,
942 .formats = SNDRV_PCM_FMTBIT_S16_LE,
943 .channels_min = 1,
944 .channels_max = 2,
945 .rate_min = 8000,
946 .rate_max = 48000,
947 },
948 .ops = &msm_dai_q6_ops,
949 .probe = msm_dai_q6_dai_probe,
950 .remove = msm_dai_q6_dai_remove,
951};
952
953static struct snd_soc_dai_driver msm_dai_q6_slimbus_tx_dai = {
954 .capture = {
955 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
956 SNDRV_PCM_RATE_16000,
957 .formats = SNDRV_PCM_FMTBIT_S16_LE,
958 .channels_min = 1,
959 .channels_max = 2,
960 .rate_min = 8000,
961 .rate_max = 48000,
962 },
963 .ops = &msm_dai_q6_ops,
964 .probe = msm_dai_q6_dai_probe,
965 .remove = msm_dai_q6_dai_remove,
966};
967
Helen Zenge3d716a2011-10-14 16:32:16 -0700968static struct snd_soc_dai_driver msm_dai_q6_incall_record_dai = {
969 .capture = {
970 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
971 SNDRV_PCM_RATE_16000,
972 .formats = SNDRV_PCM_FMTBIT_S16_LE,
973 .channels_min = 1,
974 .channels_max = 2,
975 .rate_min = 8000,
976 .rate_max = 48000,
977 },
978 .ops = &msm_dai_q6_ops,
979 .probe = msm_dai_q6_dai_probe,
980 .remove = msm_dai_q6_dai_remove,
981};
982
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700983static struct snd_soc_dai_driver msm_dai_q6_bt_sco_rx_dai = {
984 .playback = {
985 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
986 .formats = SNDRV_PCM_FMTBIT_S16_LE,
987 .channels_min = 1,
988 .channels_max = 1,
989 .rate_max = 16000,
990 .rate_min = 8000,
991 },
992 .ops = &msm_dai_q6_ops,
993 .probe = msm_dai_q6_dai_probe,
994 .remove = msm_dai_q6_dai_remove,
995};
996
997static struct snd_soc_dai_driver msm_dai_q6_bt_sco_tx_dai = {
998 .playback = {
999 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
1000 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1001 .channels_min = 1,
1002 .channels_max = 1,
1003 .rate_max = 16000,
1004 .rate_min = 8000,
1005 },
1006 .ops = &msm_dai_q6_ops,
1007 .probe = msm_dai_q6_dai_probe,
1008 .remove = msm_dai_q6_dai_remove,
1009};
1010
1011static struct snd_soc_dai_driver msm_dai_q6_fm_rx_dai = {
1012 .playback = {
1013 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1014 SNDRV_PCM_RATE_16000,
1015 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1016 .channels_min = 2,
1017 .channels_max = 2,
1018 .rate_max = 48000,
1019 .rate_min = 8000,
1020 },
1021 .ops = &msm_dai_q6_ops,
1022 .probe = msm_dai_q6_dai_probe,
1023 .remove = msm_dai_q6_dai_remove,
1024};
1025
1026static struct snd_soc_dai_driver msm_dai_q6_fm_tx_dai = {
1027 .playback = {
1028 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1029 SNDRV_PCM_RATE_16000,
1030 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1031 .channels_min = 2,
1032 .channels_max = 2,
1033 .rate_max = 48000,
1034 .rate_min = 8000,
1035 },
1036 .ops = &msm_dai_q6_ops,
1037 .probe = msm_dai_q6_dai_probe,
1038 .remove = msm_dai_q6_dai_remove,
1039};
1040
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001041static struct snd_soc_dai_driver msm_dai_q6_aux_pcm_rx_dai = {
1042 .playback = {
1043 .rates = SNDRV_PCM_RATE_8000,
1044 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1045 .channels_min = 1,
1046 .channels_max = 1,
1047 .rate_max = 8000,
1048 .rate_min = 8000,
1049 },
1050 .ops = &msm_dai_q6_auxpcm_ops,
1051 .probe = msm_dai_q6_dai_auxpcm_probe,
1052 .remove = msm_dai_q6_dai_auxpcm_remove,
1053};
1054
1055static struct snd_soc_dai_driver msm_dai_q6_aux_pcm_tx_dai = {
1056 .capture = {
1057 .rates = SNDRV_PCM_RATE_8000,
1058 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1059 .channels_min = 1,
1060 .channels_max = 1,
1061 .rate_max = 8000,
1062 .rate_min = 8000,
1063 },
1064};
1065
Kuirong Wang274f21a2011-12-15 21:29:08 -08001066static struct snd_soc_dai_driver msm_dai_q6_mi2s_rx_dai = {
1067 .playback = {
1068 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1069 SNDRV_PCM_RATE_16000,
1070 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1071 .channels_min = 1,
1072 .rate_min = 8000,
1073 .rate_max = 48000,
1074 },
1075 .ops = &msm_dai_q6_ops,
1076 .probe = msm_dai_q6_dai_mi2s_probe,
1077 .remove = msm_dai_q6_dai_probe,
1078};
1079
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001080/* To do: change to register DAIs as batch */
1081static __devinit int msm_dai_q6_dev_probe(struct platform_device *pdev)
1082{
1083 int rc = 0;
1084
1085 dev_dbg(&pdev->dev, "dev name %s\n", dev_name(&pdev->dev));
1086
1087 switch (pdev->id) {
1088 case PRIMARY_I2S_RX:
1089 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_i2s_rx_dai);
1090 break;
1091 case PRIMARY_I2S_TX:
1092 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_i2s_tx_dai);
1093 break;
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001094 case PCM_RX:
1095 rc = snd_soc_register_dai(&pdev->dev,
1096 &msm_dai_q6_aux_pcm_rx_dai);
1097 break;
1098 case PCM_TX:
1099 rc = snd_soc_register_dai(&pdev->dev,
1100 &msm_dai_q6_aux_pcm_tx_dai);
1101 break;
Kuirong Wang274f21a2011-12-15 21:29:08 -08001102 case MI2S_RX:
1103 rc = snd_soc_register_dai(&pdev->dev,
1104 &msm_dai_q6_mi2s_rx_dai);
1105 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001106 case HDMI_RX:
1107 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_hdmi_rx_dai);
1108 break;
1109 case SLIMBUS_0_RX:
1110 rc = snd_soc_register_dai(&pdev->dev,
1111 &msm_dai_q6_slimbus_rx_dai);
1112 break;
1113 case SLIMBUS_0_TX:
1114 rc = snd_soc_register_dai(&pdev->dev,
1115 &msm_dai_q6_slimbus_tx_dai);
1116 case INT_BT_SCO_RX:
1117 rc = snd_soc_register_dai(&pdev->dev,
1118 &msm_dai_q6_bt_sco_rx_dai);
1119 break;
1120 case INT_BT_SCO_TX:
1121 rc = snd_soc_register_dai(&pdev->dev,
1122 &msm_dai_q6_bt_sco_tx_dai);
1123 break;
1124 case INT_FM_RX:
1125 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_fm_rx_dai);
1126 break;
1127 case INT_FM_TX:
1128 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_fm_tx_dai);
1129 break;
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301130 case RT_PROXY_DAI_001_RX:
1131 case RT_PROXY_DAI_002_RX:
1132 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_afe_rx_dai);
1133 break;
1134 case RT_PROXY_DAI_001_TX:
1135 case RT_PROXY_DAI_002_TX:
1136 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_afe_tx_dai);
1137 break;
Helen Zeng0705a5f2011-10-14 15:29:52 -07001138 case VOICE_PLAYBACK_TX:
1139 rc = snd_soc_register_dai(&pdev->dev,
1140 &msm_dai_q6_voice_playback_tx_dai);
1141 break;
Helen Zenge3d716a2011-10-14 16:32:16 -07001142 case VOICE_RECORD_RX:
1143 case VOICE_RECORD_TX:
1144 rc = snd_soc_register_dai(&pdev->dev,
1145 &msm_dai_q6_incall_record_dai);
1146 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001147 default:
1148 rc = -ENODEV;
1149 break;
1150 }
1151 return rc;
1152}
1153
1154static __devexit int msm_dai_q6_dev_remove(struct platform_device *pdev)
1155{
1156 snd_soc_unregister_dai(&pdev->dev);
1157 return 0;
1158}
1159
1160static struct platform_driver msm_dai_q6_driver = {
1161 .probe = msm_dai_q6_dev_probe,
1162 .remove = msm_dai_q6_dev_remove,
1163 .driver = {
1164 .name = "msm-dai-q6",
1165 .owner = THIS_MODULE,
1166 },
1167};
1168
1169static int __init msm_dai_q6_init(void)
1170{
1171 return platform_driver_register(&msm_dai_q6_driver);
1172}
1173module_init(msm_dai_q6_init);
1174
1175static void __exit msm_dai_q6_exit(void)
1176{
1177 platform_driver_unregister(&msm_dai_q6_driver);
1178}
1179module_exit(msm_dai_q6_exit);
1180
1181/* Module information */
1182MODULE_DESCRIPTION("MSM DSP DAI driver");
1183MODULE_LICENSE("GPL v2");