blob: fb74c0a3142dfd805d486b3cdafccd7b3c733ab2 [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);
1008 default:
1009 rc = afe_port_start(dai->id, &dai_data->port_config,
1010 dai_data->rate);
1011 }
1012
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001013 if (IS_ERR_VALUE(rc))
Patrick Laibf978952012-06-29 09:20:42 -07001014 dev_err(dai->dev, "fail to open AFE port %x\n",
1015 dai->id);
1016 else
1017 set_bit(STATUS_PORT_STARTED,
1018 dai_data->status_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001019 }
Patrick Laibf978952012-06-29 09:20:42 -07001020
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001021 return rc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001022}
1023
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001024static int msm_dai_q6_auxpcm_trigger(struct snd_pcm_substream *substream,
1025 int cmd, struct snd_soc_dai *dai)
1026{
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001027 int rc = 0;
1028
Kiran Kandi5f4ab692012-02-23 11:23:56 -08001029 pr_debug("%s:port:%d cmd:%d aux_pcm_count= %d",
1030 __func__, dai->id, cmd, aux_pcm_count);
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001031
1032 switch (cmd) {
1033
1034 case SNDRV_PCM_TRIGGER_START:
1035 case SNDRV_PCM_TRIGGER_RESUME:
1036 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
1037 /* afe_open will be called from prepare */
1038 return 0;
1039
1040 case SNDRV_PCM_TRIGGER_STOP:
1041 case SNDRV_PCM_TRIGGER_SUSPEND:
1042 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
Kiran Kandi5f4ab692012-02-23 11:23:56 -08001043 return 0;
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001044
1045 default:
1046 rc = -EINVAL;
1047 }
1048
1049 return rc;
1050
1051}
1052
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001053static int msm_dai_q6_dai_auxpcm_probe(struct snd_soc_dai *dai)
1054{
1055 struct msm_dai_q6_dai_data *dai_data;
1056 int rc = 0;
1057
1058 struct msm_dai_auxpcm_pdata *auxpcm_pdata =
1059 (struct msm_dai_auxpcm_pdata *) dai->dev->platform_data;
1060
Kiran Kandi5f4ab692012-02-23 11:23:56 -08001061 mutex_lock(&aux_pcm_mutex);
1062
1063 if (!auxpcm_plat_data)
1064 auxpcm_plat_data = auxpcm_pdata;
1065 else if (auxpcm_plat_data != auxpcm_pdata) {
1066
1067 dev_err(dai->dev, "AUX PCM RX and TX devices does not have"
1068 " same platform data\n");
1069 return -EINVAL;
1070 }
1071
1072 /*
1073 * The clk name for AUX PCM operation is passed as platform
1074 * data to the cpu driver, since cpu drive is unaware of any
1075 * boarc specific configuration.
1076 */
1077 if (!pcm_clk) {
1078
1079 pcm_clk = clk_get(dai->dev, auxpcm_pdata->clk);
1080
1081 if (IS_ERR(pcm_clk)) {
1082 pr_err("%s: could not get pcm_clk\n", __func__);
1083 pcm_clk = NULL;
1084 return -ENODEV;
1085 }
1086 }
1087
1088 mutex_unlock(&aux_pcm_mutex);
1089
1090 dai_data = kzalloc(sizeof(struct msm_dai_q6_dai_data), GFP_KERNEL);
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001091
1092 if (!dai_data) {
1093 dev_err(dai->dev, "DAI-%d: fail to allocate dai data\n",
1094 dai->id);
1095 rc = -ENOMEM;
1096 } else
1097 dev_set_drvdata(dai->dev, dai_data);
1098
Kiran Kandi5f4ab692012-02-23 11:23:56 -08001099 pr_debug("%s : probe done for dai->id %d\n", __func__, dai->id);
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001100 return rc;
1101}
1102
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -07001103static int msm_dai_q6_dai_sec_auxpcm_probe(struct snd_soc_dai *dai)
1104{
1105 struct msm_dai_q6_dai_data *dai_data;
1106 int rc = 0;
1107 struct msm_dai_auxpcm_pdata *auxpcm_pdata =
1108 (struct msm_dai_auxpcm_pdata *) dai->dev->platform_data;
1109
1110 pr_info("%s\n", __func__);
1111
1112 mutex_lock(&aux_pcm_mutex);
1113
1114 if (!sec_auxpcm_plat_data)
1115 sec_auxpcm_plat_data = auxpcm_pdata;
1116 else if (sec_auxpcm_plat_data != auxpcm_pdata) {
1117 dev_err(dai->dev, "AUX PCM RX and TX devices does not have"
1118 " same platform data sec_auxpcm_plat_data\n");
1119 return -EINVAL;
1120 }
1121
1122 /*
1123 * The clk name for AUX PCM operation is passed as platform
1124 * data to the cpu driver, since cpu drive is unaware of any
1125 * boarc specific configuration.
1126 */
1127 if (!sec_pcm_clk) {
1128
1129 sec_pcm_clk = clk_get(dai->dev, auxpcm_pdata->clk);
1130 if (IS_ERR(sec_pcm_clk)) {
1131 pr_err("%s: could not get sec_pcm_clk\n", __func__);
1132 sec_pcm_clk = NULL;
1133 return -ENODEV;
1134 }
1135 }
1136
1137 mutex_unlock(&aux_pcm_mutex);
1138
1139 dai_data = kzalloc(sizeof(struct msm_dai_q6_dai_data), GFP_KERNEL);
1140
1141 if (!dai_data) {
1142 dev_err(dai->dev, "DAI-%d: fail to allocate dai data\n",
1143 dai->id);
1144 rc = -ENOMEM;
1145 } else
1146 dev_set_drvdata(dai->dev, dai_data);
1147
1148 pr_debug("%s : probe done for dai->id %d\n", __func__, dai->id);
1149 return rc;
1150}
1151
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001152static int msm_dai_q6_dai_auxpcm_remove(struct snd_soc_dai *dai)
1153{
1154 struct msm_dai_q6_dai_data *dai_data;
1155 int rc;
1156
1157 dai_data = dev_get_drvdata(dai->dev);
1158
Kiran Kandi5f4ab692012-02-23 11:23:56 -08001159 mutex_lock(&aux_pcm_mutex);
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001160
Kiran Kandi5f4ab692012-02-23 11:23:56 -08001161 if (aux_pcm_count == 0) {
1162 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count is 0. clean"
1163 " up and return\n", __func__, dai->id);
1164 goto done;
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001165 }
1166
Kiran Kandi5f4ab692012-02-23 11:23:56 -08001167 aux_pcm_count--;
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001168
Kiran Kandi5f4ab692012-02-23 11:23:56 -08001169 if (aux_pcm_count > 0) {
1170 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d\n",
1171 __func__, dai->id, aux_pcm_count);
1172 goto done;
1173 } else if (aux_pcm_count < 0) {
1174 dev_err(dai->dev, "%s(): ERROR: dai->id %d"
1175 " aux_pcm_count = %d < 0\n",
1176 __func__, dai->id, aux_pcm_count);
1177 goto done;
1178 }
1179
1180 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d."
1181 "closing afe\n",
1182 __func__, dai->id, aux_pcm_count);
1183
1184 rc = afe_close(PCM_RX); /* can block */
1185 if (IS_ERR_VALUE(rc))
1186 dev_err(dai->dev, "fail to close AUX PCM RX AFE port\n");
1187
1188 rc = afe_close(PCM_TX);
1189 if (IS_ERR_VALUE(rc))
1190 dev_err(dai->dev, "fail to close AUX PCM TX AFE port\n");
1191
1192done:
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001193 kfree(dai_data);
1194 snd_soc_unregister_dai(dai->dev);
1195
Kiran Kandi5f4ab692012-02-23 11:23:56 -08001196 mutex_unlock(&aux_pcm_mutex);
1197
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001198 return 0;
1199}
Patrick Lai04baee942012-05-01 14:38:47 -07001200
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -07001201static int msm_dai_q6_dai_sec_auxpcm_remove(struct snd_soc_dai *dai)
1202{
1203 struct msm_dai_q6_dai_data *dai_data;
1204 int rc;
1205
1206 pr_debug("%s\n", __func__);
1207 dai_data = dev_get_drvdata(dai->dev);
1208
1209 mutex_lock(&aux_pcm_mutex);
1210
1211 if (aux_pcm_count == 0) {
1212 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count is 0. clean"
1213 " up and return\n", __func__, dai->id);
1214 goto done;
1215 }
1216
1217 aux_pcm_count--;
1218
1219 if (aux_pcm_count > 0) {
1220 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d\n",
1221 __func__, dai->id, aux_pcm_count);
1222 goto done;
1223 } else if (aux_pcm_count < 0) {
1224 dev_err(dai->dev, "%s(): ERROR: dai->id %d"
1225 " aux_pcm_count = %d < 0\n",
1226 __func__, dai->id, aux_pcm_count);
1227 goto done;
1228 }
1229
1230 dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d."
1231 "closing afe\n",
1232 __func__, dai->id, aux_pcm_count);
1233
1234 rc = afe_close(SECONDARY_PCM_RX); /* can block */
1235 if (IS_ERR_VALUE(rc))
1236 dev_err(dai->dev, "fail to close AUX PCM RX AFE port\n");
1237
1238 rc = afe_close(SECONDARY_PCM_TX);
1239 if (IS_ERR_VALUE(rc))
1240 dev_err(dai->dev, "fail to close AUX PCM TX AFE port\n");
1241
1242done:
1243 kfree(dai_data);
1244 snd_soc_unregister_dai(dai->dev);
1245
1246 mutex_unlock(&aux_pcm_mutex);
1247
1248 return 0;
1249}
1250
Kuirong Wang274f21a2011-12-15 21:29:08 -08001251static int msm_dai_q6_dai_mi2s_probe(struct snd_soc_dai *dai)
1252{
Patrick Lai04baee942012-05-01 14:38:47 -07001253 struct msm_dai_q6_mi2s_dai_data *mi2s_dai_data =
1254 dev_get_drvdata(dai->dev);
1255 struct snd_kcontrol *kcontrol = NULL;
Kuirong Wang274f21a2011-12-15 21:29:08 -08001256 int rc = 0;
1257
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -07001258 if (mi2s_dai_data->rx_dai.mi2s_dai_data.port_config.mi2s.line) {
Patrick Lai04baee942012-05-01 14:38:47 -07001259 kcontrol = snd_ctl_new1(&mi2s_config_controls[0],
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -07001260 &mi2s_dai_data->rx_dai.mi2s_dai_data);
Patrick Lai04baee942012-05-01 14:38:47 -07001261 rc = snd_ctl_add(dai->card->snd_card, kcontrol);
Kuirong Wang274f21a2011-12-15 21:29:08 -08001262
Patrick Lai04baee942012-05-01 14:38:47 -07001263 if (IS_ERR_VALUE(rc)) {
1264 dev_err(dai->dev, "%s: err add RX fmt ctl\n", __func__);
1265 goto rtn;
1266 }
Kuirong Wang274f21a2011-12-15 21:29:08 -08001267 }
Kuirong Wang875d1ec2012-04-02 19:56:25 -07001268
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -07001269 if (mi2s_dai_data->tx_dai.mi2s_dai_data.port_config.mi2s.line) {
Patrick Lai04baee942012-05-01 14:38:47 -07001270 rc = snd_ctl_add(dai->card->snd_card,
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -07001271 snd_ctl_new1(&mi2s_config_controls[2],
1272 &mi2s_dai_data->tx_dai.mi2s_dai_data));
Patrick Lai04baee942012-05-01 14:38:47 -07001273
1274 if (IS_ERR_VALUE(rc)) {
1275 if (kcontrol)
1276 snd_ctl_remove(dai->card->snd_card, kcontrol);
1277 dev_err(dai->dev, "%s: err add TX fmt ctl\n", __func__);
1278 }
1279 }
1280
Kuirong Wang274f21a2011-12-15 21:29:08 -08001281rtn:
1282 return rc;
1283}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001284
Patrick Lai04baee942012-05-01 14:38:47 -07001285static int msm_dai_q6_dai_mi2s_remove(struct snd_soc_dai *dai)
1286{
1287 struct msm_dai_q6_mi2s_dai_data *mi2s_dai_data =
1288 dev_get_drvdata(dai->dev);
1289 int rc;
1290
1291 /* If AFE port is still up, close it */
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -07001292 if (test_bit(STATUS_PORT_STARTED,
1293 mi2s_dai_data->rx_dai.mi2s_dai_data.status_mask)) {
Patrick Lai04baee942012-05-01 14:38:47 -07001294 rc = afe_close(MI2S_RX); /* can block */
1295 if (IS_ERR_VALUE(rc))
1296 dev_err(dai->dev, "fail to close MI2S_RX port\n");
1297 clear_bit(STATUS_PORT_STARTED,
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -07001298 mi2s_dai_data->rx_dai.mi2s_dai_data.status_mask);
Patrick Lai04baee942012-05-01 14:38:47 -07001299 }
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -07001300 if (test_bit(STATUS_PORT_STARTED,
1301 mi2s_dai_data->tx_dai.mi2s_dai_data.status_mask)) {
Patrick Lai04baee942012-05-01 14:38:47 -07001302 rc = afe_close(MI2S_TX); /* can block */
1303 if (IS_ERR_VALUE(rc))
1304 dev_err(dai->dev, "fail to close MI2S_TX port\n");
1305 clear_bit(STATUS_PORT_STARTED,
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -07001306 mi2s_dai_data->tx_dai.mi2s_dai_data.status_mask);
Patrick Lai04baee942012-05-01 14:38:47 -07001307 }
1308 kfree(mi2s_dai_data);
1309 snd_soc_unregister_dai(dai->dev);
1310
1311 return 0;
1312}
1313
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001314static int msm_dai_q6_dai_probe(struct snd_soc_dai *dai)
1315{
1316 struct msm_dai_q6_dai_data *dai_data;
1317 int rc = 0;
Kuirong Wang875d1ec2012-04-02 19:56:25 -07001318 const struct snd_kcontrol_new *kcontrol;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001319
1320 dai_data = kzalloc(sizeof(struct msm_dai_q6_dai_data),
1321 GFP_KERNEL);
1322
1323 if (!dai_data) {
1324 dev_err(dai->dev, "DAI-%d: fail to allocate dai data\n",
1325 dai->id);
1326 rc = -ENOMEM;
1327 } else
1328 dev_set_drvdata(dai->dev, dai_data);
Kuirong Wang875d1ec2012-04-02 19:56:25 -07001329 if (dai->id == SECONDARY_I2S_RX) {
1330 kcontrol = &mi2s_config_controls[1];
1331 rc = snd_ctl_add(dai->card->snd_card,
1332 snd_ctl_new1(kcontrol, dai_data));
1333 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001334
1335 return rc;
1336}
1337
1338static int msm_dai_q6_dai_remove(struct snd_soc_dai *dai)
1339{
1340 struct msm_dai_q6_dai_data *dai_data;
1341 int rc;
1342
1343 dai_data = dev_get_drvdata(dai->dev);
1344
1345 /* If AFE port is still up, close it */
1346 if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
Helen Zeng0705a5f2011-10-14 15:29:52 -07001347 switch (dai->id) {
1348 case VOICE_PLAYBACK_TX:
Helen Zenge3d716a2011-10-14 16:32:16 -07001349 case VOICE_RECORD_TX:
1350 case VOICE_RECORD_RX:
Helen Zeng0705a5f2011-10-14 15:29:52 -07001351 pr_debug("%s, stop pseudo port:%d\n",
1352 __func__, dai->id);
1353 rc = afe_stop_pseudo_port(dai->id);
1354 break;
1355 default:
1356 rc = afe_close(dai->id); /* can block */
1357 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001358 if (IS_ERR_VALUE(rc))
1359 dev_err(dai->dev, "fail to close AFE port\n");
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301360 clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001361 }
1362 kfree(dai_data);
1363 snd_soc_unregister_dai(dai->dev);
1364
1365 return 0;
1366}
1367
Lei Zhou157c1842011-08-19 13:05:04 -04001368static int msm_dai_q6_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
1369{
1370 int rc = 0;
1371
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001372 dev_dbg(dai->dev, "enter %s, id = %d fmt[%d]\n", __func__,
1373 dai->id, fmt);
Lei Zhou157c1842011-08-19 13:05:04 -04001374 switch (dai->id) {
1375 case PRIMARY_I2S_TX:
1376 case PRIMARY_I2S_RX:
Kuirong Wang9bbf6132012-01-10 18:28:49 -08001377 case SECONDARY_I2S_RX:
Lei Zhou157c1842011-08-19 13:05:04 -04001378 rc = msm_dai_q6_cdc_set_fmt(dai, fmt);
1379 break;
1380 default:
1381 dev_err(dai->dev, "invalid cpu_dai set_fmt\n");
1382 rc = -EINVAL;
1383 break;
1384 }
1385
1386 return rc;
1387}
1388
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001389static int msm_dai_q6_set_channel_map(struct snd_soc_dai *dai,
1390 unsigned int tx_num, unsigned int *tx_slot,
1391 unsigned int rx_num, unsigned int *rx_slot)
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001392{
1393 int rc = 0;
1394 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
1395 unsigned int i = 0;
1396
Kiran Kandifd30c892012-05-21 23:03:26 -07001397 dev_dbg(dai->dev, "%s: dai_id = %d\n", __func__, dai->id);
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001398 switch (dai->id) {
1399 case SLIMBUS_0_RX:
Neema Shetty3c9d2862012-03-11 01:25:32 -08001400 case SLIMBUS_1_RX:
Kiran Kandifd30c892012-05-21 23:03:26 -07001401 case SLIMBUS_2_RX:
Neema Shetty74131ac2012-05-09 13:35:26 -07001402 case SLIMBUS_3_RX:
Helen Zeng8f925502012-03-05 16:50:17 -08001403 case SLIMBUS_4_RX:
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001404 /* channel number to be between 128 and 255. For RX port
1405 * use channel numbers from 138 to 144, for TX port
1406 * use channel numbers from 128 to 137
Neema Shetty3c9d2862012-03-11 01:25:32 -08001407 * For ports between MDM-APQ use channel numbers from 145
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001408 */
Bharath Ramachandramurthy94ad7e22012-02-28 18:44:07 -08001409 if (!rx_slot)
1410 return -EINVAL;
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001411 for (i = 0; i < rx_num; i++) {
1412 dai_data->port_config.slim_sch.slave_ch_mapping[i] =
1413 rx_slot[i];
1414 pr_debug("%s: find number of channels[%d] ch[%d]\n",
1415 __func__, i,
1416 rx_slot[i]);
1417 }
1418 dai_data->port_config.slim_sch.num_channels = rx_num;
Kiran Kandi1e6371d2012-03-29 11:48:57 -07001419 pr_debug("%s:SLIMBUS_%d_RX cnt[%d] ch[%d %d]\n", __func__,
1420 (dai->id - SLIMBUS_0_RX) / 2,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001421 rx_num, dai_data->port_config.slim_sch.slave_ch_mapping[0],
1422 dai_data->port_config.slim_sch.slave_ch_mapping[1]);
1423
1424 break;
1425 case SLIMBUS_0_TX:
Neema Shetty3c9d2862012-03-11 01:25:32 -08001426 case SLIMBUS_1_TX:
Kiran Kandi1e6371d2012-03-29 11:48:57 -07001427 case SLIMBUS_2_TX:
Helen Zeng38c3c962012-05-17 14:56:20 -07001428 case SLIMBUS_3_TX:
Helen Zeng8f925502012-03-05 16:50:17 -08001429 case SLIMBUS_4_TX:
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001430 /* channel number to be between 128 and 255. For RX port
1431 * use channel numbers from 138 to 144, for TX port
1432 * use channel numbers from 128 to 137
Neema Shetty3c9d2862012-03-11 01:25:32 -08001433 * For ports between MDM-APQ use channel numbers from 145
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001434 */
Bharath Ramachandramurthy94ad7e22012-02-28 18:44:07 -08001435 if (!tx_slot)
1436 return -EINVAL;
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001437 for (i = 0; i < tx_num; i++) {
1438 dai_data->port_config.slim_sch.slave_ch_mapping[i] =
1439 tx_slot[i];
1440 pr_debug("%s: find number of channels[%d] ch[%d]\n",
1441 __func__, i, tx_slot[i]);
1442 }
1443 dai_data->port_config.slim_sch.num_channels = tx_num;
Kiran Kandi1e6371d2012-03-29 11:48:57 -07001444 pr_debug("%s:SLIMBUS_%d_TX cnt[%d] ch[%d %d]\n", __func__,
1445 (dai->id - SLIMBUS_0_TX) / 2,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001446 tx_num, dai_data->port_config.slim_sch.slave_ch_mapping[0],
1447 dai_data->port_config.slim_sch.slave_ch_mapping[1]);
1448 break;
1449 default:
1450 dev_err(dai->dev, "invalid cpu_dai set_fmt\n");
1451 rc = -EINVAL;
1452 break;
1453 }
1454 return rc;
1455}
1456
Patrick Lai04baee942012-05-01 14:38:47 -07001457static struct snd_soc_dai_ops msm_dai_q6_mi2s_ops = {
1458 .startup = msm_dai_q6_mi2s_startup,
1459 .prepare = msm_dai_q6_mi2s_prepare,
Patrick Lai04baee942012-05-01 14:38:47 -07001460 .hw_params = msm_dai_q6_mi2s_hw_params,
1461 .shutdown = msm_dai_q6_mi2s_shutdown,
1462 .set_fmt = msm_dai_q6_mi2s_set_fmt,
1463};
1464
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001465static struct snd_soc_dai_ops msm_dai_q6_ops = {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001466 .prepare = msm_dai_q6_prepare,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001467 .hw_params = msm_dai_q6_hw_params,
1468 .shutdown = msm_dai_q6_shutdown,
Lei Zhou157c1842011-08-19 13:05:04 -04001469 .set_fmt = msm_dai_q6_set_fmt,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001470 .set_channel_map = msm_dai_q6_set_channel_map,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001471};
1472
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001473static struct snd_soc_dai_ops msm_dai_q6_auxpcm_ops = {
1474 .prepare = msm_dai_q6_auxpcm_prepare,
1475 .trigger = msm_dai_q6_auxpcm_trigger,
1476 .hw_params = msm_dai_q6_auxpcm_hw_params,
1477 .shutdown = msm_dai_q6_auxpcm_shutdown,
1478};
1479
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -07001480static struct snd_soc_dai_ops msm_dai_q6_sec_auxpcm_ops = {
1481 .prepare = msm_dai_q6_sec_auxpcm_prepare,
1482 .trigger = msm_dai_q6_auxpcm_trigger,
1483 .hw_params = msm_dai_q6_sec_auxpcm_hw_params,
1484 .shutdown = msm_dai_q6_sec_auxpcm_shutdown,
1485};
1486
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001487static struct snd_soc_dai_driver msm_dai_q6_i2s_rx_dai = {
1488 .playback = {
1489 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1490 SNDRV_PCM_RATE_16000,
1491 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1492 .channels_min = 1,
Kiran Kandi9db678b2012-01-15 14:25:59 -08001493 .channels_max = 4,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001494 .rate_min = 8000,
1495 .rate_max = 48000,
1496 },
1497 .ops = &msm_dai_q6_ops,
1498 .probe = msm_dai_q6_dai_probe,
1499 .remove = msm_dai_q6_dai_remove,
1500};
1501
1502static struct snd_soc_dai_driver msm_dai_q6_i2s_tx_dai = {
1503 .capture = {
1504 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1505 SNDRV_PCM_RATE_16000,
1506 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1507 .channels_min = 1,
1508 .channels_max = 2,
1509 .rate_min = 8000,
1510 .rate_max = 48000,
1511 },
1512 .ops = &msm_dai_q6_ops,
1513 .probe = msm_dai_q6_dai_probe,
1514 .remove = msm_dai_q6_dai_remove,
1515};
1516
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301517static struct snd_soc_dai_driver msm_dai_q6_afe_rx_dai = {
1518 .playback = {
1519 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1520 SNDRV_PCM_RATE_16000,
1521 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1522 .channels_min = 1,
1523 .channels_max = 2,
1524 .rate_min = 8000,
1525 .rate_max = 48000,
1526 },
1527 .ops = &msm_dai_q6_ops,
1528 .probe = msm_dai_q6_dai_probe,
1529 .remove = msm_dai_q6_dai_remove,
1530};
1531
1532static struct snd_soc_dai_driver msm_dai_q6_afe_tx_dai = {
1533 .capture = {
1534 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1535 SNDRV_PCM_RATE_16000,
1536 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1537 .channels_min = 1,
Mingming Yin647e9ea2012-03-17 19:56:10 -07001538 .channels_max = 4,
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301539 .rate_min = 8000,
1540 .rate_max = 48000,
1541 },
1542 .ops = &msm_dai_q6_ops,
1543 .probe = msm_dai_q6_dai_probe,
1544 .remove = msm_dai_q6_dai_remove,
1545};
1546
Helen Zeng0705a5f2011-10-14 15:29:52 -07001547static struct snd_soc_dai_driver msm_dai_q6_voice_playback_tx_dai = {
1548 .playback = {
1549 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1550 SNDRV_PCM_RATE_16000,
1551 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1552 .channels_min = 1,
1553 .channels_max = 2,
1554 .rate_max = 48000,
1555 .rate_min = 8000,
1556 },
1557 .ops = &msm_dai_q6_ops,
1558 .probe = msm_dai_q6_dai_probe,
1559 .remove = msm_dai_q6_dai_remove,
1560};
1561
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001562static struct snd_soc_dai_driver msm_dai_q6_slimbus_rx_dai = {
1563 .playback = {
1564 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1565 SNDRV_PCM_RATE_16000,
1566 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1567 .channels_min = 1,
1568 .channels_max = 2,
1569 .rate_min = 8000,
1570 .rate_max = 48000,
1571 },
1572 .ops = &msm_dai_q6_ops,
1573 .probe = msm_dai_q6_dai_probe,
1574 .remove = msm_dai_q6_dai_remove,
1575};
1576
1577static struct snd_soc_dai_driver msm_dai_q6_slimbus_tx_dai = {
1578 .capture = {
1579 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1580 SNDRV_PCM_RATE_16000,
1581 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1582 .channels_min = 1,
1583 .channels_max = 2,
1584 .rate_min = 8000,
1585 .rate_max = 48000,
1586 },
1587 .ops = &msm_dai_q6_ops,
1588 .probe = msm_dai_q6_dai_probe,
1589 .remove = msm_dai_q6_dai_remove,
1590};
1591
Helen Zenge3d716a2011-10-14 16:32:16 -07001592static struct snd_soc_dai_driver msm_dai_q6_incall_record_dai = {
1593 .capture = {
1594 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1595 SNDRV_PCM_RATE_16000,
1596 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1597 .channels_min = 1,
1598 .channels_max = 2,
1599 .rate_min = 8000,
1600 .rate_max = 48000,
1601 },
1602 .ops = &msm_dai_q6_ops,
1603 .probe = msm_dai_q6_dai_probe,
1604 .remove = msm_dai_q6_dai_remove,
1605};
1606
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001607static struct snd_soc_dai_driver msm_dai_q6_bt_sco_rx_dai = {
1608 .playback = {
1609 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
1610 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1611 .channels_min = 1,
1612 .channels_max = 1,
1613 .rate_max = 16000,
1614 .rate_min = 8000,
1615 },
1616 .ops = &msm_dai_q6_ops,
1617 .probe = msm_dai_q6_dai_probe,
1618 .remove = msm_dai_q6_dai_remove,
1619};
1620
1621static struct snd_soc_dai_driver msm_dai_q6_bt_sco_tx_dai = {
Patrick Laibd5021e2012-06-12 01:27:20 -07001622 .capture = {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001623 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
1624 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1625 .channels_min = 1,
1626 .channels_max = 1,
1627 .rate_max = 16000,
1628 .rate_min = 8000,
1629 },
1630 .ops = &msm_dai_q6_ops,
1631 .probe = msm_dai_q6_dai_probe,
1632 .remove = msm_dai_q6_dai_remove,
1633};
1634
1635static struct snd_soc_dai_driver msm_dai_q6_fm_rx_dai = {
1636 .playback = {
1637 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1638 SNDRV_PCM_RATE_16000,
1639 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1640 .channels_min = 2,
1641 .channels_max = 2,
1642 .rate_max = 48000,
1643 .rate_min = 8000,
1644 },
1645 .ops = &msm_dai_q6_ops,
1646 .probe = msm_dai_q6_dai_probe,
1647 .remove = msm_dai_q6_dai_remove,
1648};
1649
1650static struct snd_soc_dai_driver msm_dai_q6_fm_tx_dai = {
Patrick Laibd5021e2012-06-12 01:27:20 -07001651 .capture = {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001652 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1653 SNDRV_PCM_RATE_16000,
1654 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1655 .channels_min = 2,
1656 .channels_max = 2,
1657 .rate_max = 48000,
1658 .rate_min = 8000,
1659 },
1660 .ops = &msm_dai_q6_ops,
1661 .probe = msm_dai_q6_dai_probe,
1662 .remove = msm_dai_q6_dai_remove,
1663};
1664
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001665static struct snd_soc_dai_driver msm_dai_q6_aux_pcm_rx_dai = {
1666 .playback = {
Kuirong Wang547a9982012-05-04 18:29:11 -07001667 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001668 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1669 .channels_min = 1,
1670 .channels_max = 1,
Kuirong Wang547a9982012-05-04 18:29:11 -07001671 .rate_max = 16000,
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001672 .rate_min = 8000,
1673 },
1674 .ops = &msm_dai_q6_auxpcm_ops,
1675 .probe = msm_dai_q6_dai_auxpcm_probe,
1676 .remove = msm_dai_q6_dai_auxpcm_remove,
1677};
1678
1679static struct snd_soc_dai_driver msm_dai_q6_aux_pcm_tx_dai = {
1680 .capture = {
Kuirong Wang547a9982012-05-04 18:29:11 -07001681 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001682 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1683 .channels_min = 1,
1684 .channels_max = 1,
Kuirong Wang547a9982012-05-04 18:29:11 -07001685 .rate_max = 16000,
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001686 .rate_min = 8000,
1687 },
Kiran Kandi5f4ab692012-02-23 11:23:56 -08001688 .ops = &msm_dai_q6_auxpcm_ops,
1689 .probe = msm_dai_q6_dai_auxpcm_probe,
1690 .remove = msm_dai_q6_dai_auxpcm_remove,
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001691};
1692
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -07001693static struct snd_soc_dai_driver msm_dai_q6_sec_aux_pcm_rx_dai = {
1694 .playback = {
1695 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
1696 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1697 .channels_min = 1,
1698 .channels_max = 1,
1699 .rate_max = 16000,
1700 .rate_min = 8000,
1701 },
1702 .ops = &msm_dai_q6_sec_auxpcm_ops,
1703 .probe = msm_dai_q6_dai_sec_auxpcm_probe,
1704 .remove = msm_dai_q6_dai_sec_auxpcm_remove,
1705};
1706
1707static struct snd_soc_dai_driver msm_dai_q6_sec_aux_pcm_tx_dai = {
1708 .capture = {
1709 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
1710 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1711 .channels_min = 1,
1712 .channels_max = 1,
1713 .rate_max = 16000,
1714 .rate_min = 8000,
1715 },
1716 .ops = &msm_dai_q6_sec_auxpcm_ops,
1717 .probe = msm_dai_q6_dai_sec_auxpcm_probe,
1718 .remove = msm_dai_q6_dai_sec_auxpcm_remove,
1719};
1720
Patrick Lai04baee942012-05-01 14:38:47 -07001721/* Channel min and max are initialized base on platform data */
1722static struct snd_soc_dai_driver msm_dai_q6_mi2s_dai = {
Kuirong Wang274f21a2011-12-15 21:29:08 -08001723 .playback = {
1724 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1725 SNDRV_PCM_RATE_16000,
1726 .formats = SNDRV_PCM_FMTBIT_S16_LE,
Kuirong Wang274f21a2011-12-15 21:29:08 -08001727 .rate_min = 8000,
1728 .rate_max = 48000,
1729 },
Kuirong Wang623b50f2012-04-16 15:51:14 -07001730 .capture = {
1731 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1732 SNDRV_PCM_RATE_16000,
1733 .formats = SNDRV_PCM_FMTBIT_S16_LE,
Patrick Lai04baee942012-05-01 14:38:47 -07001734 .rate_min = 8000,
1735 .rate_max = 48000,
Kuirong Wang623b50f2012-04-16 15:51:14 -07001736 },
Patrick Lai04baee942012-05-01 14:38:47 -07001737 .ops = &msm_dai_q6_mi2s_ops,
Kuirong Wang623b50f2012-04-16 15:51:14 -07001738 .probe = msm_dai_q6_dai_mi2s_probe,
Patrick Lai04baee942012-05-01 14:38:47 -07001739 .remove = msm_dai_q6_dai_mi2s_remove,
Kuirong Wang623b50f2012-04-16 15:51:14 -07001740};
1741
Neema Shetty3c9d2862012-03-11 01:25:32 -08001742static struct snd_soc_dai_driver msm_dai_q6_slimbus_1_rx_dai = {
1743 .playback = {
1744 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
1745 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1746 .channels_min = 1,
1747 .channels_max = 1,
1748 .rate_min = 8000,
1749 .rate_max = 16000,
1750 },
1751 .ops = &msm_dai_q6_ops,
1752 .probe = msm_dai_q6_dai_probe,
1753 .remove = msm_dai_q6_dai_remove,
1754};
1755
1756static struct snd_soc_dai_driver msm_dai_q6_slimbus_1_tx_dai = {
1757 .capture = {
1758 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
1759 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1760 .channels_min = 1,
1761 .channels_max = 1,
1762 .rate_min = 8000,
1763 .rate_max = 16000,
1764 },
1765 .ops = &msm_dai_q6_ops,
1766 .probe = msm_dai_q6_dai_probe,
1767 .remove = msm_dai_q6_dai_remove,
1768};
1769
Kiran Kandifd30c892012-05-21 23:03:26 -07001770static struct snd_soc_dai_driver msm_dai_q6_slimbus_2_rx_dai = {
1771 .playback = {
1772 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1773 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_96000 |
1774 SNDRV_PCM_RATE_192000,
1775 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1776 .channels_min = 1,
1777 .channels_max = 2,
1778 .rate_min = 8000,
1779 .rate_max = 192000,
1780 },
1781 .ops = &msm_dai_q6_ops,
1782 .probe = msm_dai_q6_dai_probe,
1783 .remove = msm_dai_q6_dai_remove,
1784};
1785
Kiran Kandi1e6371d2012-03-29 11:48:57 -07001786static struct snd_soc_dai_driver msm_dai_q6_slimbus_2_tx_dai = {
1787 .capture = {
1788 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
1789 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_96000 |
1790 SNDRV_PCM_RATE_192000,
1791 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1792 .channels_min = 1,
1793 .channels_max = 4,
1794 .rate_min = 8000,
1795 .rate_max = 192000,
1796 },
1797 .ops = &msm_dai_q6_ops,
1798 .probe = msm_dai_q6_dai_probe,
1799 .remove = msm_dai_q6_dai_remove,
1800};
1801
Neema Shetty74131ac2012-05-09 13:35:26 -07001802static struct snd_soc_dai_driver msm_dai_q6_slimbus_3_rx_dai = {
1803 .playback = {
1804 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
1805 SNDRV_PCM_RATE_48000,
1806 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1807 .channels_min = 1,
1808 .channels_max = 2,
1809 .rate_min = 8000,
1810 .rate_max = 48000,
1811 },
1812 .ops = &msm_dai_q6_ops,
1813 .probe = msm_dai_q6_dai_probe,
1814 .remove = msm_dai_q6_dai_remove,
1815};
1816
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001817/* To do: change to register DAIs as batch */
1818static __devinit int msm_dai_q6_dev_probe(struct platform_device *pdev)
1819{
1820 int rc = 0;
1821
1822 dev_dbg(&pdev->dev, "dev name %s\n", dev_name(&pdev->dev));
1823
1824 switch (pdev->id) {
1825 case PRIMARY_I2S_RX:
Kuirong Wang9bbf6132012-01-10 18:28:49 -08001826 case SECONDARY_I2S_RX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001827 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_i2s_rx_dai);
1828 break;
1829 case PRIMARY_I2S_TX:
1830 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_i2s_tx_dai);
1831 break;
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001832 case PCM_RX:
1833 rc = snd_soc_register_dai(&pdev->dev,
1834 &msm_dai_q6_aux_pcm_rx_dai);
1835 break;
1836 case PCM_TX:
1837 rc = snd_soc_register_dai(&pdev->dev,
1838 &msm_dai_q6_aux_pcm_tx_dai);
1839 break;
Patrick Lai04baee942012-05-01 14:38:47 -07001840
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -07001841 case SECONDARY_PCM_RX:
1842 rc = snd_soc_register_dai(&pdev->dev,
1843 &msm_dai_q6_sec_aux_pcm_rx_dai);
1844 break;
1845 case SECONDARY_PCM_TX:
1846 rc = snd_soc_register_dai(&pdev->dev,
1847 &msm_dai_q6_sec_aux_pcm_tx_dai);
1848 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001849 case SLIMBUS_0_RX:
Helen Zeng8f925502012-03-05 16:50:17 -08001850 case SLIMBUS_4_RX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001851 rc = snd_soc_register_dai(&pdev->dev,
1852 &msm_dai_q6_slimbus_rx_dai);
1853 break;
1854 case SLIMBUS_0_TX:
Helen Zeng8f925502012-03-05 16:50:17 -08001855 case SLIMBUS_4_TX:
Helen Zeng38c3c962012-05-17 14:56:20 -07001856 case SLIMBUS_3_TX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001857 rc = snd_soc_register_dai(&pdev->dev,
1858 &msm_dai_q6_slimbus_tx_dai);
Neema Shetty3c9d2862012-03-11 01:25:32 -08001859 break;
Neema Shetty3c9d2862012-03-11 01:25:32 -08001860 case SLIMBUS_1_RX:
1861 rc = snd_soc_register_dai(&pdev->dev,
1862 &msm_dai_q6_slimbus_1_rx_dai);
1863 break;
1864 case SLIMBUS_1_TX:
1865 rc = snd_soc_register_dai(&pdev->dev,
1866 &msm_dai_q6_slimbus_1_tx_dai);
1867 break;
Kiran Kandifd30c892012-05-21 23:03:26 -07001868 case SLIMBUS_2_RX:
1869 rc = snd_soc_register_dai(&pdev->dev,
1870 &msm_dai_q6_slimbus_2_rx_dai);
1871 break;
Kiran Kandi1e6371d2012-03-29 11:48:57 -07001872 case SLIMBUS_2_TX:
1873 rc = snd_soc_register_dai(&pdev->dev,
1874 &msm_dai_q6_slimbus_2_tx_dai);
1875 break;
Neema Shetty74131ac2012-05-09 13:35:26 -07001876 case SLIMBUS_3_RX:
1877 rc = snd_soc_register_dai(&pdev->dev,
1878 &msm_dai_q6_slimbus_3_rx_dai);
1879 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001880 case INT_BT_SCO_RX:
1881 rc = snd_soc_register_dai(&pdev->dev,
1882 &msm_dai_q6_bt_sco_rx_dai);
1883 break;
1884 case INT_BT_SCO_TX:
1885 rc = snd_soc_register_dai(&pdev->dev,
1886 &msm_dai_q6_bt_sco_tx_dai);
1887 break;
1888 case INT_FM_RX:
1889 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_fm_rx_dai);
1890 break;
1891 case INT_FM_TX:
1892 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_fm_tx_dai);
1893 break;
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301894 case RT_PROXY_DAI_001_RX:
1895 case RT_PROXY_DAI_002_RX:
1896 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_afe_rx_dai);
1897 break;
1898 case RT_PROXY_DAI_001_TX:
1899 case RT_PROXY_DAI_002_TX:
1900 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_afe_tx_dai);
1901 break;
Helen Zeng0705a5f2011-10-14 15:29:52 -07001902 case VOICE_PLAYBACK_TX:
1903 rc = snd_soc_register_dai(&pdev->dev,
1904 &msm_dai_q6_voice_playback_tx_dai);
1905 break;
Helen Zenge3d716a2011-10-14 16:32:16 -07001906 case VOICE_RECORD_RX:
1907 case VOICE_RECORD_TX:
1908 rc = snd_soc_register_dai(&pdev->dev,
1909 &msm_dai_q6_incall_record_dai);
1910 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001911 default:
1912 rc = -ENODEV;
1913 break;
1914 }
1915 return rc;
1916}
1917
1918static __devexit int msm_dai_q6_dev_remove(struct platform_device *pdev)
1919{
1920 snd_soc_unregister_dai(&pdev->dev);
1921 return 0;
1922}
1923
Patrick Lai04baee942012-05-01 14:38:47 -07001924static __devinit int msm_dai_q6_mi2s_dev_probe(struct platform_device *pdev)
1925{
1926 struct msm_dai_q6_mi2s_dai_data *dai_data;
1927 int rc = 0;
1928
1929 dev_dbg(&pdev->dev, "%s: pdev %p dev %p\n", __func__, pdev, &pdev->dev);
1930
1931 dai_data = kzalloc(sizeof(struct msm_dai_q6_mi2s_dai_data),
1932 GFP_KERNEL);
1933
1934 if (!dai_data) {
1935 dev_err(&pdev->dev, "fail to allocate dai data\n");
1936 rc = -ENOMEM;
1937 goto rtn;
1938 } else
1939 dev_set_drvdata(&pdev->dev, dai_data);
1940
1941 rc = msm_dai_q6_mi2s_platform_data_validation(pdev,
1942 &msm_dai_q6_mi2s_dai);
1943 if (IS_ERR_VALUE(rc))
1944 goto err_pdata;
1945
1946 dai_data->rate_constraint.count = 1;
1947 dai_data->bitwidth_constraint.count = 1;
1948 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_mi2s_dai);
1949
1950 if (IS_ERR_VALUE(rc))
1951 goto err_pdata;
1952
1953 return 0;
1954
1955err_pdata:
Subhash Chandra Bose Naripeddy8f846892012-06-12 11:29:18 -07001956
1957 dev_err(&pdev->dev, "fail to msm_dai_q6_mi2s_dev_probe\n");
Patrick Lai04baee942012-05-01 14:38:47 -07001958 kfree(dai_data);
1959rtn:
1960 return rc;
1961}
1962
1963static __devexit int msm_dai_q6_mi2s_dev_remove(struct platform_device *pdev)
1964{
1965 snd_soc_unregister_dai(&pdev->dev);
1966 return 0;
1967}
1968
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001969static struct platform_driver msm_dai_q6_driver = {
1970 .probe = msm_dai_q6_dev_probe,
1971 .remove = msm_dai_q6_dev_remove,
1972 .driver = {
1973 .name = "msm-dai-q6",
1974 .owner = THIS_MODULE,
1975 },
1976};
1977
Patrick Lai04baee942012-05-01 14:38:47 -07001978static struct platform_driver msm_dai_q6_mi2s_driver = {
1979 .probe = msm_dai_q6_mi2s_dev_probe,
1980 .remove = msm_dai_q6_mi2s_dev_remove,
1981 .driver = {
1982 .name = "msm-dai-q6-mi2s",
1983 .owner = THIS_MODULE,
1984 },
1985};
1986
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001987static int __init msm_dai_q6_init(void)
1988{
Patrick Lai04baee942012-05-01 14:38:47 -07001989 int rc1, rc2;
1990
1991 rc1 = platform_driver_register(&msm_dai_q6_mi2s_driver);
1992
1993 if (IS_ERR_VALUE(rc1))
1994 pr_err("%s: fail to register mi2s dai driver\n", __func__);
1995
1996 rc2 = platform_driver_register(&msm_dai_q6_driver);
1997
1998 if (IS_ERR_VALUE(rc2))
1999 pr_err("%s: fail to register mi2s dai driver\n", __func__);
2000
2001 return (IS_ERR_VALUE(rc1) && IS_ERR_VALUE(rc2)) ? -1 : 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002002}
2003module_init(msm_dai_q6_init);
2004
2005static void __exit msm_dai_q6_exit(void)
2006{
2007 platform_driver_unregister(&msm_dai_q6_driver);
2008}
2009module_exit(msm_dai_q6_exit);
2010
2011/* Module information */
2012MODULE_DESCRIPTION("MSM DSP DAI driver");
2013MODULE_LICENSE("GPL v2");