blob: 27a27ecc5267fd1f18a227fc790f7783e49167c8 [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:
Kuirong Wang9bbf6132012-01-10 18:28:49 -0800423 case SECONDARY_I2S_RX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700424 rc = msm_dai_q6_cdc_hw_params(params, dai, substream->stream);
425 break;
Kuirong Wang274f21a2011-12-15 21:29:08 -0800426 case MI2S_RX:
427 rc = msm_dai_q6_mi2s_hw_params(params, dai, substream->stream);
428 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700429 case HDMI_RX:
430 rc = msm_dai_q6_hdmi_hw_params(params, dai);
431 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700432 case SLIMBUS_0_RX:
433 case SLIMBUS_0_TX:
434 rc = msm_dai_q6_slim_bus_hw_params(params, dai,
435 substream->stream);
436 break;
437 case INT_BT_SCO_RX:
438 case INT_BT_SCO_TX:
439 case INT_FM_RX:
440 case INT_FM_TX:
441 rc = msm_dai_q6_bt_fm_hw_params(params, dai, substream->stream);
442 break;
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530443 case RT_PROXY_DAI_001_TX:
444 case RT_PROXY_DAI_001_RX:
445 case RT_PROXY_DAI_002_TX:
446 case RT_PROXY_DAI_002_RX:
447 rc = msm_dai_q6_afe_rtproxy_hw_params(params, dai);
448 break;
Helen Zeng0705a5f2011-10-14 15:29:52 -0700449 case VOICE_PLAYBACK_TX:
Helen Zenge3d716a2011-10-14 16:32:16 -0700450 case VOICE_RECORD_RX:
451 case VOICE_RECORD_TX:
Helen Zeng0705a5f2011-10-14 15:29:52 -0700452 rc = 0;
453 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700454 default:
455 dev_err(dai->dev, "invalid AFE port ID\n");
456 rc = -EINVAL;
457 break;
458 }
459
460 return rc;
461}
462
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700463static void msm_dai_q6_auxpcm_shutdown(struct snd_pcm_substream *substream,
464 struct snd_soc_dai *dai)
465{
466 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
467 int rc = 0;
468
469 rc = adm_close(dai->id);
470 if (IS_ERR_VALUE(rc))
471 dev_err(dai->dev, "fail to close ADM COPP\n");
472
473 pr_debug("%s: dai->id = %d", __func__, dai->id);
474
475 if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
476 clk_disable(pcm_clk);
477 rc = afe_close(dai->id); /* can block */
478 if (IS_ERR_VALUE(rc))
479 dev_err(dai->dev, "fail to close AFE port\n");
480 pr_debug("%s: dai_data->status_mask = %ld\n", __func__,
481 *dai_data->status_mask);
482 clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
483
484 rc = afe_close(PCM_TX);
485 if (IS_ERR_VALUE(rc))
486 dev_err(dai->dev, "fail to close AUX PCM TX port\n");
487 }
488}
489
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700490static void msm_dai_q6_shutdown(struct snd_pcm_substream *substream,
491 struct snd_soc_dai *dai)
492{
493 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530494 int rc = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700495
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700496 if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
Helen Zeng0705a5f2011-10-14 15:29:52 -0700497 switch (dai->id) {
498 case VOICE_PLAYBACK_TX:
Helen Zenge3d716a2011-10-14 16:32:16 -0700499 case VOICE_RECORD_TX:
500 case VOICE_RECORD_RX:
Helen Zeng0705a5f2011-10-14 15:29:52 -0700501 pr_debug("%s, stop pseudo port:%d\n",
502 __func__, dai->id);
503 rc = afe_stop_pseudo_port(dai->id);
504 break;
505 default:
506 rc = afe_close(dai->id); /* can block */
507 break;
508 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700509 if (IS_ERR_VALUE(rc))
510 dev_err(dai->dev, "fail to close AFE port\n");
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530511 pr_debug("%s: dai_data->status_mask = %ld\n", __func__,
512 *dai_data->status_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700513 clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
514 }
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700515}
516
517static int msm_dai_q6_auxpcm_prepare(struct snd_pcm_substream *substream,
518 struct snd_soc_dai *dai)
519{
520 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
521 int rc = 0;
522
523 struct msm_dai_auxpcm_pdata *auxpcm_pdata =
524 (struct msm_dai_auxpcm_pdata *) dai->dev->platform_data;
525
526 if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
Patrick Laicf999112011-08-23 11:27:20 -0700527 rc = afe_q6_interface_prepare();
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700528 if (IS_ERR_VALUE(rc))
Patrick Laicf999112011-08-23 11:27:20 -0700529 dev_err(dai->dev, "fail to open AFE APR\n");
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700530
Patrick Laicf999112011-08-23 11:27:20 -0700531 rc = afe_q6_interface_prepare();
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700532 if (IS_ERR_VALUE(rc))
Patrick Laicf999112011-08-23 11:27:20 -0700533 dev_err(dai->dev, "fail to open AFE APR\n");
534
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700535 pr_debug("%s:dai->id:%d dai_data->status_mask = %ld\n",
536 __func__, dai->id, *dai_data->status_mask);
537
538 /*
539 * For AUX PCM Interface the below sequence of clk
540 * settings and afe_open is a strict requirement.
541 *
542 * Also using afe_open instead of afe_port_start_nowait
543 * to make sure the port is open before deasserting the
544 * clock line. This is required because pcm register is
545 * not written before clock deassert. Hence the hw does
546 * not get updated with new setting if the below clock
547 * assert/deasset and afe_open sequence is not followed.
548 */
549
550 clk_reset(pcm_clk, CLK_RESET_ASSERT);
551
552 afe_open(dai->id, &dai_data->port_config,
553 dai_data->rate);
554 set_bit(STATUS_PORT_STARTED,
555 dai_data->status_mask);
556
557 afe_open(PCM_TX, &dai_data->port_config, dai_data->rate);
558
559 rc = clk_set_rate(pcm_clk, auxpcm_pdata->pcm_clk_rate);
560 if (rc < 0) {
561 pr_err("%s: clk_set_rate failed\n", __func__);
562 return rc;
563 }
564
565 clk_enable(pcm_clk);
566 clk_reset(pcm_clk, CLK_RESET_DEASSERT);
567
568 }
569 return rc;
570}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700571
572static int msm_dai_q6_prepare(struct snd_pcm_substream *substream,
573 struct snd_soc_dai *dai)
574{
575 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
576 int rc = 0;
577
Patrick Lai831561e2011-07-26 22:51:27 -0700578 if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
Patrick Laicf999112011-08-23 11:27:20 -0700579 /* PORT START should be set if prepare called in active state */
580 rc = afe_q6_interface_prepare();
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700581 if (IS_ERR_VALUE(rc))
Patrick Laicf999112011-08-23 11:27:20 -0700582 dev_err(dai->dev, "fail to open AFE APR\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700583 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700584 return rc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700585}
586
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700587static int msm_dai_q6_auxpcm_trigger(struct snd_pcm_substream *substream,
588 int cmd, struct snd_soc_dai *dai)
589{
590 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
591 int rc = 0;
592
593 pr_debug("%s:port:%d cmd:%d dai_data->status_mask = %ld",
594 __func__, dai->id, cmd, *dai_data->status_mask);
595
596 switch (cmd) {
597
598 case SNDRV_PCM_TRIGGER_START:
599 case SNDRV_PCM_TRIGGER_RESUME:
600 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
601 /* afe_open will be called from prepare */
602 return 0;
603
604 case SNDRV_PCM_TRIGGER_STOP:
605 case SNDRV_PCM_TRIGGER_SUSPEND:
606 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
607 if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
608
609 clk_disable(pcm_clk);
610 afe_port_stop_nowait(dai->id);
611 clear_bit(STATUS_PORT_STARTED,
612 dai_data->status_mask);
613
614 afe_port_stop_nowait(PCM_TX);
615 }
616 break;
617
618 default:
619 rc = -EINVAL;
620 }
621
622 return rc;
623
624}
625
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700626static int msm_dai_q6_trigger(struct snd_pcm_substream *substream, int cmd,
627 struct snd_soc_dai *dai)
628{
629 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
630 int rc = 0;
631
632 /* Start/stop port without waiting for Q6 AFE response. Need to have
633 * native q6 AFE driver propagates AFE response in order to handle
634 * port start/stop command error properly if error does arise.
635 */
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530636 pr_debug("%s:port:%d cmd:%d dai_data->status_mask = %ld",
637 __func__, dai->id, cmd, *dai_data->status_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700638 switch (cmd) {
639 case SNDRV_PCM_TRIGGER_START:
640 case SNDRV_PCM_TRIGGER_RESUME:
641 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
642 if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
Helen Zeng0705a5f2011-10-14 15:29:52 -0700643 switch (dai->id) {
644 case VOICE_PLAYBACK_TX:
Helen Zenge3d716a2011-10-14 16:32:16 -0700645 case VOICE_RECORD_TX:
646 case VOICE_RECORD_RX:
Helen Zeng0705a5f2011-10-14 15:29:52 -0700647 afe_pseudo_port_start_nowait(dai->id);
648 break;
649 default:
650 afe_port_start_nowait(dai->id,
651 &dai_data->port_config, dai_data->rate);
652 break;
653 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700654 set_bit(STATUS_PORT_STARTED,
655 dai_data->status_mask);
656 }
657 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700658 case SNDRV_PCM_TRIGGER_STOP:
659 case SNDRV_PCM_TRIGGER_SUSPEND:
660 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
661 if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
Helen Zeng0705a5f2011-10-14 15:29:52 -0700662 switch (dai->id) {
663 case VOICE_PLAYBACK_TX:
Helen Zenge3d716a2011-10-14 16:32:16 -0700664 case VOICE_RECORD_TX:
665 case VOICE_RECORD_RX:
Helen Zeng0705a5f2011-10-14 15:29:52 -0700666 afe_pseudo_port_stop_nowait(dai->id);
667 break;
668 default:
669 afe_port_stop_nowait(dai->id);
670 break;
671 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700672 clear_bit(STATUS_PORT_STARTED,
673 dai_data->status_mask);
674 }
675 break;
676
677 default:
678 rc = -EINVAL;
679 }
680
681 return rc;
682}
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700683static int msm_dai_q6_dai_auxpcm_probe(struct snd_soc_dai *dai)
684{
685 struct msm_dai_q6_dai_data *dai_data;
686 int rc = 0;
687
688 struct msm_dai_auxpcm_pdata *auxpcm_pdata =
689 (struct msm_dai_auxpcm_pdata *) dai->dev->platform_data;
690
691 dai_data = kzalloc(sizeof(struct msm_dai_q6_dai_data),
692 GFP_KERNEL);
693
694 if (!dai_data) {
695 dev_err(dai->dev, "DAI-%d: fail to allocate dai data\n",
696 dai->id);
697 rc = -ENOMEM;
698 } else
699 dev_set_drvdata(dai->dev, dai_data);
700
701 /*
702 * The clk name for AUX PCM operation is passed as platform
703 * data to the cpu driver, since cpu drive is unaware of any
704 * boarc specific configuration.
705 */
706 pcm_clk = clk_get(NULL, auxpcm_pdata->clk);
707 if (IS_ERR(pcm_clk)) {
708 pr_err("%s: could not get pcm_clk\n", __func__);
709 return PTR_ERR(pcm_clk);
710 kfree(dai_data);
711 }
712
713 return rc;
714}
715
716static int msm_dai_q6_dai_auxpcm_remove(struct snd_soc_dai *dai)
717{
718 struct msm_dai_q6_dai_data *dai_data;
719 int rc;
720
721 dai_data = dev_get_drvdata(dai->dev);
722
723 /* If AFE port is still up, close it */
724 if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
725 rc = afe_close(dai->id); /* can block */
726 if (IS_ERR_VALUE(rc))
727 dev_err(dai->dev, "fail to close AFE port\n");
728 clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
729
730 rc = afe_close(PCM_TX);
731 if (IS_ERR_VALUE(rc))
732 dev_err(dai->dev, "fail to close AUX PCM TX port\n");
733 }
734
735
736 kfree(dai_data);
737 snd_soc_unregister_dai(dai->dev);
738
739 return 0;
740}
Kuirong Wang274f21a2011-12-15 21:29:08 -0800741static int msm_dai_q6_dai_mi2s_probe(struct snd_soc_dai *dai)
742{
743 struct msm_dai_q6_dai_data *dai_data;
744 int rc = 0;
745
746 dai_data = kzalloc(sizeof(struct msm_dai_q6_dai_data),
747 GFP_KERNEL);
748
749 if (!dai_data) {
750 dev_err(dai->dev, "DAI-%d: fail to allocate dai data\n",
751 dai->id);
752 rc = -ENOMEM;
753 goto rtn;
754 } else
755 dev_set_drvdata(dai->dev, dai_data);
756
757 rc = msm_dai_q6_mi2s_platform_data_validation(dai);
758 if (rc != 0) {
759 pr_err("%s: The msm_dai_q6_mi2s_platform_data_validation failed\n",
760 __func__);
761 kfree(dai_data);
762 }
763rtn:
764 return rc;
765}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700766
767static int msm_dai_q6_dai_probe(struct snd_soc_dai *dai)
768{
769 struct msm_dai_q6_dai_data *dai_data;
770 int rc = 0;
771
772 dai_data = kzalloc(sizeof(struct msm_dai_q6_dai_data),
773 GFP_KERNEL);
774
775 if (!dai_data) {
776 dev_err(dai->dev, "DAI-%d: fail to allocate dai data\n",
777 dai->id);
778 rc = -ENOMEM;
779 } else
780 dev_set_drvdata(dai->dev, dai_data);
781
782 return rc;
783}
784
785static int msm_dai_q6_dai_remove(struct snd_soc_dai *dai)
786{
787 struct msm_dai_q6_dai_data *dai_data;
788 int rc;
789
790 dai_data = dev_get_drvdata(dai->dev);
791
792 /* If AFE port is still up, close it */
793 if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
Helen Zeng0705a5f2011-10-14 15:29:52 -0700794 switch (dai->id) {
795 case VOICE_PLAYBACK_TX:
Helen Zenge3d716a2011-10-14 16:32:16 -0700796 case VOICE_RECORD_TX:
797 case VOICE_RECORD_RX:
Helen Zeng0705a5f2011-10-14 15:29:52 -0700798 pr_debug("%s, stop pseudo port:%d\n",
799 __func__, dai->id);
800 rc = afe_stop_pseudo_port(dai->id);
801 break;
802 default:
803 rc = afe_close(dai->id); /* can block */
804 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700805 if (IS_ERR_VALUE(rc))
806 dev_err(dai->dev, "fail to close AFE port\n");
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530807 clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700808 }
809 kfree(dai_data);
810 snd_soc_unregister_dai(dai->dev);
811
812 return 0;
813}
814
Lei Zhou157c1842011-08-19 13:05:04 -0400815static int msm_dai_q6_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
816{
817 int rc = 0;
818
819 dev_dbg(dai->dev, "enter %s, id = %d\n", __func__, dai->id);
820 switch (dai->id) {
821 case PRIMARY_I2S_TX:
822 case PRIMARY_I2S_RX:
Kuirong Wang274f21a2011-12-15 21:29:08 -0800823 case MI2S_RX:
Kuirong Wang9bbf6132012-01-10 18:28:49 -0800824 case SECONDARY_I2S_RX:
Lei Zhou157c1842011-08-19 13:05:04 -0400825 rc = msm_dai_q6_cdc_set_fmt(dai, fmt);
826 break;
827 default:
828 dev_err(dai->dev, "invalid cpu_dai set_fmt\n");
829 rc = -EINVAL;
830 break;
831 }
832
833 return rc;
834}
835
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700836static struct snd_soc_dai_ops msm_dai_q6_ops = {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700837 .prepare = msm_dai_q6_prepare,
838 .trigger = msm_dai_q6_trigger,
839 .hw_params = msm_dai_q6_hw_params,
840 .shutdown = msm_dai_q6_shutdown,
Lei Zhou157c1842011-08-19 13:05:04 -0400841 .set_fmt = msm_dai_q6_set_fmt,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700842};
843
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700844static struct snd_soc_dai_ops msm_dai_q6_auxpcm_ops = {
845 .prepare = msm_dai_q6_auxpcm_prepare,
846 .trigger = msm_dai_q6_auxpcm_trigger,
847 .hw_params = msm_dai_q6_auxpcm_hw_params,
848 .shutdown = msm_dai_q6_auxpcm_shutdown,
849};
850
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700851static struct snd_soc_dai_driver msm_dai_q6_i2s_rx_dai = {
852 .playback = {
853 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
854 SNDRV_PCM_RATE_16000,
855 .formats = SNDRV_PCM_FMTBIT_S16_LE,
856 .channels_min = 1,
Kiran Kandi9db678b2012-01-15 14:25:59 -0800857 .channels_max = 4,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700858 .rate_min = 8000,
859 .rate_max = 48000,
860 },
861 .ops = &msm_dai_q6_ops,
862 .probe = msm_dai_q6_dai_probe,
863 .remove = msm_dai_q6_dai_remove,
864};
865
866static struct snd_soc_dai_driver msm_dai_q6_i2s_tx_dai = {
867 .capture = {
868 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
869 SNDRV_PCM_RATE_16000,
870 .formats = SNDRV_PCM_FMTBIT_S16_LE,
871 .channels_min = 1,
872 .channels_max = 2,
873 .rate_min = 8000,
874 .rate_max = 48000,
875 },
876 .ops = &msm_dai_q6_ops,
877 .probe = msm_dai_q6_dai_probe,
878 .remove = msm_dai_q6_dai_remove,
879};
880
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530881static struct snd_soc_dai_driver msm_dai_q6_afe_rx_dai = {
882 .playback = {
883 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
884 SNDRV_PCM_RATE_16000,
885 .formats = SNDRV_PCM_FMTBIT_S16_LE,
886 .channels_min = 1,
887 .channels_max = 2,
888 .rate_min = 8000,
889 .rate_max = 48000,
890 },
891 .ops = &msm_dai_q6_ops,
892 .probe = msm_dai_q6_dai_probe,
893 .remove = msm_dai_q6_dai_remove,
894};
895
896static struct snd_soc_dai_driver msm_dai_q6_afe_tx_dai = {
897 .capture = {
898 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
899 SNDRV_PCM_RATE_16000,
900 .formats = SNDRV_PCM_FMTBIT_S16_LE,
901 .channels_min = 1,
902 .channels_max = 2,
903 .rate_min = 8000,
904 .rate_max = 48000,
905 },
906 .ops = &msm_dai_q6_ops,
907 .probe = msm_dai_q6_dai_probe,
908 .remove = msm_dai_q6_dai_remove,
909};
910
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700911static struct snd_soc_dai_driver msm_dai_q6_hdmi_rx_dai = {
912 .playback = {
913 .rates = SNDRV_PCM_RATE_48000,
914 .formats = SNDRV_PCM_FMTBIT_S16_LE,
915 .channels_min = 2,
916 .channels_max = 2,
917 .rate_max = 48000,
918 .rate_min = 48000,
919 },
920 .ops = &msm_dai_q6_ops,
921 .probe = msm_dai_q6_dai_probe,
922 .remove = msm_dai_q6_dai_remove,
923};
924
Helen Zeng0705a5f2011-10-14 15:29:52 -0700925static struct snd_soc_dai_driver msm_dai_q6_voice_playback_tx_dai = {
926 .playback = {
927 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
928 SNDRV_PCM_RATE_16000,
929 .formats = SNDRV_PCM_FMTBIT_S16_LE,
930 .channels_min = 1,
931 .channels_max = 2,
932 .rate_max = 48000,
933 .rate_min = 8000,
934 },
935 .ops = &msm_dai_q6_ops,
936 .probe = msm_dai_q6_dai_probe,
937 .remove = msm_dai_q6_dai_remove,
938};
939
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700940static struct snd_soc_dai_driver msm_dai_q6_slimbus_rx_dai = {
941 .playback = {
942 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
943 SNDRV_PCM_RATE_16000,
944 .formats = SNDRV_PCM_FMTBIT_S16_LE,
945 .channels_min = 1,
946 .channels_max = 2,
947 .rate_min = 8000,
948 .rate_max = 48000,
949 },
950 .ops = &msm_dai_q6_ops,
951 .probe = msm_dai_q6_dai_probe,
952 .remove = msm_dai_q6_dai_remove,
953};
954
955static struct snd_soc_dai_driver msm_dai_q6_slimbus_tx_dai = {
956 .capture = {
957 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
958 SNDRV_PCM_RATE_16000,
959 .formats = SNDRV_PCM_FMTBIT_S16_LE,
960 .channels_min = 1,
961 .channels_max = 2,
962 .rate_min = 8000,
963 .rate_max = 48000,
964 },
965 .ops = &msm_dai_q6_ops,
966 .probe = msm_dai_q6_dai_probe,
967 .remove = msm_dai_q6_dai_remove,
968};
969
Helen Zenge3d716a2011-10-14 16:32:16 -0700970static struct snd_soc_dai_driver msm_dai_q6_incall_record_dai = {
971 .capture = {
972 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
973 SNDRV_PCM_RATE_16000,
974 .formats = SNDRV_PCM_FMTBIT_S16_LE,
975 .channels_min = 1,
976 .channels_max = 2,
977 .rate_min = 8000,
978 .rate_max = 48000,
979 },
980 .ops = &msm_dai_q6_ops,
981 .probe = msm_dai_q6_dai_probe,
982 .remove = msm_dai_q6_dai_remove,
983};
984
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700985static struct snd_soc_dai_driver msm_dai_q6_bt_sco_rx_dai = {
986 .playback = {
987 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
988 .formats = SNDRV_PCM_FMTBIT_S16_LE,
989 .channels_min = 1,
990 .channels_max = 1,
991 .rate_max = 16000,
992 .rate_min = 8000,
993 },
994 .ops = &msm_dai_q6_ops,
995 .probe = msm_dai_q6_dai_probe,
996 .remove = msm_dai_q6_dai_remove,
997};
998
999static struct snd_soc_dai_driver msm_dai_q6_bt_sco_tx_dai = {
1000 .playback = {
1001 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
1002 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1003 .channels_min = 1,
1004 .channels_max = 1,
1005 .rate_max = 16000,
1006 .rate_min = 8000,
1007 },
1008 .ops = &msm_dai_q6_ops,
1009 .probe = msm_dai_q6_dai_probe,
1010 .remove = msm_dai_q6_dai_remove,
1011};
1012
1013static struct snd_soc_dai_driver msm_dai_q6_fm_rx_dai = {
1014 .playback = {
1015 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1016 SNDRV_PCM_RATE_16000,
1017 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1018 .channels_min = 2,
1019 .channels_max = 2,
1020 .rate_max = 48000,
1021 .rate_min = 8000,
1022 },
1023 .ops = &msm_dai_q6_ops,
1024 .probe = msm_dai_q6_dai_probe,
1025 .remove = msm_dai_q6_dai_remove,
1026};
1027
1028static struct snd_soc_dai_driver msm_dai_q6_fm_tx_dai = {
1029 .playback = {
1030 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1031 SNDRV_PCM_RATE_16000,
1032 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1033 .channels_min = 2,
1034 .channels_max = 2,
1035 .rate_max = 48000,
1036 .rate_min = 8000,
1037 },
1038 .ops = &msm_dai_q6_ops,
1039 .probe = msm_dai_q6_dai_probe,
1040 .remove = msm_dai_q6_dai_remove,
1041};
1042
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001043static struct snd_soc_dai_driver msm_dai_q6_aux_pcm_rx_dai = {
1044 .playback = {
1045 .rates = SNDRV_PCM_RATE_8000,
1046 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1047 .channels_min = 1,
1048 .channels_max = 1,
1049 .rate_max = 8000,
1050 .rate_min = 8000,
1051 },
1052 .ops = &msm_dai_q6_auxpcm_ops,
1053 .probe = msm_dai_q6_dai_auxpcm_probe,
1054 .remove = msm_dai_q6_dai_auxpcm_remove,
1055};
1056
1057static struct snd_soc_dai_driver msm_dai_q6_aux_pcm_tx_dai = {
1058 .capture = {
1059 .rates = SNDRV_PCM_RATE_8000,
1060 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1061 .channels_min = 1,
1062 .channels_max = 1,
1063 .rate_max = 8000,
1064 .rate_min = 8000,
1065 },
1066};
1067
Kuirong Wang274f21a2011-12-15 21:29:08 -08001068static struct snd_soc_dai_driver msm_dai_q6_mi2s_rx_dai = {
1069 .playback = {
1070 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1071 SNDRV_PCM_RATE_16000,
1072 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1073 .channels_min = 1,
1074 .rate_min = 8000,
1075 .rate_max = 48000,
1076 },
1077 .ops = &msm_dai_q6_ops,
1078 .probe = msm_dai_q6_dai_mi2s_probe,
1079 .remove = msm_dai_q6_dai_probe,
1080};
1081
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001082/* To do: change to register DAIs as batch */
1083static __devinit int msm_dai_q6_dev_probe(struct platform_device *pdev)
1084{
1085 int rc = 0;
1086
1087 dev_dbg(&pdev->dev, "dev name %s\n", dev_name(&pdev->dev));
1088
1089 switch (pdev->id) {
1090 case PRIMARY_I2S_RX:
Kuirong Wang9bbf6132012-01-10 18:28:49 -08001091 case SECONDARY_I2S_RX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001092 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_i2s_rx_dai);
1093 break;
1094 case PRIMARY_I2S_TX:
1095 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_i2s_tx_dai);
1096 break;
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001097 case PCM_RX:
1098 rc = snd_soc_register_dai(&pdev->dev,
1099 &msm_dai_q6_aux_pcm_rx_dai);
1100 break;
1101 case PCM_TX:
1102 rc = snd_soc_register_dai(&pdev->dev,
1103 &msm_dai_q6_aux_pcm_tx_dai);
1104 break;
Kuirong Wang274f21a2011-12-15 21:29:08 -08001105 case MI2S_RX:
1106 rc = snd_soc_register_dai(&pdev->dev,
1107 &msm_dai_q6_mi2s_rx_dai);
1108 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001109 case HDMI_RX:
1110 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_hdmi_rx_dai);
1111 break;
1112 case SLIMBUS_0_RX:
1113 rc = snd_soc_register_dai(&pdev->dev,
1114 &msm_dai_q6_slimbus_rx_dai);
1115 break;
1116 case SLIMBUS_0_TX:
1117 rc = snd_soc_register_dai(&pdev->dev,
1118 &msm_dai_q6_slimbus_tx_dai);
1119 case INT_BT_SCO_RX:
1120 rc = snd_soc_register_dai(&pdev->dev,
1121 &msm_dai_q6_bt_sco_rx_dai);
1122 break;
1123 case INT_BT_SCO_TX:
1124 rc = snd_soc_register_dai(&pdev->dev,
1125 &msm_dai_q6_bt_sco_tx_dai);
1126 break;
1127 case INT_FM_RX:
1128 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_fm_rx_dai);
1129 break;
1130 case INT_FM_TX:
1131 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_fm_tx_dai);
1132 break;
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301133 case RT_PROXY_DAI_001_RX:
1134 case RT_PROXY_DAI_002_RX:
1135 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_afe_rx_dai);
1136 break;
1137 case RT_PROXY_DAI_001_TX:
1138 case RT_PROXY_DAI_002_TX:
1139 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_afe_tx_dai);
1140 break;
Helen Zeng0705a5f2011-10-14 15:29:52 -07001141 case VOICE_PLAYBACK_TX:
1142 rc = snd_soc_register_dai(&pdev->dev,
1143 &msm_dai_q6_voice_playback_tx_dai);
1144 break;
Helen Zenge3d716a2011-10-14 16:32:16 -07001145 case VOICE_RECORD_RX:
1146 case VOICE_RECORD_TX:
1147 rc = snd_soc_register_dai(&pdev->dev,
1148 &msm_dai_q6_incall_record_dai);
1149 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001150 default:
1151 rc = -ENODEV;
1152 break;
1153 }
1154 return rc;
1155}
1156
1157static __devexit int msm_dai_q6_dev_remove(struct platform_device *pdev)
1158{
1159 snd_soc_unregister_dai(&pdev->dev);
1160 return 0;
1161}
1162
1163static struct platform_driver msm_dai_q6_driver = {
1164 .probe = msm_dai_q6_dev_probe,
1165 .remove = msm_dai_q6_dev_remove,
1166 .driver = {
1167 .name = "msm-dai-q6",
1168 .owner = THIS_MODULE,
1169 },
1170};
1171
1172static int __init msm_dai_q6_init(void)
1173{
1174 return platform_driver_register(&msm_dai_q6_driver);
1175}
1176module_init(msm_dai_q6_init);
1177
1178static void __exit msm_dai_q6_exit(void)
1179{
1180 platform_driver_unregister(&msm_dai_q6_driver);
1181}
1182module_exit(msm_dai_q6_exit);
1183
1184/* Module information */
1185MODULE_DESCRIPTION("MSM DSP DAI driver");
1186MODULE_LICENSE("GPL v2");