blob: 89b709fccb2e95d6ffa44661e31fd2f7aed87330 [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 Laibf978952012-06-29 09:20:42 -0700410 u16 port_id = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
411 MI2S_RX : MI2S_TX);
Patrick Lai04baee942012-05-01 14:38:47 -0700412 int rc = 0;
413
414 if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
415 /* PORT START should be set if prepare called in active state */
Patrick Laibf978952012-06-29 09:20:42 -0700416 rc = afe_port_start(port_id, &dai_data->port_config,
417 dai_data->rate);
418
Patrick Lai04baee942012-05-01 14:38:47 -0700419 if (IS_ERR_VALUE(rc))
Patrick Laibf978952012-06-29 09:20:42 -0700420 dev_err(dai->dev, "fail to open AFE port %x\n",
421 dai->id);
422 else
Patrick Lai04baee942012-05-01 14:38:47 -0700423 set_bit(STATUS_PORT_STARTED,
424 dai_data->status_mask);
Patrick Lai04baee942012-05-01 14:38:47 -0700425 }
426
427 return rc;
428}
429
430static void msm_dai_q6_mi2s_shutdown(struct snd_pcm_substream *substream,
431 struct snd_soc_dai *dai)
432{
433 struct msm_dai_q6_mi2s_dai_data *mi2s_dai_data =
434 dev_get_drvdata(dai->dev);
435 struct msm_dai_q6_dai_data *dai_data =
436 (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -0700437 &mi2s_dai_data->rx_dai.mi2s_dai_data :
438 &mi2s_dai_data->tx_dai.mi2s_dai_data);
Patrick Lai04baee942012-05-01 14:38:47 -0700439 u16 port_id = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
440 MI2S_RX : MI2S_TX);
441 int rc = 0;
442
443 if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
444 rc = afe_close(port_id);
445 if (IS_ERR_VALUE(rc))
446 dev_err(dai->dev, "fail to close AFE port\n");
447 clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
448 }
449
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -0700450 if (!test_bit(STATUS_PORT_STARTED,
451 mi2s_dai_data->rx_dai.mi2s_dai_data.status_mask) &&
452 !test_bit(STATUS_PORT_STARTED,
453 mi2s_dai_data->rx_dai.mi2s_dai_data.status_mask)) {
Patrick Lai04baee942012-05-01 14:38:47 -0700454 mi2s_dai_data->rate_constraint.list = NULL;
455 mi2s_dai_data->bitwidth_constraint.list = NULL;
456 }
457
458}
459
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700460static int msm_dai_q6_cdc_hw_params(struct snd_pcm_hw_params *params,
461 struct snd_soc_dai *dai, int stream)
462{
463 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
464
465 dai_data->channels = params_channels(params);
466 switch (dai_data->channels) {
467 case 2:
468 dai_data->port_config.mi2s.channel = MSM_AFE_STEREO;
469 break;
470 case 1:
471 dai_data->port_config.mi2s.channel = MSM_AFE_MONO;
472 break;
473 default:
474 return -EINVAL;
475 break;
476 }
477 dai_data->rate = params_rate(params);
478
479 dev_dbg(dai->dev, " channel %d sample rate %d entered\n",
480 dai_data->channels, dai_data->rate);
481
482 /* Q6 only supports 16 as now */
483 dai_data->port_config.mi2s.bitwidth = 16;
484 dai_data->port_config.mi2s.line = 1;
Kuirong Wang274f21a2011-12-15 21:29:08 -0800485 return 0;
486}
487
Lei Zhou157c1842011-08-19 13:05:04 -0400488static int msm_dai_q6_cdc_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
489{
490 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
491
492 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
493 case SND_SOC_DAIFMT_CBS_CFS:
494 dai_data->port_config.mi2s.ws = 1; /* CPU is master */
495 break;
496 case SND_SOC_DAIFMT_CBM_CFM:
497 dai_data->port_config.mi2s.ws = 0; /* CPU is slave */
498 break;
499 default:
500 return -EINVAL;
501 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700502
503 return 0;
504}
505
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700506
507static int msm_dai_q6_slim_bus_hw_params(struct snd_pcm_hw_params *params,
508 struct snd_soc_dai *dai, int stream)
509{
510 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700511
512 dai_data->channels = params_channels(params);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700513 dai_data->rate = params_rate(params);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700514
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700515 /* Q6 only supports 16 as now */
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800516 dai_data->port_config.slim_sch.bit_width = 16;
517 dai_data->port_config.slim_sch.data_format = 0;
518 dai_data->port_config.slim_sch.num_channels = dai_data->channels;
519 dai_data->port_config.slim_sch.reserved = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700520
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800521 dev_dbg(dai->dev, "%s:slimbus_dev_id[%hu] bit_wd[%hu] format[%hu]\n"
522 "num_channel %hu slave_ch_mapping[0] %hu\n"
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700523 "slave_port_mapping[1] %hu slave_port_mapping[2] %hu\n"
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700524 "slave_port_mapping[3] %hu\n sample_rate %d\n", __func__,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800525 dai_data->port_config.slim_sch.slimbus_dev_id,
526 dai_data->port_config.slim_sch.bit_width,
527 dai_data->port_config.slim_sch.data_format,
528 dai_data->port_config.slim_sch.num_channels,
529 dai_data->port_config.slim_sch.slave_ch_mapping[0],
530 dai_data->port_config.slim_sch.slave_ch_mapping[1],
531 dai_data->port_config.slim_sch.slave_ch_mapping[2],
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700532 dai_data->port_config.slim_sch.slave_ch_mapping[3],
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700533 dai_data->rate);
534
535 return 0;
536}
537
538static int msm_dai_q6_bt_fm_hw_params(struct snd_pcm_hw_params *params,
539 struct snd_soc_dai *dai, int stream)
540{
541 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
542
543 dai_data->channels = params_channels(params);
544 dai_data->rate = params_rate(params);
545
546 dev_dbg(dai->dev, "channels %d sample rate %d entered\n",
547 dai_data->channels, dai_data->rate);
548
549 memset(&dai_data->port_config, 0, sizeof(dai_data->port_config));
550
551 return 0;
552}
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700553static int msm_dai_q6_auxpcm_hw_params(
554 struct snd_pcm_substream *substream,
555 struct snd_pcm_hw_params *params,
556 struct snd_soc_dai *dai)
557{
558 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
559 struct msm_dai_auxpcm_pdata *auxpcm_pdata =
560 (struct msm_dai_auxpcm_pdata *) dai->dev->platform_data;
561
562 if (params_channels(params) != 1) {
563 dev_err(dai->dev, "AUX PCM supports only mono stream\n");
564 return -EINVAL;
565 }
566 dai_data->channels = params_channels(params);
567
Kuirong Wang547a9982012-05-04 18:29:11 -0700568 dai_data->rate = params_rate(params);
569 switch (dai_data->rate) {
570 case 8000:
571 dai_data->port_config.pcm.mode = auxpcm_pdata->mode_8k.mode;
572 dai_data->port_config.pcm.sync = auxpcm_pdata->mode_8k.sync;
573 dai_data->port_config.pcm.frame = auxpcm_pdata->mode_8k.frame;
574 dai_data->port_config.pcm.quant = auxpcm_pdata->mode_8k.quant;
575 dai_data->port_config.pcm.slot = auxpcm_pdata->mode_8k.slot;
576 dai_data->port_config.pcm.data = auxpcm_pdata->mode_8k.data;
577 break;
578 case 16000:
579 dai_data->port_config.pcm.mode = auxpcm_pdata->mode_16k.mode;
580 dai_data->port_config.pcm.sync = auxpcm_pdata->mode_16k.sync;
581 dai_data->port_config.pcm.frame = auxpcm_pdata->mode_16k.frame;
582 dai_data->port_config.pcm.quant = auxpcm_pdata->mode_16k.quant;
583 dai_data->port_config.pcm.slot = auxpcm_pdata->mode_16k.slot;
584 dai_data->port_config.pcm.data = auxpcm_pdata->mode_16k.data;
585 break;
586 default:
587 dev_err(dai->dev, "AUX PCM supports only 8kHz and 16kHz sampling rate\n");
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700588 return -EINVAL;
589 }
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700590
591 return 0;
592}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700593
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -0700594static int msm_dai_q6_sec_auxpcm_hw_params(
595 struct snd_pcm_substream *substream,
596 struct snd_pcm_hw_params *params,
597 struct snd_soc_dai *dai)
598{
599 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
600 struct msm_dai_auxpcm_pdata *auxpcm_pdata =
601 (struct msm_dai_auxpcm_pdata *) dai->dev->platform_data;
602
603 pr_debug("%s\n", __func__);
604 if (params_channels(params) != 1) {
605 dev_err(dai->dev, "SEC AUX PCM supports only mono stream\n");
606 return -EINVAL;
607 }
608 dai_data->channels = params_channels(params);
609
610 dai_data->rate = params_rate(params);
611 switch (dai_data->rate) {
612 case 8000:
613 dai_data->port_config.pcm.mode = auxpcm_pdata->mode_8k.mode;
614 dai_data->port_config.pcm.sync = auxpcm_pdata->mode_8k.sync;
615 dai_data->port_config.pcm.frame = auxpcm_pdata->mode_8k.frame;
616 dai_data->port_config.pcm.quant = auxpcm_pdata->mode_8k.quant;
617 dai_data->port_config.pcm.slot = auxpcm_pdata->mode_8k.slot;
618 dai_data->port_config.pcm.data = auxpcm_pdata->mode_8k.data;
619 break;
620 case 16000:
621 dai_data->port_config.pcm.mode = auxpcm_pdata->mode_16k.mode;
622 dai_data->port_config.pcm.sync = auxpcm_pdata->mode_16k.sync;
623 dai_data->port_config.pcm.frame = auxpcm_pdata->mode_16k.frame;
624 dai_data->port_config.pcm.quant = auxpcm_pdata->mode_16k.quant;
625 dai_data->port_config.pcm.slot = auxpcm_pdata->mode_16k.slot;
626 dai_data->port_config.pcm.data = auxpcm_pdata->mode_16k.data;
627 break;
628 default:
629 dev_err(dai->dev, "AUX PCM supports only 8kHz and 16kHz sampling rate\n");
630 return -EINVAL;
631 }
632
633 return 0;
634}
635
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530636static int msm_dai_q6_afe_rtproxy_hw_params(struct snd_pcm_hw_params *params,
637 struct snd_soc_dai *dai)
638{
639 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
640
641 dai_data->rate = params_rate(params);
642 dai_data->port_config.rtproxy.num_ch =
643 params_channels(params);
644
645 pr_debug("channel %d entered,dai_id: %d,rate: %d\n",
646 dai_data->port_config.rtproxy.num_ch, dai->id, dai_data->rate);
647
648 dai_data->port_config.rtproxy.bitwidth = 16; /* Q6 only supports 16 */
649 dai_data->port_config.rtproxy.interleaved = 1;
Asish Bhattacharyab3568cf2012-03-15 07:05:46 +0530650 dai_data->port_config.rtproxy.frame_sz = params_period_bytes(params);
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530651 dai_data->port_config.rtproxy.jitter =
652 dai_data->port_config.rtproxy.frame_sz/2;
653 dai_data->port_config.rtproxy.lw_mark = 0;
654 dai_data->port_config.rtproxy.hw_mark = 0;
655 dai_data->port_config.rtproxy.rsvd = 0;
656
657 return 0;
658}
659
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700660/* Current implementation assumes hw_param is called once
661 * This may not be the case but what to do when ADM and AFE
662 * port are already opened and parameter changes
663 */
664static int msm_dai_q6_hw_params(struct snd_pcm_substream *substream,
665 struct snd_pcm_hw_params *params,
666 struct snd_soc_dai *dai)
667{
668 int rc = 0;
669
670 switch (dai->id) {
671 case PRIMARY_I2S_TX:
672 case PRIMARY_I2S_RX:
Kuirong Wang9bbf6132012-01-10 18:28:49 -0800673 case SECONDARY_I2S_RX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700674 rc = msm_dai_q6_cdc_hw_params(params, dai, substream->stream);
675 break;
Patrick Lai04baee942012-05-01 14:38:47 -0700676
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700677 case SLIMBUS_0_RX:
Neema Shetty3c9d2862012-03-11 01:25:32 -0800678 case SLIMBUS_1_RX:
Neema Shetty74131ac2012-05-09 13:35:26 -0700679 case SLIMBUS_3_RX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700680 case SLIMBUS_0_TX:
Neema Shetty3c9d2862012-03-11 01:25:32 -0800681 case SLIMBUS_1_TX:
Kiran Kandifd30c892012-05-21 23:03:26 -0700682 case SLIMBUS_2_RX:
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700683 case SLIMBUS_2_TX:
Helen Zeng38c3c962012-05-17 14:56:20 -0700684 case SLIMBUS_3_TX:
Helen Zeng8f925502012-03-05 16:50:17 -0800685 case SLIMBUS_4_RX:
686 case SLIMBUS_4_TX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700687 rc = msm_dai_q6_slim_bus_hw_params(params, dai,
688 substream->stream);
689 break;
690 case INT_BT_SCO_RX:
691 case INT_BT_SCO_TX:
692 case INT_FM_RX:
693 case INT_FM_TX:
694 rc = msm_dai_q6_bt_fm_hw_params(params, dai, substream->stream);
695 break;
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530696 case RT_PROXY_DAI_001_TX:
697 case RT_PROXY_DAI_001_RX:
698 case RT_PROXY_DAI_002_TX:
699 case RT_PROXY_DAI_002_RX:
700 rc = msm_dai_q6_afe_rtproxy_hw_params(params, dai);
701 break;
Helen Zeng0705a5f2011-10-14 15:29:52 -0700702 case VOICE_PLAYBACK_TX:
Helen Zenge3d716a2011-10-14 16:32:16 -0700703 case VOICE_RECORD_RX:
704 case VOICE_RECORD_TX:
Helen Zeng0705a5f2011-10-14 15:29:52 -0700705 rc = 0;
706 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700707 default:
708 dev_err(dai->dev, "invalid AFE port ID\n");
709 rc = -EINVAL;
710 break;
711 }
712
713 return rc;
714}
715
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700716static void msm_dai_q6_auxpcm_shutdown(struct snd_pcm_substream *substream,
717 struct snd_soc_dai *dai)
718{
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700719 int rc = 0;
720
Kiran Kandi5f4ab692012-02-23 11:23:56 -0800721 mutex_lock(&aux_pcm_mutex);
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700722
Kiran Kandi5f4ab692012-02-23 11:23:56 -0800723 if (aux_pcm_count == 0) {
724 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count is 0. Just"
725 " return\n", __func__, dai->id);
726 mutex_unlock(&aux_pcm_mutex);
727 return;
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700728 }
Kiran Kandi5f4ab692012-02-23 11:23:56 -0800729
730 aux_pcm_count--;
731
732 if (aux_pcm_count > 0) {
733 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d\n",
734 __func__, dai->id, aux_pcm_count);
735 mutex_unlock(&aux_pcm_mutex);
736 return;
737 } else if (aux_pcm_count < 0) {
738 dev_err(dai->dev, "%s(): ERROR: dai->id %d"
739 " aux_pcm_count = %d < 0\n",
740 __func__, dai->id, aux_pcm_count);
741 aux_pcm_count = 0;
742 mutex_unlock(&aux_pcm_mutex);
743 return;
744 }
745
746 pr_debug("%s: dai->id = %d aux_pcm_count = %d\n", __func__,
747 dai->id, aux_pcm_count);
748
Asish Bhattacharya4776d962012-04-25 12:08:09 +0530749 clk_disable_unprepare(pcm_clk);
Kiran Kandi5f4ab692012-02-23 11:23:56 -0800750 rc = afe_close(PCM_RX); /* can block */
751 if (IS_ERR_VALUE(rc))
752 dev_err(dai->dev, "fail to close PCM_RX AFE port\n");
753
754 rc = afe_close(PCM_TX);
755 if (IS_ERR_VALUE(rc))
756 dev_err(dai->dev, "fail to close AUX PCM TX port\n");
757
758 mutex_unlock(&aux_pcm_mutex);
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700759}
760
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -0700761static void msm_dai_q6_sec_auxpcm_shutdown(struct snd_pcm_substream *substream,
762 struct snd_soc_dai *dai)
763{
764 int rc = 0;
765
766 pr_debug("%s\n", __func__);
767 mutex_lock(&aux_pcm_mutex);
768
769 if (aux_pcm_count == 0) {
770 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count is 0. Just"
771 " return\n", __func__, dai->id);
772 mutex_unlock(&aux_pcm_mutex);
773 return;
774 }
775
776 aux_pcm_count--;
777
778 if (aux_pcm_count > 0) {
779 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d\n",
780 __func__, dai->id, aux_pcm_count);
781 mutex_unlock(&aux_pcm_mutex);
782 return;
783 } else if (aux_pcm_count < 0) {
784 dev_err(dai->dev, "%s(): ERROR: dai->id %d"
785 " aux_pcm_count = %d < 0\n",
786 __func__, dai->id, aux_pcm_count);
787 aux_pcm_count = 0;
788 mutex_unlock(&aux_pcm_mutex);
789 return;
790 }
791
792 pr_debug("%s: dai->id = %d aux_pcm_count = %d\n", __func__,
793 dai->id, aux_pcm_count);
794
795 clk_disable_unprepare(sec_pcm_clk);
796 rc = afe_close(SECONDARY_PCM_RX); /* can block */
797 if (IS_ERR_VALUE(rc))
798 dev_err(dai->dev, "fail to close PCM_RX AFE port\n");
799
800 rc = afe_close(SECONDARY_PCM_TX);
801 if (IS_ERR_VALUE(rc))
802 dev_err(dai->dev, "fail to close AUX PCM TX port\n");
803
804 mutex_unlock(&aux_pcm_mutex);
805}
806
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700807static void msm_dai_q6_shutdown(struct snd_pcm_substream *substream,
808 struct snd_soc_dai *dai)
809{
810 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530811 int rc = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700812
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700813 if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
Helen Zeng0705a5f2011-10-14 15:29:52 -0700814 switch (dai->id) {
815 case VOICE_PLAYBACK_TX:
Helen Zenge3d716a2011-10-14 16:32:16 -0700816 case VOICE_RECORD_TX:
817 case VOICE_RECORD_RX:
Helen Zeng0705a5f2011-10-14 15:29:52 -0700818 pr_debug("%s, stop pseudo port:%d\n",
819 __func__, dai->id);
820 rc = afe_stop_pseudo_port(dai->id);
821 break;
822 default:
823 rc = afe_close(dai->id); /* can block */
824 break;
825 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700826 if (IS_ERR_VALUE(rc))
827 dev_err(dai->dev, "fail to close AFE port\n");
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530828 pr_debug("%s: dai_data->status_mask = %ld\n", __func__,
829 *dai_data->status_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700830 clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
831 }
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700832}
833
834static int msm_dai_q6_auxpcm_prepare(struct snd_pcm_substream *substream,
835 struct snd_soc_dai *dai)
836{
837 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
838 int rc = 0;
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700839 struct msm_dai_auxpcm_pdata *auxpcm_pdata =
840 (struct msm_dai_auxpcm_pdata *) dai->dev->platform_data;
Kuirong Wang547a9982012-05-04 18:29:11 -0700841 unsigned long pcm_clk_rate;
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700842
Kiran Kandi5f4ab692012-02-23 11:23:56 -0800843 mutex_lock(&aux_pcm_mutex);
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700844
Kiran Kandi5f4ab692012-02-23 11:23:56 -0800845 if (aux_pcm_count == 2) {
846 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count is 2. Just"
847 " return.\n", __func__, dai->id);
848 mutex_unlock(&aux_pcm_mutex);
849 return 0;
850 } else if (aux_pcm_count > 2) {
851 dev_err(dai->dev, "%s(): ERROR: dai->id %d"
852 " aux_pcm_count = %d > 2\n",
853 __func__, dai->id, aux_pcm_count);
854 mutex_unlock(&aux_pcm_mutex);
855 return 0;
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700856 }
Kiran Kandi5f4ab692012-02-23 11:23:56 -0800857
858 aux_pcm_count++;
859 if (aux_pcm_count == 2) {
860 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d after "
861 " increment\n", __func__, dai->id, aux_pcm_count);
862 mutex_unlock(&aux_pcm_mutex);
863 return 0;
864 }
865
866 pr_debug("%s:dai->id:%d aux_pcm_count = %d. opening afe\n",
867 __func__, dai->id, aux_pcm_count);
868
869 rc = afe_q6_interface_prepare();
870 if (IS_ERR_VALUE(rc))
871 dev_err(dai->dev, "fail to open AFE APR\n");
872
873 /*
874 * For AUX PCM Interface the below sequence of clk
Patrick Laibf978952012-06-29 09:20:42 -0700875 * settings and opening of afe port is a strict requirement.
876 * afe_port_start is called to make sure to make sure the port
877 * is open before deasserting the clock line. This is
878 * required because pcm register is not written before
879 * clock deassert. Hence the hw does not get updated with
880 * new setting if the below clock assert/deasset and afe_port_start
881 * sequence is not followed.
Kiran Kandi5f4ab692012-02-23 11:23:56 -0800882 */
883
884 clk_reset(pcm_clk, CLK_RESET_ASSERT);
885
Patrick Laibf978952012-06-29 09:20:42 -0700886 afe_port_start(PCM_RX, &dai_data->port_config, dai_data->rate);
Kiran Kandi5f4ab692012-02-23 11:23:56 -0800887
Patrick Laibf978952012-06-29 09:20:42 -0700888 afe_port_start(PCM_TX, &dai_data->port_config, dai_data->rate);
Kuirong Wang547a9982012-05-04 18:29:11 -0700889 if (dai_data->rate == 8000) {
890 pcm_clk_rate = auxpcm_pdata->mode_8k.pcm_clk_rate;
891 } else if (dai_data->rate == 16000) {
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -0700892 pcm_clk_rate = auxpcm_pdata->mode_16k.pcm_clk_rate;
Kuirong Wang547a9982012-05-04 18:29:11 -0700893 } else {
894 dev_err(dai->dev, "%s: Invalid AUX PCM rate %d\n", __func__,
895 dai_data->rate);
896 return -EINVAL;
897 }
Kiran Kandi5f4ab692012-02-23 11:23:56 -0800898
Kuirong Wang547a9982012-05-04 18:29:11 -0700899 rc = clk_set_rate(pcm_clk, pcm_clk_rate);
Kiran Kandi5f4ab692012-02-23 11:23:56 -0800900 if (rc < 0) {
901 pr_err("%s: clk_set_rate failed\n", __func__);
902 return rc;
903 }
904
Asish Bhattacharya4776d962012-04-25 12:08:09 +0530905 clk_prepare_enable(pcm_clk);
Kiran Kandi5f4ab692012-02-23 11:23:56 -0800906 clk_reset(pcm_clk, CLK_RESET_DEASSERT);
907
908 mutex_unlock(&aux_pcm_mutex);
909
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700910 return rc;
911}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700912
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -0700913static int msm_dai_q6_sec_auxpcm_prepare(struct snd_pcm_substream *substream,
914 struct snd_soc_dai *dai)
915{
916 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
917 int rc = 0;
918 struct msm_dai_auxpcm_pdata *auxpcm_pdata =
919 (struct msm_dai_auxpcm_pdata *) dai->dev->platform_data;
920 unsigned long pcm_clk_rate;
921
922 pr_info("%s\n", __func__);
923
924 mutex_lock(&aux_pcm_mutex);
925
926 if (aux_pcm_count == 2) {
927 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count is 2. Just"
928 " return.\n", __func__, dai->id);
929 mutex_unlock(&aux_pcm_mutex);
930 return 0;
931 } else if (aux_pcm_count > 2) {
932 dev_err(dai->dev, "%s(): ERROR: dai->id %d"
933 " aux_pcm_count = %d > 2\n",
934 __func__, dai->id, aux_pcm_count);
935 mutex_unlock(&aux_pcm_mutex);
936 return 0;
937 }
938
939 aux_pcm_count++;
940 if (aux_pcm_count == 2) {
941 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d after "
942 " increment\n", __func__, dai->id, aux_pcm_count);
943 mutex_unlock(&aux_pcm_mutex);
944 return 0;
945 }
946
947 pr_debug("%s:dai->id:%d aux_pcm_count = %d. opening afe\n",
948 __func__, dai->id, aux_pcm_count);
949
950 rc = afe_q6_interface_prepare();
951 if (IS_ERR_VALUE(rc))
952 dev_err(dai->dev, "fail to open AFE APR\n");
953
954 /*
955 * For AUX PCM Interface the below sequence of clk
Patrick Laibf978952012-06-29 09:20:42 -0700956 * settings and opening of afe port is a strict requirement.
957 * afe_port_start is called to make sure to make sure the port
958 * is open before deasserting the clock line. This is
959 * required because pcm register is not written before
960 * clock deassert. Hence the hw does not get updated with
961 * new setting if the below clock assert/deasset and afe_port_start
962 * sequence is not followed.
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -0700963 */
964
965 clk_reset(sec_pcm_clk, CLK_RESET_ASSERT);
966
Patrick Laibf978952012-06-29 09:20:42 -0700967 afe_port_start(SECONDARY_PCM_RX, &dai_data->port_config,
968 dai_data->rate);
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -0700969
Patrick Laibf978952012-06-29 09:20:42 -0700970 afe_port_start(SECONDARY_PCM_TX, &dai_data->port_config,
971 dai_data->rate);
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -0700972 if (dai_data->rate == 8000) {
973 pcm_clk_rate = auxpcm_pdata->mode_8k.pcm_clk_rate;
974 } else if (dai_data->rate == 16000) {
975 pcm_clk_rate = auxpcm_pdata->mode_16k.pcm_clk_rate;
976 } else {
977 dev_err(dai->dev, "%s: Invalid AUX PCM rate %d\n", __func__,
978 dai_data->rate);
979 return -EINVAL;
980 }
981
982 rc = clk_set_rate(sec_pcm_clk, pcm_clk_rate);
983 if (rc < 0) {
984 pr_err("%s: clk_set_rate failed\n", __func__);
985 return rc;
986 }
987
988 clk_prepare_enable(sec_pcm_clk);
989 clk_reset(sec_pcm_clk, CLK_RESET_DEASSERT);
990
991 mutex_unlock(&aux_pcm_mutex);
992
993 return rc;
994}
995
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700996static int msm_dai_q6_prepare(struct snd_pcm_substream *substream,
997 struct snd_soc_dai *dai)
998{
999 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
1000 int rc = 0;
1001
Patrick Lai831561e2011-07-26 22:51:27 -07001002 if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
Patrick Laibf978952012-06-29 09:20:42 -07001003 switch (dai->id) {
1004 case VOICE_PLAYBACK_TX:
1005 case VOICE_RECORD_TX:
1006 case VOICE_RECORD_RX:
1007 rc = afe_start_pseudo_port(dai->id);
Vidyakumar Athota20957ca2012-07-25 15:04:41 -07001008 break;
Patrick Laibf978952012-06-29 09:20:42 -07001009 default:
1010 rc = afe_port_start(dai->id, &dai_data->port_config,
1011 dai_data->rate);
1012 }
1013
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001014 if (IS_ERR_VALUE(rc))
Patrick Laibf978952012-06-29 09:20:42 -07001015 dev_err(dai->dev, "fail to open AFE port %x\n",
1016 dai->id);
1017 else
1018 set_bit(STATUS_PORT_STARTED,
1019 dai_data->status_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001020 }
Patrick Laibf978952012-06-29 09:20:42 -07001021
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001022 return rc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001023}
1024
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001025static int msm_dai_q6_auxpcm_trigger(struct snd_pcm_substream *substream,
1026 int cmd, struct snd_soc_dai *dai)
1027{
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001028 int rc = 0;
1029
Kiran Kandi5f4ab692012-02-23 11:23:56 -08001030 pr_debug("%s:port:%d cmd:%d aux_pcm_count= %d",
1031 __func__, dai->id, cmd, aux_pcm_count);
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001032
1033 switch (cmd) {
1034
1035 case SNDRV_PCM_TRIGGER_START:
1036 case SNDRV_PCM_TRIGGER_RESUME:
1037 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
1038 /* afe_open will be called from prepare */
1039 return 0;
1040
1041 case SNDRV_PCM_TRIGGER_STOP:
1042 case SNDRV_PCM_TRIGGER_SUSPEND:
1043 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
Kiran Kandi5f4ab692012-02-23 11:23:56 -08001044 return 0;
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001045
1046 default:
1047 rc = -EINVAL;
1048 }
1049
1050 return rc;
1051
1052}
1053
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001054static int msm_dai_q6_dai_auxpcm_probe(struct snd_soc_dai *dai)
1055{
1056 struct msm_dai_q6_dai_data *dai_data;
1057 int rc = 0;
1058
1059 struct msm_dai_auxpcm_pdata *auxpcm_pdata =
1060 (struct msm_dai_auxpcm_pdata *) dai->dev->platform_data;
1061
Kiran Kandi5f4ab692012-02-23 11:23:56 -08001062 mutex_lock(&aux_pcm_mutex);
1063
1064 if (!auxpcm_plat_data)
1065 auxpcm_plat_data = auxpcm_pdata;
1066 else if (auxpcm_plat_data != auxpcm_pdata) {
1067
1068 dev_err(dai->dev, "AUX PCM RX and TX devices does not have"
1069 " same platform data\n");
1070 return -EINVAL;
1071 }
1072
1073 /*
1074 * The clk name for AUX PCM operation is passed as platform
1075 * data to the cpu driver, since cpu drive is unaware of any
1076 * boarc specific configuration.
1077 */
1078 if (!pcm_clk) {
1079
1080 pcm_clk = clk_get(dai->dev, auxpcm_pdata->clk);
1081
1082 if (IS_ERR(pcm_clk)) {
1083 pr_err("%s: could not get pcm_clk\n", __func__);
1084 pcm_clk = NULL;
1085 return -ENODEV;
1086 }
1087 }
1088
1089 mutex_unlock(&aux_pcm_mutex);
1090
1091 dai_data = kzalloc(sizeof(struct msm_dai_q6_dai_data), GFP_KERNEL);
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001092
1093 if (!dai_data) {
1094 dev_err(dai->dev, "DAI-%d: fail to allocate dai data\n",
1095 dai->id);
1096 rc = -ENOMEM;
1097 } else
1098 dev_set_drvdata(dai->dev, dai_data);
1099
Kiran Kandi5f4ab692012-02-23 11:23:56 -08001100 pr_debug("%s : probe done for dai->id %d\n", __func__, dai->id);
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001101 return rc;
1102}
1103
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -07001104static int msm_dai_q6_dai_sec_auxpcm_probe(struct snd_soc_dai *dai)
1105{
1106 struct msm_dai_q6_dai_data *dai_data;
1107 int rc = 0;
1108 struct msm_dai_auxpcm_pdata *auxpcm_pdata =
1109 (struct msm_dai_auxpcm_pdata *) dai->dev->platform_data;
1110
1111 pr_info("%s\n", __func__);
1112
1113 mutex_lock(&aux_pcm_mutex);
1114
1115 if (!sec_auxpcm_plat_data)
1116 sec_auxpcm_plat_data = auxpcm_pdata;
1117 else if (sec_auxpcm_plat_data != auxpcm_pdata) {
1118 dev_err(dai->dev, "AUX PCM RX and TX devices does not have"
1119 " same platform data sec_auxpcm_plat_data\n");
1120 return -EINVAL;
1121 }
1122
1123 /*
1124 * The clk name for AUX PCM operation is passed as platform
1125 * data to the cpu driver, since cpu drive is unaware of any
1126 * boarc specific configuration.
1127 */
1128 if (!sec_pcm_clk) {
1129
1130 sec_pcm_clk = clk_get(dai->dev, auxpcm_pdata->clk);
1131 if (IS_ERR(sec_pcm_clk)) {
1132 pr_err("%s: could not get sec_pcm_clk\n", __func__);
1133 sec_pcm_clk = NULL;
1134 return -ENODEV;
1135 }
1136 }
1137
1138 mutex_unlock(&aux_pcm_mutex);
1139
1140 dai_data = kzalloc(sizeof(struct msm_dai_q6_dai_data), GFP_KERNEL);
1141
1142 if (!dai_data) {
1143 dev_err(dai->dev, "DAI-%d: fail to allocate dai data\n",
1144 dai->id);
1145 rc = -ENOMEM;
1146 } else
1147 dev_set_drvdata(dai->dev, dai_data);
1148
1149 pr_debug("%s : probe done for dai->id %d\n", __func__, dai->id);
1150 return rc;
1151}
1152
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001153static int msm_dai_q6_dai_auxpcm_remove(struct snd_soc_dai *dai)
1154{
1155 struct msm_dai_q6_dai_data *dai_data;
1156 int rc;
1157
1158 dai_data = dev_get_drvdata(dai->dev);
1159
Kiran Kandi5f4ab692012-02-23 11:23:56 -08001160 mutex_lock(&aux_pcm_mutex);
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001161
Kiran Kandi5f4ab692012-02-23 11:23:56 -08001162 if (aux_pcm_count == 0) {
1163 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count is 0. clean"
1164 " up and return\n", __func__, dai->id);
1165 goto done;
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001166 }
1167
Kiran Kandi5f4ab692012-02-23 11:23:56 -08001168 aux_pcm_count--;
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001169
Kiran Kandi5f4ab692012-02-23 11:23:56 -08001170 if (aux_pcm_count > 0) {
1171 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d\n",
1172 __func__, dai->id, aux_pcm_count);
1173 goto done;
1174 } else if (aux_pcm_count < 0) {
1175 dev_err(dai->dev, "%s(): ERROR: dai->id %d"
1176 " aux_pcm_count = %d < 0\n",
1177 __func__, dai->id, aux_pcm_count);
1178 goto done;
1179 }
1180
1181 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d."
1182 "closing afe\n",
1183 __func__, dai->id, aux_pcm_count);
1184
1185 rc = afe_close(PCM_RX); /* can block */
1186 if (IS_ERR_VALUE(rc))
1187 dev_err(dai->dev, "fail to close AUX PCM RX AFE port\n");
1188
1189 rc = afe_close(PCM_TX);
1190 if (IS_ERR_VALUE(rc))
1191 dev_err(dai->dev, "fail to close AUX PCM TX AFE port\n");
1192
1193done:
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001194 kfree(dai_data);
1195 snd_soc_unregister_dai(dai->dev);
1196
Kiran Kandi5f4ab692012-02-23 11:23:56 -08001197 mutex_unlock(&aux_pcm_mutex);
1198
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001199 return 0;
1200}
Patrick Lai04baee942012-05-01 14:38:47 -07001201
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -07001202static int msm_dai_q6_dai_sec_auxpcm_remove(struct snd_soc_dai *dai)
1203{
1204 struct msm_dai_q6_dai_data *dai_data;
1205 int rc;
1206
1207 pr_debug("%s\n", __func__);
1208 dai_data = dev_get_drvdata(dai->dev);
1209
1210 mutex_lock(&aux_pcm_mutex);
1211
1212 if (aux_pcm_count == 0) {
1213 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count is 0. clean"
1214 " up and return\n", __func__, dai->id);
1215 goto done;
1216 }
1217
1218 aux_pcm_count--;
1219
1220 if (aux_pcm_count > 0) {
1221 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d\n",
1222 __func__, dai->id, aux_pcm_count);
1223 goto done;
1224 } else if (aux_pcm_count < 0) {
1225 dev_err(dai->dev, "%s(): ERROR: dai->id %d"
1226 " aux_pcm_count = %d < 0\n",
1227 __func__, dai->id, aux_pcm_count);
1228 goto done;
1229 }
1230
1231 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d."
1232 "closing afe\n",
1233 __func__, dai->id, aux_pcm_count);
1234
1235 rc = afe_close(SECONDARY_PCM_RX); /* can block */
1236 if (IS_ERR_VALUE(rc))
1237 dev_err(dai->dev, "fail to close AUX PCM RX AFE port\n");
1238
1239 rc = afe_close(SECONDARY_PCM_TX);
1240 if (IS_ERR_VALUE(rc))
1241 dev_err(dai->dev, "fail to close AUX PCM TX AFE port\n");
1242
1243done:
1244 kfree(dai_data);
1245 snd_soc_unregister_dai(dai->dev);
1246
1247 mutex_unlock(&aux_pcm_mutex);
1248
1249 return 0;
1250}
1251
Kuirong Wang274f21a2011-12-15 21:29:08 -08001252static int msm_dai_q6_dai_mi2s_probe(struct snd_soc_dai *dai)
1253{
Patrick Lai04baee942012-05-01 14:38:47 -07001254 struct msm_dai_q6_mi2s_dai_data *mi2s_dai_data =
1255 dev_get_drvdata(dai->dev);
1256 struct snd_kcontrol *kcontrol = NULL;
Kuirong Wang274f21a2011-12-15 21:29:08 -08001257 int rc = 0;
1258
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -07001259 if (mi2s_dai_data->rx_dai.mi2s_dai_data.port_config.mi2s.line) {
Patrick Lai04baee942012-05-01 14:38:47 -07001260 kcontrol = snd_ctl_new1(&mi2s_config_controls[0],
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -07001261 &mi2s_dai_data->rx_dai.mi2s_dai_data);
Patrick Lai04baee942012-05-01 14:38:47 -07001262 rc = snd_ctl_add(dai->card->snd_card, kcontrol);
Kuirong Wang274f21a2011-12-15 21:29:08 -08001263
Patrick Lai04baee942012-05-01 14:38:47 -07001264 if (IS_ERR_VALUE(rc)) {
1265 dev_err(dai->dev, "%s: err add RX fmt ctl\n", __func__);
1266 goto rtn;
1267 }
Kuirong Wang274f21a2011-12-15 21:29:08 -08001268 }
Kuirong Wang875d1ec2012-04-02 19:56:25 -07001269
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -07001270 if (mi2s_dai_data->tx_dai.mi2s_dai_data.port_config.mi2s.line) {
Patrick Lai04baee942012-05-01 14:38:47 -07001271 rc = snd_ctl_add(dai->card->snd_card,
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -07001272 snd_ctl_new1(&mi2s_config_controls[2],
1273 &mi2s_dai_data->tx_dai.mi2s_dai_data));
Patrick Lai04baee942012-05-01 14:38:47 -07001274
1275 if (IS_ERR_VALUE(rc)) {
1276 if (kcontrol)
1277 snd_ctl_remove(dai->card->snd_card, kcontrol);
1278 dev_err(dai->dev, "%s: err add TX fmt ctl\n", __func__);
1279 }
1280 }
1281
Kuirong Wang274f21a2011-12-15 21:29:08 -08001282rtn:
1283 return rc;
1284}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001285
Patrick Lai04baee942012-05-01 14:38:47 -07001286static int msm_dai_q6_dai_mi2s_remove(struct snd_soc_dai *dai)
1287{
1288 struct msm_dai_q6_mi2s_dai_data *mi2s_dai_data =
1289 dev_get_drvdata(dai->dev);
1290 int rc;
1291
1292 /* If AFE port is still up, close it */
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -07001293 if (test_bit(STATUS_PORT_STARTED,
1294 mi2s_dai_data->rx_dai.mi2s_dai_data.status_mask)) {
Patrick Lai04baee942012-05-01 14:38:47 -07001295 rc = afe_close(MI2S_RX); /* can block */
1296 if (IS_ERR_VALUE(rc))
1297 dev_err(dai->dev, "fail to close MI2S_RX port\n");
1298 clear_bit(STATUS_PORT_STARTED,
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -07001299 mi2s_dai_data->rx_dai.mi2s_dai_data.status_mask);
Patrick Lai04baee942012-05-01 14:38:47 -07001300 }
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -07001301 if (test_bit(STATUS_PORT_STARTED,
1302 mi2s_dai_data->tx_dai.mi2s_dai_data.status_mask)) {
Patrick Lai04baee942012-05-01 14:38:47 -07001303 rc = afe_close(MI2S_TX); /* can block */
1304 if (IS_ERR_VALUE(rc))
1305 dev_err(dai->dev, "fail to close MI2S_TX port\n");
1306 clear_bit(STATUS_PORT_STARTED,
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -07001307 mi2s_dai_data->tx_dai.mi2s_dai_data.status_mask);
Patrick Lai04baee942012-05-01 14:38:47 -07001308 }
1309 kfree(mi2s_dai_data);
1310 snd_soc_unregister_dai(dai->dev);
1311
1312 return 0;
1313}
1314
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001315static int msm_dai_q6_dai_probe(struct snd_soc_dai *dai)
1316{
1317 struct msm_dai_q6_dai_data *dai_data;
1318 int rc = 0;
Kuirong Wang875d1ec2012-04-02 19:56:25 -07001319 const struct snd_kcontrol_new *kcontrol;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001320
1321 dai_data = kzalloc(sizeof(struct msm_dai_q6_dai_data),
1322 GFP_KERNEL);
1323
1324 if (!dai_data) {
1325 dev_err(dai->dev, "DAI-%d: fail to allocate dai data\n",
1326 dai->id);
1327 rc = -ENOMEM;
1328 } else
1329 dev_set_drvdata(dai->dev, dai_data);
Kuirong Wang875d1ec2012-04-02 19:56:25 -07001330 if (dai->id == SECONDARY_I2S_RX) {
1331 kcontrol = &mi2s_config_controls[1];
1332 rc = snd_ctl_add(dai->card->snd_card,
1333 snd_ctl_new1(kcontrol, dai_data));
1334 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001335
1336 return rc;
1337}
1338
1339static int msm_dai_q6_dai_remove(struct snd_soc_dai *dai)
1340{
1341 struct msm_dai_q6_dai_data *dai_data;
1342 int rc;
1343
1344 dai_data = dev_get_drvdata(dai->dev);
1345
1346 /* If AFE port is still up, close it */
1347 if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
Helen Zeng0705a5f2011-10-14 15:29:52 -07001348 switch (dai->id) {
1349 case VOICE_PLAYBACK_TX:
Helen Zenge3d716a2011-10-14 16:32:16 -07001350 case VOICE_RECORD_TX:
1351 case VOICE_RECORD_RX:
Helen Zeng0705a5f2011-10-14 15:29:52 -07001352 pr_debug("%s, stop pseudo port:%d\n",
1353 __func__, dai->id);
1354 rc = afe_stop_pseudo_port(dai->id);
1355 break;
1356 default:
1357 rc = afe_close(dai->id); /* can block */
1358 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001359 if (IS_ERR_VALUE(rc))
1360 dev_err(dai->dev, "fail to close AFE port\n");
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301361 clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001362 }
1363 kfree(dai_data);
1364 snd_soc_unregister_dai(dai->dev);
1365
1366 return 0;
1367}
1368
Lei Zhou157c1842011-08-19 13:05:04 -04001369static int msm_dai_q6_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
1370{
1371 int rc = 0;
1372
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001373 dev_dbg(dai->dev, "enter %s, id = %d fmt[%d]\n", __func__,
1374 dai->id, fmt);
Lei Zhou157c1842011-08-19 13:05:04 -04001375 switch (dai->id) {
1376 case PRIMARY_I2S_TX:
1377 case PRIMARY_I2S_RX:
Kuirong Wang9bbf6132012-01-10 18:28:49 -08001378 case SECONDARY_I2S_RX:
Lei Zhou157c1842011-08-19 13:05:04 -04001379 rc = msm_dai_q6_cdc_set_fmt(dai, fmt);
1380 break;
1381 default:
1382 dev_err(dai->dev, "invalid cpu_dai set_fmt\n");
1383 rc = -EINVAL;
1384 break;
1385 }
1386
1387 return rc;
1388}
1389
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001390static int msm_dai_q6_set_channel_map(struct snd_soc_dai *dai,
1391 unsigned int tx_num, unsigned int *tx_slot,
1392 unsigned int rx_num, unsigned int *rx_slot)
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001393{
1394 int rc = 0;
1395 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
1396 unsigned int i = 0;
1397
Kiran Kandifd30c892012-05-21 23:03:26 -07001398 dev_dbg(dai->dev, "%s: dai_id = %d\n", __func__, dai->id);
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001399 switch (dai->id) {
1400 case SLIMBUS_0_RX:
Neema Shetty3c9d2862012-03-11 01:25:32 -08001401 case SLIMBUS_1_RX:
Kiran Kandifd30c892012-05-21 23:03:26 -07001402 case SLIMBUS_2_RX:
Neema Shetty74131ac2012-05-09 13:35:26 -07001403 case SLIMBUS_3_RX:
Helen Zeng8f925502012-03-05 16:50:17 -08001404 case SLIMBUS_4_RX:
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001405 /* channel number to be between 128 and 255. For RX port
1406 * use channel numbers from 138 to 144, for TX port
1407 * use channel numbers from 128 to 137
Neema Shetty3c9d2862012-03-11 01:25:32 -08001408 * For ports between MDM-APQ use channel numbers from 145
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001409 */
Bharath Ramachandramurthy94ad7e22012-02-28 18:44:07 -08001410 if (!rx_slot)
1411 return -EINVAL;
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001412 for (i = 0; i < rx_num; i++) {
1413 dai_data->port_config.slim_sch.slave_ch_mapping[i] =
1414 rx_slot[i];
1415 pr_debug("%s: find number of channels[%d] ch[%d]\n",
1416 __func__, i,
1417 rx_slot[i]);
1418 }
1419 dai_data->port_config.slim_sch.num_channels = rx_num;
Kiran Kandi1e6371d2012-03-29 11:48:57 -07001420 pr_debug("%s:SLIMBUS_%d_RX cnt[%d] ch[%d %d]\n", __func__,
1421 (dai->id - SLIMBUS_0_RX) / 2,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001422 rx_num, dai_data->port_config.slim_sch.slave_ch_mapping[0],
1423 dai_data->port_config.slim_sch.slave_ch_mapping[1]);
1424
1425 break;
1426 case SLIMBUS_0_TX:
Neema Shetty3c9d2862012-03-11 01:25:32 -08001427 case SLIMBUS_1_TX:
Kiran Kandi1e6371d2012-03-29 11:48:57 -07001428 case SLIMBUS_2_TX:
Helen Zeng38c3c962012-05-17 14:56:20 -07001429 case SLIMBUS_3_TX:
Helen Zeng8f925502012-03-05 16:50:17 -08001430 case SLIMBUS_4_TX:
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001431 /* channel number to be between 128 and 255. For RX port
1432 * use channel numbers from 138 to 144, for TX port
1433 * use channel numbers from 128 to 137
Neema Shetty3c9d2862012-03-11 01:25:32 -08001434 * For ports between MDM-APQ use channel numbers from 145
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001435 */
Bharath Ramachandramurthy94ad7e22012-02-28 18:44:07 -08001436 if (!tx_slot)
1437 return -EINVAL;
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001438 for (i = 0; i < tx_num; i++) {
1439 dai_data->port_config.slim_sch.slave_ch_mapping[i] =
1440 tx_slot[i];
1441 pr_debug("%s: find number of channels[%d] ch[%d]\n",
1442 __func__, i, tx_slot[i]);
1443 }
1444 dai_data->port_config.slim_sch.num_channels = tx_num;
Kiran Kandi1e6371d2012-03-29 11:48:57 -07001445 pr_debug("%s:SLIMBUS_%d_TX cnt[%d] ch[%d %d]\n", __func__,
1446 (dai->id - SLIMBUS_0_TX) / 2,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001447 tx_num, dai_data->port_config.slim_sch.slave_ch_mapping[0],
1448 dai_data->port_config.slim_sch.slave_ch_mapping[1]);
1449 break;
1450 default:
1451 dev_err(dai->dev, "invalid cpu_dai set_fmt\n");
1452 rc = -EINVAL;
1453 break;
1454 }
1455 return rc;
1456}
1457
Patrick Lai04baee942012-05-01 14:38:47 -07001458static struct snd_soc_dai_ops msm_dai_q6_mi2s_ops = {
1459 .startup = msm_dai_q6_mi2s_startup,
1460 .prepare = msm_dai_q6_mi2s_prepare,
Patrick Lai04baee942012-05-01 14:38:47 -07001461 .hw_params = msm_dai_q6_mi2s_hw_params,
1462 .shutdown = msm_dai_q6_mi2s_shutdown,
1463 .set_fmt = msm_dai_q6_mi2s_set_fmt,
1464};
1465
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001466static struct snd_soc_dai_ops msm_dai_q6_ops = {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001467 .prepare = msm_dai_q6_prepare,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001468 .hw_params = msm_dai_q6_hw_params,
1469 .shutdown = msm_dai_q6_shutdown,
Lei Zhou157c1842011-08-19 13:05:04 -04001470 .set_fmt = msm_dai_q6_set_fmt,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001471 .set_channel_map = msm_dai_q6_set_channel_map,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001472};
1473
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001474static struct snd_soc_dai_ops msm_dai_q6_auxpcm_ops = {
1475 .prepare = msm_dai_q6_auxpcm_prepare,
1476 .trigger = msm_dai_q6_auxpcm_trigger,
1477 .hw_params = msm_dai_q6_auxpcm_hw_params,
1478 .shutdown = msm_dai_q6_auxpcm_shutdown,
1479};
1480
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -07001481static struct snd_soc_dai_ops msm_dai_q6_sec_auxpcm_ops = {
1482 .prepare = msm_dai_q6_sec_auxpcm_prepare,
1483 .trigger = msm_dai_q6_auxpcm_trigger,
1484 .hw_params = msm_dai_q6_sec_auxpcm_hw_params,
1485 .shutdown = msm_dai_q6_sec_auxpcm_shutdown,
1486};
1487
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001488static struct snd_soc_dai_driver msm_dai_q6_i2s_rx_dai = {
1489 .playback = {
1490 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1491 SNDRV_PCM_RATE_16000,
1492 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1493 .channels_min = 1,
Kiran Kandi9db678b2012-01-15 14:25:59 -08001494 .channels_max = 4,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001495 .rate_min = 8000,
1496 .rate_max = 48000,
1497 },
1498 .ops = &msm_dai_q6_ops,
1499 .probe = msm_dai_q6_dai_probe,
1500 .remove = msm_dai_q6_dai_remove,
1501};
1502
1503static struct snd_soc_dai_driver msm_dai_q6_i2s_tx_dai = {
1504 .capture = {
1505 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1506 SNDRV_PCM_RATE_16000,
1507 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1508 .channels_min = 1,
1509 .channels_max = 2,
1510 .rate_min = 8000,
1511 .rate_max = 48000,
1512 },
1513 .ops = &msm_dai_q6_ops,
1514 .probe = msm_dai_q6_dai_probe,
1515 .remove = msm_dai_q6_dai_remove,
1516};
1517
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301518static struct snd_soc_dai_driver msm_dai_q6_afe_rx_dai = {
1519 .playback = {
1520 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1521 SNDRV_PCM_RATE_16000,
1522 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1523 .channels_min = 1,
1524 .channels_max = 2,
1525 .rate_min = 8000,
1526 .rate_max = 48000,
1527 },
1528 .ops = &msm_dai_q6_ops,
1529 .probe = msm_dai_q6_dai_probe,
1530 .remove = msm_dai_q6_dai_remove,
1531};
1532
1533static struct snd_soc_dai_driver msm_dai_q6_afe_tx_dai = {
1534 .capture = {
1535 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1536 SNDRV_PCM_RATE_16000,
1537 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1538 .channels_min = 1,
Mingming Yin647e9ea2012-03-17 19:56:10 -07001539 .channels_max = 4,
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301540 .rate_min = 8000,
1541 .rate_max = 48000,
1542 },
1543 .ops = &msm_dai_q6_ops,
1544 .probe = msm_dai_q6_dai_probe,
1545 .remove = msm_dai_q6_dai_remove,
1546};
1547
Helen Zeng0705a5f2011-10-14 15:29:52 -07001548static struct snd_soc_dai_driver msm_dai_q6_voice_playback_tx_dai = {
1549 .playback = {
1550 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1551 SNDRV_PCM_RATE_16000,
1552 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1553 .channels_min = 1,
1554 .channels_max = 2,
1555 .rate_max = 48000,
1556 .rate_min = 8000,
1557 },
1558 .ops = &msm_dai_q6_ops,
1559 .probe = msm_dai_q6_dai_probe,
1560 .remove = msm_dai_q6_dai_remove,
1561};
1562
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001563static struct snd_soc_dai_driver msm_dai_q6_slimbus_rx_dai = {
1564 .playback = {
1565 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1566 SNDRV_PCM_RATE_16000,
1567 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1568 .channels_min = 1,
1569 .channels_max = 2,
1570 .rate_min = 8000,
1571 .rate_max = 48000,
1572 },
1573 .ops = &msm_dai_q6_ops,
1574 .probe = msm_dai_q6_dai_probe,
1575 .remove = msm_dai_q6_dai_remove,
1576};
1577
1578static struct snd_soc_dai_driver msm_dai_q6_slimbus_tx_dai = {
1579 .capture = {
1580 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1581 SNDRV_PCM_RATE_16000,
1582 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1583 .channels_min = 1,
1584 .channels_max = 2,
1585 .rate_min = 8000,
1586 .rate_max = 48000,
1587 },
1588 .ops = &msm_dai_q6_ops,
1589 .probe = msm_dai_q6_dai_probe,
1590 .remove = msm_dai_q6_dai_remove,
1591};
1592
Helen Zenge3d716a2011-10-14 16:32:16 -07001593static struct snd_soc_dai_driver msm_dai_q6_incall_record_dai = {
1594 .capture = {
1595 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1596 SNDRV_PCM_RATE_16000,
1597 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1598 .channels_min = 1,
1599 .channels_max = 2,
1600 .rate_min = 8000,
1601 .rate_max = 48000,
1602 },
1603 .ops = &msm_dai_q6_ops,
1604 .probe = msm_dai_q6_dai_probe,
1605 .remove = msm_dai_q6_dai_remove,
1606};
1607
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001608static struct snd_soc_dai_driver msm_dai_q6_bt_sco_rx_dai = {
1609 .playback = {
1610 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
1611 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1612 .channels_min = 1,
1613 .channels_max = 1,
1614 .rate_max = 16000,
1615 .rate_min = 8000,
1616 },
1617 .ops = &msm_dai_q6_ops,
1618 .probe = msm_dai_q6_dai_probe,
1619 .remove = msm_dai_q6_dai_remove,
1620};
1621
1622static struct snd_soc_dai_driver msm_dai_q6_bt_sco_tx_dai = {
Patrick Laibd5021e2012-06-12 01:27:20 -07001623 .capture = {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001624 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
1625 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1626 .channels_min = 1,
1627 .channels_max = 1,
1628 .rate_max = 16000,
1629 .rate_min = 8000,
1630 },
1631 .ops = &msm_dai_q6_ops,
1632 .probe = msm_dai_q6_dai_probe,
1633 .remove = msm_dai_q6_dai_remove,
1634};
1635
1636static struct snd_soc_dai_driver msm_dai_q6_fm_rx_dai = {
1637 .playback = {
1638 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1639 SNDRV_PCM_RATE_16000,
1640 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1641 .channels_min = 2,
1642 .channels_max = 2,
1643 .rate_max = 48000,
1644 .rate_min = 8000,
1645 },
1646 .ops = &msm_dai_q6_ops,
1647 .probe = msm_dai_q6_dai_probe,
1648 .remove = msm_dai_q6_dai_remove,
1649};
1650
1651static struct snd_soc_dai_driver msm_dai_q6_fm_tx_dai = {
Patrick Laibd5021e2012-06-12 01:27:20 -07001652 .capture = {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001653 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1654 SNDRV_PCM_RATE_16000,
1655 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1656 .channels_min = 2,
1657 .channels_max = 2,
1658 .rate_max = 48000,
1659 .rate_min = 8000,
1660 },
1661 .ops = &msm_dai_q6_ops,
1662 .probe = msm_dai_q6_dai_probe,
1663 .remove = msm_dai_q6_dai_remove,
1664};
1665
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001666static struct snd_soc_dai_driver msm_dai_q6_aux_pcm_rx_dai = {
1667 .playback = {
Kuirong Wang547a9982012-05-04 18:29:11 -07001668 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001669 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1670 .channels_min = 1,
1671 .channels_max = 1,
Kuirong Wang547a9982012-05-04 18:29:11 -07001672 .rate_max = 16000,
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001673 .rate_min = 8000,
1674 },
1675 .ops = &msm_dai_q6_auxpcm_ops,
1676 .probe = msm_dai_q6_dai_auxpcm_probe,
1677 .remove = msm_dai_q6_dai_auxpcm_remove,
1678};
1679
1680static struct snd_soc_dai_driver msm_dai_q6_aux_pcm_tx_dai = {
1681 .capture = {
Kuirong Wang547a9982012-05-04 18:29:11 -07001682 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001683 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1684 .channels_min = 1,
1685 .channels_max = 1,
Kuirong Wang547a9982012-05-04 18:29:11 -07001686 .rate_max = 16000,
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001687 .rate_min = 8000,
1688 },
Kiran Kandi5f4ab692012-02-23 11:23:56 -08001689 .ops = &msm_dai_q6_auxpcm_ops,
1690 .probe = msm_dai_q6_dai_auxpcm_probe,
1691 .remove = msm_dai_q6_dai_auxpcm_remove,
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001692};
1693
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -07001694static struct snd_soc_dai_driver msm_dai_q6_sec_aux_pcm_rx_dai = {
1695 .playback = {
1696 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
1697 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1698 .channels_min = 1,
1699 .channels_max = 1,
1700 .rate_max = 16000,
1701 .rate_min = 8000,
1702 },
1703 .ops = &msm_dai_q6_sec_auxpcm_ops,
1704 .probe = msm_dai_q6_dai_sec_auxpcm_probe,
1705 .remove = msm_dai_q6_dai_sec_auxpcm_remove,
1706};
1707
1708static struct snd_soc_dai_driver msm_dai_q6_sec_aux_pcm_tx_dai = {
1709 .capture = {
1710 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
1711 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1712 .channels_min = 1,
1713 .channels_max = 1,
1714 .rate_max = 16000,
1715 .rate_min = 8000,
1716 },
1717 .ops = &msm_dai_q6_sec_auxpcm_ops,
1718 .probe = msm_dai_q6_dai_sec_auxpcm_probe,
1719 .remove = msm_dai_q6_dai_sec_auxpcm_remove,
1720};
1721
Patrick Lai04baee942012-05-01 14:38:47 -07001722/* Channel min and max are initialized base on platform data */
1723static struct snd_soc_dai_driver msm_dai_q6_mi2s_dai = {
Kuirong Wang274f21a2011-12-15 21:29:08 -08001724 .playback = {
1725 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1726 SNDRV_PCM_RATE_16000,
1727 .formats = SNDRV_PCM_FMTBIT_S16_LE,
Kuirong Wang274f21a2011-12-15 21:29:08 -08001728 .rate_min = 8000,
1729 .rate_max = 48000,
1730 },
Kuirong Wang623b50f2012-04-16 15:51:14 -07001731 .capture = {
1732 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1733 SNDRV_PCM_RATE_16000,
1734 .formats = SNDRV_PCM_FMTBIT_S16_LE,
Patrick Lai04baee942012-05-01 14:38:47 -07001735 .rate_min = 8000,
1736 .rate_max = 48000,
Kuirong Wang623b50f2012-04-16 15:51:14 -07001737 },
Patrick Lai04baee942012-05-01 14:38:47 -07001738 .ops = &msm_dai_q6_mi2s_ops,
Kuirong Wang623b50f2012-04-16 15:51:14 -07001739 .probe = msm_dai_q6_dai_mi2s_probe,
Patrick Lai04baee942012-05-01 14:38:47 -07001740 .remove = msm_dai_q6_dai_mi2s_remove,
Kuirong Wang623b50f2012-04-16 15:51:14 -07001741};
1742
Neema Shetty3c9d2862012-03-11 01:25:32 -08001743static struct snd_soc_dai_driver msm_dai_q6_slimbus_1_rx_dai = {
1744 .playback = {
1745 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
1746 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1747 .channels_min = 1,
1748 .channels_max = 1,
1749 .rate_min = 8000,
1750 .rate_max = 16000,
1751 },
1752 .ops = &msm_dai_q6_ops,
1753 .probe = msm_dai_q6_dai_probe,
1754 .remove = msm_dai_q6_dai_remove,
1755};
1756
1757static struct snd_soc_dai_driver msm_dai_q6_slimbus_1_tx_dai = {
1758 .capture = {
1759 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
1760 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1761 .channels_min = 1,
1762 .channels_max = 1,
1763 .rate_min = 8000,
1764 .rate_max = 16000,
1765 },
1766 .ops = &msm_dai_q6_ops,
1767 .probe = msm_dai_q6_dai_probe,
1768 .remove = msm_dai_q6_dai_remove,
1769};
1770
Kiran Kandifd30c892012-05-21 23:03:26 -07001771static struct snd_soc_dai_driver msm_dai_q6_slimbus_2_rx_dai = {
1772 .playback = {
1773 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1774 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_96000 |
1775 SNDRV_PCM_RATE_192000,
1776 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1777 .channels_min = 1,
1778 .channels_max = 2,
1779 .rate_min = 8000,
1780 .rate_max = 192000,
1781 },
1782 .ops = &msm_dai_q6_ops,
1783 .probe = msm_dai_q6_dai_probe,
1784 .remove = msm_dai_q6_dai_remove,
1785};
1786
Kiran Kandi1e6371d2012-03-29 11:48:57 -07001787static struct snd_soc_dai_driver msm_dai_q6_slimbus_2_tx_dai = {
1788 .capture = {
1789 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1790 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_96000 |
1791 SNDRV_PCM_RATE_192000,
1792 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1793 .channels_min = 1,
1794 .channels_max = 4,
1795 .rate_min = 8000,
1796 .rate_max = 192000,
1797 },
1798 .ops = &msm_dai_q6_ops,
1799 .probe = msm_dai_q6_dai_probe,
1800 .remove = msm_dai_q6_dai_remove,
1801};
1802
Neema Shetty74131ac2012-05-09 13:35:26 -07001803static struct snd_soc_dai_driver msm_dai_q6_slimbus_3_rx_dai = {
1804 .playback = {
1805 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
1806 SNDRV_PCM_RATE_48000,
1807 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1808 .channels_min = 1,
1809 .channels_max = 2,
1810 .rate_min = 8000,
1811 .rate_max = 48000,
1812 },
1813 .ops = &msm_dai_q6_ops,
1814 .probe = msm_dai_q6_dai_probe,
1815 .remove = msm_dai_q6_dai_remove,
1816};
1817
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001818/* To do: change to register DAIs as batch */
1819static __devinit int msm_dai_q6_dev_probe(struct platform_device *pdev)
1820{
1821 int rc = 0;
1822
1823 dev_dbg(&pdev->dev, "dev name %s\n", dev_name(&pdev->dev));
1824
1825 switch (pdev->id) {
1826 case PRIMARY_I2S_RX:
Kuirong Wang9bbf6132012-01-10 18:28:49 -08001827 case SECONDARY_I2S_RX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001828 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_i2s_rx_dai);
1829 break;
1830 case PRIMARY_I2S_TX:
1831 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_i2s_tx_dai);
1832 break;
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001833 case PCM_RX:
1834 rc = snd_soc_register_dai(&pdev->dev,
1835 &msm_dai_q6_aux_pcm_rx_dai);
1836 break;
1837 case PCM_TX:
1838 rc = snd_soc_register_dai(&pdev->dev,
1839 &msm_dai_q6_aux_pcm_tx_dai);
1840 break;
Patrick Lai04baee942012-05-01 14:38:47 -07001841
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -07001842 case SECONDARY_PCM_RX:
1843 rc = snd_soc_register_dai(&pdev->dev,
1844 &msm_dai_q6_sec_aux_pcm_rx_dai);
1845 break;
1846 case SECONDARY_PCM_TX:
1847 rc = snd_soc_register_dai(&pdev->dev,
1848 &msm_dai_q6_sec_aux_pcm_tx_dai);
1849 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001850 case SLIMBUS_0_RX:
Helen Zeng8f925502012-03-05 16:50:17 -08001851 case SLIMBUS_4_RX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001852 rc = snd_soc_register_dai(&pdev->dev,
1853 &msm_dai_q6_slimbus_rx_dai);
1854 break;
1855 case SLIMBUS_0_TX:
Helen Zeng8f925502012-03-05 16:50:17 -08001856 case SLIMBUS_4_TX:
Helen Zeng38c3c962012-05-17 14:56:20 -07001857 case SLIMBUS_3_TX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001858 rc = snd_soc_register_dai(&pdev->dev,
1859 &msm_dai_q6_slimbus_tx_dai);
Neema Shetty3c9d2862012-03-11 01:25:32 -08001860 break;
Neema Shetty3c9d2862012-03-11 01:25:32 -08001861 case SLIMBUS_1_RX:
1862 rc = snd_soc_register_dai(&pdev->dev,
1863 &msm_dai_q6_slimbus_1_rx_dai);
1864 break;
1865 case SLIMBUS_1_TX:
1866 rc = snd_soc_register_dai(&pdev->dev,
1867 &msm_dai_q6_slimbus_1_tx_dai);
1868 break;
Kiran Kandifd30c892012-05-21 23:03:26 -07001869 case SLIMBUS_2_RX:
1870 rc = snd_soc_register_dai(&pdev->dev,
1871 &msm_dai_q6_slimbus_2_rx_dai);
1872 break;
Kiran Kandi1e6371d2012-03-29 11:48:57 -07001873 case SLIMBUS_2_TX:
1874 rc = snd_soc_register_dai(&pdev->dev,
1875 &msm_dai_q6_slimbus_2_tx_dai);
1876 break;
Neema Shetty74131ac2012-05-09 13:35:26 -07001877 case SLIMBUS_3_RX:
1878 rc = snd_soc_register_dai(&pdev->dev,
1879 &msm_dai_q6_slimbus_3_rx_dai);
1880 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001881 case INT_BT_SCO_RX:
1882 rc = snd_soc_register_dai(&pdev->dev,
1883 &msm_dai_q6_bt_sco_rx_dai);
1884 break;
1885 case INT_BT_SCO_TX:
1886 rc = snd_soc_register_dai(&pdev->dev,
1887 &msm_dai_q6_bt_sco_tx_dai);
1888 break;
1889 case INT_FM_RX:
1890 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_fm_rx_dai);
1891 break;
1892 case INT_FM_TX:
1893 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_fm_tx_dai);
1894 break;
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301895 case RT_PROXY_DAI_001_RX:
1896 case RT_PROXY_DAI_002_RX:
1897 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_afe_rx_dai);
1898 break;
1899 case RT_PROXY_DAI_001_TX:
1900 case RT_PROXY_DAI_002_TX:
1901 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_afe_tx_dai);
1902 break;
Helen Zeng0705a5f2011-10-14 15:29:52 -07001903 case VOICE_PLAYBACK_TX:
1904 rc = snd_soc_register_dai(&pdev->dev,
1905 &msm_dai_q6_voice_playback_tx_dai);
1906 break;
Helen Zenge3d716a2011-10-14 16:32:16 -07001907 case VOICE_RECORD_RX:
1908 case VOICE_RECORD_TX:
1909 rc = snd_soc_register_dai(&pdev->dev,
1910 &msm_dai_q6_incall_record_dai);
1911 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001912 default:
1913 rc = -ENODEV;
1914 break;
1915 }
1916 return rc;
1917}
1918
1919static __devexit int msm_dai_q6_dev_remove(struct platform_device *pdev)
1920{
1921 snd_soc_unregister_dai(&pdev->dev);
1922 return 0;
1923}
1924
Patrick Lai04baee942012-05-01 14:38:47 -07001925static __devinit int msm_dai_q6_mi2s_dev_probe(struct platform_device *pdev)
1926{
1927 struct msm_dai_q6_mi2s_dai_data *dai_data;
1928 int rc = 0;
1929
1930 dev_dbg(&pdev->dev, "%s: pdev %p dev %p\n", __func__, pdev, &pdev->dev);
1931
1932 dai_data = kzalloc(sizeof(struct msm_dai_q6_mi2s_dai_data),
1933 GFP_KERNEL);
1934
1935 if (!dai_data) {
1936 dev_err(&pdev->dev, "fail to allocate dai data\n");
1937 rc = -ENOMEM;
1938 goto rtn;
1939 } else
1940 dev_set_drvdata(&pdev->dev, dai_data);
1941
1942 rc = msm_dai_q6_mi2s_platform_data_validation(pdev,
1943 &msm_dai_q6_mi2s_dai);
1944 if (IS_ERR_VALUE(rc))
1945 goto err_pdata;
1946
1947 dai_data->rate_constraint.count = 1;
1948 dai_data->bitwidth_constraint.count = 1;
1949 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_mi2s_dai);
1950
1951 if (IS_ERR_VALUE(rc))
1952 goto err_pdata;
1953
1954 return 0;
1955
1956err_pdata:
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -07001957
1958 dev_err(&pdev->dev, "fail to msm_dai_q6_mi2s_dev_probe\n");
Patrick Lai04baee942012-05-01 14:38:47 -07001959 kfree(dai_data);
1960rtn:
1961 return rc;
1962}
1963
1964static __devexit int msm_dai_q6_mi2s_dev_remove(struct platform_device *pdev)
1965{
1966 snd_soc_unregister_dai(&pdev->dev);
1967 return 0;
1968}
1969
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001970static struct platform_driver msm_dai_q6_driver = {
1971 .probe = msm_dai_q6_dev_probe,
1972 .remove = msm_dai_q6_dev_remove,
1973 .driver = {
1974 .name = "msm-dai-q6",
1975 .owner = THIS_MODULE,
1976 },
1977};
1978
Patrick Lai04baee942012-05-01 14:38:47 -07001979static struct platform_driver msm_dai_q6_mi2s_driver = {
1980 .probe = msm_dai_q6_mi2s_dev_probe,
1981 .remove = msm_dai_q6_mi2s_dev_remove,
1982 .driver = {
1983 .name = "msm-dai-q6-mi2s",
1984 .owner = THIS_MODULE,
1985 },
1986};
1987
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001988static int __init msm_dai_q6_init(void)
1989{
Patrick Lai04baee942012-05-01 14:38:47 -07001990 int rc1, rc2;
1991
1992 rc1 = platform_driver_register(&msm_dai_q6_mi2s_driver);
1993
1994 if (IS_ERR_VALUE(rc1))
1995 pr_err("%s: fail to register mi2s dai driver\n", __func__);
1996
1997 rc2 = platform_driver_register(&msm_dai_q6_driver);
1998
1999 if (IS_ERR_VALUE(rc2))
2000 pr_err("%s: fail to register mi2s dai driver\n", __func__);
2001
2002 return (IS_ERR_VALUE(rc1) && IS_ERR_VALUE(rc2)) ? -1 : 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002003}
2004module_init(msm_dai_q6_init);
2005
2006static void __exit msm_dai_q6_exit(void)
2007{
2008 platform_driver_unregister(&msm_dai_q6_driver);
2009}
2010module_exit(msm_dai_q6_exit);
2011
2012/* Module information */
2013MODULE_DESCRIPTION("MSM DSP DAI driver");
2014MODULE_LICENSE("GPL v2");