blob: 147316ec17500a6d4c3867bd69d3adebfb89781e [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>
Asish Bhattacharyab3568cf2012-03-15 07:05:46 +053027#include <sound/pcm_params.h>
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -070028#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;
Patrick Lai04baee942012-05-01 14:38:47 -070039 u32 bitwidth;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070040 union afe_port_config port_config;
41};
42
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -070043struct msm_dai_q6_mi2s_dai_config {
44 u16 pdata_mi2s_lines;
45 struct msm_dai_q6_dai_data mi2s_dai_data;
46};
47
Patrick Lai04baee942012-05-01 14:38:47 -070048struct msm_dai_q6_mi2s_dai_data {
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -070049 struct msm_dai_q6_mi2s_dai_config tx_dai;
50 struct msm_dai_q6_mi2s_dai_config rx_dai;
Patrick Lai04baee942012-05-01 14:38:47 -070051 struct snd_pcm_hw_constraint_list rate_constraint;
52 struct snd_pcm_hw_constraint_list bitwidth_constraint;
53};
54
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -070055static struct clk *pcm_clk;
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -070056static struct clk *sec_pcm_clk;
Kiran Kandi5f4ab692012-02-23 11:23:56 -080057static DEFINE_MUTEX(aux_pcm_mutex);
58static int aux_pcm_count;
59static struct msm_dai_auxpcm_pdata *auxpcm_plat_data;
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -070060static struct msm_dai_auxpcm_pdata *sec_auxpcm_plat_data;
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -070061
Kuirong Wang875d1ec2012-04-02 19:56:25 -070062static int msm_dai_q6_mi2s_format_put(struct snd_kcontrol *kcontrol,
63 struct snd_ctl_elem_value *ucontrol)
64{
65
66 struct msm_dai_q6_dai_data *dai_data = kcontrol->private_data;
67 int value = ucontrol->value.integer.value[0];
68 dai_data->port_config.mi2s.format = value;
69 pr_debug("%s: value = %d, channel = %d, line = %d\n",
70 __func__, value, dai_data->port_config.mi2s.channel,
71 dai_data->port_config.mi2s.line);
72 return 0;
73}
74
75static int msm_dai_q6_mi2s_format_get(struct snd_kcontrol *kcontrol,
76 struct snd_ctl_elem_value *ucontrol)
77{
78
79 struct msm_dai_q6_dai_data *dai_data = kcontrol->private_data;
80 ucontrol->value.integer.value[0] = dai_data->port_config.mi2s.format ;
81 return 0;
82}
83
84
85/* MI2S format field for AFE_PORT_CMD_I2S_CONFIG command
86 * 0: linear PCM
87 * 1: non-linear PCM
88 * 2: PCM data in IEC 60968 container
89 * 3: compressed data in IEC 60958 container
90 */
91static const char *mi2s_format[] = {
92 "LPCM",
93 "Compr",
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -070094 "LPCM-60958",
95 "Compr-60958"};
Kuirong Wang875d1ec2012-04-02 19:56:25 -070096
97static const struct soc_enum mi2s_config_enum[] = {
98 SOC_ENUM_SINGLE_EXT(4, mi2s_format),
99};
100
101static const struct snd_kcontrol_new mi2s_config_controls[] = {
102 SOC_ENUM_EXT("MI2S RX Format", mi2s_config_enum[0],
103 msm_dai_q6_mi2s_format_get,
104 msm_dai_q6_mi2s_format_put),
105 SOC_ENUM_EXT("SEC RX Format", mi2s_config_enum[0],
106 msm_dai_q6_mi2s_format_get,
107 msm_dai_q6_mi2s_format_put),
Kuirong Wang623b50f2012-04-16 15:51:14 -0700108 SOC_ENUM_EXT("MI2S TX Format", mi2s_config_enum[0],
109 msm_dai_q6_mi2s_format_get,
110 msm_dai_q6_mi2s_format_put),
Kuirong Wang875d1ec2012-04-02 19:56:25 -0700111};
112
Kuirong Wang274f21a2011-12-15 21:29:08 -0800113static u8 num_of_bits_set(u8 sd_line_mask)
114{
115 u8 num_bits_set = 0;
116
117 while (sd_line_mask) {
118 num_bits_set++;
119 sd_line_mask = sd_line_mask & (sd_line_mask - 1);
120 }
121 return num_bits_set;
122}
123
Patrick Lai04baee942012-05-01 14:38:47 -0700124static int msm_dai_q6_mi2s_startup(struct snd_pcm_substream *substream,
125 struct snd_soc_dai *dai)
126{
127 struct msm_dai_q6_mi2s_dai_data *mi2s_dai_data =
128 dev_get_drvdata(dai->dev);
129
130 dev_dbg(dai->dev, "%s: cnst list %p\n", __func__,
131 mi2s_dai_data->rate_constraint.list);
132
133 if (mi2s_dai_data->rate_constraint.list) {
134 snd_pcm_hw_constraint_list(substream->runtime, 0,
135 SNDRV_PCM_HW_PARAM_RATE,
136 &mi2s_dai_data->rate_constraint);
137 snd_pcm_hw_constraint_list(substream->runtime, 0,
138 SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
139 &mi2s_dai_data->bitwidth_constraint);
140 }
141
142 return 0;
143}
144
145static int msm_dai_q6_mi2s_hw_params(struct snd_pcm_substream *substream,
146 struct snd_pcm_hw_params *params,
147 struct snd_soc_dai *dai)
148{
149 struct msm_dai_q6_mi2s_dai_data *mi2s_dai_data =
150 dev_get_drvdata(dai->dev);
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -0700151 struct msm_dai_q6_mi2s_dai_config *mi2s_dai_config =
Patrick Lai04baee942012-05-01 14:38:47 -0700152 (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
153 &mi2s_dai_data->rx_dai : &mi2s_dai_data->tx_dai);
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -0700154 struct msm_dai_q6_dai_data *dai_data = &mi2s_dai_config->mi2s_dai_data;
Patrick Lai04baee942012-05-01 14:38:47 -0700155
156 dai_data->channels = params_channels(params);
157 switch (dai_data->channels) {
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -0700158 case 8:
159 case 7:
160 if (mi2s_dai_config->pdata_mi2s_lines < AFE_I2S_8CHS)
161 goto error_invalid_data;
162 dai_data->port_config.mi2s.line = AFE_I2S_8CHS;
Patrick Lai04baee942012-05-01 14:38:47 -0700163 break;
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -0700164 case 6:
165 case 5:
166 if (mi2s_dai_config->pdata_mi2s_lines < AFE_I2S_6CHS)
167 goto error_invalid_data;
168 dai_data->port_config.mi2s.line = AFE_I2S_6CHS;
169 break;
170 case 4:
171 case 3:
172 if (mi2s_dai_config->pdata_mi2s_lines < AFE_I2S_QUAD01)
173 goto error_invalid_data;
174 if (mi2s_dai_config->pdata_mi2s_lines == AFE_I2S_QUAD23)
175 dai_data->port_config.mi2s.line =
176 mi2s_dai_config->pdata_mi2s_lines;
177 else
178 dai_data->port_config.mi2s.line = AFE_I2S_QUAD01;
179 break;
180 case 2:
Patrick Lai04baee942012-05-01 14:38:47 -0700181 case 1:
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -0700182 if (mi2s_dai_config->pdata_mi2s_lines < AFE_I2S_SD0)
183 goto error_invalid_data;
184 switch (mi2s_dai_config->pdata_mi2s_lines) {
185 case AFE_I2S_SD0:
186 case AFE_I2S_SD1:
187 case AFE_I2S_SD2:
188 case AFE_I2S_SD3:
189 dai_data->port_config.mi2s.line =
190 mi2s_dai_config->pdata_mi2s_lines;
191 break;
192 case AFE_I2S_QUAD01:
193 case AFE_I2S_6CHS:
194 case AFE_I2S_8CHS:
195 dai_data->port_config.mi2s.line = AFE_I2S_SD0;
196 break;
197 case AFE_I2S_QUAD23:
198 dai_data->port_config.mi2s.line = AFE_I2S_SD2;
199 break;
200 }
201 if (dai_data->channels == 2)
202 dai_data->port_config.mi2s.channel = MSM_AFE_STEREO;
203 else
204 dai_data->port_config.mi2s.channel = MSM_AFE_MONO;
Patrick Lai04baee942012-05-01 14:38:47 -0700205 break;
206 default:
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -0700207 goto error_invalid_data;
Patrick Lai04baee942012-05-01 14:38:47 -0700208 }
209 dai_data->rate = params_rate(params);
210 dai_data->port_config.mi2s.bitwidth = 16;
211 dai_data->bitwidth = 16;
212 if (!mi2s_dai_data->rate_constraint.list) {
213 mi2s_dai_data->rate_constraint.list = &dai_data->rate;
214 mi2s_dai_data->bitwidth_constraint.list = &dai_data->bitwidth;
215 }
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -0700216
217 pr_debug("%s: dai_data->channels = %d, line = %d\n", __func__,
218 dai_data->channels, dai_data->port_config.mi2s.line);
Patrick Lai04baee942012-05-01 14:38:47 -0700219 return 0;
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -0700220error_invalid_data:
221 pr_err("%s: dai_data->channels = %d, line = %d\n", __func__,
222 dai_data->channels, dai_data->port_config.mi2s.line);
223 return -EINVAL;
Patrick Lai04baee942012-05-01 14:38:47 -0700224}
225
226static int msm_dai_q6_mi2s_get_lineconfig(u16 sd_lines, u16 *config_ptr,
227 unsigned int *ch_cnt)
228{
229 u8 num_of_sd_lines;
230
231 num_of_sd_lines = num_of_bits_set(sd_lines);
232
233 switch (num_of_sd_lines) {
234 case 0:
235 pr_debug("%s: no line is assigned\n", __func__);
236 break;
237 case 1:
238 switch (sd_lines) {
239 case MSM_MI2S_SD0:
240 *config_ptr = AFE_I2S_SD0;
241 break;
242 case MSM_MI2S_SD1:
243 *config_ptr = AFE_I2S_SD1;
244 break;
245 case MSM_MI2S_SD2:
246 *config_ptr = AFE_I2S_SD2;
247 break;
248 case MSM_MI2S_SD3:
249 *config_ptr = AFE_I2S_SD3;
250 break;
251 default:
252 pr_err("%s: invalid SD line\n",
253 __func__);
254 goto error_invalid_data;
255 }
256 break;
257 case 2:
258 switch (sd_lines) {
259 case MSM_MI2S_SD0 | MSM_MI2S_SD1:
260 *config_ptr = AFE_I2S_QUAD01;
261 break;
262 case MSM_MI2S_SD2 | MSM_MI2S_SD3:
263 *config_ptr = AFE_I2S_QUAD23;
264 break;
265 default:
266 pr_err("%s: invalid SD line\n",
267 __func__);
268 goto error_invalid_data;
269 }
270 break;
271 case 3:
272 switch (sd_lines) {
273 case MSM_MI2S_SD0 | MSM_MI2S_SD1 | MSM_MI2S_SD2:
274 *config_ptr = AFE_I2S_6CHS;
275 break;
276 default:
277 pr_err("%s: invalid SD lines\n",
278 __func__);
279 goto error_invalid_data;
280 }
281 break;
282 case 4:
283 switch (sd_lines) {
284 case MSM_MI2S_SD0 | MSM_MI2S_SD1 | MSM_MI2S_SD2 | MSM_MI2S_SD3:
285 *config_ptr = AFE_I2S_8CHS;
286 break;
287 default:
288 pr_err("%s: invalid SD lines\n",
289 __func__);
290 goto error_invalid_data;
291 }
292 break;
293 default:
294 pr_err("%s: invalid SD lines\n", __func__);
295 goto error_invalid_data;
296 }
297
298 *ch_cnt = num_of_sd_lines;
299
300 return 0;
301
302error_invalid_data:
303 return -EINVAL;
304}
305
306static int msm_dai_q6_mi2s_platform_data_validation(
307 struct platform_device *pdev, struct snd_soc_dai_driver *dai_driver)
308{
309 struct msm_dai_q6_mi2s_dai_data *dai_data = dev_get_drvdata(&pdev->dev);
310 struct msm_mi2s_pdata *mi2s_pdata =
311 (struct msm_mi2s_pdata *) pdev->dev.platform_data;
312 u16 sdline_config;
313 unsigned int ch_cnt;
314 int rc = 0;
315
316 if ((mi2s_pdata->rx_sd_lines & mi2s_pdata->tx_sd_lines) ||
317 (!mi2s_pdata->rx_sd_lines && !mi2s_pdata->tx_sd_lines)) {
318 dev_err(&pdev->dev,
319 "error sd line conflict or no line assigned\n");
320 rc = -EINVAL;
321 goto rtn;
322 }
323
324 rc = msm_dai_q6_mi2s_get_lineconfig(mi2s_pdata->rx_sd_lines,
325 &sdline_config, &ch_cnt);
326
327 if (IS_ERR_VALUE(rc)) {
328 dev_err(&pdev->dev, "invalid MI2S RX sd line config\n");
329 goto rtn;
330 }
331
332 if (ch_cnt) {
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -0700333 dai_data->rx_dai.mi2s_dai_data.port_config.mi2s.line =
334 sdline_config;
335 dai_data->rx_dai.pdata_mi2s_lines = sdline_config;
Patrick Lai04baee942012-05-01 14:38:47 -0700336 dai_driver->playback.channels_min = 1;
337 dai_driver->playback.channels_max = ch_cnt << 1;
338 } else {
339 dai_driver->playback.channels_min = 0;
340 dai_driver->playback.channels_max = 0;
341 }
342 rc = msm_dai_q6_mi2s_get_lineconfig(mi2s_pdata->tx_sd_lines,
343 &sdline_config, &ch_cnt);
344
345 if (IS_ERR_VALUE(rc)) {
346 dev_err(&pdev->dev, "invalid MI2S TX sd line config\n");
347 goto rtn;
348 }
349
350 if (ch_cnt) {
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -0700351 dai_data->tx_dai.mi2s_dai_data.port_config.mi2s.line =
352 sdline_config;
353 dai_data->tx_dai.pdata_mi2s_lines = sdline_config;
Patrick Lai04baee942012-05-01 14:38:47 -0700354 dai_driver->capture.channels_min = 1;
355 dai_driver->capture.channels_max = ch_cnt << 1;
356 } else {
357 dai_driver->capture.channels_min = 0;
358 dai_driver->capture.channels_max = 0;
359 }
360
361 dev_info(&pdev->dev, "%s: playback sdline %x capture sdline %x\n",
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -0700362 __func__, dai_data->rx_dai.pdata_mi2s_lines,
363 dai_data->tx_dai.pdata_mi2s_lines);
Patrick Lai04baee942012-05-01 14:38:47 -0700364 dev_info(&pdev->dev, "%s: playback ch_max %d capture ch_mx %d\n",
365 __func__, dai_driver->playback.channels_max,
366 dai_driver->capture.channels_max);
367rtn:
368 return rc;
369}
370
371static int msm_dai_q6_mi2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
372{
373 struct msm_dai_q6_mi2s_dai_data *mi2s_dai_data =
374 dev_get_drvdata(dai->dev);
375
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -0700376 if (test_bit(STATUS_PORT_STARTED,
377 mi2s_dai_data->rx_dai.mi2s_dai_data.status_mask) ||
378 test_bit(STATUS_PORT_STARTED,
379 mi2s_dai_data->tx_dai.mi2s_dai_data.status_mask)) {
Patrick Lai04baee942012-05-01 14:38:47 -0700380 dev_err(dai->dev, "%s: err chg i2s mode while dai running",
381 __func__);
382 return -EPERM;
383 }
384
385 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
386 case SND_SOC_DAIFMT_CBS_CFS:
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -0700387 mi2s_dai_data->rx_dai.mi2s_dai_data.port_config.mi2s.ws = 1;
388 mi2s_dai_data->tx_dai.mi2s_dai_data.port_config.mi2s.ws = 1;
Patrick Lai04baee942012-05-01 14:38:47 -0700389 break;
390 case SND_SOC_DAIFMT_CBM_CFM:
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -0700391 mi2s_dai_data->rx_dai.mi2s_dai_data.port_config.mi2s.ws = 0;
392 mi2s_dai_data->tx_dai.mi2s_dai_data.port_config.mi2s.ws = 0;
Patrick Lai04baee942012-05-01 14:38:47 -0700393 break;
394 default:
395 return -EINVAL;
396 }
397
398 return 0;
399}
400
401static int msm_dai_q6_mi2s_prepare(struct snd_pcm_substream *substream,
402 struct snd_soc_dai *dai)
403{
404 struct msm_dai_q6_mi2s_dai_data *mi2s_dai_data =
405 dev_get_drvdata(dai->dev);
406 struct msm_dai_q6_dai_data *dai_data =
407 (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -0700408 &mi2s_dai_data->rx_dai.mi2s_dai_data :
409 &mi2s_dai_data->tx_dai.mi2s_dai_data);
Patrick Lai04baee942012-05-01 14:38:47 -0700410 int rc = 0;
411
412 if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
413 /* PORT START should be set if prepare called in active state */
414 rc = afe_q6_interface_prepare();
415 if (IS_ERR_VALUE(rc))
416 dev_err(dai->dev, "fail to open AFE APR\n");
417 }
418 return rc;
419}
420
421static int msm_dai_q6_mi2s_trigger(struct snd_pcm_substream *substream, int cmd,
422 struct snd_soc_dai *dai)
423{
424 struct msm_dai_q6_mi2s_dai_data *mi2s_dai_data =
425 dev_get_drvdata(dai->dev);
426 struct msm_dai_q6_dai_data *dai_data =
427 (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -0700428 &mi2s_dai_data->rx_dai.mi2s_dai_data :
429 &mi2s_dai_data->tx_dai.mi2s_dai_data);
Patrick Lai04baee942012-05-01 14:38:47 -0700430 u16 port_id = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
431 MI2S_RX : MI2S_TX);
432 int rc = 0;
433
434 dev_dbg(dai->dev, "%s: cmd:%d dai_data->status_mask = %ld",
435 __func__, cmd, *dai_data->status_mask);
436 switch (cmd) {
437 case SNDRV_PCM_TRIGGER_START:
438 case SNDRV_PCM_TRIGGER_RESUME:
439 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
440 if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
441 afe_port_start_nowait(port_id,
442 &dai_data->port_config, dai_data->rate);
443 set_bit(STATUS_PORT_STARTED,
444 dai_data->status_mask);
445 }
446 break;
447 case SNDRV_PCM_TRIGGER_STOP:
448 case SNDRV_PCM_TRIGGER_SUSPEND:
449 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
450 if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
451 afe_port_stop_nowait(port_id);
452 clear_bit(STATUS_PORT_STARTED,
453 dai_data->status_mask);
454 }
455 break;
456
457 default:
458 rc = -EINVAL;
459 }
460
461 return rc;
462}
463
464static void msm_dai_q6_mi2s_shutdown(struct snd_pcm_substream *substream,
465 struct snd_soc_dai *dai)
466{
467 struct msm_dai_q6_mi2s_dai_data *mi2s_dai_data =
468 dev_get_drvdata(dai->dev);
469 struct msm_dai_q6_dai_data *dai_data =
470 (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -0700471 &mi2s_dai_data->rx_dai.mi2s_dai_data :
472 &mi2s_dai_data->tx_dai.mi2s_dai_data);
Patrick Lai04baee942012-05-01 14:38:47 -0700473 u16 port_id = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
474 MI2S_RX : MI2S_TX);
475 int rc = 0;
476
477 if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
478 rc = afe_close(port_id);
479 if (IS_ERR_VALUE(rc))
480 dev_err(dai->dev, "fail to close AFE port\n");
481 clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
482 }
483
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -0700484 if (!test_bit(STATUS_PORT_STARTED,
485 mi2s_dai_data->rx_dai.mi2s_dai_data.status_mask) &&
486 !test_bit(STATUS_PORT_STARTED,
487 mi2s_dai_data->rx_dai.mi2s_dai_data.status_mask)) {
Patrick Lai04baee942012-05-01 14:38:47 -0700488 mi2s_dai_data->rate_constraint.list = NULL;
489 mi2s_dai_data->bitwidth_constraint.list = NULL;
490 }
491
492}
493
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700494static int msm_dai_q6_cdc_hw_params(struct snd_pcm_hw_params *params,
495 struct snd_soc_dai *dai, int stream)
496{
497 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
498
499 dai_data->channels = params_channels(params);
500 switch (dai_data->channels) {
501 case 2:
502 dai_data->port_config.mi2s.channel = MSM_AFE_STEREO;
503 break;
504 case 1:
505 dai_data->port_config.mi2s.channel = MSM_AFE_MONO;
506 break;
507 default:
508 return -EINVAL;
509 break;
510 }
511 dai_data->rate = params_rate(params);
512
513 dev_dbg(dai->dev, " channel %d sample rate %d entered\n",
514 dai_data->channels, dai_data->rate);
515
516 /* Q6 only supports 16 as now */
517 dai_data->port_config.mi2s.bitwidth = 16;
518 dai_data->port_config.mi2s.line = 1;
Kuirong Wang274f21a2011-12-15 21:29:08 -0800519 return 0;
520}
521
Lei Zhou157c1842011-08-19 13:05:04 -0400522static int msm_dai_q6_cdc_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
523{
524 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
525
526 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
527 case SND_SOC_DAIFMT_CBS_CFS:
528 dai_data->port_config.mi2s.ws = 1; /* CPU is master */
529 break;
530 case SND_SOC_DAIFMT_CBM_CFM:
531 dai_data->port_config.mi2s.ws = 0; /* CPU is slave */
532 break;
533 default:
534 return -EINVAL;
535 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700536
537 return 0;
538}
539
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700540
541static int msm_dai_q6_slim_bus_hw_params(struct snd_pcm_hw_params *params,
542 struct snd_soc_dai *dai, int stream)
543{
544 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700545
546 dai_data->channels = params_channels(params);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700547 dai_data->rate = params_rate(params);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700548
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700549 /* Q6 only supports 16 as now */
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800550 dai_data->port_config.slim_sch.bit_width = 16;
551 dai_data->port_config.slim_sch.data_format = 0;
552 dai_data->port_config.slim_sch.num_channels = dai_data->channels;
553 dai_data->port_config.slim_sch.reserved = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700554
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800555 dev_dbg(dai->dev, "%s:slimbus_dev_id[%hu] bit_wd[%hu] format[%hu]\n"
556 "num_channel %hu slave_ch_mapping[0] %hu\n"
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700557 "slave_port_mapping[1] %hu slave_port_mapping[2] %hu\n"
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700558 "slave_port_mapping[3] %hu\n sample_rate %d\n", __func__,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800559 dai_data->port_config.slim_sch.slimbus_dev_id,
560 dai_data->port_config.slim_sch.bit_width,
561 dai_data->port_config.slim_sch.data_format,
562 dai_data->port_config.slim_sch.num_channels,
563 dai_data->port_config.slim_sch.slave_ch_mapping[0],
564 dai_data->port_config.slim_sch.slave_ch_mapping[1],
565 dai_data->port_config.slim_sch.slave_ch_mapping[2],
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700566 dai_data->port_config.slim_sch.slave_ch_mapping[3],
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700567 dai_data->rate);
568
569 return 0;
570}
571
572static int msm_dai_q6_bt_fm_hw_params(struct snd_pcm_hw_params *params,
573 struct snd_soc_dai *dai, int stream)
574{
575 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
576
577 dai_data->channels = params_channels(params);
578 dai_data->rate = params_rate(params);
579
580 dev_dbg(dai->dev, "channels %d sample rate %d entered\n",
581 dai_data->channels, dai_data->rate);
582
583 memset(&dai_data->port_config, 0, sizeof(dai_data->port_config));
584
585 return 0;
586}
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700587static int msm_dai_q6_auxpcm_hw_params(
588 struct snd_pcm_substream *substream,
589 struct snd_pcm_hw_params *params,
590 struct snd_soc_dai *dai)
591{
592 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
593 struct msm_dai_auxpcm_pdata *auxpcm_pdata =
594 (struct msm_dai_auxpcm_pdata *) dai->dev->platform_data;
595
596 if (params_channels(params) != 1) {
597 dev_err(dai->dev, "AUX PCM supports only mono stream\n");
598 return -EINVAL;
599 }
600 dai_data->channels = params_channels(params);
601
Kuirong Wang547a9982012-05-04 18:29:11 -0700602 dai_data->rate = params_rate(params);
603 switch (dai_data->rate) {
604 case 8000:
605 dai_data->port_config.pcm.mode = auxpcm_pdata->mode_8k.mode;
606 dai_data->port_config.pcm.sync = auxpcm_pdata->mode_8k.sync;
607 dai_data->port_config.pcm.frame = auxpcm_pdata->mode_8k.frame;
608 dai_data->port_config.pcm.quant = auxpcm_pdata->mode_8k.quant;
609 dai_data->port_config.pcm.slot = auxpcm_pdata->mode_8k.slot;
610 dai_data->port_config.pcm.data = auxpcm_pdata->mode_8k.data;
611 break;
612 case 16000:
613 dai_data->port_config.pcm.mode = auxpcm_pdata->mode_16k.mode;
614 dai_data->port_config.pcm.sync = auxpcm_pdata->mode_16k.sync;
615 dai_data->port_config.pcm.frame = auxpcm_pdata->mode_16k.frame;
616 dai_data->port_config.pcm.quant = auxpcm_pdata->mode_16k.quant;
617 dai_data->port_config.pcm.slot = auxpcm_pdata->mode_16k.slot;
618 dai_data->port_config.pcm.data = auxpcm_pdata->mode_16k.data;
619 break;
620 default:
621 dev_err(dai->dev, "AUX PCM supports only 8kHz and 16kHz sampling rate\n");
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700622 return -EINVAL;
623 }
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700624
625 return 0;
626}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700627
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -0700628static int msm_dai_q6_sec_auxpcm_hw_params(
629 struct snd_pcm_substream *substream,
630 struct snd_pcm_hw_params *params,
631 struct snd_soc_dai *dai)
632{
633 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
634 struct msm_dai_auxpcm_pdata *auxpcm_pdata =
635 (struct msm_dai_auxpcm_pdata *) dai->dev->platform_data;
636
637 pr_debug("%s\n", __func__);
638 if (params_channels(params) != 1) {
639 dev_err(dai->dev, "SEC AUX PCM supports only mono stream\n");
640 return -EINVAL;
641 }
642 dai_data->channels = params_channels(params);
643
644 dai_data->rate = params_rate(params);
645 switch (dai_data->rate) {
646 case 8000:
647 dai_data->port_config.pcm.mode = auxpcm_pdata->mode_8k.mode;
648 dai_data->port_config.pcm.sync = auxpcm_pdata->mode_8k.sync;
649 dai_data->port_config.pcm.frame = auxpcm_pdata->mode_8k.frame;
650 dai_data->port_config.pcm.quant = auxpcm_pdata->mode_8k.quant;
651 dai_data->port_config.pcm.slot = auxpcm_pdata->mode_8k.slot;
652 dai_data->port_config.pcm.data = auxpcm_pdata->mode_8k.data;
653 break;
654 case 16000:
655 dai_data->port_config.pcm.mode = auxpcm_pdata->mode_16k.mode;
656 dai_data->port_config.pcm.sync = auxpcm_pdata->mode_16k.sync;
657 dai_data->port_config.pcm.frame = auxpcm_pdata->mode_16k.frame;
658 dai_data->port_config.pcm.quant = auxpcm_pdata->mode_16k.quant;
659 dai_data->port_config.pcm.slot = auxpcm_pdata->mode_16k.slot;
660 dai_data->port_config.pcm.data = auxpcm_pdata->mode_16k.data;
661 break;
662 default:
663 dev_err(dai->dev, "AUX PCM supports only 8kHz and 16kHz sampling rate\n");
664 return -EINVAL;
665 }
666
667 return 0;
668}
669
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530670static int msm_dai_q6_afe_rtproxy_hw_params(struct snd_pcm_hw_params *params,
671 struct snd_soc_dai *dai)
672{
673 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
674
675 dai_data->rate = params_rate(params);
676 dai_data->port_config.rtproxy.num_ch =
677 params_channels(params);
678
679 pr_debug("channel %d entered,dai_id: %d,rate: %d\n",
680 dai_data->port_config.rtproxy.num_ch, dai->id, dai_data->rate);
681
682 dai_data->port_config.rtproxy.bitwidth = 16; /* Q6 only supports 16 */
683 dai_data->port_config.rtproxy.interleaved = 1;
Asish Bhattacharyab3568cf2012-03-15 07:05:46 +0530684 dai_data->port_config.rtproxy.frame_sz = params_period_bytes(params);
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530685 dai_data->port_config.rtproxy.jitter =
686 dai_data->port_config.rtproxy.frame_sz/2;
687 dai_data->port_config.rtproxy.lw_mark = 0;
688 dai_data->port_config.rtproxy.hw_mark = 0;
689 dai_data->port_config.rtproxy.rsvd = 0;
690
691 return 0;
692}
693
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700694/* Current implementation assumes hw_param is called once
695 * This may not be the case but what to do when ADM and AFE
696 * port are already opened and parameter changes
697 */
698static int msm_dai_q6_hw_params(struct snd_pcm_substream *substream,
699 struct snd_pcm_hw_params *params,
700 struct snd_soc_dai *dai)
701{
702 int rc = 0;
703
704 switch (dai->id) {
705 case PRIMARY_I2S_TX:
706 case PRIMARY_I2S_RX:
Kuirong Wang9bbf6132012-01-10 18:28:49 -0800707 case SECONDARY_I2S_RX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700708 rc = msm_dai_q6_cdc_hw_params(params, dai, substream->stream);
709 break;
Patrick Lai04baee942012-05-01 14:38:47 -0700710
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700711 case SLIMBUS_0_RX:
Neema Shetty3c9d2862012-03-11 01:25:32 -0800712 case SLIMBUS_1_RX:
Neema Shetty74131ac2012-05-09 13:35:26 -0700713 case SLIMBUS_3_RX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700714 case SLIMBUS_0_TX:
Neema Shetty3c9d2862012-03-11 01:25:32 -0800715 case SLIMBUS_1_TX:
Kiran Kandifd30c892012-05-21 23:03:26 -0700716 case SLIMBUS_2_RX:
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700717 case SLIMBUS_2_TX:
Helen Zeng38c3c962012-05-17 14:56:20 -0700718 case SLIMBUS_3_TX:
Helen Zeng8f925502012-03-05 16:50:17 -0800719 case SLIMBUS_4_RX:
720 case SLIMBUS_4_TX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700721 rc = msm_dai_q6_slim_bus_hw_params(params, dai,
722 substream->stream);
723 break;
724 case INT_BT_SCO_RX:
725 case INT_BT_SCO_TX:
726 case INT_FM_RX:
727 case INT_FM_TX:
728 rc = msm_dai_q6_bt_fm_hw_params(params, dai, substream->stream);
729 break;
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530730 case RT_PROXY_DAI_001_TX:
731 case RT_PROXY_DAI_001_RX:
732 case RT_PROXY_DAI_002_TX:
733 case RT_PROXY_DAI_002_RX:
734 rc = msm_dai_q6_afe_rtproxy_hw_params(params, dai);
735 break;
Helen Zeng0705a5f2011-10-14 15:29:52 -0700736 case VOICE_PLAYBACK_TX:
Helen Zenge3d716a2011-10-14 16:32:16 -0700737 case VOICE_RECORD_RX:
738 case VOICE_RECORD_TX:
Helen Zeng0705a5f2011-10-14 15:29:52 -0700739 rc = 0;
740 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700741 default:
742 dev_err(dai->dev, "invalid AFE port ID\n");
743 rc = -EINVAL;
744 break;
745 }
746
747 return rc;
748}
749
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700750static void msm_dai_q6_auxpcm_shutdown(struct snd_pcm_substream *substream,
751 struct snd_soc_dai *dai)
752{
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700753 int rc = 0;
754
Kiran Kandi5f4ab692012-02-23 11:23:56 -0800755 mutex_lock(&aux_pcm_mutex);
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700756
Kiran Kandi5f4ab692012-02-23 11:23:56 -0800757 if (aux_pcm_count == 0) {
758 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count is 0. Just"
759 " return\n", __func__, dai->id);
760 mutex_unlock(&aux_pcm_mutex);
761 return;
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700762 }
Kiran Kandi5f4ab692012-02-23 11:23:56 -0800763
764 aux_pcm_count--;
765
766 if (aux_pcm_count > 0) {
767 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d\n",
768 __func__, dai->id, aux_pcm_count);
769 mutex_unlock(&aux_pcm_mutex);
770 return;
771 } else if (aux_pcm_count < 0) {
772 dev_err(dai->dev, "%s(): ERROR: dai->id %d"
773 " aux_pcm_count = %d < 0\n",
774 __func__, dai->id, aux_pcm_count);
775 aux_pcm_count = 0;
776 mutex_unlock(&aux_pcm_mutex);
777 return;
778 }
779
780 pr_debug("%s: dai->id = %d aux_pcm_count = %d\n", __func__,
781 dai->id, aux_pcm_count);
782
Asish Bhattacharya4776d962012-04-25 12:08:09 +0530783 clk_disable_unprepare(pcm_clk);
Kiran Kandi5f4ab692012-02-23 11:23:56 -0800784 rc = afe_close(PCM_RX); /* can block */
785 if (IS_ERR_VALUE(rc))
786 dev_err(dai->dev, "fail to close PCM_RX AFE port\n");
787
788 rc = afe_close(PCM_TX);
789 if (IS_ERR_VALUE(rc))
790 dev_err(dai->dev, "fail to close AUX PCM TX port\n");
791
792 mutex_unlock(&aux_pcm_mutex);
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700793}
794
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -0700795static void msm_dai_q6_sec_auxpcm_shutdown(struct snd_pcm_substream *substream,
796 struct snd_soc_dai *dai)
797{
798 int rc = 0;
799
800 pr_debug("%s\n", __func__);
801 mutex_lock(&aux_pcm_mutex);
802
803 if (aux_pcm_count == 0) {
804 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count is 0. Just"
805 " return\n", __func__, dai->id);
806 mutex_unlock(&aux_pcm_mutex);
807 return;
808 }
809
810 aux_pcm_count--;
811
812 if (aux_pcm_count > 0) {
813 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d\n",
814 __func__, dai->id, aux_pcm_count);
815 mutex_unlock(&aux_pcm_mutex);
816 return;
817 } else if (aux_pcm_count < 0) {
818 dev_err(dai->dev, "%s(): ERROR: dai->id %d"
819 " aux_pcm_count = %d < 0\n",
820 __func__, dai->id, aux_pcm_count);
821 aux_pcm_count = 0;
822 mutex_unlock(&aux_pcm_mutex);
823 return;
824 }
825
826 pr_debug("%s: dai->id = %d aux_pcm_count = %d\n", __func__,
827 dai->id, aux_pcm_count);
828
829 clk_disable_unprepare(sec_pcm_clk);
830 rc = afe_close(SECONDARY_PCM_RX); /* can block */
831 if (IS_ERR_VALUE(rc))
832 dev_err(dai->dev, "fail to close PCM_RX AFE port\n");
833
834 rc = afe_close(SECONDARY_PCM_TX);
835 if (IS_ERR_VALUE(rc))
836 dev_err(dai->dev, "fail to close AUX PCM TX port\n");
837
838 mutex_unlock(&aux_pcm_mutex);
839}
840
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700841static void msm_dai_q6_shutdown(struct snd_pcm_substream *substream,
842 struct snd_soc_dai *dai)
843{
844 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530845 int rc = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700846
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700847 if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
Helen Zeng0705a5f2011-10-14 15:29:52 -0700848 switch (dai->id) {
849 case VOICE_PLAYBACK_TX:
Helen Zenge3d716a2011-10-14 16:32:16 -0700850 case VOICE_RECORD_TX:
851 case VOICE_RECORD_RX:
Helen Zeng0705a5f2011-10-14 15:29:52 -0700852 pr_debug("%s, stop pseudo port:%d\n",
853 __func__, dai->id);
854 rc = afe_stop_pseudo_port(dai->id);
855 break;
856 default:
857 rc = afe_close(dai->id); /* can block */
858 break;
859 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700860 if (IS_ERR_VALUE(rc))
861 dev_err(dai->dev, "fail to close AFE port\n");
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530862 pr_debug("%s: dai_data->status_mask = %ld\n", __func__,
863 *dai_data->status_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700864 clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
865 }
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700866}
867
868static int msm_dai_q6_auxpcm_prepare(struct snd_pcm_substream *substream,
869 struct snd_soc_dai *dai)
870{
871 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
872 int rc = 0;
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700873 struct msm_dai_auxpcm_pdata *auxpcm_pdata =
874 (struct msm_dai_auxpcm_pdata *) dai->dev->platform_data;
Kuirong Wang547a9982012-05-04 18:29:11 -0700875 unsigned long pcm_clk_rate;
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700876
Kiran Kandi5f4ab692012-02-23 11:23:56 -0800877 mutex_lock(&aux_pcm_mutex);
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700878
Kiran Kandi5f4ab692012-02-23 11:23:56 -0800879 if (aux_pcm_count == 2) {
880 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count is 2. Just"
881 " return.\n", __func__, dai->id);
882 mutex_unlock(&aux_pcm_mutex);
883 return 0;
884 } else if (aux_pcm_count > 2) {
885 dev_err(dai->dev, "%s(): ERROR: dai->id %d"
886 " aux_pcm_count = %d > 2\n",
887 __func__, dai->id, aux_pcm_count);
888 mutex_unlock(&aux_pcm_mutex);
889 return 0;
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700890 }
Kiran Kandi5f4ab692012-02-23 11:23:56 -0800891
892 aux_pcm_count++;
893 if (aux_pcm_count == 2) {
894 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d after "
895 " increment\n", __func__, dai->id, aux_pcm_count);
896 mutex_unlock(&aux_pcm_mutex);
897 return 0;
898 }
899
900 pr_debug("%s:dai->id:%d aux_pcm_count = %d. opening afe\n",
901 __func__, dai->id, aux_pcm_count);
902
903 rc = afe_q6_interface_prepare();
904 if (IS_ERR_VALUE(rc))
905 dev_err(dai->dev, "fail to open AFE APR\n");
906
907 /*
908 * For AUX PCM Interface the below sequence of clk
909 * settings and afe_open is a strict requirement.
910 *
911 * Also using afe_open instead of afe_port_start_nowait
912 * to make sure the port is open before deasserting the
913 * clock line. This is required because pcm register is
914 * not written before clock deassert. Hence the hw does
915 * not get updated with new setting if the below clock
916 * assert/deasset and afe_open sequence is not followed.
917 */
918
919 clk_reset(pcm_clk, CLK_RESET_ASSERT);
920
921 afe_open(PCM_RX, &dai_data->port_config, dai_data->rate);
922
923 afe_open(PCM_TX, &dai_data->port_config, dai_data->rate);
Kuirong Wang547a9982012-05-04 18:29:11 -0700924 if (dai_data->rate == 8000) {
925 pcm_clk_rate = auxpcm_pdata->mode_8k.pcm_clk_rate;
926 } else if (dai_data->rate == 16000) {
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -0700927 pcm_clk_rate = auxpcm_pdata->mode_16k.pcm_clk_rate;
Kuirong Wang547a9982012-05-04 18:29:11 -0700928 } else {
929 dev_err(dai->dev, "%s: Invalid AUX PCM rate %d\n", __func__,
930 dai_data->rate);
931 return -EINVAL;
932 }
Kiran Kandi5f4ab692012-02-23 11:23:56 -0800933
Kuirong Wang547a9982012-05-04 18:29:11 -0700934 rc = clk_set_rate(pcm_clk, pcm_clk_rate);
Kiran Kandi5f4ab692012-02-23 11:23:56 -0800935 if (rc < 0) {
936 pr_err("%s: clk_set_rate failed\n", __func__);
937 return rc;
938 }
939
Asish Bhattacharya4776d962012-04-25 12:08:09 +0530940 clk_prepare_enable(pcm_clk);
Kiran Kandi5f4ab692012-02-23 11:23:56 -0800941 clk_reset(pcm_clk, CLK_RESET_DEASSERT);
942
943 mutex_unlock(&aux_pcm_mutex);
944
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700945 return rc;
946}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700947
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -0700948static int msm_dai_q6_sec_auxpcm_prepare(struct snd_pcm_substream *substream,
949 struct snd_soc_dai *dai)
950{
951 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
952 int rc = 0;
953 struct msm_dai_auxpcm_pdata *auxpcm_pdata =
954 (struct msm_dai_auxpcm_pdata *) dai->dev->platform_data;
955 unsigned long pcm_clk_rate;
956
957 pr_info("%s\n", __func__);
958
959 mutex_lock(&aux_pcm_mutex);
960
961 if (aux_pcm_count == 2) {
962 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count is 2. Just"
963 " return.\n", __func__, dai->id);
964 mutex_unlock(&aux_pcm_mutex);
965 return 0;
966 } else if (aux_pcm_count > 2) {
967 dev_err(dai->dev, "%s(): ERROR: dai->id %d"
968 " aux_pcm_count = %d > 2\n",
969 __func__, dai->id, aux_pcm_count);
970 mutex_unlock(&aux_pcm_mutex);
971 return 0;
972 }
973
974 aux_pcm_count++;
975 if (aux_pcm_count == 2) {
976 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d after "
977 " increment\n", __func__, dai->id, aux_pcm_count);
978 mutex_unlock(&aux_pcm_mutex);
979 return 0;
980 }
981
982 pr_debug("%s:dai->id:%d aux_pcm_count = %d. opening afe\n",
983 __func__, dai->id, aux_pcm_count);
984
985 rc = afe_q6_interface_prepare();
986 if (IS_ERR_VALUE(rc))
987 dev_err(dai->dev, "fail to open AFE APR\n");
988
989 /*
990 * For AUX PCM Interface the below sequence of clk
991 * settings and afe_open is a strict requirement.
992 *
993 * Also using afe_open instead of afe_port_start_nowait
994 * to make sure the port is open before deasserting the
995 * clock line. This is required because pcm register is
996 * not written before clock deassert. Hence the hw does
997 * not get updated with new setting if the below clock
998 * assert/deasset and afe_open sequence is not followed.
999 */
1000
1001 clk_reset(sec_pcm_clk, CLK_RESET_ASSERT);
1002
1003 afe_open(SECONDARY_PCM_RX, &dai_data->port_config, dai_data->rate);
1004
1005 afe_open(SECONDARY_PCM_TX, &dai_data->port_config, dai_data->rate);
1006 if (dai_data->rate == 8000) {
1007 pcm_clk_rate = auxpcm_pdata->mode_8k.pcm_clk_rate;
1008 } else if (dai_data->rate == 16000) {
1009 pcm_clk_rate = auxpcm_pdata->mode_16k.pcm_clk_rate;
1010 } else {
1011 dev_err(dai->dev, "%s: Invalid AUX PCM rate %d\n", __func__,
1012 dai_data->rate);
1013 return -EINVAL;
1014 }
1015
1016 rc = clk_set_rate(sec_pcm_clk, pcm_clk_rate);
1017 if (rc < 0) {
1018 pr_err("%s: clk_set_rate failed\n", __func__);
1019 return rc;
1020 }
1021
1022 clk_prepare_enable(sec_pcm_clk);
1023 clk_reset(sec_pcm_clk, CLK_RESET_DEASSERT);
1024
1025 mutex_unlock(&aux_pcm_mutex);
1026
1027 return rc;
1028}
1029
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001030static int msm_dai_q6_prepare(struct snd_pcm_substream *substream,
1031 struct snd_soc_dai *dai)
1032{
1033 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
1034 int rc = 0;
1035
Patrick Lai831561e2011-07-26 22:51:27 -07001036 if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
Patrick Laicf999112011-08-23 11:27:20 -07001037 /* PORT START should be set if prepare called in active state */
1038 rc = afe_q6_interface_prepare();
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001039 if (IS_ERR_VALUE(rc))
Patrick Laicf999112011-08-23 11:27:20 -07001040 dev_err(dai->dev, "fail to open AFE APR\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001041 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001042 return rc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001043}
1044
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001045static int msm_dai_q6_auxpcm_trigger(struct snd_pcm_substream *substream,
1046 int cmd, struct snd_soc_dai *dai)
1047{
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001048 int rc = 0;
1049
Kiran Kandi5f4ab692012-02-23 11:23:56 -08001050 pr_debug("%s:port:%d cmd:%d aux_pcm_count= %d",
1051 __func__, dai->id, cmd, aux_pcm_count);
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001052
1053 switch (cmd) {
1054
1055 case SNDRV_PCM_TRIGGER_START:
1056 case SNDRV_PCM_TRIGGER_RESUME:
1057 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
1058 /* afe_open will be called from prepare */
1059 return 0;
1060
1061 case SNDRV_PCM_TRIGGER_STOP:
1062 case SNDRV_PCM_TRIGGER_SUSPEND:
1063 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
Kiran Kandi5f4ab692012-02-23 11:23:56 -08001064 return 0;
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001065
1066 default:
1067 rc = -EINVAL;
1068 }
1069
1070 return rc;
1071
1072}
1073
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001074static int msm_dai_q6_trigger(struct snd_pcm_substream *substream, int cmd,
1075 struct snd_soc_dai *dai)
1076{
1077 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
1078 int rc = 0;
1079
1080 /* Start/stop port without waiting for Q6 AFE response. Need to have
1081 * native q6 AFE driver propagates AFE response in order to handle
1082 * port start/stop command error properly if error does arise.
1083 */
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301084 pr_debug("%s:port:%d cmd:%d dai_data->status_mask = %ld",
1085 __func__, dai->id, cmd, *dai_data->status_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001086 switch (cmd) {
1087 case SNDRV_PCM_TRIGGER_START:
1088 case SNDRV_PCM_TRIGGER_RESUME:
1089 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
1090 if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
Helen Zeng0705a5f2011-10-14 15:29:52 -07001091 switch (dai->id) {
1092 case VOICE_PLAYBACK_TX:
Helen Zenge3d716a2011-10-14 16:32:16 -07001093 case VOICE_RECORD_TX:
1094 case VOICE_RECORD_RX:
Helen Zeng0705a5f2011-10-14 15:29:52 -07001095 afe_pseudo_port_start_nowait(dai->id);
1096 break;
1097 default:
1098 afe_port_start_nowait(dai->id,
1099 &dai_data->port_config, dai_data->rate);
1100 break;
1101 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001102 set_bit(STATUS_PORT_STARTED,
1103 dai_data->status_mask);
1104 }
1105 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001106 case SNDRV_PCM_TRIGGER_STOP:
1107 case SNDRV_PCM_TRIGGER_SUSPEND:
1108 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
1109 if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
Helen Zeng0705a5f2011-10-14 15:29:52 -07001110 switch (dai->id) {
1111 case VOICE_PLAYBACK_TX:
Helen Zenge3d716a2011-10-14 16:32:16 -07001112 case VOICE_RECORD_TX:
1113 case VOICE_RECORD_RX:
Helen Zeng0705a5f2011-10-14 15:29:52 -07001114 afe_pseudo_port_stop_nowait(dai->id);
1115 break;
1116 default:
1117 afe_port_stop_nowait(dai->id);
1118 break;
1119 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001120 clear_bit(STATUS_PORT_STARTED,
1121 dai_data->status_mask);
1122 }
1123 break;
1124
1125 default:
1126 rc = -EINVAL;
1127 }
1128
1129 return rc;
1130}
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001131static int msm_dai_q6_dai_auxpcm_probe(struct snd_soc_dai *dai)
1132{
1133 struct msm_dai_q6_dai_data *dai_data;
1134 int rc = 0;
1135
1136 struct msm_dai_auxpcm_pdata *auxpcm_pdata =
1137 (struct msm_dai_auxpcm_pdata *) dai->dev->platform_data;
1138
Kiran Kandi5f4ab692012-02-23 11:23:56 -08001139 mutex_lock(&aux_pcm_mutex);
1140
1141 if (!auxpcm_plat_data)
1142 auxpcm_plat_data = auxpcm_pdata;
1143 else if (auxpcm_plat_data != auxpcm_pdata) {
1144
1145 dev_err(dai->dev, "AUX PCM RX and TX devices does not have"
1146 " same platform data\n");
1147 return -EINVAL;
1148 }
1149
1150 /*
1151 * The clk name for AUX PCM operation is passed as platform
1152 * data to the cpu driver, since cpu drive is unaware of any
1153 * boarc specific configuration.
1154 */
1155 if (!pcm_clk) {
1156
1157 pcm_clk = clk_get(dai->dev, auxpcm_pdata->clk);
1158
1159 if (IS_ERR(pcm_clk)) {
1160 pr_err("%s: could not get pcm_clk\n", __func__);
1161 pcm_clk = NULL;
1162 return -ENODEV;
1163 }
1164 }
1165
1166 mutex_unlock(&aux_pcm_mutex);
1167
1168 dai_data = kzalloc(sizeof(struct msm_dai_q6_dai_data), GFP_KERNEL);
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001169
1170 if (!dai_data) {
1171 dev_err(dai->dev, "DAI-%d: fail to allocate dai data\n",
1172 dai->id);
1173 rc = -ENOMEM;
1174 } else
1175 dev_set_drvdata(dai->dev, dai_data);
1176
Kiran Kandi5f4ab692012-02-23 11:23:56 -08001177 pr_debug("%s : probe done for dai->id %d\n", __func__, dai->id);
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001178 return rc;
1179}
1180
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -07001181static int msm_dai_q6_dai_sec_auxpcm_probe(struct snd_soc_dai *dai)
1182{
1183 struct msm_dai_q6_dai_data *dai_data;
1184 int rc = 0;
1185 struct msm_dai_auxpcm_pdata *auxpcm_pdata =
1186 (struct msm_dai_auxpcm_pdata *) dai->dev->platform_data;
1187
1188 pr_info("%s\n", __func__);
1189
1190 mutex_lock(&aux_pcm_mutex);
1191
1192 if (!sec_auxpcm_plat_data)
1193 sec_auxpcm_plat_data = auxpcm_pdata;
1194 else if (sec_auxpcm_plat_data != auxpcm_pdata) {
1195 dev_err(dai->dev, "AUX PCM RX and TX devices does not have"
1196 " same platform data sec_auxpcm_plat_data\n");
1197 return -EINVAL;
1198 }
1199
1200 /*
1201 * The clk name for AUX PCM operation is passed as platform
1202 * data to the cpu driver, since cpu drive is unaware of any
1203 * boarc specific configuration.
1204 */
1205 if (!sec_pcm_clk) {
1206
1207 sec_pcm_clk = clk_get(dai->dev, auxpcm_pdata->clk);
1208 if (IS_ERR(sec_pcm_clk)) {
1209 pr_err("%s: could not get sec_pcm_clk\n", __func__);
1210 sec_pcm_clk = NULL;
1211 return -ENODEV;
1212 }
1213 }
1214
1215 mutex_unlock(&aux_pcm_mutex);
1216
1217 dai_data = kzalloc(sizeof(struct msm_dai_q6_dai_data), GFP_KERNEL);
1218
1219 if (!dai_data) {
1220 dev_err(dai->dev, "DAI-%d: fail to allocate dai data\n",
1221 dai->id);
1222 rc = -ENOMEM;
1223 } else
1224 dev_set_drvdata(dai->dev, dai_data);
1225
1226 pr_debug("%s : probe done for dai->id %d\n", __func__, dai->id);
1227 return rc;
1228}
1229
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001230static int msm_dai_q6_dai_auxpcm_remove(struct snd_soc_dai *dai)
1231{
1232 struct msm_dai_q6_dai_data *dai_data;
1233 int rc;
1234
1235 dai_data = dev_get_drvdata(dai->dev);
1236
Kiran Kandi5f4ab692012-02-23 11:23:56 -08001237 mutex_lock(&aux_pcm_mutex);
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001238
Kiran Kandi5f4ab692012-02-23 11:23:56 -08001239 if (aux_pcm_count == 0) {
1240 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count is 0. clean"
1241 " up and return\n", __func__, dai->id);
1242 goto done;
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001243 }
1244
Kiran Kandi5f4ab692012-02-23 11:23:56 -08001245 aux_pcm_count--;
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001246
Kiran Kandi5f4ab692012-02-23 11:23:56 -08001247 if (aux_pcm_count > 0) {
1248 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d\n",
1249 __func__, dai->id, aux_pcm_count);
1250 goto done;
1251 } else if (aux_pcm_count < 0) {
1252 dev_err(dai->dev, "%s(): ERROR: dai->id %d"
1253 " aux_pcm_count = %d < 0\n",
1254 __func__, dai->id, aux_pcm_count);
1255 goto done;
1256 }
1257
1258 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d."
1259 "closing afe\n",
1260 __func__, dai->id, aux_pcm_count);
1261
1262 rc = afe_close(PCM_RX); /* can block */
1263 if (IS_ERR_VALUE(rc))
1264 dev_err(dai->dev, "fail to close AUX PCM RX AFE port\n");
1265
1266 rc = afe_close(PCM_TX);
1267 if (IS_ERR_VALUE(rc))
1268 dev_err(dai->dev, "fail to close AUX PCM TX AFE port\n");
1269
1270done:
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001271 kfree(dai_data);
1272 snd_soc_unregister_dai(dai->dev);
1273
Kiran Kandi5f4ab692012-02-23 11:23:56 -08001274 mutex_unlock(&aux_pcm_mutex);
1275
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001276 return 0;
1277}
Patrick Lai04baee942012-05-01 14:38:47 -07001278
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -07001279static int msm_dai_q6_dai_sec_auxpcm_remove(struct snd_soc_dai *dai)
1280{
1281 struct msm_dai_q6_dai_data *dai_data;
1282 int rc;
1283
1284 pr_debug("%s\n", __func__);
1285 dai_data = dev_get_drvdata(dai->dev);
1286
1287 mutex_lock(&aux_pcm_mutex);
1288
1289 if (aux_pcm_count == 0) {
1290 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count is 0. clean"
1291 " up and return\n", __func__, dai->id);
1292 goto done;
1293 }
1294
1295 aux_pcm_count--;
1296
1297 if (aux_pcm_count > 0) {
1298 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d\n",
1299 __func__, dai->id, aux_pcm_count);
1300 goto done;
1301 } else if (aux_pcm_count < 0) {
1302 dev_err(dai->dev, "%s(): ERROR: dai->id %d"
1303 " aux_pcm_count = %d < 0\n",
1304 __func__, dai->id, aux_pcm_count);
1305 goto done;
1306 }
1307
1308 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d."
1309 "closing afe\n",
1310 __func__, dai->id, aux_pcm_count);
1311
1312 rc = afe_close(SECONDARY_PCM_RX); /* can block */
1313 if (IS_ERR_VALUE(rc))
1314 dev_err(dai->dev, "fail to close AUX PCM RX AFE port\n");
1315
1316 rc = afe_close(SECONDARY_PCM_TX);
1317 if (IS_ERR_VALUE(rc))
1318 dev_err(dai->dev, "fail to close AUX PCM TX AFE port\n");
1319
1320done:
1321 kfree(dai_data);
1322 snd_soc_unregister_dai(dai->dev);
1323
1324 mutex_unlock(&aux_pcm_mutex);
1325
1326 return 0;
1327}
1328
Kuirong Wang274f21a2011-12-15 21:29:08 -08001329static int msm_dai_q6_dai_mi2s_probe(struct snd_soc_dai *dai)
1330{
Patrick Lai04baee942012-05-01 14:38:47 -07001331 struct msm_dai_q6_mi2s_dai_data *mi2s_dai_data =
1332 dev_get_drvdata(dai->dev);
1333 struct snd_kcontrol *kcontrol = NULL;
Kuirong Wang274f21a2011-12-15 21:29:08 -08001334 int rc = 0;
1335
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -07001336 if (mi2s_dai_data->rx_dai.mi2s_dai_data.port_config.mi2s.line) {
Patrick Lai04baee942012-05-01 14:38:47 -07001337 kcontrol = snd_ctl_new1(&mi2s_config_controls[0],
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -07001338 &mi2s_dai_data->rx_dai.mi2s_dai_data);
Patrick Lai04baee942012-05-01 14:38:47 -07001339 rc = snd_ctl_add(dai->card->snd_card, kcontrol);
Kuirong Wang274f21a2011-12-15 21:29:08 -08001340
Patrick Lai04baee942012-05-01 14:38:47 -07001341 if (IS_ERR_VALUE(rc)) {
1342 dev_err(dai->dev, "%s: err add RX fmt ctl\n", __func__);
1343 goto rtn;
1344 }
Kuirong Wang274f21a2011-12-15 21:29:08 -08001345 }
Kuirong Wang875d1ec2012-04-02 19:56:25 -07001346
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -07001347 if (mi2s_dai_data->tx_dai.mi2s_dai_data.port_config.mi2s.line) {
Patrick Lai04baee942012-05-01 14:38:47 -07001348 rc = snd_ctl_add(dai->card->snd_card,
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -07001349 snd_ctl_new1(&mi2s_config_controls[2],
1350 &mi2s_dai_data->tx_dai.mi2s_dai_data));
Patrick Lai04baee942012-05-01 14:38:47 -07001351
1352 if (IS_ERR_VALUE(rc)) {
1353 if (kcontrol)
1354 snd_ctl_remove(dai->card->snd_card, kcontrol);
1355 dev_err(dai->dev, "%s: err add TX fmt ctl\n", __func__);
1356 }
1357 }
1358
Kuirong Wang274f21a2011-12-15 21:29:08 -08001359rtn:
1360 return rc;
1361}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001362
Patrick Lai04baee942012-05-01 14:38:47 -07001363static int msm_dai_q6_dai_mi2s_remove(struct snd_soc_dai *dai)
1364{
1365 struct msm_dai_q6_mi2s_dai_data *mi2s_dai_data =
1366 dev_get_drvdata(dai->dev);
1367 int rc;
1368
1369 /* If AFE port is still up, close it */
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -07001370 if (test_bit(STATUS_PORT_STARTED,
1371 mi2s_dai_data->rx_dai.mi2s_dai_data.status_mask)) {
Patrick Lai04baee942012-05-01 14:38:47 -07001372 rc = afe_close(MI2S_RX); /* can block */
1373 if (IS_ERR_VALUE(rc))
1374 dev_err(dai->dev, "fail to close MI2S_RX port\n");
1375 clear_bit(STATUS_PORT_STARTED,
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -07001376 mi2s_dai_data->rx_dai.mi2s_dai_data.status_mask);
Patrick Lai04baee942012-05-01 14:38:47 -07001377 }
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -07001378 if (test_bit(STATUS_PORT_STARTED,
1379 mi2s_dai_data->tx_dai.mi2s_dai_data.status_mask)) {
Patrick Lai04baee942012-05-01 14:38:47 -07001380 rc = afe_close(MI2S_TX); /* can block */
1381 if (IS_ERR_VALUE(rc))
1382 dev_err(dai->dev, "fail to close MI2S_TX port\n");
1383 clear_bit(STATUS_PORT_STARTED,
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -07001384 mi2s_dai_data->tx_dai.mi2s_dai_data.status_mask);
Patrick Lai04baee942012-05-01 14:38:47 -07001385 }
1386 kfree(mi2s_dai_data);
1387 snd_soc_unregister_dai(dai->dev);
1388
1389 return 0;
1390}
1391
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001392static int msm_dai_q6_dai_probe(struct snd_soc_dai *dai)
1393{
1394 struct msm_dai_q6_dai_data *dai_data;
1395 int rc = 0;
Kuirong Wang875d1ec2012-04-02 19:56:25 -07001396 const struct snd_kcontrol_new *kcontrol;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001397
1398 dai_data = kzalloc(sizeof(struct msm_dai_q6_dai_data),
1399 GFP_KERNEL);
1400
1401 if (!dai_data) {
1402 dev_err(dai->dev, "DAI-%d: fail to allocate dai data\n",
1403 dai->id);
1404 rc = -ENOMEM;
1405 } else
1406 dev_set_drvdata(dai->dev, dai_data);
Kuirong Wang875d1ec2012-04-02 19:56:25 -07001407 if (dai->id == SECONDARY_I2S_RX) {
1408 kcontrol = &mi2s_config_controls[1];
1409 rc = snd_ctl_add(dai->card->snd_card,
1410 snd_ctl_new1(kcontrol, dai_data));
1411 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001412
1413 return rc;
1414}
1415
1416static int msm_dai_q6_dai_remove(struct snd_soc_dai *dai)
1417{
1418 struct msm_dai_q6_dai_data *dai_data;
1419 int rc;
1420
1421 dai_data = dev_get_drvdata(dai->dev);
1422
1423 /* If AFE port is still up, close it */
1424 if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
Helen Zeng0705a5f2011-10-14 15:29:52 -07001425 switch (dai->id) {
1426 case VOICE_PLAYBACK_TX:
Helen Zenge3d716a2011-10-14 16:32:16 -07001427 case VOICE_RECORD_TX:
1428 case VOICE_RECORD_RX:
Helen Zeng0705a5f2011-10-14 15:29:52 -07001429 pr_debug("%s, stop pseudo port:%d\n",
1430 __func__, dai->id);
1431 rc = afe_stop_pseudo_port(dai->id);
1432 break;
1433 default:
1434 rc = afe_close(dai->id); /* can block */
1435 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001436 if (IS_ERR_VALUE(rc))
1437 dev_err(dai->dev, "fail to close AFE port\n");
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301438 clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001439 }
1440 kfree(dai_data);
1441 snd_soc_unregister_dai(dai->dev);
1442
1443 return 0;
1444}
1445
Lei Zhou157c1842011-08-19 13:05:04 -04001446static int msm_dai_q6_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
1447{
1448 int rc = 0;
1449
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001450 dev_dbg(dai->dev, "enter %s, id = %d fmt[%d]\n", __func__,
1451 dai->id, fmt);
Lei Zhou157c1842011-08-19 13:05:04 -04001452 switch (dai->id) {
1453 case PRIMARY_I2S_TX:
1454 case PRIMARY_I2S_RX:
Kuirong Wang9bbf6132012-01-10 18:28:49 -08001455 case SECONDARY_I2S_RX:
Lei Zhou157c1842011-08-19 13:05:04 -04001456 rc = msm_dai_q6_cdc_set_fmt(dai, fmt);
1457 break;
1458 default:
1459 dev_err(dai->dev, "invalid cpu_dai set_fmt\n");
1460 rc = -EINVAL;
1461 break;
1462 }
1463
1464 return rc;
1465}
1466
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001467static int msm_dai_q6_set_channel_map(struct snd_soc_dai *dai,
1468 unsigned int tx_num, unsigned int *tx_slot,
1469 unsigned int rx_num, unsigned int *rx_slot)
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001470{
1471 int rc = 0;
1472 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
1473 unsigned int i = 0;
1474
Kiran Kandifd30c892012-05-21 23:03:26 -07001475 dev_dbg(dai->dev, "%s: dai_id = %d\n", __func__, dai->id);
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001476 switch (dai->id) {
1477 case SLIMBUS_0_RX:
Neema Shetty3c9d2862012-03-11 01:25:32 -08001478 case SLIMBUS_1_RX:
Kiran Kandifd30c892012-05-21 23:03:26 -07001479 case SLIMBUS_2_RX:
Neema Shetty74131ac2012-05-09 13:35:26 -07001480 case SLIMBUS_3_RX:
Helen Zeng8f925502012-03-05 16:50:17 -08001481 case SLIMBUS_4_RX:
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001482 /* channel number to be between 128 and 255. For RX port
1483 * use channel numbers from 138 to 144, for TX port
1484 * use channel numbers from 128 to 137
Neema Shetty3c9d2862012-03-11 01:25:32 -08001485 * For ports between MDM-APQ use channel numbers from 145
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001486 */
Bharath Ramachandramurthy94ad7e22012-02-28 18:44:07 -08001487 if (!rx_slot)
1488 return -EINVAL;
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001489 for (i = 0; i < rx_num; i++) {
1490 dai_data->port_config.slim_sch.slave_ch_mapping[i] =
1491 rx_slot[i];
1492 pr_debug("%s: find number of channels[%d] ch[%d]\n",
1493 __func__, i,
1494 rx_slot[i]);
1495 }
1496 dai_data->port_config.slim_sch.num_channels = rx_num;
Kiran Kandi1e6371d2012-03-29 11:48:57 -07001497 pr_debug("%s:SLIMBUS_%d_RX cnt[%d] ch[%d %d]\n", __func__,
1498 (dai->id - SLIMBUS_0_RX) / 2,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001499 rx_num, dai_data->port_config.slim_sch.slave_ch_mapping[0],
1500 dai_data->port_config.slim_sch.slave_ch_mapping[1]);
1501
1502 break;
1503 case SLIMBUS_0_TX:
Neema Shetty3c9d2862012-03-11 01:25:32 -08001504 case SLIMBUS_1_TX:
Kiran Kandi1e6371d2012-03-29 11:48:57 -07001505 case SLIMBUS_2_TX:
Helen Zeng38c3c962012-05-17 14:56:20 -07001506 case SLIMBUS_3_TX:
Helen Zeng8f925502012-03-05 16:50:17 -08001507 case SLIMBUS_4_TX:
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001508 /* channel number to be between 128 and 255. For RX port
1509 * use channel numbers from 138 to 144, for TX port
1510 * use channel numbers from 128 to 137
Neema Shetty3c9d2862012-03-11 01:25:32 -08001511 * For ports between MDM-APQ use channel numbers from 145
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001512 */
Bharath Ramachandramurthy94ad7e22012-02-28 18:44:07 -08001513 if (!tx_slot)
1514 return -EINVAL;
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001515 for (i = 0; i < tx_num; i++) {
1516 dai_data->port_config.slim_sch.slave_ch_mapping[i] =
1517 tx_slot[i];
1518 pr_debug("%s: find number of channels[%d] ch[%d]\n",
1519 __func__, i, tx_slot[i]);
1520 }
1521 dai_data->port_config.slim_sch.num_channels = tx_num;
Kiran Kandi1e6371d2012-03-29 11:48:57 -07001522 pr_debug("%s:SLIMBUS_%d_TX cnt[%d] ch[%d %d]\n", __func__,
1523 (dai->id - SLIMBUS_0_TX) / 2,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001524 tx_num, dai_data->port_config.slim_sch.slave_ch_mapping[0],
1525 dai_data->port_config.slim_sch.slave_ch_mapping[1]);
1526 break;
1527 default:
1528 dev_err(dai->dev, "invalid cpu_dai set_fmt\n");
1529 rc = -EINVAL;
1530 break;
1531 }
1532 return rc;
1533}
1534
Patrick Lai04baee942012-05-01 14:38:47 -07001535static struct snd_soc_dai_ops msm_dai_q6_mi2s_ops = {
1536 .startup = msm_dai_q6_mi2s_startup,
1537 .prepare = msm_dai_q6_mi2s_prepare,
1538 .trigger = msm_dai_q6_mi2s_trigger,
1539 .hw_params = msm_dai_q6_mi2s_hw_params,
1540 .shutdown = msm_dai_q6_mi2s_shutdown,
1541 .set_fmt = msm_dai_q6_mi2s_set_fmt,
1542};
1543
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001544static struct snd_soc_dai_ops msm_dai_q6_ops = {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001545 .prepare = msm_dai_q6_prepare,
1546 .trigger = msm_dai_q6_trigger,
1547 .hw_params = msm_dai_q6_hw_params,
1548 .shutdown = msm_dai_q6_shutdown,
Lei Zhou157c1842011-08-19 13:05:04 -04001549 .set_fmt = msm_dai_q6_set_fmt,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001550 .set_channel_map = msm_dai_q6_set_channel_map,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001551};
1552
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001553static struct snd_soc_dai_ops msm_dai_q6_auxpcm_ops = {
1554 .prepare = msm_dai_q6_auxpcm_prepare,
1555 .trigger = msm_dai_q6_auxpcm_trigger,
1556 .hw_params = msm_dai_q6_auxpcm_hw_params,
1557 .shutdown = msm_dai_q6_auxpcm_shutdown,
1558};
1559
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -07001560static struct snd_soc_dai_ops msm_dai_q6_sec_auxpcm_ops = {
1561 .prepare = msm_dai_q6_sec_auxpcm_prepare,
1562 .trigger = msm_dai_q6_auxpcm_trigger,
1563 .hw_params = msm_dai_q6_sec_auxpcm_hw_params,
1564 .shutdown = msm_dai_q6_sec_auxpcm_shutdown,
1565};
1566
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001567static struct snd_soc_dai_driver msm_dai_q6_i2s_rx_dai = {
1568 .playback = {
1569 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1570 SNDRV_PCM_RATE_16000,
1571 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1572 .channels_min = 1,
Kiran Kandi9db678b2012-01-15 14:25:59 -08001573 .channels_max = 4,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001574 .rate_min = 8000,
1575 .rate_max = 48000,
1576 },
1577 .ops = &msm_dai_q6_ops,
1578 .probe = msm_dai_q6_dai_probe,
1579 .remove = msm_dai_q6_dai_remove,
1580};
1581
1582static struct snd_soc_dai_driver msm_dai_q6_i2s_tx_dai = {
1583 .capture = {
1584 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1585 SNDRV_PCM_RATE_16000,
1586 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1587 .channels_min = 1,
1588 .channels_max = 2,
1589 .rate_min = 8000,
1590 .rate_max = 48000,
1591 },
1592 .ops = &msm_dai_q6_ops,
1593 .probe = msm_dai_q6_dai_probe,
1594 .remove = msm_dai_q6_dai_remove,
1595};
1596
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301597static struct snd_soc_dai_driver msm_dai_q6_afe_rx_dai = {
1598 .playback = {
1599 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1600 SNDRV_PCM_RATE_16000,
1601 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1602 .channels_min = 1,
1603 .channels_max = 2,
1604 .rate_min = 8000,
1605 .rate_max = 48000,
1606 },
1607 .ops = &msm_dai_q6_ops,
1608 .probe = msm_dai_q6_dai_probe,
1609 .remove = msm_dai_q6_dai_remove,
1610};
1611
1612static struct snd_soc_dai_driver msm_dai_q6_afe_tx_dai = {
1613 .capture = {
1614 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1615 SNDRV_PCM_RATE_16000,
1616 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1617 .channels_min = 1,
Mingming Yin647e9ea2012-03-17 19:56:10 -07001618 .channels_max = 4,
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301619 .rate_min = 8000,
1620 .rate_max = 48000,
1621 },
1622 .ops = &msm_dai_q6_ops,
1623 .probe = msm_dai_q6_dai_probe,
1624 .remove = msm_dai_q6_dai_remove,
1625};
1626
Helen Zeng0705a5f2011-10-14 15:29:52 -07001627static struct snd_soc_dai_driver msm_dai_q6_voice_playback_tx_dai = {
1628 .playback = {
1629 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1630 SNDRV_PCM_RATE_16000,
1631 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1632 .channels_min = 1,
1633 .channels_max = 2,
1634 .rate_max = 48000,
1635 .rate_min = 8000,
1636 },
1637 .ops = &msm_dai_q6_ops,
1638 .probe = msm_dai_q6_dai_probe,
1639 .remove = msm_dai_q6_dai_remove,
1640};
1641
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001642static struct snd_soc_dai_driver msm_dai_q6_slimbus_rx_dai = {
1643 .playback = {
1644 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1645 SNDRV_PCM_RATE_16000,
1646 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1647 .channels_min = 1,
1648 .channels_max = 2,
1649 .rate_min = 8000,
1650 .rate_max = 48000,
1651 },
1652 .ops = &msm_dai_q6_ops,
1653 .probe = msm_dai_q6_dai_probe,
1654 .remove = msm_dai_q6_dai_remove,
1655};
1656
1657static struct snd_soc_dai_driver msm_dai_q6_slimbus_tx_dai = {
1658 .capture = {
1659 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1660 SNDRV_PCM_RATE_16000,
1661 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1662 .channels_min = 1,
1663 .channels_max = 2,
1664 .rate_min = 8000,
1665 .rate_max = 48000,
1666 },
1667 .ops = &msm_dai_q6_ops,
1668 .probe = msm_dai_q6_dai_probe,
1669 .remove = msm_dai_q6_dai_remove,
1670};
1671
Helen Zenge3d716a2011-10-14 16:32:16 -07001672static struct snd_soc_dai_driver msm_dai_q6_incall_record_dai = {
1673 .capture = {
1674 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1675 SNDRV_PCM_RATE_16000,
1676 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1677 .channels_min = 1,
1678 .channels_max = 2,
1679 .rate_min = 8000,
1680 .rate_max = 48000,
1681 },
1682 .ops = &msm_dai_q6_ops,
1683 .probe = msm_dai_q6_dai_probe,
1684 .remove = msm_dai_q6_dai_remove,
1685};
1686
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001687static struct snd_soc_dai_driver msm_dai_q6_bt_sco_rx_dai = {
1688 .playback = {
1689 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
1690 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1691 .channels_min = 1,
1692 .channels_max = 1,
1693 .rate_max = 16000,
1694 .rate_min = 8000,
1695 },
1696 .ops = &msm_dai_q6_ops,
1697 .probe = msm_dai_q6_dai_probe,
1698 .remove = msm_dai_q6_dai_remove,
1699};
1700
1701static struct snd_soc_dai_driver msm_dai_q6_bt_sco_tx_dai = {
Patrick Laibd5021e2012-06-12 01:27:20 -07001702 .capture = {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001703 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
1704 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1705 .channels_min = 1,
1706 .channels_max = 1,
1707 .rate_max = 16000,
1708 .rate_min = 8000,
1709 },
1710 .ops = &msm_dai_q6_ops,
1711 .probe = msm_dai_q6_dai_probe,
1712 .remove = msm_dai_q6_dai_remove,
1713};
1714
1715static struct snd_soc_dai_driver msm_dai_q6_fm_rx_dai = {
1716 .playback = {
1717 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1718 SNDRV_PCM_RATE_16000,
1719 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1720 .channels_min = 2,
1721 .channels_max = 2,
1722 .rate_max = 48000,
1723 .rate_min = 8000,
1724 },
1725 .ops = &msm_dai_q6_ops,
1726 .probe = msm_dai_q6_dai_probe,
1727 .remove = msm_dai_q6_dai_remove,
1728};
1729
1730static struct snd_soc_dai_driver msm_dai_q6_fm_tx_dai = {
Patrick Laibd5021e2012-06-12 01:27:20 -07001731 .capture = {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001732 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1733 SNDRV_PCM_RATE_16000,
1734 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1735 .channels_min = 2,
1736 .channels_max = 2,
1737 .rate_max = 48000,
1738 .rate_min = 8000,
1739 },
1740 .ops = &msm_dai_q6_ops,
1741 .probe = msm_dai_q6_dai_probe,
1742 .remove = msm_dai_q6_dai_remove,
1743};
1744
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001745static struct snd_soc_dai_driver msm_dai_q6_aux_pcm_rx_dai = {
1746 .playback = {
Kuirong Wang547a9982012-05-04 18:29:11 -07001747 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001748 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1749 .channels_min = 1,
1750 .channels_max = 1,
Kuirong Wang547a9982012-05-04 18:29:11 -07001751 .rate_max = 16000,
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001752 .rate_min = 8000,
1753 },
1754 .ops = &msm_dai_q6_auxpcm_ops,
1755 .probe = msm_dai_q6_dai_auxpcm_probe,
1756 .remove = msm_dai_q6_dai_auxpcm_remove,
1757};
1758
1759static struct snd_soc_dai_driver msm_dai_q6_aux_pcm_tx_dai = {
1760 .capture = {
Kuirong Wang547a9982012-05-04 18:29:11 -07001761 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001762 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1763 .channels_min = 1,
1764 .channels_max = 1,
Kuirong Wang547a9982012-05-04 18:29:11 -07001765 .rate_max = 16000,
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001766 .rate_min = 8000,
1767 },
Kiran Kandi5f4ab692012-02-23 11:23:56 -08001768 .ops = &msm_dai_q6_auxpcm_ops,
1769 .probe = msm_dai_q6_dai_auxpcm_probe,
1770 .remove = msm_dai_q6_dai_auxpcm_remove,
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001771};
1772
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -07001773static struct snd_soc_dai_driver msm_dai_q6_sec_aux_pcm_rx_dai = {
1774 .playback = {
1775 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
1776 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1777 .channels_min = 1,
1778 .channels_max = 1,
1779 .rate_max = 16000,
1780 .rate_min = 8000,
1781 },
1782 .ops = &msm_dai_q6_sec_auxpcm_ops,
1783 .probe = msm_dai_q6_dai_sec_auxpcm_probe,
1784 .remove = msm_dai_q6_dai_sec_auxpcm_remove,
1785};
1786
1787static struct snd_soc_dai_driver msm_dai_q6_sec_aux_pcm_tx_dai = {
1788 .capture = {
1789 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
1790 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1791 .channels_min = 1,
1792 .channels_max = 1,
1793 .rate_max = 16000,
1794 .rate_min = 8000,
1795 },
1796 .ops = &msm_dai_q6_sec_auxpcm_ops,
1797 .probe = msm_dai_q6_dai_sec_auxpcm_probe,
1798 .remove = msm_dai_q6_dai_sec_auxpcm_remove,
1799};
1800
Patrick Lai04baee942012-05-01 14:38:47 -07001801/* Channel min and max are initialized base on platform data */
1802static struct snd_soc_dai_driver msm_dai_q6_mi2s_dai = {
Kuirong Wang274f21a2011-12-15 21:29:08 -08001803 .playback = {
1804 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1805 SNDRV_PCM_RATE_16000,
1806 .formats = SNDRV_PCM_FMTBIT_S16_LE,
Kuirong Wang274f21a2011-12-15 21:29:08 -08001807 .rate_min = 8000,
1808 .rate_max = 48000,
1809 },
Kuirong Wang623b50f2012-04-16 15:51:14 -07001810 .capture = {
1811 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1812 SNDRV_PCM_RATE_16000,
1813 .formats = SNDRV_PCM_FMTBIT_S16_LE,
Patrick Lai04baee942012-05-01 14:38:47 -07001814 .rate_min = 8000,
1815 .rate_max = 48000,
Kuirong Wang623b50f2012-04-16 15:51:14 -07001816 },
Patrick Lai04baee942012-05-01 14:38:47 -07001817 .ops = &msm_dai_q6_mi2s_ops,
Kuirong Wang623b50f2012-04-16 15:51:14 -07001818 .probe = msm_dai_q6_dai_mi2s_probe,
Patrick Lai04baee942012-05-01 14:38:47 -07001819 .remove = msm_dai_q6_dai_mi2s_remove,
Kuirong Wang623b50f2012-04-16 15:51:14 -07001820};
1821
Neema Shetty3c9d2862012-03-11 01:25:32 -08001822static struct snd_soc_dai_driver msm_dai_q6_slimbus_1_rx_dai = {
1823 .playback = {
1824 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
1825 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1826 .channels_min = 1,
1827 .channels_max = 1,
1828 .rate_min = 8000,
1829 .rate_max = 16000,
1830 },
1831 .ops = &msm_dai_q6_ops,
1832 .probe = msm_dai_q6_dai_probe,
1833 .remove = msm_dai_q6_dai_remove,
1834};
1835
1836static struct snd_soc_dai_driver msm_dai_q6_slimbus_1_tx_dai = {
1837 .capture = {
1838 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
1839 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1840 .channels_min = 1,
1841 .channels_max = 1,
1842 .rate_min = 8000,
1843 .rate_max = 16000,
1844 },
1845 .ops = &msm_dai_q6_ops,
1846 .probe = msm_dai_q6_dai_probe,
1847 .remove = msm_dai_q6_dai_remove,
1848};
1849
Kiran Kandifd30c892012-05-21 23:03:26 -07001850static struct snd_soc_dai_driver msm_dai_q6_slimbus_2_rx_dai = {
1851 .playback = {
1852 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1853 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_96000 |
1854 SNDRV_PCM_RATE_192000,
1855 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1856 .channels_min = 1,
1857 .channels_max = 2,
1858 .rate_min = 8000,
1859 .rate_max = 192000,
1860 },
1861 .ops = &msm_dai_q6_ops,
1862 .probe = msm_dai_q6_dai_probe,
1863 .remove = msm_dai_q6_dai_remove,
1864};
1865
Kiran Kandi1e6371d2012-03-29 11:48:57 -07001866static struct snd_soc_dai_driver msm_dai_q6_slimbus_2_tx_dai = {
1867 .capture = {
1868 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1869 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_96000 |
1870 SNDRV_PCM_RATE_192000,
1871 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1872 .channels_min = 1,
1873 .channels_max = 4,
1874 .rate_min = 8000,
1875 .rate_max = 192000,
1876 },
1877 .ops = &msm_dai_q6_ops,
1878 .probe = msm_dai_q6_dai_probe,
1879 .remove = msm_dai_q6_dai_remove,
1880};
1881
Neema Shetty74131ac2012-05-09 13:35:26 -07001882static struct snd_soc_dai_driver msm_dai_q6_slimbus_3_rx_dai = {
1883 .playback = {
1884 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
1885 SNDRV_PCM_RATE_48000,
1886 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1887 .channels_min = 1,
1888 .channels_max = 2,
1889 .rate_min = 8000,
1890 .rate_max = 48000,
1891 },
1892 .ops = &msm_dai_q6_ops,
1893 .probe = msm_dai_q6_dai_probe,
1894 .remove = msm_dai_q6_dai_remove,
1895};
1896
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001897/* To do: change to register DAIs as batch */
1898static __devinit int msm_dai_q6_dev_probe(struct platform_device *pdev)
1899{
1900 int rc = 0;
1901
1902 dev_dbg(&pdev->dev, "dev name %s\n", dev_name(&pdev->dev));
1903
1904 switch (pdev->id) {
1905 case PRIMARY_I2S_RX:
Kuirong Wang9bbf6132012-01-10 18:28:49 -08001906 case SECONDARY_I2S_RX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001907 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_i2s_rx_dai);
1908 break;
1909 case PRIMARY_I2S_TX:
1910 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_i2s_tx_dai);
1911 break;
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001912 case PCM_RX:
1913 rc = snd_soc_register_dai(&pdev->dev,
1914 &msm_dai_q6_aux_pcm_rx_dai);
1915 break;
1916 case PCM_TX:
1917 rc = snd_soc_register_dai(&pdev->dev,
1918 &msm_dai_q6_aux_pcm_tx_dai);
1919 break;
Patrick Lai04baee942012-05-01 14:38:47 -07001920
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -07001921 case SECONDARY_PCM_RX:
1922 rc = snd_soc_register_dai(&pdev->dev,
1923 &msm_dai_q6_sec_aux_pcm_rx_dai);
1924 break;
1925 case SECONDARY_PCM_TX:
1926 rc = snd_soc_register_dai(&pdev->dev,
1927 &msm_dai_q6_sec_aux_pcm_tx_dai);
1928 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001929 case SLIMBUS_0_RX:
Helen Zeng8f925502012-03-05 16:50:17 -08001930 case SLIMBUS_4_RX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001931 rc = snd_soc_register_dai(&pdev->dev,
1932 &msm_dai_q6_slimbus_rx_dai);
1933 break;
1934 case SLIMBUS_0_TX:
Helen Zeng8f925502012-03-05 16:50:17 -08001935 case SLIMBUS_4_TX:
Helen Zeng38c3c962012-05-17 14:56:20 -07001936 case SLIMBUS_3_TX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001937 rc = snd_soc_register_dai(&pdev->dev,
1938 &msm_dai_q6_slimbus_tx_dai);
Neema Shetty3c9d2862012-03-11 01:25:32 -08001939 break;
Neema Shetty3c9d2862012-03-11 01:25:32 -08001940 case SLIMBUS_1_RX:
1941 rc = snd_soc_register_dai(&pdev->dev,
1942 &msm_dai_q6_slimbus_1_rx_dai);
1943 break;
1944 case SLIMBUS_1_TX:
1945 rc = snd_soc_register_dai(&pdev->dev,
1946 &msm_dai_q6_slimbus_1_tx_dai);
1947 break;
Kiran Kandifd30c892012-05-21 23:03:26 -07001948 case SLIMBUS_2_RX:
1949 rc = snd_soc_register_dai(&pdev->dev,
1950 &msm_dai_q6_slimbus_2_rx_dai);
1951 break;
Kiran Kandi1e6371d2012-03-29 11:48:57 -07001952 case SLIMBUS_2_TX:
1953 rc = snd_soc_register_dai(&pdev->dev,
1954 &msm_dai_q6_slimbus_2_tx_dai);
1955 break;
Neema Shetty74131ac2012-05-09 13:35:26 -07001956 case SLIMBUS_3_RX:
1957 rc = snd_soc_register_dai(&pdev->dev,
1958 &msm_dai_q6_slimbus_3_rx_dai);
1959 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001960 case INT_BT_SCO_RX:
1961 rc = snd_soc_register_dai(&pdev->dev,
1962 &msm_dai_q6_bt_sco_rx_dai);
1963 break;
1964 case INT_BT_SCO_TX:
1965 rc = snd_soc_register_dai(&pdev->dev,
1966 &msm_dai_q6_bt_sco_tx_dai);
1967 break;
1968 case INT_FM_RX:
1969 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_fm_rx_dai);
1970 break;
1971 case INT_FM_TX:
1972 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_fm_tx_dai);
1973 break;
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301974 case RT_PROXY_DAI_001_RX:
1975 case RT_PROXY_DAI_002_RX:
1976 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_afe_rx_dai);
1977 break;
1978 case RT_PROXY_DAI_001_TX:
1979 case RT_PROXY_DAI_002_TX:
1980 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_afe_tx_dai);
1981 break;
Helen Zeng0705a5f2011-10-14 15:29:52 -07001982 case VOICE_PLAYBACK_TX:
1983 rc = snd_soc_register_dai(&pdev->dev,
1984 &msm_dai_q6_voice_playback_tx_dai);
1985 break;
Helen Zenge3d716a2011-10-14 16:32:16 -07001986 case VOICE_RECORD_RX:
1987 case VOICE_RECORD_TX:
1988 rc = snd_soc_register_dai(&pdev->dev,
1989 &msm_dai_q6_incall_record_dai);
1990 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001991 default:
1992 rc = -ENODEV;
1993 break;
1994 }
1995 return rc;
1996}
1997
1998static __devexit int msm_dai_q6_dev_remove(struct platform_device *pdev)
1999{
2000 snd_soc_unregister_dai(&pdev->dev);
2001 return 0;
2002}
2003
Patrick Lai04baee942012-05-01 14:38:47 -07002004static __devinit int msm_dai_q6_mi2s_dev_probe(struct platform_device *pdev)
2005{
2006 struct msm_dai_q6_mi2s_dai_data *dai_data;
2007 int rc = 0;
2008
2009 dev_dbg(&pdev->dev, "%s: pdev %p dev %p\n", __func__, pdev, &pdev->dev);
2010
2011 dai_data = kzalloc(sizeof(struct msm_dai_q6_mi2s_dai_data),
2012 GFP_KERNEL);
2013
2014 if (!dai_data) {
2015 dev_err(&pdev->dev, "fail to allocate dai data\n");
2016 rc = -ENOMEM;
2017 goto rtn;
2018 } else
2019 dev_set_drvdata(&pdev->dev, dai_data);
2020
2021 rc = msm_dai_q6_mi2s_platform_data_validation(pdev,
2022 &msm_dai_q6_mi2s_dai);
2023 if (IS_ERR_VALUE(rc))
2024 goto err_pdata;
2025
2026 dai_data->rate_constraint.count = 1;
2027 dai_data->bitwidth_constraint.count = 1;
2028 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_mi2s_dai);
2029
2030 if (IS_ERR_VALUE(rc))
2031 goto err_pdata;
2032
2033 return 0;
2034
2035err_pdata:
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -07002036
2037 dev_err(&pdev->dev, "fail to msm_dai_q6_mi2s_dev_probe\n");
Patrick Lai04baee942012-05-01 14:38:47 -07002038 kfree(dai_data);
2039rtn:
2040 return rc;
2041}
2042
2043static __devexit int msm_dai_q6_mi2s_dev_remove(struct platform_device *pdev)
2044{
2045 snd_soc_unregister_dai(&pdev->dev);
2046 return 0;
2047}
2048
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002049static struct platform_driver msm_dai_q6_driver = {
2050 .probe = msm_dai_q6_dev_probe,
2051 .remove = msm_dai_q6_dev_remove,
2052 .driver = {
2053 .name = "msm-dai-q6",
2054 .owner = THIS_MODULE,
2055 },
2056};
2057
Patrick Lai04baee942012-05-01 14:38:47 -07002058static struct platform_driver msm_dai_q6_mi2s_driver = {
2059 .probe = msm_dai_q6_mi2s_dev_probe,
2060 .remove = msm_dai_q6_mi2s_dev_remove,
2061 .driver = {
2062 .name = "msm-dai-q6-mi2s",
2063 .owner = THIS_MODULE,
2064 },
2065};
2066
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002067static int __init msm_dai_q6_init(void)
2068{
Patrick Lai04baee942012-05-01 14:38:47 -07002069 int rc1, rc2;
2070
2071 rc1 = platform_driver_register(&msm_dai_q6_mi2s_driver);
2072
2073 if (IS_ERR_VALUE(rc1))
2074 pr_err("%s: fail to register mi2s dai driver\n", __func__);
2075
2076 rc2 = platform_driver_register(&msm_dai_q6_driver);
2077
2078 if (IS_ERR_VALUE(rc2))
2079 pr_err("%s: fail to register mi2s dai driver\n", __func__);
2080
2081 return (IS_ERR_VALUE(rc1) && IS_ERR_VALUE(rc2)) ? -1 : 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002082}
2083module_init(msm_dai_q6_init);
2084
2085static void __exit msm_dai_q6_exit(void)
2086{
2087 platform_driver_unregister(&msm_dai_q6_driver);
2088}
2089module_exit(msm_dai_q6_exit);
2090
2091/* Module information */
2092MODULE_DESCRIPTION("MSM DSP DAI driver");
2093MODULE_LICENSE("GPL v2");