blob: 5f3c036e47d6352c4c74553cae8e4f856924c0a1 [file] [log] [blame]
Duy Truonge833aca2013-02-12 13:35:08 -08001/* Copyright (c) 2011-2012, The Linux Foundation. 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);
Ajay Dudani501307f2012-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 */
Ajay Dudani501307f2012-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))
Ajay Dudani501307f2012-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:
Aviral Gupta33eeb702012-08-09 17:00:30 +0530468 case 4:
469 case 6:
470 case 8:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700471 dai_data->port_config.mi2s.channel = MSM_AFE_STEREO;
472 break;
473 case 1:
474 dai_data->port_config.mi2s.channel = MSM_AFE_MONO;
475 break;
476 default:
477 return -EINVAL;
478 break;
479 }
480 dai_data->rate = params_rate(params);
481
482 dev_dbg(dai->dev, " channel %d sample rate %d entered\n",
483 dai_data->channels, dai_data->rate);
484
485 /* Q6 only supports 16 as now */
486 dai_data->port_config.mi2s.bitwidth = 16;
487 dai_data->port_config.mi2s.line = 1;
Kuirong Wang274f21a2011-12-15 21:29:08 -0800488 return 0;
489}
490
Lei Zhou157c1842011-08-19 13:05:04 -0400491static int msm_dai_q6_cdc_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
492{
493 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
494
495 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
496 case SND_SOC_DAIFMT_CBS_CFS:
497 dai_data->port_config.mi2s.ws = 1; /* CPU is master */
498 break;
499 case SND_SOC_DAIFMT_CBM_CFM:
500 dai_data->port_config.mi2s.ws = 0; /* CPU is slave */
501 break;
502 default:
503 return -EINVAL;
504 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700505
506 return 0;
507}
508
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700509
510static int msm_dai_q6_slim_bus_hw_params(struct snd_pcm_hw_params *params,
511 struct snd_soc_dai *dai, int stream)
512{
513 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700514
515 dai_data->channels = params_channels(params);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700516 dai_data->rate = params_rate(params);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700517
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700518 /* Q6 only supports 16 as now */
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800519 dai_data->port_config.slim_sch.bit_width = 16;
520 dai_data->port_config.slim_sch.data_format = 0;
521 dai_data->port_config.slim_sch.num_channels = dai_data->channels;
522 dai_data->port_config.slim_sch.reserved = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700523
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800524 dev_dbg(dai->dev, "%s:slimbus_dev_id[%hu] bit_wd[%hu] format[%hu]\n"
525 "num_channel %hu slave_ch_mapping[0] %hu\n"
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700526 "slave_port_mapping[1] %hu slave_port_mapping[2] %hu\n"
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700527 "slave_port_mapping[3] %hu\n sample_rate %d\n", __func__,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800528 dai_data->port_config.slim_sch.slimbus_dev_id,
529 dai_data->port_config.slim_sch.bit_width,
530 dai_data->port_config.slim_sch.data_format,
531 dai_data->port_config.slim_sch.num_channels,
532 dai_data->port_config.slim_sch.slave_ch_mapping[0],
533 dai_data->port_config.slim_sch.slave_ch_mapping[1],
534 dai_data->port_config.slim_sch.slave_ch_mapping[2],
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700535 dai_data->port_config.slim_sch.slave_ch_mapping[3],
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700536 dai_data->rate);
537
538 return 0;
539}
540
541static int msm_dai_q6_bt_fm_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);
545
546 dai_data->channels = params_channels(params);
547 dai_data->rate = params_rate(params);
548
549 dev_dbg(dai->dev, "channels %d sample rate %d entered\n",
550 dai_data->channels, dai_data->rate);
551
552 memset(&dai_data->port_config, 0, sizeof(dai_data->port_config));
553
554 return 0;
555}
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700556static int msm_dai_q6_auxpcm_hw_params(
557 struct snd_pcm_substream *substream,
558 struct snd_pcm_hw_params *params,
559 struct snd_soc_dai *dai)
560{
561 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
562 struct msm_dai_auxpcm_pdata *auxpcm_pdata =
563 (struct msm_dai_auxpcm_pdata *) dai->dev->platform_data;
564
565 if (params_channels(params) != 1) {
566 dev_err(dai->dev, "AUX PCM supports only mono stream\n");
567 return -EINVAL;
568 }
569 dai_data->channels = params_channels(params);
570
Kuirong Wang547a9982012-05-04 18:29:11 -0700571 dai_data->rate = params_rate(params);
572 switch (dai_data->rate) {
573 case 8000:
574 dai_data->port_config.pcm.mode = auxpcm_pdata->mode_8k.mode;
575 dai_data->port_config.pcm.sync = auxpcm_pdata->mode_8k.sync;
576 dai_data->port_config.pcm.frame = auxpcm_pdata->mode_8k.frame;
577 dai_data->port_config.pcm.quant = auxpcm_pdata->mode_8k.quant;
578 dai_data->port_config.pcm.slot = auxpcm_pdata->mode_8k.slot;
579 dai_data->port_config.pcm.data = auxpcm_pdata->mode_8k.data;
580 break;
581 case 16000:
582 dai_data->port_config.pcm.mode = auxpcm_pdata->mode_16k.mode;
583 dai_data->port_config.pcm.sync = auxpcm_pdata->mode_16k.sync;
584 dai_data->port_config.pcm.frame = auxpcm_pdata->mode_16k.frame;
585 dai_data->port_config.pcm.quant = auxpcm_pdata->mode_16k.quant;
586 dai_data->port_config.pcm.slot = auxpcm_pdata->mode_16k.slot;
587 dai_data->port_config.pcm.data = auxpcm_pdata->mode_16k.data;
588 break;
589 default:
590 dev_err(dai->dev, "AUX PCM supports only 8kHz and 16kHz sampling rate\n");
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700591 return -EINVAL;
592 }
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700593
594 return 0;
595}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700596
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -0700597static int msm_dai_q6_sec_auxpcm_hw_params(
598 struct snd_pcm_substream *substream,
599 struct snd_pcm_hw_params *params,
600 struct snd_soc_dai *dai)
601{
602 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
603 struct msm_dai_auxpcm_pdata *auxpcm_pdata =
604 (struct msm_dai_auxpcm_pdata *) dai->dev->platform_data;
605
606 pr_debug("%s\n", __func__);
607 if (params_channels(params) != 1) {
608 dev_err(dai->dev, "SEC AUX PCM supports only mono stream\n");
609 return -EINVAL;
610 }
611 dai_data->channels = params_channels(params);
612
613 dai_data->rate = params_rate(params);
614 switch (dai_data->rate) {
615 case 8000:
616 dai_data->port_config.pcm.mode = auxpcm_pdata->mode_8k.mode;
617 dai_data->port_config.pcm.sync = auxpcm_pdata->mode_8k.sync;
618 dai_data->port_config.pcm.frame = auxpcm_pdata->mode_8k.frame;
619 dai_data->port_config.pcm.quant = auxpcm_pdata->mode_8k.quant;
620 dai_data->port_config.pcm.slot = auxpcm_pdata->mode_8k.slot;
621 dai_data->port_config.pcm.data = auxpcm_pdata->mode_8k.data;
622 break;
623 case 16000:
624 dai_data->port_config.pcm.mode = auxpcm_pdata->mode_16k.mode;
625 dai_data->port_config.pcm.sync = auxpcm_pdata->mode_16k.sync;
626 dai_data->port_config.pcm.frame = auxpcm_pdata->mode_16k.frame;
627 dai_data->port_config.pcm.quant = auxpcm_pdata->mode_16k.quant;
628 dai_data->port_config.pcm.slot = auxpcm_pdata->mode_16k.slot;
629 dai_data->port_config.pcm.data = auxpcm_pdata->mode_16k.data;
630 break;
631 default:
632 dev_err(dai->dev, "AUX PCM supports only 8kHz and 16kHz sampling rate\n");
633 return -EINVAL;
634 }
635
636 return 0;
637}
638
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530639static int msm_dai_q6_afe_rtproxy_hw_params(struct snd_pcm_hw_params *params,
640 struct snd_soc_dai *dai)
641{
642 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
643
644 dai_data->rate = params_rate(params);
645 dai_data->port_config.rtproxy.num_ch =
646 params_channels(params);
647
648 pr_debug("channel %d entered,dai_id: %d,rate: %d\n",
649 dai_data->port_config.rtproxy.num_ch, dai->id, dai_data->rate);
650
651 dai_data->port_config.rtproxy.bitwidth = 16; /* Q6 only supports 16 */
652 dai_data->port_config.rtproxy.interleaved = 1;
Asish Bhattacharyab3568cf2012-03-15 07:05:46 +0530653 dai_data->port_config.rtproxy.frame_sz = params_period_bytes(params);
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530654 dai_data->port_config.rtproxy.jitter =
655 dai_data->port_config.rtproxy.frame_sz/2;
656 dai_data->port_config.rtproxy.lw_mark = 0;
657 dai_data->port_config.rtproxy.hw_mark = 0;
658 dai_data->port_config.rtproxy.rsvd = 0;
659
660 return 0;
661}
662
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700663/* Current implementation assumes hw_param is called once
664 * This may not be the case but what to do when ADM and AFE
665 * port are already opened and parameter changes
666 */
667static int msm_dai_q6_hw_params(struct snd_pcm_substream *substream,
668 struct snd_pcm_hw_params *params,
669 struct snd_soc_dai *dai)
670{
671 int rc = 0;
672
673 switch (dai->id) {
674 case PRIMARY_I2S_TX:
675 case PRIMARY_I2S_RX:
Kuirong Wang9bbf6132012-01-10 18:28:49 -0800676 case SECONDARY_I2S_RX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700677 rc = msm_dai_q6_cdc_hw_params(params, dai, substream->stream);
678 break;
Patrick Lai04baee942012-05-01 14:38:47 -0700679
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700680 case SLIMBUS_0_RX:
Neema Shetty3c9d2862012-03-11 01:25:32 -0800681 case SLIMBUS_1_RX:
Neema Shetty74131ac2012-05-09 13:35:26 -0700682 case SLIMBUS_3_RX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700683 case SLIMBUS_0_TX:
Neema Shetty3c9d2862012-03-11 01:25:32 -0800684 case SLIMBUS_1_TX:
Kiran Kandifd30c892012-05-21 23:03:26 -0700685 case SLIMBUS_2_RX:
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700686 case SLIMBUS_2_TX:
ehgrace.kim9b771372012-08-13 15:08:56 -0700687 case SLIMBUS_3_TX:
Helen Zeng8f925502012-03-05 16:50:17 -0800688 case SLIMBUS_4_RX:
689 case SLIMBUS_4_TX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700690 rc = msm_dai_q6_slim_bus_hw_params(params, dai,
691 substream->stream);
692 break;
693 case INT_BT_SCO_RX:
694 case INT_BT_SCO_TX:
695 case INT_FM_RX:
696 case INT_FM_TX:
697 rc = msm_dai_q6_bt_fm_hw_params(params, dai, substream->stream);
698 break;
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530699 case RT_PROXY_DAI_001_TX:
700 case RT_PROXY_DAI_001_RX:
701 case RT_PROXY_DAI_002_TX:
702 case RT_PROXY_DAI_002_RX:
703 rc = msm_dai_q6_afe_rtproxy_hw_params(params, dai);
704 break;
Helen Zeng0705a5f2011-10-14 15:29:52 -0700705 case VOICE_PLAYBACK_TX:
Helen Zenge3d716a2011-10-14 16:32:16 -0700706 case VOICE_RECORD_RX:
707 case VOICE_RECORD_TX:
Helen Zeng0705a5f2011-10-14 15:29:52 -0700708 rc = 0;
709 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700710 default:
711 dev_err(dai->dev, "invalid AFE port ID\n");
712 rc = -EINVAL;
713 break;
714 }
715
716 return rc;
717}
718
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700719static void msm_dai_q6_auxpcm_shutdown(struct snd_pcm_substream *substream,
720 struct snd_soc_dai *dai)
721{
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700722 int rc = 0;
723
Kiran Kandi5f4ab692012-02-23 11:23:56 -0800724 mutex_lock(&aux_pcm_mutex);
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700725
Kiran Kandi5f4ab692012-02-23 11:23:56 -0800726 if (aux_pcm_count == 0) {
727 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count is 0. Just"
728 " return\n", __func__, dai->id);
729 mutex_unlock(&aux_pcm_mutex);
730 return;
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700731 }
Kiran Kandi5f4ab692012-02-23 11:23:56 -0800732
733 aux_pcm_count--;
734
735 if (aux_pcm_count > 0) {
736 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d\n",
737 __func__, dai->id, aux_pcm_count);
738 mutex_unlock(&aux_pcm_mutex);
739 return;
740 } else if (aux_pcm_count < 0) {
741 dev_err(dai->dev, "%s(): ERROR: dai->id %d"
742 " aux_pcm_count = %d < 0\n",
743 __func__, dai->id, aux_pcm_count);
744 aux_pcm_count = 0;
745 mutex_unlock(&aux_pcm_mutex);
746 return;
747 }
748
749 pr_debug("%s: dai->id = %d aux_pcm_count = %d\n", __func__,
750 dai->id, aux_pcm_count);
751
Asish Bhattacharya4776d962012-04-25 12:08:09 +0530752 clk_disable_unprepare(pcm_clk);
Kiran Kandi5f4ab692012-02-23 11:23:56 -0800753 rc = afe_close(PCM_RX); /* can block */
754 if (IS_ERR_VALUE(rc))
755 dev_err(dai->dev, "fail to close PCM_RX AFE port\n");
756
757 rc = afe_close(PCM_TX);
758 if (IS_ERR_VALUE(rc))
759 dev_err(dai->dev, "fail to close AUX PCM TX port\n");
760
761 mutex_unlock(&aux_pcm_mutex);
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700762}
763
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -0700764static void msm_dai_q6_sec_auxpcm_shutdown(struct snd_pcm_substream *substream,
765 struct snd_soc_dai *dai)
766{
767 int rc = 0;
768
769 pr_debug("%s\n", __func__);
770 mutex_lock(&aux_pcm_mutex);
771
772 if (aux_pcm_count == 0) {
773 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count is 0. Just"
774 " return\n", __func__, dai->id);
775 mutex_unlock(&aux_pcm_mutex);
776 return;
777 }
778
779 aux_pcm_count--;
780
781 if (aux_pcm_count > 0) {
782 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d\n",
783 __func__, dai->id, aux_pcm_count);
784 mutex_unlock(&aux_pcm_mutex);
785 return;
786 } else if (aux_pcm_count < 0) {
787 dev_err(dai->dev, "%s(): ERROR: dai->id %d"
788 " aux_pcm_count = %d < 0\n",
789 __func__, dai->id, aux_pcm_count);
790 aux_pcm_count = 0;
791 mutex_unlock(&aux_pcm_mutex);
792 return;
793 }
794
795 pr_debug("%s: dai->id = %d aux_pcm_count = %d\n", __func__,
796 dai->id, aux_pcm_count);
797
798 clk_disable_unprepare(sec_pcm_clk);
799 rc = afe_close(SECONDARY_PCM_RX); /* can block */
800 if (IS_ERR_VALUE(rc))
801 dev_err(dai->dev, "fail to close PCM_RX AFE port\n");
802
803 rc = afe_close(SECONDARY_PCM_TX);
804 if (IS_ERR_VALUE(rc))
805 dev_err(dai->dev, "fail to close AUX PCM TX port\n");
806
807 mutex_unlock(&aux_pcm_mutex);
808}
809
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700810static void msm_dai_q6_shutdown(struct snd_pcm_substream *substream,
811 struct snd_soc_dai *dai)
812{
813 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530814 int rc = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700815
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700816 if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
Helen Zeng0705a5f2011-10-14 15:29:52 -0700817 switch (dai->id) {
818 case VOICE_PLAYBACK_TX:
Helen Zenge3d716a2011-10-14 16:32:16 -0700819 case VOICE_RECORD_TX:
820 case VOICE_RECORD_RX:
Helen Zeng0705a5f2011-10-14 15:29:52 -0700821 pr_debug("%s, stop pseudo port:%d\n",
822 __func__, dai->id);
823 rc = afe_stop_pseudo_port(dai->id);
824 break;
825 default:
826 rc = afe_close(dai->id); /* can block */
827 break;
828 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700829 if (IS_ERR_VALUE(rc))
830 dev_err(dai->dev, "fail to close AFE port\n");
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530831 pr_debug("%s: dai_data->status_mask = %ld\n", __func__,
832 *dai_data->status_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700833 clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
834 }
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700835}
836
837static int msm_dai_q6_auxpcm_prepare(struct snd_pcm_substream *substream,
838 struct snd_soc_dai *dai)
839{
840 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
841 int rc = 0;
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700842 struct msm_dai_auxpcm_pdata *auxpcm_pdata =
843 (struct msm_dai_auxpcm_pdata *) dai->dev->platform_data;
Kuirong Wang547a9982012-05-04 18:29:11 -0700844 unsigned long pcm_clk_rate;
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700845
Kiran Kandi5f4ab692012-02-23 11:23:56 -0800846 mutex_lock(&aux_pcm_mutex);
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700847
Kiran Kandi5f4ab692012-02-23 11:23:56 -0800848 if (aux_pcm_count == 2) {
849 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count is 2. Just"
850 " return.\n", __func__, dai->id);
851 mutex_unlock(&aux_pcm_mutex);
852 return 0;
853 } else if (aux_pcm_count > 2) {
854 dev_err(dai->dev, "%s(): ERROR: dai->id %d"
855 " aux_pcm_count = %d > 2\n",
856 __func__, dai->id, aux_pcm_count);
857 mutex_unlock(&aux_pcm_mutex);
858 return 0;
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700859 }
Kiran Kandi5f4ab692012-02-23 11:23:56 -0800860
861 aux_pcm_count++;
862 if (aux_pcm_count == 2) {
863 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d after "
864 " increment\n", __func__, dai->id, aux_pcm_count);
865 mutex_unlock(&aux_pcm_mutex);
866 return 0;
867 }
868
869 pr_debug("%s:dai->id:%d aux_pcm_count = %d. opening afe\n",
870 __func__, dai->id, aux_pcm_count);
871
872 rc = afe_q6_interface_prepare();
873 if (IS_ERR_VALUE(rc))
874 dev_err(dai->dev, "fail to open AFE APR\n");
875
876 /*
877 * For AUX PCM Interface the below sequence of clk
Ajay Dudani501307f2012-06-29 09:20:42 -0700878 * settings and opening of afe port is a strict requirement.
879 * afe_port_start is called to make sure to make sure the port
880 * is open before deasserting the clock line. This is
881 * required because pcm register is not written before
882 * clock deassert. Hence the hw does not get updated with
883 * new setting if the below clock assert/deasset and afe_port_start
884 * sequence is not followed.
Kiran Kandi5f4ab692012-02-23 11:23:56 -0800885 */
886
887 clk_reset(pcm_clk, CLK_RESET_ASSERT);
888
Ajay Dudani501307f2012-06-29 09:20:42 -0700889 afe_port_start(PCM_RX, &dai_data->port_config, dai_data->rate);
Kiran Kandi5f4ab692012-02-23 11:23:56 -0800890
Ajay Dudani501307f2012-06-29 09:20:42 -0700891 afe_port_start(PCM_TX, &dai_data->port_config, dai_data->rate);
Kuirong Wang547a9982012-05-04 18:29:11 -0700892 if (dai_data->rate == 8000) {
893 pcm_clk_rate = auxpcm_pdata->mode_8k.pcm_clk_rate;
894 } else if (dai_data->rate == 16000) {
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -0700895 pcm_clk_rate = auxpcm_pdata->mode_16k.pcm_clk_rate;
Kuirong Wang547a9982012-05-04 18:29:11 -0700896 } else {
897 dev_err(dai->dev, "%s: Invalid AUX PCM rate %d\n", __func__,
898 dai_data->rate);
899 return -EINVAL;
900 }
Kiran Kandi5f4ab692012-02-23 11:23:56 -0800901
Kuirong Wang547a9982012-05-04 18:29:11 -0700902 rc = clk_set_rate(pcm_clk, pcm_clk_rate);
Kiran Kandi5f4ab692012-02-23 11:23:56 -0800903 if (rc < 0) {
904 pr_err("%s: clk_set_rate failed\n", __func__);
905 return rc;
906 }
907
Asish Bhattacharya4776d962012-04-25 12:08:09 +0530908 clk_prepare_enable(pcm_clk);
Kiran Kandi5f4ab692012-02-23 11:23:56 -0800909 clk_reset(pcm_clk, CLK_RESET_DEASSERT);
910
911 mutex_unlock(&aux_pcm_mutex);
912
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700913 return rc;
914}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700915
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -0700916static int msm_dai_q6_sec_auxpcm_prepare(struct snd_pcm_substream *substream,
917 struct snd_soc_dai *dai)
918{
919 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
920 int rc = 0;
921 struct msm_dai_auxpcm_pdata *auxpcm_pdata =
922 (struct msm_dai_auxpcm_pdata *) dai->dev->platform_data;
923 unsigned long pcm_clk_rate;
924
925 pr_info("%s\n", __func__);
926
927 mutex_lock(&aux_pcm_mutex);
928
929 if (aux_pcm_count == 2) {
930 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count is 2. Just"
931 " return.\n", __func__, dai->id);
932 mutex_unlock(&aux_pcm_mutex);
933 return 0;
934 } else if (aux_pcm_count > 2) {
935 dev_err(dai->dev, "%s(): ERROR: dai->id %d"
936 " aux_pcm_count = %d > 2\n",
937 __func__, dai->id, aux_pcm_count);
938 mutex_unlock(&aux_pcm_mutex);
939 return 0;
940 }
941
942 aux_pcm_count++;
943 if (aux_pcm_count == 2) {
944 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d after "
945 " increment\n", __func__, dai->id, aux_pcm_count);
946 mutex_unlock(&aux_pcm_mutex);
947 return 0;
948 }
949
950 pr_debug("%s:dai->id:%d aux_pcm_count = %d. opening afe\n",
951 __func__, dai->id, aux_pcm_count);
952
953 rc = afe_q6_interface_prepare();
954 if (IS_ERR_VALUE(rc))
955 dev_err(dai->dev, "fail to open AFE APR\n");
956
957 /*
958 * For AUX PCM Interface the below sequence of clk
Ajay Dudani501307f2012-06-29 09:20:42 -0700959 * settings and opening of afe port is a strict requirement.
960 * afe_port_start is called to make sure to make sure the port
961 * is open before deasserting the clock line. This is
962 * required because pcm register is not written before
963 * clock deassert. Hence the hw does not get updated with
964 * new setting if the below clock assert/deasset and afe_port_start
965 * sequence is not followed.
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -0700966 */
967
968 clk_reset(sec_pcm_clk, CLK_RESET_ASSERT);
969
Ajay Dudani501307f2012-06-29 09:20:42 -0700970 afe_port_start(SECONDARY_PCM_RX, &dai_data->port_config,
971 dai_data->rate);
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -0700972
Ajay Dudani501307f2012-06-29 09:20:42 -0700973 afe_port_start(SECONDARY_PCM_TX, &dai_data->port_config,
974 dai_data->rate);
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -0700975 if (dai_data->rate == 8000) {
976 pcm_clk_rate = auxpcm_pdata->mode_8k.pcm_clk_rate;
977 } else if (dai_data->rate == 16000) {
978 pcm_clk_rate = auxpcm_pdata->mode_16k.pcm_clk_rate;
979 } else {
980 dev_err(dai->dev, "%s: Invalid AUX PCM rate %d\n", __func__,
981 dai_data->rate);
982 return -EINVAL;
983 }
984
985 rc = clk_set_rate(sec_pcm_clk, pcm_clk_rate);
986 if (rc < 0) {
987 pr_err("%s: clk_set_rate failed\n", __func__);
988 return rc;
989 }
990
991 clk_prepare_enable(sec_pcm_clk);
992 clk_reset(sec_pcm_clk, CLK_RESET_DEASSERT);
993
994 mutex_unlock(&aux_pcm_mutex);
995
996 return rc;
997}
998
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700999static int msm_dai_q6_prepare(struct snd_pcm_substream *substream,
1000 struct snd_soc_dai *dai)
1001{
1002 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
1003 int rc = 0;
1004
Patrick Lai831561e2011-07-26 22:51:27 -07001005 if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
Ajay Dudani501307f2012-06-29 09:20:42 -07001006 switch (dai->id) {
1007 case VOICE_PLAYBACK_TX:
1008 case VOICE_RECORD_TX:
1009 case VOICE_RECORD_RX:
1010 rc = afe_start_pseudo_port(dai->id);
Vidyakumar Athota20957ca2012-07-25 15:04:41 -07001011 break;
Ajay Dudani501307f2012-06-29 09:20:42 -07001012 default:
1013 rc = afe_port_start(dai->id, &dai_data->port_config,
1014 dai_data->rate);
1015 }
1016
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001017 if (IS_ERR_VALUE(rc))
Ajay Dudani501307f2012-06-29 09:20:42 -07001018 dev_err(dai->dev, "fail to open AFE port %x\n",
1019 dai->id);
1020 else
1021 set_bit(STATUS_PORT_STARTED,
1022 dai_data->status_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001023 }
Ajay Dudani501307f2012-06-29 09:20:42 -07001024
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001025 return rc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001026}
1027
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001028static int msm_dai_q6_auxpcm_trigger(struct snd_pcm_substream *substream,
1029 int cmd, struct snd_soc_dai *dai)
1030{
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001031 int rc = 0;
1032
Kiran Kandi5f4ab692012-02-23 11:23:56 -08001033 pr_debug("%s:port:%d cmd:%d aux_pcm_count= %d",
1034 __func__, dai->id, cmd, aux_pcm_count);
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001035
1036 switch (cmd) {
1037
1038 case SNDRV_PCM_TRIGGER_START:
1039 case SNDRV_PCM_TRIGGER_RESUME:
1040 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
1041 /* afe_open will be called from prepare */
1042 return 0;
1043
1044 case SNDRV_PCM_TRIGGER_STOP:
1045 case SNDRV_PCM_TRIGGER_SUSPEND:
1046 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
Kiran Kandi5f4ab692012-02-23 11:23:56 -08001047 return 0;
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001048
1049 default:
1050 rc = -EINVAL;
1051 }
1052
1053 return rc;
1054
1055}
1056
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001057static int msm_dai_q6_dai_auxpcm_probe(struct snd_soc_dai *dai)
1058{
1059 struct msm_dai_q6_dai_data *dai_data;
1060 int rc = 0;
1061
1062 struct msm_dai_auxpcm_pdata *auxpcm_pdata =
1063 (struct msm_dai_auxpcm_pdata *) dai->dev->platform_data;
1064
Kiran Kandi5f4ab692012-02-23 11:23:56 -08001065 mutex_lock(&aux_pcm_mutex);
1066
1067 if (!auxpcm_plat_data)
1068 auxpcm_plat_data = auxpcm_pdata;
1069 else if (auxpcm_plat_data != auxpcm_pdata) {
1070
1071 dev_err(dai->dev, "AUX PCM RX and TX devices does not have"
1072 " same platform data\n");
1073 return -EINVAL;
1074 }
1075
1076 /*
1077 * The clk name for AUX PCM operation is passed as platform
1078 * data to the cpu driver, since cpu drive is unaware of any
1079 * boarc specific configuration.
1080 */
1081 if (!pcm_clk) {
1082
1083 pcm_clk = clk_get(dai->dev, auxpcm_pdata->clk);
1084
1085 if (IS_ERR(pcm_clk)) {
1086 pr_err("%s: could not get pcm_clk\n", __func__);
1087 pcm_clk = NULL;
1088 return -ENODEV;
1089 }
1090 }
1091
1092 mutex_unlock(&aux_pcm_mutex);
1093
1094 dai_data = kzalloc(sizeof(struct msm_dai_q6_dai_data), GFP_KERNEL);
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001095
1096 if (!dai_data) {
1097 dev_err(dai->dev, "DAI-%d: fail to allocate dai data\n",
1098 dai->id);
1099 rc = -ENOMEM;
1100 } else
1101 dev_set_drvdata(dai->dev, dai_data);
1102
Kiran Kandi5f4ab692012-02-23 11:23:56 -08001103 pr_debug("%s : probe done for dai->id %d\n", __func__, dai->id);
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001104 return rc;
1105}
1106
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -07001107static int msm_dai_q6_dai_sec_auxpcm_probe(struct snd_soc_dai *dai)
1108{
1109 struct msm_dai_q6_dai_data *dai_data;
1110 int rc = 0;
1111 struct msm_dai_auxpcm_pdata *auxpcm_pdata =
1112 (struct msm_dai_auxpcm_pdata *) dai->dev->platform_data;
1113
1114 pr_info("%s\n", __func__);
1115
1116 mutex_lock(&aux_pcm_mutex);
1117
1118 if (!sec_auxpcm_plat_data)
1119 sec_auxpcm_plat_data = auxpcm_pdata;
1120 else if (sec_auxpcm_plat_data != auxpcm_pdata) {
1121 dev_err(dai->dev, "AUX PCM RX and TX devices does not have"
1122 " same platform data sec_auxpcm_plat_data\n");
1123 return -EINVAL;
1124 }
1125
1126 /*
1127 * The clk name for AUX PCM operation is passed as platform
1128 * data to the cpu driver, since cpu drive is unaware of any
1129 * boarc specific configuration.
1130 */
1131 if (!sec_pcm_clk) {
1132
1133 sec_pcm_clk = clk_get(dai->dev, auxpcm_pdata->clk);
1134 if (IS_ERR(sec_pcm_clk)) {
1135 pr_err("%s: could not get sec_pcm_clk\n", __func__);
1136 sec_pcm_clk = NULL;
1137 return -ENODEV;
1138 }
1139 }
1140
1141 mutex_unlock(&aux_pcm_mutex);
1142
1143 dai_data = kzalloc(sizeof(struct msm_dai_q6_dai_data), GFP_KERNEL);
1144
1145 if (!dai_data) {
1146 dev_err(dai->dev, "DAI-%d: fail to allocate dai data\n",
1147 dai->id);
1148 rc = -ENOMEM;
1149 } else
1150 dev_set_drvdata(dai->dev, dai_data);
1151
1152 pr_debug("%s : probe done for dai->id %d\n", __func__, dai->id);
1153 return rc;
1154}
1155
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001156static int msm_dai_q6_dai_auxpcm_remove(struct snd_soc_dai *dai)
1157{
1158 struct msm_dai_q6_dai_data *dai_data;
1159 int rc;
1160
1161 dai_data = dev_get_drvdata(dai->dev);
1162
Kiran Kandi5f4ab692012-02-23 11:23:56 -08001163 mutex_lock(&aux_pcm_mutex);
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001164
Kiran Kandi5f4ab692012-02-23 11:23:56 -08001165 if (aux_pcm_count == 0) {
1166 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count is 0. clean"
1167 " up and return\n", __func__, dai->id);
1168 goto done;
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001169 }
1170
Kiran Kandi5f4ab692012-02-23 11:23:56 -08001171 aux_pcm_count--;
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001172
Kiran Kandi5f4ab692012-02-23 11:23:56 -08001173 if (aux_pcm_count > 0) {
1174 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d\n",
1175 __func__, dai->id, aux_pcm_count);
1176 goto done;
1177 } else if (aux_pcm_count < 0) {
1178 dev_err(dai->dev, "%s(): ERROR: dai->id %d"
1179 " aux_pcm_count = %d < 0\n",
1180 __func__, dai->id, aux_pcm_count);
1181 goto done;
1182 }
1183
1184 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d."
1185 "closing afe\n",
1186 __func__, dai->id, aux_pcm_count);
1187
1188 rc = afe_close(PCM_RX); /* can block */
1189 if (IS_ERR_VALUE(rc))
1190 dev_err(dai->dev, "fail to close AUX PCM RX AFE port\n");
1191
1192 rc = afe_close(PCM_TX);
1193 if (IS_ERR_VALUE(rc))
1194 dev_err(dai->dev, "fail to close AUX PCM TX AFE port\n");
1195
1196done:
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001197 kfree(dai_data);
1198 snd_soc_unregister_dai(dai->dev);
1199
Kiran Kandi5f4ab692012-02-23 11:23:56 -08001200 mutex_unlock(&aux_pcm_mutex);
1201
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001202 return 0;
1203}
Patrick Lai04baee942012-05-01 14:38:47 -07001204
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -07001205static int msm_dai_q6_dai_sec_auxpcm_remove(struct snd_soc_dai *dai)
1206{
1207 struct msm_dai_q6_dai_data *dai_data;
1208 int rc;
1209
1210 pr_debug("%s\n", __func__);
1211 dai_data = dev_get_drvdata(dai->dev);
1212
1213 mutex_lock(&aux_pcm_mutex);
1214
1215 if (aux_pcm_count == 0) {
1216 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count is 0. clean"
1217 " up and return\n", __func__, dai->id);
1218 goto done;
1219 }
1220
1221 aux_pcm_count--;
1222
1223 if (aux_pcm_count > 0) {
1224 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d\n",
1225 __func__, dai->id, aux_pcm_count);
1226 goto done;
1227 } else if (aux_pcm_count < 0) {
1228 dev_err(dai->dev, "%s(): ERROR: dai->id %d"
1229 " aux_pcm_count = %d < 0\n",
1230 __func__, dai->id, aux_pcm_count);
1231 goto done;
1232 }
1233
1234 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d."
1235 "closing afe\n",
1236 __func__, dai->id, aux_pcm_count);
1237
1238 rc = afe_close(SECONDARY_PCM_RX); /* can block */
1239 if (IS_ERR_VALUE(rc))
1240 dev_err(dai->dev, "fail to close AUX PCM RX AFE port\n");
1241
1242 rc = afe_close(SECONDARY_PCM_TX);
1243 if (IS_ERR_VALUE(rc))
1244 dev_err(dai->dev, "fail to close AUX PCM TX AFE port\n");
1245
1246done:
1247 kfree(dai_data);
1248 snd_soc_unregister_dai(dai->dev);
1249
1250 mutex_unlock(&aux_pcm_mutex);
1251
1252 return 0;
1253}
1254
Kuirong Wang274f21a2011-12-15 21:29:08 -08001255static int msm_dai_q6_dai_mi2s_probe(struct snd_soc_dai *dai)
1256{
Patrick Lai04baee942012-05-01 14:38:47 -07001257 struct msm_dai_q6_mi2s_dai_data *mi2s_dai_data =
1258 dev_get_drvdata(dai->dev);
1259 struct snd_kcontrol *kcontrol = NULL;
Kuirong Wang274f21a2011-12-15 21:29:08 -08001260 int rc = 0;
1261
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -07001262 if (mi2s_dai_data->rx_dai.mi2s_dai_data.port_config.mi2s.line) {
Patrick Lai04baee942012-05-01 14:38:47 -07001263 kcontrol = snd_ctl_new1(&mi2s_config_controls[0],
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -07001264 &mi2s_dai_data->rx_dai.mi2s_dai_data);
Patrick Lai04baee942012-05-01 14:38:47 -07001265 rc = snd_ctl_add(dai->card->snd_card, kcontrol);
Kuirong Wang274f21a2011-12-15 21:29:08 -08001266
Patrick Lai04baee942012-05-01 14:38:47 -07001267 if (IS_ERR_VALUE(rc)) {
1268 dev_err(dai->dev, "%s: err add RX fmt ctl\n", __func__);
1269 goto rtn;
1270 }
Kuirong Wang274f21a2011-12-15 21:29:08 -08001271 }
Kuirong Wang875d1ec2012-04-02 19:56:25 -07001272
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -07001273 if (mi2s_dai_data->tx_dai.mi2s_dai_data.port_config.mi2s.line) {
Patrick Lai04baee942012-05-01 14:38:47 -07001274 rc = snd_ctl_add(dai->card->snd_card,
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -07001275 snd_ctl_new1(&mi2s_config_controls[2],
1276 &mi2s_dai_data->tx_dai.mi2s_dai_data));
Patrick Lai04baee942012-05-01 14:38:47 -07001277
1278 if (IS_ERR_VALUE(rc)) {
1279 if (kcontrol)
1280 snd_ctl_remove(dai->card->snd_card, kcontrol);
1281 dev_err(dai->dev, "%s: err add TX fmt ctl\n", __func__);
1282 }
1283 }
1284
Kuirong Wang274f21a2011-12-15 21:29:08 -08001285rtn:
1286 return rc;
1287}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001288
Patrick Lai04baee942012-05-01 14:38:47 -07001289static int msm_dai_q6_dai_mi2s_remove(struct snd_soc_dai *dai)
1290{
1291 struct msm_dai_q6_mi2s_dai_data *mi2s_dai_data =
1292 dev_get_drvdata(dai->dev);
1293 int rc;
1294
1295 /* If AFE port is still up, close it */
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -07001296 if (test_bit(STATUS_PORT_STARTED,
1297 mi2s_dai_data->rx_dai.mi2s_dai_data.status_mask)) {
Patrick Lai04baee942012-05-01 14:38:47 -07001298 rc = afe_close(MI2S_RX); /* can block */
1299 if (IS_ERR_VALUE(rc))
1300 dev_err(dai->dev, "fail to close MI2S_RX port\n");
1301 clear_bit(STATUS_PORT_STARTED,
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -07001302 mi2s_dai_data->rx_dai.mi2s_dai_data.status_mask);
Patrick Lai04baee942012-05-01 14:38:47 -07001303 }
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -07001304 if (test_bit(STATUS_PORT_STARTED,
1305 mi2s_dai_data->tx_dai.mi2s_dai_data.status_mask)) {
Patrick Lai04baee942012-05-01 14:38:47 -07001306 rc = afe_close(MI2S_TX); /* can block */
1307 if (IS_ERR_VALUE(rc))
1308 dev_err(dai->dev, "fail to close MI2S_TX port\n");
1309 clear_bit(STATUS_PORT_STARTED,
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -07001310 mi2s_dai_data->tx_dai.mi2s_dai_data.status_mask);
Patrick Lai04baee942012-05-01 14:38:47 -07001311 }
1312 kfree(mi2s_dai_data);
1313 snd_soc_unregister_dai(dai->dev);
1314
1315 return 0;
1316}
1317
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001318static int msm_dai_q6_dai_probe(struct snd_soc_dai *dai)
1319{
1320 struct msm_dai_q6_dai_data *dai_data;
1321 int rc = 0;
Kuirong Wang875d1ec2012-04-02 19:56:25 -07001322 const struct snd_kcontrol_new *kcontrol;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001323
1324 dai_data = kzalloc(sizeof(struct msm_dai_q6_dai_data),
1325 GFP_KERNEL);
1326
1327 if (!dai_data) {
1328 dev_err(dai->dev, "DAI-%d: fail to allocate dai data\n",
1329 dai->id);
1330 rc = -ENOMEM;
1331 } else
1332 dev_set_drvdata(dai->dev, dai_data);
Kuirong Wang875d1ec2012-04-02 19:56:25 -07001333 if (dai->id == SECONDARY_I2S_RX) {
1334 kcontrol = &mi2s_config_controls[1];
1335 rc = snd_ctl_add(dai->card->snd_card,
1336 snd_ctl_new1(kcontrol, dai_data));
1337 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001338
1339 return rc;
1340}
1341
1342static int msm_dai_q6_dai_remove(struct snd_soc_dai *dai)
1343{
1344 struct msm_dai_q6_dai_data *dai_data;
1345 int rc;
1346
1347 dai_data = dev_get_drvdata(dai->dev);
1348
1349 /* If AFE port is still up, close it */
1350 if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
Helen Zeng0705a5f2011-10-14 15:29:52 -07001351 switch (dai->id) {
1352 case VOICE_PLAYBACK_TX:
Helen Zenge3d716a2011-10-14 16:32:16 -07001353 case VOICE_RECORD_TX:
1354 case VOICE_RECORD_RX:
Helen Zeng0705a5f2011-10-14 15:29:52 -07001355 pr_debug("%s, stop pseudo port:%d\n",
1356 __func__, dai->id);
1357 rc = afe_stop_pseudo_port(dai->id);
1358 break;
1359 default:
1360 rc = afe_close(dai->id); /* can block */
1361 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001362 if (IS_ERR_VALUE(rc))
1363 dev_err(dai->dev, "fail to close AFE port\n");
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301364 clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001365 }
1366 kfree(dai_data);
1367 snd_soc_unregister_dai(dai->dev);
1368
1369 return 0;
1370}
1371
Lei Zhou157c1842011-08-19 13:05:04 -04001372static int msm_dai_q6_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
1373{
1374 int rc = 0;
1375
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001376 dev_dbg(dai->dev, "enter %s, id = %d fmt[%d]\n", __func__,
1377 dai->id, fmt);
Lei Zhou157c1842011-08-19 13:05:04 -04001378 switch (dai->id) {
1379 case PRIMARY_I2S_TX:
1380 case PRIMARY_I2S_RX:
Kuirong Wang9bbf6132012-01-10 18:28:49 -08001381 case SECONDARY_I2S_RX:
Lei Zhou157c1842011-08-19 13:05:04 -04001382 rc = msm_dai_q6_cdc_set_fmt(dai, fmt);
1383 break;
1384 default:
1385 dev_err(dai->dev, "invalid cpu_dai set_fmt\n");
1386 rc = -EINVAL;
1387 break;
1388 }
1389
1390 return rc;
1391}
1392
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001393static int msm_dai_q6_set_channel_map(struct snd_soc_dai *dai,
1394 unsigned int tx_num, unsigned int *tx_slot,
1395 unsigned int rx_num, unsigned int *rx_slot)
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001396{
1397 int rc = 0;
1398 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
1399 unsigned int i = 0;
1400
Kiran Kandifd30c892012-05-21 23:03:26 -07001401 dev_dbg(dai->dev, "%s: dai_id = %d\n", __func__, dai->id);
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001402 switch (dai->id) {
1403 case SLIMBUS_0_RX:
Neema Shetty3c9d2862012-03-11 01:25:32 -08001404 case SLIMBUS_1_RX:
Kiran Kandifd30c892012-05-21 23:03:26 -07001405 case SLIMBUS_2_RX:
Neema Shetty74131ac2012-05-09 13:35:26 -07001406 case SLIMBUS_3_RX:
Helen Zeng8f925502012-03-05 16:50:17 -08001407 case SLIMBUS_4_RX:
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001408 /* channel number to be between 128 and 255. For RX port
1409 * use channel numbers from 138 to 144, for TX port
1410 * use channel numbers from 128 to 137
Neema Shetty3c9d2862012-03-11 01:25:32 -08001411 * For ports between MDM-APQ use channel numbers from 145
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001412 */
Bharath Ramachandramurthy94ad7e22012-02-28 18:44:07 -08001413 if (!rx_slot)
1414 return -EINVAL;
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001415 for (i = 0; i < rx_num; i++) {
1416 dai_data->port_config.slim_sch.slave_ch_mapping[i] =
1417 rx_slot[i];
1418 pr_debug("%s: find number of channels[%d] ch[%d]\n",
1419 __func__, i,
1420 rx_slot[i]);
1421 }
1422 dai_data->port_config.slim_sch.num_channels = rx_num;
Kiran Kandi1e6371d2012-03-29 11:48:57 -07001423 pr_debug("%s:SLIMBUS_%d_RX cnt[%d] ch[%d %d]\n", __func__,
1424 (dai->id - SLIMBUS_0_RX) / 2,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001425 rx_num, dai_data->port_config.slim_sch.slave_ch_mapping[0],
1426 dai_data->port_config.slim_sch.slave_ch_mapping[1]);
1427
1428 break;
1429 case SLIMBUS_0_TX:
Neema Shetty3c9d2862012-03-11 01:25:32 -08001430 case SLIMBUS_1_TX:
Kiran Kandi1e6371d2012-03-29 11:48:57 -07001431 case SLIMBUS_2_TX:
ehgrace.kim9b771372012-08-13 15:08:56 -07001432 case SLIMBUS_3_TX:
Helen Zeng8f925502012-03-05 16:50:17 -08001433 case SLIMBUS_4_TX:
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001434 /* channel number to be between 128 and 255. For RX port
1435 * use channel numbers from 138 to 144, for TX port
1436 * use channel numbers from 128 to 137
Neema Shetty3c9d2862012-03-11 01:25:32 -08001437 * For ports between MDM-APQ use channel numbers from 145
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001438 */
Bharath Ramachandramurthy94ad7e22012-02-28 18:44:07 -08001439 if (!tx_slot)
1440 return -EINVAL;
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001441 for (i = 0; i < tx_num; i++) {
1442 dai_data->port_config.slim_sch.slave_ch_mapping[i] =
1443 tx_slot[i];
1444 pr_debug("%s: find number of channels[%d] ch[%d]\n",
1445 __func__, i, tx_slot[i]);
1446 }
1447 dai_data->port_config.slim_sch.num_channels = tx_num;
Kiran Kandi1e6371d2012-03-29 11:48:57 -07001448 pr_debug("%s:SLIMBUS_%d_TX cnt[%d] ch[%d %d]\n", __func__,
1449 (dai->id - SLIMBUS_0_TX) / 2,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001450 tx_num, dai_data->port_config.slim_sch.slave_ch_mapping[0],
1451 dai_data->port_config.slim_sch.slave_ch_mapping[1]);
1452 break;
1453 default:
1454 dev_err(dai->dev, "invalid cpu_dai set_fmt\n");
1455 rc = -EINVAL;
1456 break;
1457 }
1458 return rc;
1459}
1460
Patrick Lai04baee942012-05-01 14:38:47 -07001461static struct snd_soc_dai_ops msm_dai_q6_mi2s_ops = {
1462 .startup = msm_dai_q6_mi2s_startup,
1463 .prepare = msm_dai_q6_mi2s_prepare,
Patrick Lai04baee942012-05-01 14:38:47 -07001464 .hw_params = msm_dai_q6_mi2s_hw_params,
1465 .shutdown = msm_dai_q6_mi2s_shutdown,
1466 .set_fmt = msm_dai_q6_mi2s_set_fmt,
1467};
1468
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001469static struct snd_soc_dai_ops msm_dai_q6_ops = {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001470 .prepare = msm_dai_q6_prepare,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001471 .hw_params = msm_dai_q6_hw_params,
1472 .shutdown = msm_dai_q6_shutdown,
Lei Zhou157c1842011-08-19 13:05:04 -04001473 .set_fmt = msm_dai_q6_set_fmt,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001474 .set_channel_map = msm_dai_q6_set_channel_map,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001475};
1476
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001477static struct snd_soc_dai_ops msm_dai_q6_auxpcm_ops = {
1478 .prepare = msm_dai_q6_auxpcm_prepare,
1479 .trigger = msm_dai_q6_auxpcm_trigger,
1480 .hw_params = msm_dai_q6_auxpcm_hw_params,
1481 .shutdown = msm_dai_q6_auxpcm_shutdown,
1482};
1483
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -07001484static struct snd_soc_dai_ops msm_dai_q6_sec_auxpcm_ops = {
1485 .prepare = msm_dai_q6_sec_auxpcm_prepare,
1486 .trigger = msm_dai_q6_auxpcm_trigger,
1487 .hw_params = msm_dai_q6_sec_auxpcm_hw_params,
1488 .shutdown = msm_dai_q6_sec_auxpcm_shutdown,
1489};
1490
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001491static struct snd_soc_dai_driver msm_dai_q6_i2s_rx_dai = {
1492 .playback = {
1493 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1494 SNDRV_PCM_RATE_16000,
1495 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1496 .channels_min = 1,
Kiran Kandi9db678b2012-01-15 14:25:59 -08001497 .channels_max = 4,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001498 .rate_min = 8000,
1499 .rate_max = 48000,
1500 },
1501 .ops = &msm_dai_q6_ops,
1502 .probe = msm_dai_q6_dai_probe,
1503 .remove = msm_dai_q6_dai_remove,
1504};
1505
1506static struct snd_soc_dai_driver msm_dai_q6_i2s_tx_dai = {
1507 .capture = {
1508 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1509 SNDRV_PCM_RATE_16000,
1510 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1511 .channels_min = 1,
1512 .channels_max = 2,
1513 .rate_min = 8000,
1514 .rate_max = 48000,
1515 },
1516 .ops = &msm_dai_q6_ops,
1517 .probe = msm_dai_q6_dai_probe,
1518 .remove = msm_dai_q6_dai_remove,
1519};
1520
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301521static struct snd_soc_dai_driver msm_dai_q6_afe_rx_dai = {
1522 .playback = {
1523 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1524 SNDRV_PCM_RATE_16000,
1525 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1526 .channels_min = 1,
1527 .channels_max = 2,
1528 .rate_min = 8000,
1529 .rate_max = 48000,
1530 },
1531 .ops = &msm_dai_q6_ops,
1532 .probe = msm_dai_q6_dai_probe,
1533 .remove = msm_dai_q6_dai_remove,
1534};
1535
1536static struct snd_soc_dai_driver msm_dai_q6_afe_tx_dai = {
1537 .capture = {
1538 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1539 SNDRV_PCM_RATE_16000,
1540 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1541 .channels_min = 1,
Mingming Yin647e9ea2012-03-17 19:56:10 -07001542 .channels_max = 4,
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301543 .rate_min = 8000,
1544 .rate_max = 48000,
1545 },
1546 .ops = &msm_dai_q6_ops,
1547 .probe = msm_dai_q6_dai_probe,
1548 .remove = msm_dai_q6_dai_remove,
1549};
1550
Helen Zeng0705a5f2011-10-14 15:29:52 -07001551static struct snd_soc_dai_driver msm_dai_q6_voice_playback_tx_dai = {
1552 .playback = {
1553 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1554 SNDRV_PCM_RATE_16000,
1555 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1556 .channels_min = 1,
1557 .channels_max = 2,
1558 .rate_max = 48000,
1559 .rate_min = 8000,
1560 },
1561 .ops = &msm_dai_q6_ops,
1562 .probe = msm_dai_q6_dai_probe,
1563 .remove = msm_dai_q6_dai_remove,
1564};
1565
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001566static struct snd_soc_dai_driver msm_dai_q6_slimbus_rx_dai = {
1567 .playback = {
1568 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1569 SNDRV_PCM_RATE_16000,
1570 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1571 .channels_min = 1,
1572 .channels_max = 2,
1573 .rate_min = 8000,
1574 .rate_max = 48000,
1575 },
1576 .ops = &msm_dai_q6_ops,
1577 .probe = msm_dai_q6_dai_probe,
1578 .remove = msm_dai_q6_dai_remove,
1579};
1580
1581static struct snd_soc_dai_driver msm_dai_q6_slimbus_tx_dai = {
1582 .capture = {
1583 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1584 SNDRV_PCM_RATE_16000,
1585 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1586 .channels_min = 1,
1587 .channels_max = 2,
1588 .rate_min = 8000,
1589 .rate_max = 48000,
1590 },
1591 .ops = &msm_dai_q6_ops,
1592 .probe = msm_dai_q6_dai_probe,
1593 .remove = msm_dai_q6_dai_remove,
1594};
1595
Helen Zenge3d716a2011-10-14 16:32:16 -07001596static struct snd_soc_dai_driver msm_dai_q6_incall_record_dai = {
1597 .capture = {
1598 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1599 SNDRV_PCM_RATE_16000,
1600 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1601 .channels_min = 1,
1602 .channels_max = 2,
1603 .rate_min = 8000,
1604 .rate_max = 48000,
1605 },
1606 .ops = &msm_dai_q6_ops,
1607 .probe = msm_dai_q6_dai_probe,
1608 .remove = msm_dai_q6_dai_remove,
1609};
1610
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001611static struct snd_soc_dai_driver msm_dai_q6_bt_sco_rx_dai = {
1612 .playback = {
1613 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
1614 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1615 .channels_min = 1,
1616 .channels_max = 1,
1617 .rate_max = 16000,
1618 .rate_min = 8000,
1619 },
1620 .ops = &msm_dai_q6_ops,
1621 .probe = msm_dai_q6_dai_probe,
1622 .remove = msm_dai_q6_dai_remove,
1623};
1624
1625static struct snd_soc_dai_driver msm_dai_q6_bt_sco_tx_dai = {
Patrick Laibd5021e2012-06-12 01:27:20 -07001626 .capture = {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001627 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
1628 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1629 .channels_min = 1,
1630 .channels_max = 1,
1631 .rate_max = 16000,
1632 .rate_min = 8000,
1633 },
1634 .ops = &msm_dai_q6_ops,
1635 .probe = msm_dai_q6_dai_probe,
1636 .remove = msm_dai_q6_dai_remove,
1637};
1638
1639static struct snd_soc_dai_driver msm_dai_q6_fm_rx_dai = {
1640 .playback = {
1641 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1642 SNDRV_PCM_RATE_16000,
1643 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1644 .channels_min = 2,
1645 .channels_max = 2,
1646 .rate_max = 48000,
1647 .rate_min = 8000,
1648 },
1649 .ops = &msm_dai_q6_ops,
1650 .probe = msm_dai_q6_dai_probe,
1651 .remove = msm_dai_q6_dai_remove,
1652};
1653
1654static struct snd_soc_dai_driver msm_dai_q6_fm_tx_dai = {
Patrick Laibd5021e2012-06-12 01:27:20 -07001655 .capture = {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001656 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1657 SNDRV_PCM_RATE_16000,
1658 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1659 .channels_min = 2,
1660 .channels_max = 2,
1661 .rate_max = 48000,
1662 .rate_min = 8000,
1663 },
1664 .ops = &msm_dai_q6_ops,
1665 .probe = msm_dai_q6_dai_probe,
1666 .remove = msm_dai_q6_dai_remove,
1667};
1668
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001669static struct snd_soc_dai_driver msm_dai_q6_aux_pcm_rx_dai = {
1670 .playback = {
Kuirong Wang547a9982012-05-04 18:29:11 -07001671 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001672 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1673 .channels_min = 1,
1674 .channels_max = 1,
Kuirong Wang547a9982012-05-04 18:29:11 -07001675 .rate_max = 16000,
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001676 .rate_min = 8000,
1677 },
1678 .ops = &msm_dai_q6_auxpcm_ops,
1679 .probe = msm_dai_q6_dai_auxpcm_probe,
1680 .remove = msm_dai_q6_dai_auxpcm_remove,
1681};
1682
1683static struct snd_soc_dai_driver msm_dai_q6_aux_pcm_tx_dai = {
1684 .capture = {
Kuirong Wang547a9982012-05-04 18:29:11 -07001685 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001686 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1687 .channels_min = 1,
1688 .channels_max = 1,
Kuirong Wang547a9982012-05-04 18:29:11 -07001689 .rate_max = 16000,
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001690 .rate_min = 8000,
1691 },
Kiran Kandi5f4ab692012-02-23 11:23:56 -08001692 .ops = &msm_dai_q6_auxpcm_ops,
1693 .probe = msm_dai_q6_dai_auxpcm_probe,
1694 .remove = msm_dai_q6_dai_auxpcm_remove,
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001695};
1696
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -07001697static struct snd_soc_dai_driver msm_dai_q6_sec_aux_pcm_rx_dai = {
1698 .playback = {
1699 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
1700 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1701 .channels_min = 1,
1702 .channels_max = 1,
1703 .rate_max = 16000,
1704 .rate_min = 8000,
1705 },
1706 .ops = &msm_dai_q6_sec_auxpcm_ops,
1707 .probe = msm_dai_q6_dai_sec_auxpcm_probe,
1708 .remove = msm_dai_q6_dai_sec_auxpcm_remove,
1709};
1710
1711static struct snd_soc_dai_driver msm_dai_q6_sec_aux_pcm_tx_dai = {
1712 .capture = {
1713 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
1714 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1715 .channels_min = 1,
1716 .channels_max = 1,
1717 .rate_max = 16000,
1718 .rate_min = 8000,
1719 },
1720 .ops = &msm_dai_q6_sec_auxpcm_ops,
1721 .probe = msm_dai_q6_dai_sec_auxpcm_probe,
1722 .remove = msm_dai_q6_dai_sec_auxpcm_remove,
1723};
1724
Patrick Lai04baee942012-05-01 14:38:47 -07001725/* Channel min and max are initialized base on platform data */
1726static struct snd_soc_dai_driver msm_dai_q6_mi2s_dai = {
Kuirong Wang274f21a2011-12-15 21:29:08 -08001727 .playback = {
1728 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1729 SNDRV_PCM_RATE_16000,
1730 .formats = SNDRV_PCM_FMTBIT_S16_LE,
Kuirong Wang274f21a2011-12-15 21:29:08 -08001731 .rate_min = 8000,
1732 .rate_max = 48000,
1733 },
Kuirong Wang623b50f2012-04-16 15:51:14 -07001734 .capture = {
1735 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1736 SNDRV_PCM_RATE_16000,
1737 .formats = SNDRV_PCM_FMTBIT_S16_LE,
Patrick Lai04baee942012-05-01 14:38:47 -07001738 .rate_min = 8000,
1739 .rate_max = 48000,
Kuirong Wang623b50f2012-04-16 15:51:14 -07001740 },
Patrick Lai04baee942012-05-01 14:38:47 -07001741 .ops = &msm_dai_q6_mi2s_ops,
Kuirong Wang623b50f2012-04-16 15:51:14 -07001742 .probe = msm_dai_q6_dai_mi2s_probe,
Patrick Lai04baee942012-05-01 14:38:47 -07001743 .remove = msm_dai_q6_dai_mi2s_remove,
Kuirong Wang623b50f2012-04-16 15:51:14 -07001744};
1745
Neema Shetty3c9d2862012-03-11 01:25:32 -08001746static struct snd_soc_dai_driver msm_dai_q6_slimbus_1_rx_dai = {
1747 .playback = {
1748 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
1749 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1750 .channels_min = 1,
1751 .channels_max = 1,
1752 .rate_min = 8000,
1753 .rate_max = 16000,
1754 },
1755 .ops = &msm_dai_q6_ops,
1756 .probe = msm_dai_q6_dai_probe,
1757 .remove = msm_dai_q6_dai_remove,
1758};
1759
1760static struct snd_soc_dai_driver msm_dai_q6_slimbus_1_tx_dai = {
1761 .capture = {
1762 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
1763 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1764 .channels_min = 1,
1765 .channels_max = 1,
1766 .rate_min = 8000,
1767 .rate_max = 16000,
1768 },
1769 .ops = &msm_dai_q6_ops,
1770 .probe = msm_dai_q6_dai_probe,
1771 .remove = msm_dai_q6_dai_remove,
1772};
1773
Kiran Kandifd30c892012-05-21 23:03:26 -07001774static struct snd_soc_dai_driver msm_dai_q6_slimbus_2_rx_dai = {
1775 .playback = {
1776 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1777 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_96000 |
1778 SNDRV_PCM_RATE_192000,
1779 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1780 .channels_min = 1,
1781 .channels_max = 2,
1782 .rate_min = 8000,
1783 .rate_max = 192000,
1784 },
1785 .ops = &msm_dai_q6_ops,
1786 .probe = msm_dai_q6_dai_probe,
1787 .remove = msm_dai_q6_dai_remove,
1788};
1789
Kiran Kandi1e6371d2012-03-29 11:48:57 -07001790static struct snd_soc_dai_driver msm_dai_q6_slimbus_2_tx_dai = {
1791 .capture = {
1792 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1793 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_96000 |
1794 SNDRV_PCM_RATE_192000,
1795 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1796 .channels_min = 1,
1797 .channels_max = 4,
1798 .rate_min = 8000,
1799 .rate_max = 192000,
1800 },
1801 .ops = &msm_dai_q6_ops,
1802 .probe = msm_dai_q6_dai_probe,
1803 .remove = msm_dai_q6_dai_remove,
1804};
1805
Neema Shetty74131ac2012-05-09 13:35:26 -07001806static struct snd_soc_dai_driver msm_dai_q6_slimbus_3_rx_dai = {
1807 .playback = {
1808 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
1809 SNDRV_PCM_RATE_48000,
1810 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1811 .channels_min = 1,
1812 .channels_max = 2,
1813 .rate_min = 8000,
1814 .rate_max = 48000,
1815 },
1816 .ops = &msm_dai_q6_ops,
1817 .probe = msm_dai_q6_dai_probe,
1818 .remove = msm_dai_q6_dai_remove,
1819};
1820
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001821/* To do: change to register DAIs as batch */
1822static __devinit int msm_dai_q6_dev_probe(struct platform_device *pdev)
1823{
1824 int rc = 0;
1825
1826 dev_dbg(&pdev->dev, "dev name %s\n", dev_name(&pdev->dev));
1827
1828 switch (pdev->id) {
1829 case PRIMARY_I2S_RX:
Kuirong Wang9bbf6132012-01-10 18:28:49 -08001830 case SECONDARY_I2S_RX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001831 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_i2s_rx_dai);
1832 break;
1833 case PRIMARY_I2S_TX:
1834 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_i2s_tx_dai);
1835 break;
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001836 case PCM_RX:
1837 rc = snd_soc_register_dai(&pdev->dev,
1838 &msm_dai_q6_aux_pcm_rx_dai);
1839 break;
1840 case PCM_TX:
1841 rc = snd_soc_register_dai(&pdev->dev,
1842 &msm_dai_q6_aux_pcm_tx_dai);
1843 break;
Patrick Lai04baee942012-05-01 14:38:47 -07001844
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -07001845 case SECONDARY_PCM_RX:
1846 rc = snd_soc_register_dai(&pdev->dev,
1847 &msm_dai_q6_sec_aux_pcm_rx_dai);
1848 break;
1849 case SECONDARY_PCM_TX:
1850 rc = snd_soc_register_dai(&pdev->dev,
1851 &msm_dai_q6_sec_aux_pcm_tx_dai);
1852 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001853 case SLIMBUS_0_RX:
Helen Zeng8f925502012-03-05 16:50:17 -08001854 case SLIMBUS_4_RX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001855 rc = snd_soc_register_dai(&pdev->dev,
1856 &msm_dai_q6_slimbus_rx_dai);
1857 break;
1858 case SLIMBUS_0_TX:
Helen Zeng8f925502012-03-05 16:50:17 -08001859 case SLIMBUS_4_TX:
ehgrace.kim9b771372012-08-13 15:08:56 -07001860 case SLIMBUS_3_TX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001861 rc = snd_soc_register_dai(&pdev->dev,
1862 &msm_dai_q6_slimbus_tx_dai);
Neema Shetty3c9d2862012-03-11 01:25:32 -08001863 break;
Neema Shetty3c9d2862012-03-11 01:25:32 -08001864 case SLIMBUS_1_RX:
1865 rc = snd_soc_register_dai(&pdev->dev,
1866 &msm_dai_q6_slimbus_1_rx_dai);
1867 break;
1868 case SLIMBUS_1_TX:
1869 rc = snd_soc_register_dai(&pdev->dev,
1870 &msm_dai_q6_slimbus_1_tx_dai);
1871 break;
Kiran Kandifd30c892012-05-21 23:03:26 -07001872 case SLIMBUS_2_RX:
1873 rc = snd_soc_register_dai(&pdev->dev,
1874 &msm_dai_q6_slimbus_2_rx_dai);
1875 break;
Kiran Kandi1e6371d2012-03-29 11:48:57 -07001876 case SLIMBUS_2_TX:
1877 rc = snd_soc_register_dai(&pdev->dev,
1878 &msm_dai_q6_slimbus_2_tx_dai);
1879 break;
Neema Shetty74131ac2012-05-09 13:35:26 -07001880 case SLIMBUS_3_RX:
1881 rc = snd_soc_register_dai(&pdev->dev,
1882 &msm_dai_q6_slimbus_3_rx_dai);
1883 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001884 case INT_BT_SCO_RX:
1885 rc = snd_soc_register_dai(&pdev->dev,
1886 &msm_dai_q6_bt_sco_rx_dai);
1887 break;
1888 case INT_BT_SCO_TX:
1889 rc = snd_soc_register_dai(&pdev->dev,
1890 &msm_dai_q6_bt_sco_tx_dai);
1891 break;
1892 case INT_FM_RX:
1893 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_fm_rx_dai);
1894 break;
1895 case INT_FM_TX:
1896 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_fm_tx_dai);
1897 break;
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301898 case RT_PROXY_DAI_001_RX:
1899 case RT_PROXY_DAI_002_RX:
1900 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_afe_rx_dai);
1901 break;
1902 case RT_PROXY_DAI_001_TX:
1903 case RT_PROXY_DAI_002_TX:
1904 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_afe_tx_dai);
1905 break;
Helen Zeng0705a5f2011-10-14 15:29:52 -07001906 case VOICE_PLAYBACK_TX:
1907 rc = snd_soc_register_dai(&pdev->dev,
1908 &msm_dai_q6_voice_playback_tx_dai);
1909 break;
Helen Zenge3d716a2011-10-14 16:32:16 -07001910 case VOICE_RECORD_RX:
1911 case VOICE_RECORD_TX:
1912 rc = snd_soc_register_dai(&pdev->dev,
1913 &msm_dai_q6_incall_record_dai);
1914 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001915 default:
1916 rc = -ENODEV;
1917 break;
1918 }
1919 return rc;
1920}
1921
1922static __devexit int msm_dai_q6_dev_remove(struct platform_device *pdev)
1923{
1924 snd_soc_unregister_dai(&pdev->dev);
1925 return 0;
1926}
1927
Patrick Lai04baee942012-05-01 14:38:47 -07001928static __devinit int msm_dai_q6_mi2s_dev_probe(struct platform_device *pdev)
1929{
1930 struct msm_dai_q6_mi2s_dai_data *dai_data;
1931 int rc = 0;
1932
1933 dev_dbg(&pdev->dev, "%s: pdev %p dev %p\n", __func__, pdev, &pdev->dev);
1934
1935 dai_data = kzalloc(sizeof(struct msm_dai_q6_mi2s_dai_data),
1936 GFP_KERNEL);
1937
1938 if (!dai_data) {
1939 dev_err(&pdev->dev, "fail to allocate dai data\n");
1940 rc = -ENOMEM;
1941 goto rtn;
1942 } else
1943 dev_set_drvdata(&pdev->dev, dai_data);
1944
1945 rc = msm_dai_q6_mi2s_platform_data_validation(pdev,
1946 &msm_dai_q6_mi2s_dai);
1947 if (IS_ERR_VALUE(rc))
1948 goto err_pdata;
1949
1950 dai_data->rate_constraint.count = 1;
1951 dai_data->bitwidth_constraint.count = 1;
1952 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_mi2s_dai);
1953
1954 if (IS_ERR_VALUE(rc))
1955 goto err_pdata;
1956
1957 return 0;
1958
1959err_pdata:
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -07001960
1961 dev_err(&pdev->dev, "fail to msm_dai_q6_mi2s_dev_probe\n");
Patrick Lai04baee942012-05-01 14:38:47 -07001962 kfree(dai_data);
1963rtn:
1964 return rc;
1965}
1966
1967static __devexit int msm_dai_q6_mi2s_dev_remove(struct platform_device *pdev)
1968{
1969 snd_soc_unregister_dai(&pdev->dev);
1970 return 0;
1971}
1972
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001973static struct platform_driver msm_dai_q6_driver = {
1974 .probe = msm_dai_q6_dev_probe,
1975 .remove = msm_dai_q6_dev_remove,
1976 .driver = {
1977 .name = "msm-dai-q6",
1978 .owner = THIS_MODULE,
1979 },
1980};
1981
Patrick Lai04baee942012-05-01 14:38:47 -07001982static struct platform_driver msm_dai_q6_mi2s_driver = {
1983 .probe = msm_dai_q6_mi2s_dev_probe,
1984 .remove = msm_dai_q6_mi2s_dev_remove,
1985 .driver = {
1986 .name = "msm-dai-q6-mi2s",
1987 .owner = THIS_MODULE,
1988 },
1989};
1990
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001991static int __init msm_dai_q6_init(void)
1992{
Patrick Lai04baee942012-05-01 14:38:47 -07001993 int rc1, rc2;
1994
1995 rc1 = platform_driver_register(&msm_dai_q6_mi2s_driver);
1996
1997 if (IS_ERR_VALUE(rc1))
1998 pr_err("%s: fail to register mi2s dai driver\n", __func__);
1999
2000 rc2 = platform_driver_register(&msm_dai_q6_driver);
2001
2002 if (IS_ERR_VALUE(rc2))
2003 pr_err("%s: fail to register mi2s dai driver\n", __func__);
2004
2005 return (IS_ERR_VALUE(rc1) && IS_ERR_VALUE(rc2)) ? -1 : 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002006}
2007module_init(msm_dai_q6_init);
2008
2009static void __exit msm_dai_q6_exit(void)
2010{
2011 platform_driver_unregister(&msm_dai_q6_driver);
2012}
2013module_exit(msm_dai_q6_exit);
2014
2015/* Module information */
2016MODULE_DESCRIPTION("MSM DSP DAI driver");
2017MODULE_LICENSE("GPL v2");