blob: c69600f11a0d65169ef47135f1c277cd32d45ec1 [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
2 *
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>
17#include <linux/mfd/wcd9310/core.h>
18#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>
26#include <sound/q6adm.h>
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -070027#include <sound/msm-dai-q6.h>
28#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;
39 union afe_port_config port_config;
40};
41
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -070042static struct clk *pcm_clk;
43
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070044static int msm_dai_q6_cdc_hw_params(struct snd_pcm_hw_params *params,
45 struct snd_soc_dai *dai, int stream)
46{
47 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
48
49 dai_data->channels = params_channels(params);
50 switch (dai_data->channels) {
51 case 2:
52 dai_data->port_config.mi2s.channel = MSM_AFE_STEREO;
53 break;
54 case 1:
55 dai_data->port_config.mi2s.channel = MSM_AFE_MONO;
56 break;
57 default:
58 return -EINVAL;
59 break;
60 }
61 dai_data->rate = params_rate(params);
62
63 dev_dbg(dai->dev, " channel %d sample rate %d entered\n",
64 dai_data->channels, dai_data->rate);
65
66 /* Q6 only supports 16 as now */
67 dai_data->port_config.mi2s.bitwidth = 16;
68 dai_data->port_config.mi2s.line = 1;
Lei Zhou157c1842011-08-19 13:05:04 -040069
70 return 0;
71}
72
73static int msm_dai_q6_cdc_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
74{
75 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
76
77 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
78 case SND_SOC_DAIFMT_CBS_CFS:
79 dai_data->port_config.mi2s.ws = 1; /* CPU is master */
80 break;
81 case SND_SOC_DAIFMT_CBM_CFM:
82 dai_data->port_config.mi2s.ws = 0; /* CPU is slave */
83 break;
84 default:
85 return -EINVAL;
86 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070087
88 return 0;
89}
90
91static int msm_dai_q6_hdmi_hw_params(struct snd_pcm_hw_params *params,
92 struct snd_soc_dai *dai)
93{
94 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
95
96 dev_dbg(dai->dev, "%s start HDMI port\n", __func__);
97
98 dai_data->channels = params_channels(params);
99 switch (dai_data->channels) {
100 case 2:
101 dai_data->port_config.hdmi.channel_mode = 0; /* Put in macro */
102 break;
103 default:
104 return -EINVAL;
105 break;
106 }
107
108 /* Q6 only supports 16 as now */
109 dai_data->port_config.hdmi.bitwidth = 16;
110 dai_data->port_config.hdmi.data_type = 0;
111 dai_data->rate = params_rate(params);
112
113 return 0;
114}
115
116static int msm_dai_q6_slim_bus_hw_params(struct snd_pcm_hw_params *params,
117 struct snd_soc_dai *dai, int stream)
118{
119 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
120 u8 pgd_la, inf_la;
121
122 memset(dai_data->port_config.slimbus.slave_port_mapping, 0,
123 sizeof(dai_data->port_config.slimbus.slave_port_mapping));
124
125 dai_data->channels = params_channels(params);
126 switch (dai_data->channels) {
127 case 2:
128 if (dai->id == SLIMBUS_0_RX) {
129 dai_data->port_config.slimbus.slave_port_mapping[0] = 1;
130 dai_data->port_config.slimbus.slave_port_mapping[1] = 2;
131 } else {
132 dai_data->port_config.slimbus.slave_port_mapping[0] = 7;
133 dai_data->port_config.slimbus.slave_port_mapping[1] = 8;
134 }
135 break;
136 case 1:
137 if (dai->id == SLIMBUS_0_RX)
138 dai_data->port_config.slimbus.slave_port_mapping[0] = 1;
139 else
140 dai_data->port_config.slimbus.slave_port_mapping[0] = 7;
141 break;
142 default:
143 return -EINVAL;
144 break;
145 }
146 dai_data->rate = params_rate(params);
147 tabla_get_logical_addresses(&pgd_la, &inf_la);
148
149 dai_data->port_config.slimbus.slimbus_dev_id = AFE_SLIMBUS_DEVICE_1;
150 dai_data->port_config.slimbus.slave_dev_pgd_la = pgd_la;
151 dai_data->port_config.slimbus.slave_dev_intfdev_la = inf_la;
152 /* Q6 only supports 16 as now */
153 dai_data->port_config.slimbus.bit_width = 16;
154 dai_data->port_config.slimbus.data_format = 0;
155 dai_data->port_config.slimbus.num_channels = dai_data->channels;
156 dai_data->port_config.slimbus.reserved = 0;
157
158 dev_dbg(dai->dev, "slimbus_dev_id %hu slave_dev_pgd_la 0x%hx\n"
159 "slave_dev_intfdev_la 0x%hx bit_width %hu data_format %hu\n"
160 "num_channel %hu slave_port_mapping[0] %hu\n"
161 "slave_port_mapping[1] %hu slave_port_mapping[2] %hu\n"
162 "sample_rate %d\n",
163 dai_data->port_config.slimbus.slimbus_dev_id,
164 dai_data->port_config.slimbus.slave_dev_pgd_la,
165 dai_data->port_config.slimbus.slave_dev_intfdev_la,
166 dai_data->port_config.slimbus.bit_width,
167 dai_data->port_config.slimbus.data_format,
168 dai_data->port_config.slimbus.num_channels,
169 dai_data->port_config.slimbus.slave_port_mapping[0],
170 dai_data->port_config.slimbus.slave_port_mapping[1],
171 dai_data->port_config.slimbus.slave_port_mapping[2],
172 dai_data->rate);
173
174 return 0;
175}
176
177static int msm_dai_q6_bt_fm_hw_params(struct snd_pcm_hw_params *params,
178 struct snd_soc_dai *dai, int stream)
179{
180 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
181
182 dai_data->channels = params_channels(params);
183 dai_data->rate = params_rate(params);
184
185 dev_dbg(dai->dev, "channels %d sample rate %d entered\n",
186 dai_data->channels, dai_data->rate);
187
188 memset(&dai_data->port_config, 0, sizeof(dai_data->port_config));
189
190 return 0;
191}
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700192static int msm_dai_q6_auxpcm_hw_params(
193 struct snd_pcm_substream *substream,
194 struct snd_pcm_hw_params *params,
195 struct snd_soc_dai *dai)
196{
197 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
198 struct msm_dai_auxpcm_pdata *auxpcm_pdata =
199 (struct msm_dai_auxpcm_pdata *) dai->dev->platform_data;
200
201 if (params_channels(params) != 1) {
202 dev_err(dai->dev, "AUX PCM supports only mono stream\n");
203 return -EINVAL;
204 }
205 dai_data->channels = params_channels(params);
206
207 if (params_rate(params) != 8000) {
208 dev_err(dai->dev, "AUX PCM supports only 8KHz sampling rate\n");
209 return -EINVAL;
210 }
211 dai_data->rate = params_rate(params);
212 dai_data->port_config.pcm.mode = auxpcm_pdata->mode;
213 dai_data->port_config.pcm.sync = auxpcm_pdata->sync;
214 dai_data->port_config.pcm.frame = auxpcm_pdata->frame;
215 dai_data->port_config.pcm.quant = auxpcm_pdata->quant;
216 dai_data->port_config.pcm.slot = auxpcm_pdata->slot;
217 dai_data->port_config.pcm.data = auxpcm_pdata->data;
218
219 return 0;
220}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700221
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530222static int get_frame_size(u16 rate, u16 ch)
223{
224 if (rate == 8000) {
225 if (ch == 1)
226 return 128 * 2;
227 else
228 return 128 * 2 * 2;
229 } else if (rate == 16000) {
230 if (ch == 1)
231 return 128 * 2 * 2;
232 else
233 return 128 * 2 * 4;
234 } else if (rate == 48000) {
235 if (ch == 1)
236 return 128 * 2 * 6;
237 else
238 return 128 * 2 * 12;
239 } else
240 return 128 * 2 * 12;
241}
242
243static int msm_dai_q6_afe_rtproxy_hw_params(struct snd_pcm_hw_params *params,
244 struct snd_soc_dai *dai)
245{
246 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
247
248 dai_data->rate = params_rate(params);
249 dai_data->port_config.rtproxy.num_ch =
250 params_channels(params);
251
252 pr_debug("channel %d entered,dai_id: %d,rate: %d\n",
253 dai_data->port_config.rtproxy.num_ch, dai->id, dai_data->rate);
254
255 dai_data->port_config.rtproxy.bitwidth = 16; /* Q6 only supports 16 */
256 dai_data->port_config.rtproxy.interleaved = 1;
257 dai_data->port_config.rtproxy.frame_sz = get_frame_size(dai_data->rate,
258 dai_data->port_config.rtproxy.num_ch);
259 dai_data->port_config.rtproxy.jitter =
260 dai_data->port_config.rtproxy.frame_sz/2;
261 dai_data->port_config.rtproxy.lw_mark = 0;
262 dai_data->port_config.rtproxy.hw_mark = 0;
263 dai_data->port_config.rtproxy.rsvd = 0;
264
265 return 0;
266}
267
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700268/* Current implementation assumes hw_param is called once
269 * This may not be the case but what to do when ADM and AFE
270 * port are already opened and parameter changes
271 */
272static int msm_dai_q6_hw_params(struct snd_pcm_substream *substream,
273 struct snd_pcm_hw_params *params,
274 struct snd_soc_dai *dai)
275{
276 int rc = 0;
277
278 switch (dai->id) {
279 case PRIMARY_I2S_TX:
280 case PRIMARY_I2S_RX:
281 rc = msm_dai_q6_cdc_hw_params(params, dai, substream->stream);
282 break;
283 case HDMI_RX:
284 rc = msm_dai_q6_hdmi_hw_params(params, dai);
285 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700286 case SLIMBUS_0_RX:
287 case SLIMBUS_0_TX:
288 rc = msm_dai_q6_slim_bus_hw_params(params, dai,
289 substream->stream);
290 break;
291 case INT_BT_SCO_RX:
292 case INT_BT_SCO_TX:
293 case INT_FM_RX:
294 case INT_FM_TX:
295 rc = msm_dai_q6_bt_fm_hw_params(params, dai, substream->stream);
296 break;
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530297 case RT_PROXY_DAI_001_TX:
298 case RT_PROXY_DAI_001_RX:
299 case RT_PROXY_DAI_002_TX:
300 case RT_PROXY_DAI_002_RX:
301 rc = msm_dai_q6_afe_rtproxy_hw_params(params, dai);
302 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700303 default:
304 dev_err(dai->dev, "invalid AFE port ID\n");
305 rc = -EINVAL;
306 break;
307 }
308
309 return rc;
310}
311
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700312static void msm_dai_q6_auxpcm_shutdown(struct snd_pcm_substream *substream,
313 struct snd_soc_dai *dai)
314{
315 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
316 int rc = 0;
317
318 rc = adm_close(dai->id);
319 if (IS_ERR_VALUE(rc))
320 dev_err(dai->dev, "fail to close ADM COPP\n");
321
322 pr_debug("%s: dai->id = %d", __func__, dai->id);
323
324 if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
325 clk_disable(pcm_clk);
326 rc = afe_close(dai->id); /* can block */
327 if (IS_ERR_VALUE(rc))
328 dev_err(dai->dev, "fail to close AFE port\n");
329 pr_debug("%s: dai_data->status_mask = %ld\n", __func__,
330 *dai_data->status_mask);
331 clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
332
333 rc = afe_close(PCM_TX);
334 if (IS_ERR_VALUE(rc))
335 dev_err(dai->dev, "fail to close AUX PCM TX port\n");
336 }
337}
338
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700339static void msm_dai_q6_shutdown(struct snd_pcm_substream *substream,
340 struct snd_soc_dai *dai)
341{
342 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530343 int rc = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700344
345 rc = adm_close(dai->id);
346
347 if (IS_ERR_VALUE(rc))
348 dev_err(dai->dev, "fail to close ADM COPP\n");
349
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530350 pr_debug("%s: dai->id = %d", __func__, dai->id);
351
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700352 if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
353 rc = afe_close(dai->id); /* can block */
354 if (IS_ERR_VALUE(rc))
355 dev_err(dai->dev, "fail to close AFE port\n");
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530356 pr_debug("%s: dai_data->status_mask = %ld\n", __func__,
357 *dai_data->status_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700358 clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
359 }
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700360}
361
362static int msm_dai_q6_auxpcm_prepare(struct snd_pcm_substream *substream,
363 struct snd_soc_dai *dai)
364{
365 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
366 int rc = 0;
367
368 struct msm_dai_auxpcm_pdata *auxpcm_pdata =
369 (struct msm_dai_auxpcm_pdata *) dai->dev->platform_data;
370
371 if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
372 rc = adm_open_mixer(dai->id, 1, dai_data->rate,
373 dai_data->channels, DEFAULT_COPP_TOPOLOGY);
374
375 if (IS_ERR_VALUE(rc))
376 dev_err(dai->dev, "fail to open ADM\n");
377 else {
378 rc = afe_q6_interface_prepare();
379 if (IS_ERR_VALUE(rc))
380 dev_err(dai->dev, "fail to open AFE APR\n");
381 }
382
383 rc = adm_open_mixer(PCM_TX, 2, dai_data->rate,
384 dai_data->channels, DEFAULT_COPP_TOPOLOGY);
385
386 if (IS_ERR_VALUE(rc))
387 dev_err(dai->dev, "fail to open ADM\n");
388 else {
389 rc = afe_q6_interface_prepare();
390 if (IS_ERR_VALUE(rc))
391 dev_err(dai->dev, "fail to open AFE APR\n");
392 }
393 pr_debug("%s:dai->id:%d dai_data->status_mask = %ld\n",
394 __func__, dai->id, *dai_data->status_mask);
395
396 /*
397 * For AUX PCM Interface the below sequence of clk
398 * settings and afe_open is a strict requirement.
399 *
400 * Also using afe_open instead of afe_port_start_nowait
401 * to make sure the port is open before deasserting the
402 * clock line. This is required because pcm register is
403 * not written before clock deassert. Hence the hw does
404 * not get updated with new setting if the below clock
405 * assert/deasset and afe_open sequence is not followed.
406 */
407
408 clk_reset(pcm_clk, CLK_RESET_ASSERT);
409
410 afe_open(dai->id, &dai_data->port_config,
411 dai_data->rate);
412 set_bit(STATUS_PORT_STARTED,
413 dai_data->status_mask);
414
415 afe_open(PCM_TX, &dai_data->port_config, dai_data->rate);
416
417 rc = clk_set_rate(pcm_clk, auxpcm_pdata->pcm_clk_rate);
418 if (rc < 0) {
419 pr_err("%s: clk_set_rate failed\n", __func__);
420 return rc;
421 }
422
423 clk_enable(pcm_clk);
424 clk_reset(pcm_clk, CLK_RESET_DEASSERT);
425
426 }
427 return rc;
428}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700429
430static int msm_dai_q6_prepare(struct snd_pcm_substream *substream,
431 struct snd_soc_dai *dai)
432{
433 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
434 int rc = 0;
435
Patrick Lai831561e2011-07-26 22:51:27 -0700436 if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700437 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
438 rc = adm_open_mixer(dai->id, 1, dai_data->rate,
439 dai_data->channels, DEFAULT_COPP_TOPOLOGY);
440 else
441 rc = adm_open_mixer(dai->id, 2, dai_data->rate,
442 dai_data->channels, DEFAULT_COPP_TOPOLOGY);
443 if (IS_ERR_VALUE(rc))
444 dev_err(dai->dev, "fail to open ADM\n");
Jay Wang6a305432011-08-05 16:01:54 -0700445 else {
446 rc = afe_q6_interface_prepare();
447 if (IS_ERR_VALUE(rc))
448 dev_err(dai->dev, "fail to open AFE APR\n");
449 }
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530450 pr_debug("%s:dai->id:%d dai_data->status_mask = %ld\n",
451 __func__, dai->id, *dai_data->status_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700452 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700453 return rc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700454}
455
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700456static int msm_dai_q6_auxpcm_trigger(struct snd_pcm_substream *substream,
457 int cmd, struct snd_soc_dai *dai)
458{
459 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
460 int rc = 0;
461
462 pr_debug("%s:port:%d cmd:%d dai_data->status_mask = %ld",
463 __func__, dai->id, cmd, *dai_data->status_mask);
464
465 switch (cmd) {
466
467 case SNDRV_PCM_TRIGGER_START:
468 case SNDRV_PCM_TRIGGER_RESUME:
469 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
470 /* afe_open will be called from prepare */
471 return 0;
472
473 case SNDRV_PCM_TRIGGER_STOP:
474 case SNDRV_PCM_TRIGGER_SUSPEND:
475 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
476 if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
477
478 clk_disable(pcm_clk);
479 afe_port_stop_nowait(dai->id);
480 clear_bit(STATUS_PORT_STARTED,
481 dai_data->status_mask);
482
483 afe_port_stop_nowait(PCM_TX);
484 }
485 break;
486
487 default:
488 rc = -EINVAL;
489 }
490
491 return rc;
492
493}
494
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700495static int msm_dai_q6_trigger(struct snd_pcm_substream *substream, int cmd,
496 struct snd_soc_dai *dai)
497{
498 struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
499 int rc = 0;
500
501 /* Start/stop port without waiting for Q6 AFE response. Need to have
502 * native q6 AFE driver propagates AFE response in order to handle
503 * port start/stop command error properly if error does arise.
504 */
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530505 pr_debug("%s:port:%d cmd:%d dai_data->status_mask = %ld",
506 __func__, dai->id, cmd, *dai_data->status_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700507 switch (cmd) {
508 case SNDRV_PCM_TRIGGER_START:
509 case SNDRV_PCM_TRIGGER_RESUME:
510 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
511 if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
512 afe_port_start_nowait(dai->id, &dai_data->port_config,
513 dai_data->rate);
514 set_bit(STATUS_PORT_STARTED,
515 dai_data->status_mask);
516 }
517 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700518 case SNDRV_PCM_TRIGGER_STOP:
519 case SNDRV_PCM_TRIGGER_SUSPEND:
520 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
521 if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
522 afe_port_stop_nowait(dai->id);
523 clear_bit(STATUS_PORT_STARTED,
524 dai_data->status_mask);
525 }
526 break;
527
528 default:
529 rc = -EINVAL;
530 }
531
532 return rc;
533}
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700534static int msm_dai_q6_dai_auxpcm_probe(struct snd_soc_dai *dai)
535{
536 struct msm_dai_q6_dai_data *dai_data;
537 int rc = 0;
538
539 struct msm_dai_auxpcm_pdata *auxpcm_pdata =
540 (struct msm_dai_auxpcm_pdata *) dai->dev->platform_data;
541
542 dai_data = kzalloc(sizeof(struct msm_dai_q6_dai_data),
543 GFP_KERNEL);
544
545 if (!dai_data) {
546 dev_err(dai->dev, "DAI-%d: fail to allocate dai data\n",
547 dai->id);
548 rc = -ENOMEM;
549 } else
550 dev_set_drvdata(dai->dev, dai_data);
551
552 /*
553 * The clk name for AUX PCM operation is passed as platform
554 * data to the cpu driver, since cpu drive is unaware of any
555 * boarc specific configuration.
556 */
557 pcm_clk = clk_get(NULL, auxpcm_pdata->clk);
558 if (IS_ERR(pcm_clk)) {
559 pr_err("%s: could not get pcm_clk\n", __func__);
560 return PTR_ERR(pcm_clk);
561 kfree(dai_data);
562 }
563
564 return rc;
565}
566
567static int msm_dai_q6_dai_auxpcm_remove(struct snd_soc_dai *dai)
568{
569 struct msm_dai_q6_dai_data *dai_data;
570 int rc;
571
572 dai_data = dev_get_drvdata(dai->dev);
573
574 /* If AFE port is still up, close it */
575 if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
576 rc = afe_close(dai->id); /* can block */
577 if (IS_ERR_VALUE(rc))
578 dev_err(dai->dev, "fail to close AFE port\n");
579 clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
580
581 rc = afe_close(PCM_TX);
582 if (IS_ERR_VALUE(rc))
583 dev_err(dai->dev, "fail to close AUX PCM TX port\n");
584 }
585
586
587 kfree(dai_data);
588 snd_soc_unregister_dai(dai->dev);
589
590 return 0;
591}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700592
593static int msm_dai_q6_dai_probe(struct snd_soc_dai *dai)
594{
595 struct msm_dai_q6_dai_data *dai_data;
596 int rc = 0;
597
598 dai_data = kzalloc(sizeof(struct msm_dai_q6_dai_data),
599 GFP_KERNEL);
600
601 if (!dai_data) {
602 dev_err(dai->dev, "DAI-%d: fail to allocate dai data\n",
603 dai->id);
604 rc = -ENOMEM;
605 } else
606 dev_set_drvdata(dai->dev, dai_data);
607
608 return rc;
609}
610
611static int msm_dai_q6_dai_remove(struct snd_soc_dai *dai)
612{
613 struct msm_dai_q6_dai_data *dai_data;
614 int rc;
615
616 dai_data = dev_get_drvdata(dai->dev);
617
618 /* If AFE port is still up, close it */
619 if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
620 rc = afe_close(dai->id); /* can block */
621 if (IS_ERR_VALUE(rc))
622 dev_err(dai->dev, "fail to close AFE port\n");
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530623 clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700624 }
625 kfree(dai_data);
626 snd_soc_unregister_dai(dai->dev);
627
628 return 0;
629}
630
Lei Zhou157c1842011-08-19 13:05:04 -0400631static int msm_dai_q6_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
632{
633 int rc = 0;
634
635 dev_dbg(dai->dev, "enter %s, id = %d\n", __func__, dai->id);
636 switch (dai->id) {
637 case PRIMARY_I2S_TX:
638 case PRIMARY_I2S_RX:
639 rc = msm_dai_q6_cdc_set_fmt(dai, fmt);
640 break;
641 default:
642 dev_err(dai->dev, "invalid cpu_dai set_fmt\n");
643 rc = -EINVAL;
644 break;
645 }
646
647 return rc;
648}
649
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700650static struct snd_soc_dai_ops msm_dai_q6_ops = {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700651 .prepare = msm_dai_q6_prepare,
652 .trigger = msm_dai_q6_trigger,
653 .hw_params = msm_dai_q6_hw_params,
654 .shutdown = msm_dai_q6_shutdown,
Lei Zhou157c1842011-08-19 13:05:04 -0400655 .set_fmt = msm_dai_q6_set_fmt,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700656};
657
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700658static struct snd_soc_dai_ops msm_dai_q6_auxpcm_ops = {
659 .prepare = msm_dai_q6_auxpcm_prepare,
660 .trigger = msm_dai_q6_auxpcm_trigger,
661 .hw_params = msm_dai_q6_auxpcm_hw_params,
662 .shutdown = msm_dai_q6_auxpcm_shutdown,
663};
664
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700665static struct snd_soc_dai_driver msm_dai_q6_i2s_rx_dai = {
666 .playback = {
667 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
668 SNDRV_PCM_RATE_16000,
669 .formats = SNDRV_PCM_FMTBIT_S16_LE,
670 .channels_min = 1,
671 .channels_max = 2,
672 .rate_min = 8000,
673 .rate_max = 48000,
674 },
675 .ops = &msm_dai_q6_ops,
676 .probe = msm_dai_q6_dai_probe,
677 .remove = msm_dai_q6_dai_remove,
678};
679
680static struct snd_soc_dai_driver msm_dai_q6_i2s_tx_dai = {
681 .capture = {
682 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
683 SNDRV_PCM_RATE_16000,
684 .formats = SNDRV_PCM_FMTBIT_S16_LE,
685 .channels_min = 1,
686 .channels_max = 2,
687 .rate_min = 8000,
688 .rate_max = 48000,
689 },
690 .ops = &msm_dai_q6_ops,
691 .probe = msm_dai_q6_dai_probe,
692 .remove = msm_dai_q6_dai_remove,
693};
694
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530695static struct snd_soc_dai_driver msm_dai_q6_afe_rx_dai = {
696 .playback = {
697 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
698 SNDRV_PCM_RATE_16000,
699 .formats = SNDRV_PCM_FMTBIT_S16_LE,
700 .channels_min = 1,
701 .channels_max = 2,
702 .rate_min = 8000,
703 .rate_max = 48000,
704 },
705 .ops = &msm_dai_q6_ops,
706 .probe = msm_dai_q6_dai_probe,
707 .remove = msm_dai_q6_dai_remove,
708};
709
710static struct snd_soc_dai_driver msm_dai_q6_afe_tx_dai = {
711 .capture = {
712 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
713 SNDRV_PCM_RATE_16000,
714 .formats = SNDRV_PCM_FMTBIT_S16_LE,
715 .channels_min = 1,
716 .channels_max = 2,
717 .rate_min = 8000,
718 .rate_max = 48000,
719 },
720 .ops = &msm_dai_q6_ops,
721 .probe = msm_dai_q6_dai_probe,
722 .remove = msm_dai_q6_dai_remove,
723};
724
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700725static struct snd_soc_dai_driver msm_dai_q6_hdmi_rx_dai = {
726 .playback = {
727 .rates = SNDRV_PCM_RATE_48000,
728 .formats = SNDRV_PCM_FMTBIT_S16_LE,
729 .channels_min = 2,
730 .channels_max = 2,
731 .rate_max = 48000,
732 .rate_min = 48000,
733 },
734 .ops = &msm_dai_q6_ops,
735 .probe = msm_dai_q6_dai_probe,
736 .remove = msm_dai_q6_dai_remove,
737};
738
739static struct snd_soc_dai_driver msm_dai_q6_slimbus_rx_dai = {
740 .playback = {
741 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
742 SNDRV_PCM_RATE_16000,
743 .formats = SNDRV_PCM_FMTBIT_S16_LE,
744 .channels_min = 1,
745 .channels_max = 2,
746 .rate_min = 8000,
747 .rate_max = 48000,
748 },
749 .ops = &msm_dai_q6_ops,
750 .probe = msm_dai_q6_dai_probe,
751 .remove = msm_dai_q6_dai_remove,
752};
753
754static struct snd_soc_dai_driver msm_dai_q6_slimbus_tx_dai = {
755 .capture = {
756 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
757 SNDRV_PCM_RATE_16000,
758 .formats = SNDRV_PCM_FMTBIT_S16_LE,
759 .channels_min = 1,
760 .channels_max = 2,
761 .rate_min = 8000,
762 .rate_max = 48000,
763 },
764 .ops = &msm_dai_q6_ops,
765 .probe = msm_dai_q6_dai_probe,
766 .remove = msm_dai_q6_dai_remove,
767};
768
769static struct snd_soc_dai_driver msm_dai_q6_bt_sco_rx_dai = {
770 .playback = {
771 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
772 .formats = SNDRV_PCM_FMTBIT_S16_LE,
773 .channels_min = 1,
774 .channels_max = 1,
775 .rate_max = 16000,
776 .rate_min = 8000,
777 },
778 .ops = &msm_dai_q6_ops,
779 .probe = msm_dai_q6_dai_probe,
780 .remove = msm_dai_q6_dai_remove,
781};
782
783static struct snd_soc_dai_driver msm_dai_q6_bt_sco_tx_dai = {
784 .playback = {
785 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
786 .formats = SNDRV_PCM_FMTBIT_S16_LE,
787 .channels_min = 1,
788 .channels_max = 1,
789 .rate_max = 16000,
790 .rate_min = 8000,
791 },
792 .ops = &msm_dai_q6_ops,
793 .probe = msm_dai_q6_dai_probe,
794 .remove = msm_dai_q6_dai_remove,
795};
796
797static struct snd_soc_dai_driver msm_dai_q6_fm_rx_dai = {
798 .playback = {
799 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
800 SNDRV_PCM_RATE_16000,
801 .formats = SNDRV_PCM_FMTBIT_S16_LE,
802 .channels_min = 2,
803 .channels_max = 2,
804 .rate_max = 48000,
805 .rate_min = 8000,
806 },
807 .ops = &msm_dai_q6_ops,
808 .probe = msm_dai_q6_dai_probe,
809 .remove = msm_dai_q6_dai_remove,
810};
811
812static struct snd_soc_dai_driver msm_dai_q6_fm_tx_dai = {
813 .playback = {
814 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
815 SNDRV_PCM_RATE_16000,
816 .formats = SNDRV_PCM_FMTBIT_S16_LE,
817 .channels_min = 2,
818 .channels_max = 2,
819 .rate_max = 48000,
820 .rate_min = 8000,
821 },
822 .ops = &msm_dai_q6_ops,
823 .probe = msm_dai_q6_dai_probe,
824 .remove = msm_dai_q6_dai_remove,
825};
826
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700827static struct snd_soc_dai_driver msm_dai_q6_aux_pcm_rx_dai = {
828 .playback = {
829 .rates = SNDRV_PCM_RATE_8000,
830 .formats = SNDRV_PCM_FMTBIT_S16_LE,
831 .channels_min = 1,
832 .channels_max = 1,
833 .rate_max = 8000,
834 .rate_min = 8000,
835 },
836 .ops = &msm_dai_q6_auxpcm_ops,
837 .probe = msm_dai_q6_dai_auxpcm_probe,
838 .remove = msm_dai_q6_dai_auxpcm_remove,
839};
840
841static struct snd_soc_dai_driver msm_dai_q6_aux_pcm_tx_dai = {
842 .capture = {
843 .rates = SNDRV_PCM_RATE_8000,
844 .formats = SNDRV_PCM_FMTBIT_S16_LE,
845 .channels_min = 1,
846 .channels_max = 1,
847 .rate_max = 8000,
848 .rate_min = 8000,
849 },
850};
851
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700852/* To do: change to register DAIs as batch */
853static __devinit int msm_dai_q6_dev_probe(struct platform_device *pdev)
854{
855 int rc = 0;
856
857 dev_dbg(&pdev->dev, "dev name %s\n", dev_name(&pdev->dev));
858
859 switch (pdev->id) {
860 case PRIMARY_I2S_RX:
861 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_i2s_rx_dai);
862 break;
863 case PRIMARY_I2S_TX:
864 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_i2s_tx_dai);
865 break;
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700866 case PCM_RX:
867 rc = snd_soc_register_dai(&pdev->dev,
868 &msm_dai_q6_aux_pcm_rx_dai);
869 break;
870 case PCM_TX:
871 rc = snd_soc_register_dai(&pdev->dev,
872 &msm_dai_q6_aux_pcm_tx_dai);
873 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700874 case HDMI_RX:
875 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_hdmi_rx_dai);
876 break;
877 case SLIMBUS_0_RX:
878 rc = snd_soc_register_dai(&pdev->dev,
879 &msm_dai_q6_slimbus_rx_dai);
880 break;
881 case SLIMBUS_0_TX:
882 rc = snd_soc_register_dai(&pdev->dev,
883 &msm_dai_q6_slimbus_tx_dai);
884 case INT_BT_SCO_RX:
885 rc = snd_soc_register_dai(&pdev->dev,
886 &msm_dai_q6_bt_sco_rx_dai);
887 break;
888 case INT_BT_SCO_TX:
889 rc = snd_soc_register_dai(&pdev->dev,
890 &msm_dai_q6_bt_sco_tx_dai);
891 break;
892 case INT_FM_RX:
893 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_fm_rx_dai);
894 break;
895 case INT_FM_TX:
896 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_fm_tx_dai);
897 break;
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530898 case RT_PROXY_DAI_001_RX:
899 case RT_PROXY_DAI_002_RX:
900 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_afe_rx_dai);
901 break;
902 case RT_PROXY_DAI_001_TX:
903 case RT_PROXY_DAI_002_TX:
904 rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_afe_tx_dai);
905 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700906 default:
907 rc = -ENODEV;
908 break;
909 }
910 return rc;
911}
912
913static __devexit int msm_dai_q6_dev_remove(struct platform_device *pdev)
914{
915 snd_soc_unregister_dai(&pdev->dev);
916 return 0;
917}
918
919static struct platform_driver msm_dai_q6_driver = {
920 .probe = msm_dai_q6_dev_probe,
921 .remove = msm_dai_q6_dev_remove,
922 .driver = {
923 .name = "msm-dai-q6",
924 .owner = THIS_MODULE,
925 },
926};
927
928static int __init msm_dai_q6_init(void)
929{
930 return platform_driver_register(&msm_dai_q6_driver);
931}
932module_init(msm_dai_q6_init);
933
934static void __exit msm_dai_q6_exit(void)
935{
936 platform_driver_unregister(&msm_dai_q6_driver);
937}
938module_exit(msm_dai_q6_exit);
939
940/* Module information */
941MODULE_DESCRIPTION("MSM DSP DAI driver");
942MODULE_LICENSE("GPL v2");