blob: cd2d8071740872696a44925c9ecc0ef0fa4d3246 [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>
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053017#include <linux/mfd/wcd9xxx/core.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070018#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 }
Kuirong Wangc70819f2012-02-08 16:12:23 -0800103 dai_data->rate = params_rate(params);
Kuirong Wang274f21a2011-12-15 21:29:08 -0800104 /* 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
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700210
211static int msm_dai_q6_slim_bus_hw_params(struct snd_pcm_hw_params *params,
212 struct snd_soc_dai *dai, int stream)
213{
214 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700215
216 dai_data->channels = params_channels(params);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700217 dai_data->rate = params_rate(params);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700218
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:
Neema Shetty3c9d2862012-03-11 01:25:32 -0800352 case SLIMBUS_1_RX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700353 case SLIMBUS_0_TX:
Neema Shetty3c9d2862012-03-11 01:25:32 -0800354 case SLIMBUS_1_TX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700355 rc = msm_dai_q6_slim_bus_hw_params(params, dai,
356 substream->stream);
357 break;
358 case INT_BT_SCO_RX:
359 case INT_BT_SCO_TX:
360 case INT_FM_RX:
361 case INT_FM_TX:
362 rc = msm_dai_q6_bt_fm_hw_params(params, dai, substream->stream);
363 break;
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530364 case RT_PROXY_DAI_001_TX:
365 case RT_PROXY_DAI_001_RX:
366 case RT_PROXY_DAI_002_TX:
367 case RT_PROXY_DAI_002_RX:
368 rc = msm_dai_q6_afe_rtproxy_hw_params(params, dai);
369 break;
Helen Zeng0705a5f2011-10-14 15:29:52 -0700370 case VOICE_PLAYBACK_TX:
Helen Zenge3d716a2011-10-14 16:32:16 -0700371 case VOICE_RECORD_RX:
372 case VOICE_RECORD_TX:
Helen Zeng0705a5f2011-10-14 15:29:52 -0700373 rc = 0;
374 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700375 default:
376 dev_err(dai->dev, "invalid AFE port ID\n");
377 rc = -EINVAL;
378 break;
379 }
380
381 return rc;
382}
383
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700384static void msm_dai_q6_auxpcm_shutdown(struct snd_pcm_substream *substream,
385 struct snd_soc_dai *dai)
386{
387 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
388 int rc = 0;
389
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700390 pr_debug("%s: dai->id = %d", __func__, dai->id);
391
392 if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
393 clk_disable(pcm_clk);
394 rc = afe_close(dai->id); /* can block */
395 if (IS_ERR_VALUE(rc))
396 dev_err(dai->dev, "fail to close AFE port\n");
397 pr_debug("%s: dai_data->status_mask = %ld\n", __func__,
398 *dai_data->status_mask);
399 clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
400
401 rc = afe_close(PCM_TX);
402 if (IS_ERR_VALUE(rc))
403 dev_err(dai->dev, "fail to close AUX PCM TX port\n");
404 }
405}
406
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700407static void msm_dai_q6_shutdown(struct snd_pcm_substream *substream,
408 struct snd_soc_dai *dai)
409{
410 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530411 int rc = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700412
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700413 if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
Helen Zeng0705a5f2011-10-14 15:29:52 -0700414 switch (dai->id) {
415 case VOICE_PLAYBACK_TX:
Helen Zenge3d716a2011-10-14 16:32:16 -0700416 case VOICE_RECORD_TX:
417 case VOICE_RECORD_RX:
Helen Zeng0705a5f2011-10-14 15:29:52 -0700418 pr_debug("%s, stop pseudo port:%d\n",
419 __func__, dai->id);
420 rc = afe_stop_pseudo_port(dai->id);
421 break;
422 default:
423 rc = afe_close(dai->id); /* can block */
424 break;
425 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700426 if (IS_ERR_VALUE(rc))
427 dev_err(dai->dev, "fail to close AFE port\n");
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530428 pr_debug("%s: dai_data->status_mask = %ld\n", __func__,
429 *dai_data->status_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700430 clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
431 }
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700432}
433
434static int msm_dai_q6_auxpcm_prepare(struct snd_pcm_substream *substream,
435 struct snd_soc_dai *dai)
436{
437 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
438 int rc = 0;
439
440 struct msm_dai_auxpcm_pdata *auxpcm_pdata =
441 (struct msm_dai_auxpcm_pdata *) dai->dev->platform_data;
442
443 if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
Patrick Laicf999112011-08-23 11:27:20 -0700444 rc = afe_q6_interface_prepare();
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700445 if (IS_ERR_VALUE(rc))
Patrick Laicf999112011-08-23 11:27:20 -0700446 dev_err(dai->dev, "fail to open AFE APR\n");
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700447
Patrick Laicf999112011-08-23 11:27:20 -0700448 rc = afe_q6_interface_prepare();
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700449 if (IS_ERR_VALUE(rc))
Patrick Laicf999112011-08-23 11:27:20 -0700450 dev_err(dai->dev, "fail to open AFE APR\n");
451
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700452 pr_debug("%s:dai->id:%d dai_data->status_mask = %ld\n",
453 __func__, dai->id, *dai_data->status_mask);
454
455 /*
456 * For AUX PCM Interface the below sequence of clk
457 * settings and afe_open is a strict requirement.
458 *
459 * Also using afe_open instead of afe_port_start_nowait
460 * to make sure the port is open before deasserting the
461 * clock line. This is required because pcm register is
462 * not written before clock deassert. Hence the hw does
463 * not get updated with new setting if the below clock
464 * assert/deasset and afe_open sequence is not followed.
465 */
466
467 clk_reset(pcm_clk, CLK_RESET_ASSERT);
468
469 afe_open(dai->id, &dai_data->port_config,
470 dai_data->rate);
471 set_bit(STATUS_PORT_STARTED,
472 dai_data->status_mask);
473
474 afe_open(PCM_TX, &dai_data->port_config, dai_data->rate);
475
476 rc = clk_set_rate(pcm_clk, auxpcm_pdata->pcm_clk_rate);
477 if (rc < 0) {
478 pr_err("%s: clk_set_rate failed\n", __func__);
479 return rc;
480 }
481
482 clk_enable(pcm_clk);
483 clk_reset(pcm_clk, CLK_RESET_DEASSERT);
484
485 }
486 return rc;
487}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700488
489static int msm_dai_q6_prepare(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);
493 int rc = 0;
494
Patrick Lai831561e2011-07-26 22:51:27 -0700495 if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
Patrick Laicf999112011-08-23 11:27:20 -0700496 /* PORT START should be set if prepare called in active state */
497 rc = afe_q6_interface_prepare();
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700498 if (IS_ERR_VALUE(rc))
Patrick Laicf999112011-08-23 11:27:20 -0700499 dev_err(dai->dev, "fail to open AFE APR\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700500 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700501 return rc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700502}
503
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700504static int msm_dai_q6_auxpcm_trigger(struct snd_pcm_substream *substream,
505 int cmd, struct snd_soc_dai *dai)
506{
507 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
508 int rc = 0;
509
510 pr_debug("%s:port:%d cmd:%d dai_data->status_mask = %ld",
511 __func__, dai->id, cmd, *dai_data->status_mask);
512
513 switch (cmd) {
514
515 case SNDRV_PCM_TRIGGER_START:
516 case SNDRV_PCM_TRIGGER_RESUME:
517 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
518 /* afe_open will be called from prepare */
519 return 0;
520
521 case SNDRV_PCM_TRIGGER_STOP:
522 case SNDRV_PCM_TRIGGER_SUSPEND:
523 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
524 if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
525
526 clk_disable(pcm_clk);
527 afe_port_stop_nowait(dai->id);
528 clear_bit(STATUS_PORT_STARTED,
529 dai_data->status_mask);
530
531 afe_port_stop_nowait(PCM_TX);
532 }
533 break;
534
535 default:
536 rc = -EINVAL;
537 }
538
539 return rc;
540
541}
542
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700543static int msm_dai_q6_trigger(struct snd_pcm_substream *substream, int cmd,
544 struct snd_soc_dai *dai)
545{
546 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
547 int rc = 0;
548
549 /* Start/stop port without waiting for Q6 AFE response. Need to have
550 * native q6 AFE driver propagates AFE response in order to handle
551 * port start/stop command error properly if error does arise.
552 */
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530553 pr_debug("%s:port:%d cmd:%d dai_data->status_mask = %ld",
554 __func__, dai->id, cmd, *dai_data->status_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700555 switch (cmd) {
556 case SNDRV_PCM_TRIGGER_START:
557 case SNDRV_PCM_TRIGGER_RESUME:
558 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
559 if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
Helen Zeng0705a5f2011-10-14 15:29:52 -0700560 switch (dai->id) {
561 case VOICE_PLAYBACK_TX:
Helen Zenge3d716a2011-10-14 16:32:16 -0700562 case VOICE_RECORD_TX:
563 case VOICE_RECORD_RX:
Helen Zeng0705a5f2011-10-14 15:29:52 -0700564 afe_pseudo_port_start_nowait(dai->id);
565 break;
566 default:
567 afe_port_start_nowait(dai->id,
568 &dai_data->port_config, dai_data->rate);
569 break;
570 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700571 set_bit(STATUS_PORT_STARTED,
572 dai_data->status_mask);
573 }
574 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700575 case SNDRV_PCM_TRIGGER_STOP:
576 case SNDRV_PCM_TRIGGER_SUSPEND:
577 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
578 if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
Helen Zeng0705a5f2011-10-14 15:29:52 -0700579 switch (dai->id) {
580 case VOICE_PLAYBACK_TX:
Helen Zenge3d716a2011-10-14 16:32:16 -0700581 case VOICE_RECORD_TX:
582 case VOICE_RECORD_RX:
Helen Zeng0705a5f2011-10-14 15:29:52 -0700583 afe_pseudo_port_stop_nowait(dai->id);
584 break;
585 default:
586 afe_port_stop_nowait(dai->id);
587 break;
588 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700589 clear_bit(STATUS_PORT_STARTED,
590 dai_data->status_mask);
591 }
592 break;
593
594 default:
595 rc = -EINVAL;
596 }
597
598 return rc;
599}
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700600static int msm_dai_q6_dai_auxpcm_probe(struct snd_soc_dai *dai)
601{
602 struct msm_dai_q6_dai_data *dai_data;
603 int rc = 0;
604
605 struct msm_dai_auxpcm_pdata *auxpcm_pdata =
606 (struct msm_dai_auxpcm_pdata *) dai->dev->platform_data;
607
608 dai_data = kzalloc(sizeof(struct msm_dai_q6_dai_data),
609 GFP_KERNEL);
610
611 if (!dai_data) {
612 dev_err(dai->dev, "DAI-%d: fail to allocate dai data\n",
613 dai->id);
614 rc = -ENOMEM;
615 } else
616 dev_set_drvdata(dai->dev, dai_data);
617
618 /*
619 * The clk name for AUX PCM operation is passed as platform
620 * data to the cpu driver, since cpu drive is unaware of any
621 * boarc specific configuration.
622 */
Kuirong Wanga9c3acc2012-02-09 17:00:45 -0800623 pcm_clk = clk_get(dai->dev, auxpcm_pdata->clk);
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700624 if (IS_ERR(pcm_clk)) {
625 pr_err("%s: could not get pcm_clk\n", __func__);
626 return PTR_ERR(pcm_clk);
627 kfree(dai_data);
628 }
629
630 return rc;
631}
632
633static int msm_dai_q6_dai_auxpcm_remove(struct snd_soc_dai *dai)
634{
635 struct msm_dai_q6_dai_data *dai_data;
636 int rc;
637
638 dai_data = dev_get_drvdata(dai->dev);
639
640 /* If AFE port is still up, close it */
641 if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
642 rc = afe_close(dai->id); /* can block */
643 if (IS_ERR_VALUE(rc))
644 dev_err(dai->dev, "fail to close AFE port\n");
645 clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
646
647 rc = afe_close(PCM_TX);
648 if (IS_ERR_VALUE(rc))
649 dev_err(dai->dev, "fail to close AUX PCM TX port\n");
650 }
651
652
653 kfree(dai_data);
654 snd_soc_unregister_dai(dai->dev);
655
656 return 0;
657}
Kuirong Wang274f21a2011-12-15 21:29:08 -0800658static int msm_dai_q6_dai_mi2s_probe(struct snd_soc_dai *dai)
659{
660 struct msm_dai_q6_dai_data *dai_data;
661 int rc = 0;
662
663 dai_data = kzalloc(sizeof(struct msm_dai_q6_dai_data),
664 GFP_KERNEL);
665
666 if (!dai_data) {
667 dev_err(dai->dev, "DAI-%d: fail to allocate dai data\n",
668 dai->id);
669 rc = -ENOMEM;
670 goto rtn;
671 } else
672 dev_set_drvdata(dai->dev, dai_data);
673
674 rc = msm_dai_q6_mi2s_platform_data_validation(dai);
675 if (rc != 0) {
676 pr_err("%s: The msm_dai_q6_mi2s_platform_data_validation failed\n",
677 __func__);
678 kfree(dai_data);
679 }
680rtn:
681 return rc;
682}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700683
684static int msm_dai_q6_dai_probe(struct snd_soc_dai *dai)
685{
686 struct msm_dai_q6_dai_data *dai_data;
687 int rc = 0;
688
689 dai_data = kzalloc(sizeof(struct msm_dai_q6_dai_data),
690 GFP_KERNEL);
691
692 if (!dai_data) {
693 dev_err(dai->dev, "DAI-%d: fail to allocate dai data\n",
694 dai->id);
695 rc = -ENOMEM;
696 } else
697 dev_set_drvdata(dai->dev, dai_data);
698
699 return rc;
700}
701
702static int msm_dai_q6_dai_remove(struct snd_soc_dai *dai)
703{
704 struct msm_dai_q6_dai_data *dai_data;
705 int rc;
706
707 dai_data = dev_get_drvdata(dai->dev);
708
709 /* If AFE port is still up, close it */
710 if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
Helen Zeng0705a5f2011-10-14 15:29:52 -0700711 switch (dai->id) {
712 case VOICE_PLAYBACK_TX:
Helen Zenge3d716a2011-10-14 16:32:16 -0700713 case VOICE_RECORD_TX:
714 case VOICE_RECORD_RX:
Helen Zeng0705a5f2011-10-14 15:29:52 -0700715 pr_debug("%s, stop pseudo port:%d\n",
716 __func__, dai->id);
717 rc = afe_stop_pseudo_port(dai->id);
718 break;
719 default:
720 rc = afe_close(dai->id); /* can block */
721 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700722 if (IS_ERR_VALUE(rc))
723 dev_err(dai->dev, "fail to close AFE port\n");
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530724 clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700725 }
726 kfree(dai_data);
727 snd_soc_unregister_dai(dai->dev);
728
729 return 0;
730}
731
Lei Zhou157c1842011-08-19 13:05:04 -0400732static int msm_dai_q6_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
733{
734 int rc = 0;
735
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800736 dev_dbg(dai->dev, "enter %s, id = %d fmt[%d]\n", __func__,
737 dai->id, fmt);
Lei Zhou157c1842011-08-19 13:05:04 -0400738 switch (dai->id) {
739 case PRIMARY_I2S_TX:
740 case PRIMARY_I2S_RX:
Kuirong Wang274f21a2011-12-15 21:29:08 -0800741 case MI2S_RX:
Kuirong Wang9bbf6132012-01-10 18:28:49 -0800742 case SECONDARY_I2S_RX:
Lei Zhou157c1842011-08-19 13:05:04 -0400743 rc = msm_dai_q6_cdc_set_fmt(dai, fmt);
744 break;
745 default:
746 dev_err(dai->dev, "invalid cpu_dai set_fmt\n");
747 rc = -EINVAL;
748 break;
749 }
750
751 return rc;
752}
753
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800754static int msm_dai_q6_set_channel_map(struct snd_soc_dai *dai,
755 unsigned int tx_num, unsigned int *tx_slot,
756 unsigned int rx_num, unsigned int *rx_slot)
757
758{
759 int rc = 0;
760 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
761 unsigned int i = 0;
762
763 dev_dbg(dai->dev, "enter %s, id = %d\n", __func__,
764 dai->id);
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800765 switch (dai->id) {
766 case SLIMBUS_0_RX:
Neema Shetty3c9d2862012-03-11 01:25:32 -0800767 case SLIMBUS_1_RX:
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800768 /* channel number to be between 128 and 255. For RX port
769 * use channel numbers from 138 to 144, for TX port
770 * use channel numbers from 128 to 137
Neema Shetty3c9d2862012-03-11 01:25:32 -0800771 * For ports between MDM-APQ use channel numbers from 145
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800772 */
Bharath Ramachandramurthy94ad7e22012-02-28 18:44:07 -0800773 if (!rx_slot)
774 return -EINVAL;
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800775 for (i = 0; i < rx_num; i++) {
776 dai_data->port_config.slim_sch.slave_ch_mapping[i] =
777 rx_slot[i];
778 pr_debug("%s: find number of channels[%d] ch[%d]\n",
779 __func__, i,
780 rx_slot[i]);
781 }
782 dai_data->port_config.slim_sch.num_channels = rx_num;
783 pr_debug("%s:SLIMBUS_0_RX cnt[%d] ch[%d %d]\n", __func__,
784 rx_num, dai_data->port_config.slim_sch.slave_ch_mapping[0],
785 dai_data->port_config.slim_sch.slave_ch_mapping[1]);
786
787 break;
788 case SLIMBUS_0_TX:
Neema Shetty3c9d2862012-03-11 01:25:32 -0800789 case SLIMBUS_1_TX:
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800790 /* channel number to be between 128 and 255. For RX port
791 * use channel numbers from 138 to 144, for TX port
792 * use channel numbers from 128 to 137
Neema Shetty3c9d2862012-03-11 01:25:32 -0800793 * For ports between MDM-APQ use channel numbers from 145
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800794 */
Bharath Ramachandramurthy94ad7e22012-02-28 18:44:07 -0800795 if (!tx_slot)
796 return -EINVAL;
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800797 for (i = 0; i < tx_num; i++) {
798 dai_data->port_config.slim_sch.slave_ch_mapping[i] =
799 tx_slot[i];
800 pr_debug("%s: find number of channels[%d] ch[%d]\n",
801 __func__, i, tx_slot[i]);
802 }
803 dai_data->port_config.slim_sch.num_channels = tx_num;
804 pr_debug("%s:SLIMBUS_0_TX cnt[%d] ch[%d %d]\n", __func__,
805 tx_num, dai_data->port_config.slim_sch.slave_ch_mapping[0],
806 dai_data->port_config.slim_sch.slave_ch_mapping[1]);
807 break;
808 default:
809 dev_err(dai->dev, "invalid cpu_dai set_fmt\n");
810 rc = -EINVAL;
811 break;
812 }
813 return rc;
814}
815
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700816static struct snd_soc_dai_ops msm_dai_q6_ops = {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700817 .prepare = msm_dai_q6_prepare,
818 .trigger = msm_dai_q6_trigger,
819 .hw_params = msm_dai_q6_hw_params,
820 .shutdown = msm_dai_q6_shutdown,
Lei Zhou157c1842011-08-19 13:05:04 -0400821 .set_fmt = msm_dai_q6_set_fmt,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800822 .set_channel_map = msm_dai_q6_set_channel_map,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700823};
824
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700825static struct snd_soc_dai_ops msm_dai_q6_auxpcm_ops = {
826 .prepare = msm_dai_q6_auxpcm_prepare,
827 .trigger = msm_dai_q6_auxpcm_trigger,
828 .hw_params = msm_dai_q6_auxpcm_hw_params,
829 .shutdown = msm_dai_q6_auxpcm_shutdown,
830};
831
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700832static struct snd_soc_dai_driver msm_dai_q6_i2s_rx_dai = {
833 .playback = {
834 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
835 SNDRV_PCM_RATE_16000,
836 .formats = SNDRV_PCM_FMTBIT_S16_LE,
837 .channels_min = 1,
Kiran Kandi9db678b2012-01-15 14:25:59 -0800838 .channels_max = 4,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700839 .rate_min = 8000,
840 .rate_max = 48000,
841 },
842 .ops = &msm_dai_q6_ops,
843 .probe = msm_dai_q6_dai_probe,
844 .remove = msm_dai_q6_dai_remove,
845};
846
847static struct snd_soc_dai_driver msm_dai_q6_i2s_tx_dai = {
848 .capture = {
849 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
850 SNDRV_PCM_RATE_16000,
851 .formats = SNDRV_PCM_FMTBIT_S16_LE,
852 .channels_min = 1,
853 .channels_max = 2,
854 .rate_min = 8000,
855 .rate_max = 48000,
856 },
857 .ops = &msm_dai_q6_ops,
858 .probe = msm_dai_q6_dai_probe,
859 .remove = msm_dai_q6_dai_remove,
860};
861
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530862static struct snd_soc_dai_driver msm_dai_q6_afe_rx_dai = {
863 .playback = {
864 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
865 SNDRV_PCM_RATE_16000,
866 .formats = SNDRV_PCM_FMTBIT_S16_LE,
867 .channels_min = 1,
868 .channels_max = 2,
869 .rate_min = 8000,
870 .rate_max = 48000,
871 },
872 .ops = &msm_dai_q6_ops,
873 .probe = msm_dai_q6_dai_probe,
874 .remove = msm_dai_q6_dai_remove,
875};
876
877static struct snd_soc_dai_driver msm_dai_q6_afe_tx_dai = {
878 .capture = {
879 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
880 SNDRV_PCM_RATE_16000,
881 .formats = SNDRV_PCM_FMTBIT_S16_LE,
882 .channels_min = 1,
883 .channels_max = 2,
884 .rate_min = 8000,
885 .rate_max = 48000,
886 },
887 .ops = &msm_dai_q6_ops,
888 .probe = msm_dai_q6_dai_probe,
889 .remove = msm_dai_q6_dai_remove,
890};
891
Helen Zeng0705a5f2011-10-14 15:29:52 -0700892static struct snd_soc_dai_driver msm_dai_q6_voice_playback_tx_dai = {
893 .playback = {
894 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
895 SNDRV_PCM_RATE_16000,
896 .formats = SNDRV_PCM_FMTBIT_S16_LE,
897 .channels_min = 1,
898 .channels_max = 2,
899 .rate_max = 48000,
900 .rate_min = 8000,
901 },
902 .ops = &msm_dai_q6_ops,
903 .probe = msm_dai_q6_dai_probe,
904 .remove = msm_dai_q6_dai_remove,
905};
906
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700907static struct snd_soc_dai_driver msm_dai_q6_slimbus_rx_dai = {
908 .playback = {
909 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
910 SNDRV_PCM_RATE_16000,
911 .formats = SNDRV_PCM_FMTBIT_S16_LE,
912 .channels_min = 1,
913 .channels_max = 2,
914 .rate_min = 8000,
915 .rate_max = 48000,
916 },
917 .ops = &msm_dai_q6_ops,
918 .probe = msm_dai_q6_dai_probe,
919 .remove = msm_dai_q6_dai_remove,
920};
921
922static struct snd_soc_dai_driver msm_dai_q6_slimbus_tx_dai = {
923 .capture = {
924 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
925 SNDRV_PCM_RATE_16000,
926 .formats = SNDRV_PCM_FMTBIT_S16_LE,
927 .channels_min = 1,
928 .channels_max = 2,
929 .rate_min = 8000,
930 .rate_max = 48000,
931 },
932 .ops = &msm_dai_q6_ops,
933 .probe = msm_dai_q6_dai_probe,
934 .remove = msm_dai_q6_dai_remove,
935};
936
Helen Zenge3d716a2011-10-14 16:32:16 -0700937static struct snd_soc_dai_driver msm_dai_q6_incall_record_dai = {
938 .capture = {
939 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
940 SNDRV_PCM_RATE_16000,
941 .formats = SNDRV_PCM_FMTBIT_S16_LE,
942 .channels_min = 1,
943 .channels_max = 2,
944 .rate_min = 8000,
945 .rate_max = 48000,
946 },
947 .ops = &msm_dai_q6_ops,
948 .probe = msm_dai_q6_dai_probe,
949 .remove = msm_dai_q6_dai_remove,
950};
951
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700952static struct snd_soc_dai_driver msm_dai_q6_bt_sco_rx_dai = {
953 .playback = {
954 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
955 .formats = SNDRV_PCM_FMTBIT_S16_LE,
956 .channels_min = 1,
957 .channels_max = 1,
958 .rate_max = 16000,
959 .rate_min = 8000,
960 },
961 .ops = &msm_dai_q6_ops,
962 .probe = msm_dai_q6_dai_probe,
963 .remove = msm_dai_q6_dai_remove,
964};
965
966static struct snd_soc_dai_driver msm_dai_q6_bt_sco_tx_dai = {
967 .playback = {
968 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
969 .formats = SNDRV_PCM_FMTBIT_S16_LE,
970 .channels_min = 1,
971 .channels_max = 1,
972 .rate_max = 16000,
973 .rate_min = 8000,
974 },
975 .ops = &msm_dai_q6_ops,
976 .probe = msm_dai_q6_dai_probe,
977 .remove = msm_dai_q6_dai_remove,
978};
979
980static struct snd_soc_dai_driver msm_dai_q6_fm_rx_dai = {
981 .playback = {
982 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
983 SNDRV_PCM_RATE_16000,
984 .formats = SNDRV_PCM_FMTBIT_S16_LE,
985 .channels_min = 2,
986 .channels_max = 2,
987 .rate_max = 48000,
988 .rate_min = 8000,
989 },
990 .ops = &msm_dai_q6_ops,
991 .probe = msm_dai_q6_dai_probe,
992 .remove = msm_dai_q6_dai_remove,
993};
994
995static struct snd_soc_dai_driver msm_dai_q6_fm_tx_dai = {
996 .playback = {
997 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
998 SNDRV_PCM_RATE_16000,
999 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1000 .channels_min = 2,
1001 .channels_max = 2,
1002 .rate_max = 48000,
1003 .rate_min = 8000,
1004 },
1005 .ops = &msm_dai_q6_ops,
1006 .probe = msm_dai_q6_dai_probe,
1007 .remove = msm_dai_q6_dai_remove,
1008};
1009
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001010static struct snd_soc_dai_driver msm_dai_q6_aux_pcm_rx_dai = {
1011 .playback = {
1012 .rates = SNDRV_PCM_RATE_8000,
1013 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1014 .channels_min = 1,
1015 .channels_max = 1,
1016 .rate_max = 8000,
1017 .rate_min = 8000,
1018 },
1019 .ops = &msm_dai_q6_auxpcm_ops,
1020 .probe = msm_dai_q6_dai_auxpcm_probe,
1021 .remove = msm_dai_q6_dai_auxpcm_remove,
1022};
1023
1024static struct snd_soc_dai_driver msm_dai_q6_aux_pcm_tx_dai = {
1025 .capture = {
1026 .rates = SNDRV_PCM_RATE_8000,
1027 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1028 .channels_min = 1,
1029 .channels_max = 1,
1030 .rate_max = 8000,
1031 .rate_min = 8000,
1032 },
1033};
1034
Kuirong Wang274f21a2011-12-15 21:29:08 -08001035static struct snd_soc_dai_driver msm_dai_q6_mi2s_rx_dai = {
1036 .playback = {
1037 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1038 SNDRV_PCM_RATE_16000,
1039 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1040 .channels_min = 1,
1041 .rate_min = 8000,
1042 .rate_max = 48000,
1043 },
1044 .ops = &msm_dai_q6_ops,
1045 .probe = msm_dai_q6_dai_mi2s_probe,
1046 .remove = msm_dai_q6_dai_probe,
1047};
1048
Neema Shetty3c9d2862012-03-11 01:25:32 -08001049static struct snd_soc_dai_driver msm_dai_q6_slimbus_1_rx_dai = {
1050 .playback = {
1051 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
1052 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1053 .channels_min = 1,
1054 .channels_max = 1,
1055 .rate_min = 8000,
1056 .rate_max = 16000,
1057 },
1058 .ops = &msm_dai_q6_ops,
1059 .probe = msm_dai_q6_dai_probe,
1060 .remove = msm_dai_q6_dai_remove,
1061};
1062
1063static struct snd_soc_dai_driver msm_dai_q6_slimbus_1_tx_dai = {
1064 .capture = {
1065 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
1066 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1067 .channels_min = 1,
1068 .channels_max = 1,
1069 .rate_min = 8000,
1070 .rate_max = 16000,
1071 },
1072 .ops = &msm_dai_q6_ops,
1073 .probe = msm_dai_q6_dai_probe,
1074 .remove = msm_dai_q6_dai_remove,
1075};
1076
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001077/* To do: change to register DAIs as batch */
1078static __devinit int msm_dai_q6_dev_probe(struct platform_device *pdev)
1079{
1080 int rc = 0;
1081
1082 dev_dbg(&pdev->dev, "dev name %s\n", dev_name(&pdev->dev));
1083
1084 switch (pdev->id) {
1085 case PRIMARY_I2S_RX:
Kuirong Wang9bbf6132012-01-10 18:28:49 -08001086 case SECONDARY_I2S_RX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001087 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_i2s_rx_dai);
1088 break;
1089 case PRIMARY_I2S_TX:
1090 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_i2s_tx_dai);
1091 break;
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001092 case PCM_RX:
1093 rc = snd_soc_register_dai(&pdev->dev,
1094 &msm_dai_q6_aux_pcm_rx_dai);
1095 break;
1096 case PCM_TX:
1097 rc = snd_soc_register_dai(&pdev->dev,
1098 &msm_dai_q6_aux_pcm_tx_dai);
1099 break;
Kuirong Wang274f21a2011-12-15 21:29:08 -08001100 case MI2S_RX:
1101 rc = snd_soc_register_dai(&pdev->dev,
1102 &msm_dai_q6_mi2s_rx_dai);
1103 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001104 case SLIMBUS_0_RX:
1105 rc = snd_soc_register_dai(&pdev->dev,
1106 &msm_dai_q6_slimbus_rx_dai);
1107 break;
1108 case SLIMBUS_0_TX:
1109 rc = snd_soc_register_dai(&pdev->dev,
1110 &msm_dai_q6_slimbus_tx_dai);
Neema Shetty3c9d2862012-03-11 01:25:32 -08001111 break;
1112
1113 case SLIMBUS_1_RX:
1114 rc = snd_soc_register_dai(&pdev->dev,
1115 &msm_dai_q6_slimbus_1_rx_dai);
1116 break;
1117 case SLIMBUS_1_TX:
1118 rc = snd_soc_register_dai(&pdev->dev,
1119 &msm_dai_q6_slimbus_1_tx_dai);
1120 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001121 case INT_BT_SCO_RX:
1122 rc = snd_soc_register_dai(&pdev->dev,
1123 &msm_dai_q6_bt_sco_rx_dai);
1124 break;
1125 case INT_BT_SCO_TX:
1126 rc = snd_soc_register_dai(&pdev->dev,
1127 &msm_dai_q6_bt_sco_tx_dai);
1128 break;
1129 case INT_FM_RX:
1130 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_fm_rx_dai);
1131 break;
1132 case INT_FM_TX:
1133 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_fm_tx_dai);
1134 break;
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301135 case RT_PROXY_DAI_001_RX:
1136 case RT_PROXY_DAI_002_RX:
1137 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_afe_rx_dai);
1138 break;
1139 case RT_PROXY_DAI_001_TX:
1140 case RT_PROXY_DAI_002_TX:
1141 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_afe_tx_dai);
1142 break;
Helen Zeng0705a5f2011-10-14 15:29:52 -07001143 case VOICE_PLAYBACK_TX:
1144 rc = snd_soc_register_dai(&pdev->dev,
1145 &msm_dai_q6_voice_playback_tx_dai);
1146 break;
Helen Zenge3d716a2011-10-14 16:32:16 -07001147 case VOICE_RECORD_RX:
1148 case VOICE_RECORD_TX:
1149 rc = snd_soc_register_dai(&pdev->dev,
1150 &msm_dai_q6_incall_record_dai);
1151 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001152 default:
1153 rc = -ENODEV;
1154 break;
1155 }
1156 return rc;
1157}
1158
1159static __devexit int msm_dai_q6_dev_remove(struct platform_device *pdev)
1160{
1161 snd_soc_unregister_dai(&pdev->dev);
1162 return 0;
1163}
1164
1165static struct platform_driver msm_dai_q6_driver = {
1166 .probe = msm_dai_q6_dev_probe,
1167 .remove = msm_dai_q6_dev_remove,
1168 .driver = {
1169 .name = "msm-dai-q6",
1170 .owner = THIS_MODULE,
1171 },
1172};
1173
1174static int __init msm_dai_q6_init(void)
1175{
1176 return platform_driver_register(&msm_dai_q6_driver);
1177}
1178module_init(msm_dai_q6_init);
1179
1180static void __exit msm_dai_q6_exit(void)
1181{
1182 platform_driver_unregister(&msm_dai_q6_driver);
1183}
1184module_exit(msm_dai_q6_exit);
1185
1186/* Module information */
1187MODULE_DESCRIPTION("MSM DSP DAI driver");
1188MODULE_LICENSE("GPL v2");