blob: 1f36e3b19c0f23aee0ccbc5ab8336aac5f8f4439 [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* linux/sound/soc/msm/msm7k-pcm.c
2 *
3 * Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
4 *
5 * All source code in this file is licensed under the following license except
6 * where indicated.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License version 2 as published
10 * by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 *
16 * See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you can find it at http://www.fsf.org.
19 */
20
21
22
23#include <linux/init.h>
24#include <linux/err.h>
25#include <linux/module.h>
26#include <linux/moduleparam.h>
27#include <linux/time.h>
28#include <linux/wait.h>
29#include <linux/platform_device.h>
30#include <linux/slab.h>
31#include <sound/core.h>
32#include <sound/soc.h>
33#include <sound/soc-dapm.h>
34#include <sound/pcm.h>
35#include <sound/initval.h>
36#include <sound/control.h>
37#include <asm/dma.h>
38#include <linux/dma-mapping.h>
39
40#include "msm-pcm.h"
41
42#define SND_DRIVER "snd_msm"
43#define MAX_PCM_DEVICES SNDRV_CARDS
44#define MAX_PCM_SUBSTREAMS 1
45
46struct snd_msm {
47 struct snd_card *card;
48 struct snd_pcm *pcm;
49};
50
51int copy_count;
52
53struct audio_locks the_locks;
54EXPORT_SYMBOL(the_locks);
55struct msm_volume msm_vol_ctl;
56EXPORT_SYMBOL(msm_vol_ctl);
57
58
59static unsigned convert_dsp_samp_index(unsigned index)
60{
61 switch (index) {
62 case 48000:
63 return AUDREC_CMD_SAMP_RATE_INDX_48000;
64 case 44100:
65 return AUDREC_CMD_SAMP_RATE_INDX_44100;
66 case 32000:
67 return AUDREC_CMD_SAMP_RATE_INDX_32000;
68 case 24000:
69 return AUDREC_CMD_SAMP_RATE_INDX_24000;
70 case 22050:
71 return AUDREC_CMD_SAMP_RATE_INDX_22050;
72 case 16000:
73 return AUDREC_CMD_SAMP_RATE_INDX_16000;
74 case 12000:
75 return AUDREC_CMD_SAMP_RATE_INDX_12000;
76 case 11025:
77 return AUDREC_CMD_SAMP_RATE_INDX_11025;
78 case 8000:
79 return AUDREC_CMD_SAMP_RATE_INDX_8000;
80 default:
81 return AUDREC_CMD_SAMP_RATE_INDX_44100;
82 }
83}
84
85static unsigned convert_samp_rate(unsigned hz)
86{
87 switch (hz) {
88 case 48000:
89 return RPC_AUD_DEF_SAMPLE_RATE_48000;
90 case 44100:
91 return RPC_AUD_DEF_SAMPLE_RATE_44100;
92 case 32000:
93 return RPC_AUD_DEF_SAMPLE_RATE_32000;
94 case 24000:
95 return RPC_AUD_DEF_SAMPLE_RATE_24000;
96 case 22050:
97 return RPC_AUD_DEF_SAMPLE_RATE_22050;
98 case 16000:
99 return RPC_AUD_DEF_SAMPLE_RATE_16000;
100 case 12000:
101 return RPC_AUD_DEF_SAMPLE_RATE_12000;
102 case 11025:
103 return RPC_AUD_DEF_SAMPLE_RATE_11025;
104 case 8000:
105 return RPC_AUD_DEF_SAMPLE_RATE_8000;
106 default:
107 return RPC_AUD_DEF_SAMPLE_RATE_44100;
108 }
109}
110
111static struct snd_pcm_hardware msm_pcm_playback_hardware = {
112 .info = SNDRV_PCM_INFO_INTERLEAVED,
113 .formats = USE_FORMATS,
114 .rates = USE_RATE,
115 .rate_min = USE_RATE_MIN,
116 .rate_max = USE_RATE_MAX,
117 .channels_min = USE_CHANNELS_MIN,
118 .channels_max = USE_CHANNELS_MAX,
119 .buffer_bytes_max = MAX_BUFFER_PLAYBACK_SIZE,
120 .period_bytes_min = 64,
121 .period_bytes_max = MAX_PERIOD_SIZE,
122 .periods_min = USE_PERIODS_MIN,
123 .periods_max = USE_PERIODS_MAX,
124 .fifo_size = 0,
125};
126
127static struct snd_pcm_hardware msm_pcm_capture_hardware = {
128 .info = SNDRV_PCM_INFO_INTERLEAVED,
129 .formats = USE_FORMATS,
130 .rates = USE_RATE,
131 .rate_min = USE_RATE_MIN,
132 .rate_max = USE_RATE_MAX,
133 .channels_min = USE_CHANNELS_MIN,
134 .channels_max = USE_CHANNELS_MAX,
135 .buffer_bytes_max = MAX_BUFFER_CAPTURE_SIZE,
136 .period_bytes_min = CAPTURE_SIZE,
137 .period_bytes_max = CAPTURE_SIZE,
138 .periods_min = USE_PERIODS_MIN,
139 .periods_max = USE_PERIODS_MAX,
140 .fifo_size = 0,
141};
142
143/* Conventional and unconventional sample rate supported */
144static unsigned int supported_sample_rates[] = {
145 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
146};
147
148static struct snd_pcm_hw_constraint_list constraints_sample_rates = {
149 .count = ARRAY_SIZE(supported_sample_rates),
150 .list = supported_sample_rates,
151 .mask = 0,
152};
153
154static void playback_event_handler(void *data)
155{
156 struct msm_audio *prtd = data;
157 snd_pcm_period_elapsed(prtd->playback_substream);
158}
159
160static void capture_event_handler(void *data)
161{
162 struct msm_audio *prtd = data;
163 snd_pcm_period_elapsed(prtd->capture_substream);
164}
165
166static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream)
167{
168 struct snd_pcm_runtime *runtime = substream->runtime;
169 struct msm_audio *prtd = runtime->private_data;
170
171 prtd->pcm_size = snd_pcm_lib_buffer_bytes(substream);
172 prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
173 prtd->pcm_irq_pos = 0;
174 prtd->pcm_buf_pos = 0;
175
176 /* rate and channels are sent to audio driver */
177 prtd->out_sample_rate = runtime->rate;
178 prtd->out_channel_mode = runtime->channels;
179
180 return 0;
181}
182
183static int msm_pcm_capture_prepare(struct snd_pcm_substream *substream)
184{
185 struct snd_pcm_runtime *runtime = substream->runtime;
186 struct msm_audio *prtd = runtime->private_data;
187 struct audmgr_config cfg;
188 int rc;
189
190 prtd->pcm_size = snd_pcm_lib_buffer_bytes(substream);
191 prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
192 prtd->pcm_irq_pos = 0;
193 prtd->pcm_buf_pos = 0;
194
195 /* rate and channels are sent to audio driver */
196 prtd->samp_rate = convert_samp_rate(runtime->rate);
197 prtd->samp_rate_index = convert_dsp_samp_index(runtime->rate);
198 prtd->channel_mode = (runtime->channels - 1);
199 prtd->buffer_size = prtd->channel_mode ? STEREO_DATA_SIZE : \
200 MONO_DATA_SIZE;
201
202 if (prtd->enabled == 1)
203 return 0;
204
205 prtd->type = AUDREC_CMD_TYPE_0_INDEX_WAV;
206
207 cfg.tx_rate = convert_samp_rate(runtime->rate);
208 cfg.rx_rate = RPC_AUD_DEF_SAMPLE_RATE_NONE;
209 cfg.def_method = RPC_AUD_DEF_METHOD_RECORD;
210 cfg.codec = RPC_AUD_DEF_CODEC_PCM;
211 cfg.snd_method = RPC_SND_METHOD_MIDI;
212
213 rc = audmgr_enable(&prtd->audmgr, &cfg);
214 if (rc < 0)
215 return rc;
216
217 if (msm_adsp_enable(prtd->audpre)) {
218 audmgr_disable(&prtd->audmgr);
219 return -ENODEV;
220 }
221 if (msm_adsp_enable(prtd->audrec)) {
222 msm_adsp_disable(prtd->audpre);
223 audmgr_disable(&prtd->audmgr);
224 return -ENODEV;
225 }
226 prtd->enabled = 1;
227 alsa_rec_dsp_enable(prtd, 1);
228
229 return 0;
230}
231
232static int msm_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
233{
234 int ret = 0;
235
236 switch (cmd) {
237 case SNDRV_PCM_TRIGGER_START:
238 case SNDRV_PCM_TRIGGER_RESUME:
239 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
240 break;
241 case SNDRV_PCM_TRIGGER_STOP:
242 case SNDRV_PCM_TRIGGER_SUSPEND:
243 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
244 break;
245 default:
246 ret = -EINVAL;
247 }
248
249 return ret;
250}
251
252static snd_pcm_uframes_t
253msm_pcm_playback_pointer(struct snd_pcm_substream *substream)
254{
255 struct snd_pcm_runtime *runtime = substream->runtime;
256 struct msm_audio *prtd = runtime->private_data;
257
258 if (prtd->pcm_irq_pos == prtd->pcm_size)
259 prtd->pcm_irq_pos = 0;
260 return bytes_to_frames(runtime, (prtd->pcm_irq_pos));
261}
262
263static int msm_pcm_capture_copy(struct snd_pcm_substream *substream,
264 int channel, snd_pcm_uframes_t hwoff, void __user *buf,
265 snd_pcm_uframes_t frames)
266{
267 int rc = 0, rc1 = 0, rc2 = 0;
268 int fbytes = 0;
269 struct snd_pcm_runtime *runtime = substream->runtime;
270 struct msm_audio *prtd = substream->runtime->private_data;
271
272 int monofbytes = 0;
273 char *bufferp = NULL;
274
275 fbytes = frames_to_bytes(runtime, frames);
276 monofbytes = fbytes / 2;
277 if (runtime->channels == 2) {
278 rc = alsa_buffer_read(prtd, buf, fbytes, NULL);
279 } else {
280 bufferp = buf;
281 rc1 = alsa_buffer_read(prtd, bufferp, monofbytes, NULL);
282 bufferp = buf + monofbytes ;
283 rc2 = alsa_buffer_read(prtd, bufferp, monofbytes, NULL);
284 rc = rc1 + rc2;
285 }
286 prtd->pcm_buf_pos += fbytes;
287 return rc;
288}
289
290static snd_pcm_uframes_t
291msm_pcm_capture_pointer(struct snd_pcm_substream *substream)
292{
293 struct snd_pcm_runtime *runtime = substream->runtime;
294 struct msm_audio *prtd = runtime->private_data;
295
296 return bytes_to_frames(runtime, (prtd->pcm_irq_pos));
297}
298
299static int msm_pcm_capture_close(struct snd_pcm_substream *substream)
300{
301 struct snd_pcm_runtime *runtime = substream->runtime;
302 struct msm_audio *prtd = runtime->private_data;
303
304 alsa_audrec_disable(prtd);
305 audmgr_close(&prtd->audmgr);
306 msm_adsp_put(prtd->audrec);
307 msm_adsp_put(prtd->audpre);
308 kfree(prtd);
309
310 return 0;
311}
312
313struct msm_audio_event_callbacks snd_msm_audio_ops = {
314 .playback = playback_event_handler,
315 .capture = capture_event_handler,
316};
317
318static int msm_pcm_open(struct snd_pcm_substream *substream)
319{
320 struct snd_pcm_runtime *runtime = substream->runtime;
321 struct msm_audio *prtd;
322 int ret = 0;
323
324 prtd = kzalloc(sizeof(struct msm_audio), GFP_KERNEL);
325 if (prtd == NULL) {
326 ret = -ENOMEM;
327 return ret;
328 }
329 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
330 msm_vol_ctl.update = 1; /* Update Volume, with Cached value */
331 runtime->hw = msm_pcm_playback_hardware;
332 prtd->dir = SNDRV_PCM_STREAM_PLAYBACK;
333 prtd->playback_substream = substream;
334 prtd->eos_ack = 0;
335 } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
336 runtime->hw = msm_pcm_capture_hardware;
337 prtd->dir = SNDRV_PCM_STREAM_CAPTURE;
338 prtd->capture_substream = substream;
339 }
340 ret = snd_pcm_hw_constraint_list(runtime, 0,
341 SNDRV_PCM_HW_PARAM_RATE,
342 &constraints_sample_rates);
343 if (ret < 0)
344 goto out;
345 /* Ensure that buffer size is a multiple of period size */
346 ret = snd_pcm_hw_constraint_integer(runtime,
347 SNDRV_PCM_HW_PARAM_PERIODS);
348 if (ret < 0)
349 goto out;
350
351 prtd->ops = &snd_msm_audio_ops;
352 prtd->out[0].used = BUF_INVALID_LEN;
353 prtd->out_head = 1; /* point to second buffer on startup */
354 runtime->private_data = prtd;
355
356 ret = alsa_adsp_configure(prtd);
357 if (ret)
358 goto out;
359 copy_count = 0;
360 return 0;
361
362 out:
363 kfree(prtd);
364 return ret;
365}
366
367static int msm_pcm_playback_copy(struct snd_pcm_substream *substream, int a,
368 snd_pcm_uframes_t hwoff, void __user *buf, snd_pcm_uframes_t frames)
369{
370 int rc = 1;
371 int fbytes = 0;
372
373 struct snd_pcm_runtime *runtime = substream->runtime;
374 struct msm_audio *prtd = runtime->private_data;
375
376 fbytes = frames_to_bytes(runtime, frames);
377 rc = alsa_send_buffer(prtd, buf, fbytes, NULL);
378 ++copy_count;
379 prtd->pcm_buf_pos += fbytes;
380 if (copy_count == 1) {
381 mutex_lock(&the_locks.lock);
382 alsa_audio_configure(prtd);
383 mutex_unlock(&the_locks.lock);
384 }
385 if ((prtd->running) && (msm_vol_ctl.update)) {
386 rc = msm_audio_volume_update(PCMPLAYBACK_DECODERID,
387 msm_vol_ctl.volume, msm_vol_ctl.pan);
388 msm_vol_ctl.update = 0;
389 }
390
391 return rc;
392}
393
394static int msm_pcm_playback_close(struct snd_pcm_substream *substream)
395{
396 struct snd_pcm_runtime *runtime = substream->runtime;
397 struct msm_audio *prtd = runtime->private_data;
398
399 int rc = 0;
400
401 pr_debug("%s()\n", __func__);
402
403 /* pcm dmamiss message is sent continously
404 * when decoder is starved so no race
405 * condition concern
406 */
407 if (prtd->enabled)
408 rc = wait_event_interruptible(the_locks.eos_wait,
409 prtd->eos_ack);
410
411 alsa_audio_disable(prtd);
412 audmgr_close(&prtd->audmgr);
413 kfree(prtd);
414
415 return 0;
416}
417
418
419static int msm_pcm_copy(struct snd_pcm_substream *substream, int a,
420 snd_pcm_uframes_t hwoff, void __user *buf, snd_pcm_uframes_t frames)
421{
422 int ret = 0;
423
424 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
425 ret = msm_pcm_playback_copy(substream, a, hwoff, buf, frames);
426 else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
427 ret = msm_pcm_capture_copy(substream, a, hwoff, buf, frames);
428 return ret;
429}
430
431static int msm_pcm_close(struct snd_pcm_substream *substream)
432{
433 int ret = 0;
434
435 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
436 ret = msm_pcm_playback_close(substream);
437 else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
438 ret = msm_pcm_capture_close(substream);
439 return ret;
440}
441static int msm_pcm_prepare(struct snd_pcm_substream *substream)
442{
443 int ret = 0;
444
445 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
446 ret = msm_pcm_playback_prepare(substream);
447 else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
448 ret = msm_pcm_capture_prepare(substream);
449 return ret;
450}
451
452static snd_pcm_uframes_t msm_pcm_pointer(struct snd_pcm_substream *substream)
453{
454 snd_pcm_uframes_t ret = 0;
455
456 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
457 ret = msm_pcm_playback_pointer(substream);
458 else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
459 ret = msm_pcm_capture_pointer(substream);
460 return ret;
461}
462
463int msm_pcm_hw_params(struct snd_pcm_substream *substream,
464 struct snd_pcm_hw_params *params)
465{
466 struct snd_pcm_runtime *runtime = substream->runtime;
467
468 if (substream->pcm->device & 1) {
469 runtime->hw.info &= ~SNDRV_PCM_INFO_INTERLEAVED;
470 runtime->hw.info |= SNDRV_PCM_INFO_NONINTERLEAVED;
471 }
472 return 0;
473
474}
475
476static struct snd_pcm_ops msm_pcm_ops = {
477 .open = msm_pcm_open,
478 .copy = msm_pcm_copy,
479 .hw_params = msm_pcm_hw_params,
480 .close = msm_pcm_close,
481 .ioctl = snd_pcm_lib_ioctl,
482 .prepare = msm_pcm_prepare,
483 .trigger = msm_pcm_trigger,
484 .pointer = msm_pcm_pointer,
485};
486
487static int pcm_preallocate_dma_buffer(struct snd_pcm *pcm,
488 int stream)
489{
490 struct snd_pcm_substream *substream = pcm->streams[stream].substream;
491 struct snd_dma_buffer *buf = &substream->dma_buffer;
492 size_t size;
493 if (!stream)
494 size = PLAYBACK_DMASZ;
495 else
496 size = CAPTURE_DMASZ;
497
498 buf->dev.type = SNDRV_DMA_TYPE_DEV;
499 buf->dev.dev = pcm->card->dev;
500 buf->private_data = NULL;
501 buf->area = dma_alloc_coherent(pcm->card->dev, size,
502 &buf->addr, GFP_KERNEL);
503 if (!buf->area)
504 return -ENOMEM;
505
506 buf->bytes = size;
507 return 0;
508}
509
510static void msm_pcm_free_dma_buffers(struct snd_pcm *pcm)
511{
512 struct snd_pcm_substream *substream;
513 struct snd_dma_buffer *buf;
514 int stream;
515
516 for (stream = 0; stream < 2; stream++) {
517 substream = pcm->streams[stream].substream;
518 if (!substream)
519 continue;
520
521 buf = &substream->dma_buffer;
522 if (!buf->area)
523 continue;
524
525 dma_free_coherent(pcm->card->dev, buf->bytes,
526 buf->area, buf->addr);
527 buf->area = NULL;
528 }
529}
530
531static int msm_pcm_new(struct snd_soc_pcm_runtime *rtd)
532{
533 int ret;
534 struct snd_card *card = rtd->card->snd_card;
535 struct snd_pcm *pcm = rtd->pcm;
536
537 if (!card->dev->coherent_dma_mask)
538 card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
539
540 ret = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_PLAYBACK, 1);
541 if (ret)
542 return ret;
543 ret = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_CAPTURE, 1);
544 if (ret)
545 return ret;
546 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &msm_pcm_ops);
547 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &msm_pcm_ops);
548
549 ret = pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK);
550 if (ret)
551 return ret;
552
553 ret = pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_CAPTURE);
554 if (ret)
555 msm_pcm_free_dma_buffers(pcm);
556 return ret;
557}
558
559struct snd_soc_platform_driver msm_soc_platform = {
560 .ops = &msm_pcm_ops,
561 .pcm_new = msm_pcm_new,
562 .pcm_free = msm_pcm_free_dma_buffers,
563};
564EXPORT_SYMBOL(msm_soc_platform);
565
566static __devinit int msm_pcm_probe(struct platform_device *pdev)
567{
568 return snd_soc_register_platform(&pdev->dev,
569 &msm_soc_platform);
570}
571
572static int msm_pcm_remove(struct platform_device *pdev)
573{
574 snd_soc_unregister_platform(&pdev->dev);
575 return 0;
576}
577
578static struct platform_driver msm_pcm_driver = {
579 .driver = {
580 .name = "msm-dsp-audio",
581 .owner = THIS_MODULE,
582 },
583 .probe = msm_pcm_probe,
584 .remove = __devexit_p(msm_pcm_remove),
585};
586
587static int __init msm_soc_platform_init(void)
588{
589 return platform_driver_register(&msm_pcm_driver);
590}
591module_init(msm_soc_platform_init);
592
593static void __exit msm_soc_platform_exit(void)
594{
595 platform_driver_unregister(&msm_pcm_driver);
596}
597module_exit(msm_soc_platform_exit);
598
599MODULE_DESCRIPTION("PCM module platform driver");
600MODULE_LICENSE("GPL v2");