2 * rk29_pcm.c -- ALSA SoC ROCKCHIP PCM Audio Layer Platform driver
4 * Driver for rockchip pcm audio
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
13 #include <linux/module.h>
14 #include <linux/init.h>
16 #include <linux/platform_device.h>
17 #include <linux/slab.h>
18 #include <linux/dma-mapping.h>
20 #include <sound/core.h>
21 #include <sound/pcm.h>
22 #include <sound/pcm_params.h>
23 #include <sound/soc.h>
26 #include <mach/hardware.h>
31 #ifdef CONFIG_ANDROID_POWER
32 #include <linux/android_power.h>
33 static android_suspend_lock_t audio_lock;
37 #define DBG(x...) printk(KERN_INFO x)
39 #define DBG(x...) do { } while (0)
43 static const struct snd_pcm_hardware rockchip_pcm_hardware = {
44 .info = SNDRV_PCM_INFO_INTERLEAVED |
45 SNDRV_PCM_INFO_BLOCK_TRANSFER |
47 SNDRV_PCM_INFO_MMAP_VALID |
48 SNDRV_PCM_INFO_PAUSE |
49 SNDRV_PCM_INFO_RESUME,
50 .formats = SNDRV_PCM_FMTBIT_S24_LE |
51 SNDRV_PCM_FMTBIT_S20_3LE |
52 SNDRV_PCM_FMTBIT_S16_LE,
55 .buffer_bytes_max = 128*1024,
56 .period_bytes_min = 64, ///PAGE_SIZE,
57 .period_bytes_max = 2048*4,///PAGE_SIZE*2,
58 .periods_min = 3,///2,
64 struct rockchip_dma_buf_set {
65 struct rockchip_dma_buf_set *next;
66 struct scatterlist sg;
69 struct rockchip_runtime_data {
73 unsigned int dma_loaded;
74 unsigned int dma_limit;
75 unsigned int dma_period;
79 struct rockchip_pcm_dma_params *params;
80 struct rockchip_dma_buf_set *curr; /* current dma buffer set */
81 struct rockchip_dma_buf_set *next; /* next buffer set to load */
82 struct rockchip_dma_buf_set *end; /* end of queue set*/
86 /* rockchip__dma_buf_enqueue
88 *queue an given buffer for dma transfer set.
89 *data the physical address of the buffer data
90 *size the size of the buffer in bytes
92 static int rockchip_dma_buffer_set_enqueue(struct rockchip_runtime_data *prtd, dma_addr_t data, int size)
94 struct rockchip_dma_buf_set *sg_buf;
96 DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
97 sg_buf = kzalloc(sizeof(struct rockchip_dma_buf_set), GFP_ATOMIC);/* ddl@rock-chips.com:GFP_KERNEL->GFP_ATOMIC */
100 DBG("scatter sg buffer allocate failed,no memory!\n");
104 sg_buf->sg.dma_address = data;
105 sg_buf->sg.length = size/4; ////4;
106 if( prtd->curr == NULL) {
111 if (prtd->end == NULL)
112 DBG("prtd->end is NULL\n");
113 prtd->end->next = sg_buf;
116 /* if necessary, update the next buffer field */
117 if (prtd->next == NULL)
122 void rockchip_pcm_dma_irq(s32 ch, void *data);
124 void audio_start_dma(struct snd_pcm_substream *substream, int mode)
126 struct rockchip_runtime_data *prtd;
128 struct rockchip_dma_buf_set *sg_buf;
130 DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
132 prtd = substream->runtime->private_data;
136 if (prtd->transfer_first == 1) {
137 prtd->transfer_first = 0;
140 if (sg_buf != NULL) {
141 prtd->curr = sg_buf->next;
142 prtd->next = sg_buf->next;
150 DBG("Enter::%s----%d---length=%x---dma_address=%x\n",__FUNCTION__,__LINE__,sg_buf->sg.length,sg_buf->sg.dma_address);
152 spin_lock_irqsave(&prtd->lock, flags);
153 disable_dma(prtd->params->channel);
154 //set_dma_sg(prtd->params->channel, &(sg_buf->sg), 1);
155 set_dma_mode(prtd->params->channel, DMA_MODE_WRITE);
156 set_dma_handler(prtd->params->channel, rockchip_pcm_dma_irq, substream, DMA_IRQ_RIGHTNOW_MODE);
157 __set_dma_addr(prtd->params->channel, (void *)(sg_buf->sg.dma_address));
158 set_dma_count(prtd->params->channel, sg_buf->sg.length);
159 enable_dma(prtd->params->channel);
160 spin_unlock_irqrestore(&prtd->lock, flags);
162 DBG("next buffer is NULL for playback\n");
167 if (prtd->transfer_first == 1) {
168 prtd->transfer_first = 0;
171 if (sg_buf != NULL) {
172 prtd->curr = sg_buf->next;
173 prtd->next = sg_buf->next;
182 spin_lock_irqsave(&prtd->lock, flags);
183 disable_dma(prtd->params->channel);
184 //set_dma_sg(prtd->params->channel, &(sg_buf->sg), 1);
185 set_dma_mode(prtd->params->channel, DMA_MODE_READ);
186 set_dma_handler(prtd->params->channel, rockchip_pcm_dma_irq, substream, DMA_IRQ_RIGHTNOW_MODE);
187 __set_dma_addr(prtd->params->channel, (void *)(sg_buf->sg.dma_address));
188 set_dma_count(prtd->params->channel, sg_buf->sg.length);
189 enable_dma(prtd->params->channel);
190 spin_unlock_irqrestore(&prtd->lock, flags);
192 DBG("next buffer is NULL for capture\n");
199 /* rockchip_pcm_enqueue
201 * place a dma buffer onto the queue for the dma system
204 static void rockchip_pcm_enqueue(struct snd_pcm_substream *substream)
206 struct rockchip_runtime_data *prtd = substream->runtime->private_data;
207 dma_addr_t pos = prtd->dma_pos;
213 DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
215 while (prtd->dma_loaded < prtd->dma_limit) {
216 unsigned long len = prtd->dma_period;
218 DBG("dma_loaded: %d\n", prtd->dma_loaded);
219 if ((pos + len) > prtd->dma_end) {
220 len = prtd->dma_end - pos;
223 if((len%(prtd->params->dma_size*16) == 0) && (prtd->params->flag == 1))
225 ret = rk29_dma_config(prtd->params->channel,
226 prtd->params->dma_size, 16);
227 prtd->params->flag = 0;
228 DBG("size = 16, channel = %d, flag = %d\n",prtd->params->channel,prtd->params->flag);
230 else if((len%(prtd->params->dma_size*16) != 0) && (prtd->params->flag == 0))
232 ret = rk29_dma_config(prtd->params->channel,
233 prtd->params->dma_size, 1);
234 prtd->params->flag = 1;
235 DBG("size = 1, channel = %d, flag = %d\n",prtd->params->channel,prtd->params->flag);
239 //ret = rockchip_dma_buffer_set_enqueue(prtd, pos, len);
240 ret = rk29_dma_enqueue(prtd->params->channel,
241 substream, pos, len);
243 DBG("Enter::%s, %d, ret=%d, Channel=%d, Addr=0x%X, Len=%d\n",
244 __FUNCTION__,__LINE__, ret, prtd->params->channel, pos, len);
247 pos += prtd->dma_period;
248 if (pos >= prtd->dma_end)
249 pos = prtd->dma_start;
257 void rockchip_pcm_dma_irq(s32 ch, void *data)
259 struct snd_pcm_substream *substream = data;
260 struct rockchip_runtime_data *prtd;
263 DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
265 prtd = substream->runtime->private_data;
267 snd_pcm_period_elapsed(substream);
268 spin_lock(&prtd->lock);
270 if (prtd->state & ST_RUNNING) {
271 rockchip_pcm_enqueue(substream);
273 spin_unlock(&prtd->lock);
274 local_irq_save(flags);
275 if (prtd->state & ST_RUNNING) {
276 if (prtd->dma_loaded) {
277 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
278 audio_start_dma(substream, DMA_MODE_WRITE);
280 audio_start_dma(substream, DMA_MODE_READ);
283 local_irq_restore(flags);
287 void rk29_audio_buffdone(void *dev_id, int size,
288 enum rk29_dma_buffresult result)
290 struct snd_pcm_substream *substream = dev_id;
291 struct rockchip_runtime_data *prtd;
294 DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
298 if (!substream->runtime)
301 prtd = substream->runtime->private_data;
302 DBG("Enter::%s----%d, substream=0x%08X, prtd=0x%08X\n",__FUNCTION__,__LINE__, substream, prtd);
304 snd_pcm_period_elapsed(substream);
306 spin_lock(&prtd->lock);
308 if (prtd->state & ST_RUNNING) {
309 rockchip_pcm_enqueue(substream);
311 spin_unlock(&prtd->lock);
315 static int rockchip_pcm_hw_params(struct snd_pcm_substream *substream,
316 struct snd_pcm_hw_params *params)
318 struct snd_pcm_runtime *runtime = substream->runtime;
319 struct rockchip_runtime_data *prtd = runtime->private_data;
320 struct snd_soc_pcm_runtime *rtd = substream->private_data;
321 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
322 struct rockchip_pcm_dma_params *dma = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
324 struct rockchip_pcm_dma_params *dma = rtd->dai->cpu_dai->dma_data;
326 unsigned long totbytes = params_buffer_bytes(params);
329 DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
330 /*by Vincent Hsiung for EQ Vol Change*/
331 #define HW_PARAMS_FLAG_EQVOL_ON 0x21
332 #define HW_PARAMS_FLAG_EQVOL_OFF 0x22
334 if ((params->flags == HW_PARAMS_FLAG_EQVOL_ON)||(params->flags == HW_PARAMS_FLAG_EQVOL_OFF))
339 /* return if this is a bufferless transfer e.g.
340 * codec <--> BT codec or GSM modem -- lg FIXME */
344 /* this may get called several times by oss emulation
345 * with different params -HW */
346 if (prtd->params == NULL) {
349 #ifdef CONFIG_SND_I2S_DMA_EVENT_DYNAMIC
350 DBG("params %p, client %p, channel %d\n", prtd->params,
351 prtd->params->client, prtd->params->channel);
353 //ret = request_dma(prtd->params->channel, "i2s"); ///prtd->params->client->name);
354 ret = rk29_dma_request(prtd->params->channel, prtd->params->client, NULL);
355 DBG("Enter::%s, %d, ret=%d, Channel=%d\n", __FUNCTION__, __LINE__, ret, prtd->params->channel);
358 for(prtd->params->channel=5;prtd->params->channel>0;prtd->params->channel--){
359 ret = request_dma(prtd->params->channel, "i2s");
365 DBG(KERN_ERR "failed to get dma channel\n");
371 rk29_dma_set_buffdone_fn(prtd->params->channel, rk29_audio_buffdone);
373 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
375 runtime->dma_bytes = totbytes;
377 spin_lock_irq(&prtd->lock);
378 prtd->dma_loaded = 0;
379 prtd->dma_limit = runtime->hw.periods_min;
380 prtd->dma_period = params_period_bytes(params);
381 prtd->dma_start = runtime->dma_addr;
382 prtd->dma_pos = prtd->dma_start;
383 prtd->dma_end = prtd->dma_start + totbytes;
384 prtd->transfer_first = 1;
388 spin_unlock_irq(&prtd->lock);
392 static int rockchip_pcm_hw_free(struct snd_pcm_substream *substream)
394 struct rockchip_runtime_data *prtd = substream->runtime->private_data;
396 DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
397 /* TODO - do we need to ensure DMA flushed */
398 snd_pcm_set_runtime_buffer(substream, NULL);
401 #ifdef CONFIG_SND_I2S_DMA_EVENT_DYNAMIC
402 //free_dma(prtd->params->channel);
403 rk29_dma_free(prtd->params->channel, prtd->params->client);
411 static int rockchip_pcm_prepare(struct snd_pcm_substream *substream)
413 struct rockchip_runtime_data *prtd = substream->runtime->private_data;
416 DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
418 /* return if this is a bufferless transfer e.g.
419 * codec <--> BT codec or GSM modem -- lg FIXME */
423 if(substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
424 ret = rk29_dma_devconfig(prtd->params->channel,
426 prtd->params->dma_addr);
428 ret = rk29_dma_devconfig(prtd->params->channel,
430 prtd->params->dma_addr);
432 DBG("Enter::%s, %d, ret=%d, Channel=%d, Addr=0x%X\n", __FUNCTION__, __LINE__, ret, prtd->params->channel, prtd->params->dma_addr);
433 ret = rk29_dma_config(prtd->params->channel,
434 prtd->params->dma_size, 16);
436 DBG("Enter:%s, %d, ret = %d, Channel=%d, Size=%d\n",
437 __FUNCTION__, __LINE__, ret, prtd->params->channel,
438 prtd->params->dma_size);
440 ret= rk29_dma_ctrl(prtd->params->channel, RK29_DMAOP_FLUSH);
441 DBG("Enter:%s, %d, ret = %d, Channel=%d\n",
442 __FUNCTION__, __LINE__, ret, prtd->params->channel);
444 prtd->dma_loaded = 0;
445 prtd->dma_pos = prtd->dma_start;
447 /* enqueue dma buffers */
448 rockchip_pcm_enqueue(substream);
452 static int rockchip_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
454 struct rockchip_runtime_data *prtd = substream->runtime->private_data;
456 /**************add by qiuen for volume*****/
457 struct snd_soc_pcm_runtime *rtd = substream->private_data;
458 struct snd_soc_dai *pCodec_dai = rtd->dai->codec_dai;
462 DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
464 if(cmd==SNDRV_PCM_TRIGGER_VOLUME){
465 vol = substream->number % 100;
466 streamType = (substream->number / 100) % 100;
467 DBG("enter:vol=%d,streamType=%d\n",vol,streamType);
468 if(pCodec_dai->ops->set_volume)
469 pCodec_dai->ops->set_volume(streamType, vol);
471 /****************************************************/
472 spin_lock(&prtd->lock);
475 case SNDRV_PCM_TRIGGER_START:
477 prtd->state |= ST_RUNNING;
478 rk29_dma_ctrl(prtd->params->channel, RK29_DMAOP_START);
480 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
481 audio_start_dma(substream, DMA_MODE_WRITE);
483 audio_start_dma(substream, DMA_MODE_READ);
486 #ifdef CONFIG_ANDROID_POWER
487 android_lock_suspend(&audio_lock);
488 DBG("%s::start audio , lock system suspend\n" , __func__ );
491 case SNDRV_PCM_TRIGGER_RESUME:
494 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
498 case SNDRV_PCM_TRIGGER_STOP:
499 case SNDRV_PCM_TRIGGER_SUSPEND:
500 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
502 prtd->state &= ~ST_RUNNING;
503 rk29_dma_ctrl(prtd->params->channel, RK29_DMAOP_STOP);
504 //disable_dma(prtd->params->channel);
505 #ifdef CONFIG_ANDROID_POWER
506 android_unlock_suspend(&audio_lock );
507 DBG("%s::stop audio , unlock system suspend\n" , __func__ );
516 spin_unlock(&prtd->lock);
521 static snd_pcm_uframes_t
522 rockchip_pcm_pointer(struct snd_pcm_substream *substream)
524 struct snd_pcm_runtime *runtime = substream->runtime;
525 struct rockchip_runtime_data *prtd = runtime->private_data;
528 snd_pcm_uframes_t ret;
530 DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
531 spin_lock(&prtd->lock);
533 //get_dma_position(prtd->params->channel, &src, &dst);
534 rk29_dma_getposition(prtd->params->channel, &src, &dst);
535 //dma_getposition(prtd->params->channel, &src, &dst);
537 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
538 res = dst - prtd->dma_start;
540 res = src - prtd->dma_start;
542 spin_unlock(&prtd->lock);
544 DBG("Pointer %x %x\n",src,dst);
546 ret = bytes_to_frames(runtime, res);
547 if (ret == runtime->buffer_size)
553 static int rockchip_pcm_open(struct snd_pcm_substream *substream)
555 struct snd_pcm_runtime *runtime = substream->runtime;
556 struct rockchip_runtime_data *prtd;
558 DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
560 snd_soc_set_runtime_hwparams(substream, &rockchip_pcm_hardware);
562 prtd = kzalloc(sizeof(struct rockchip_runtime_data), GFP_KERNEL);
566 spin_lock_init(&prtd->lock);
568 runtime->private_data = prtd;
572 static int rockchip_pcm_close(struct snd_pcm_substream *substream)
574 struct snd_pcm_runtime *runtime = substream->runtime;
575 struct rockchip_runtime_data *prtd = runtime->private_data;
576 struct rockchip_dma_buf_set *sg_buf = NULL;
577 DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
580 DBG("rockchip_pcm_close called with prtd == NULL\n");
584 while (sg_buf != NULL) {
585 prtd->curr = sg_buf->next;
586 prtd->next = sg_buf->next;
597 static int rockchip_pcm_mmap(struct snd_pcm_substream *substream,
598 struct vm_area_struct *vma)
600 struct snd_pcm_runtime *runtime = substream->runtime;
602 DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
604 return dma_mmap_writecombine(substream->pcm->card->dev, vma,
610 static struct snd_pcm_ops rockchip_pcm_ops = {
611 .open = rockchip_pcm_open,
612 .close = rockchip_pcm_close,
613 .ioctl = snd_pcm_lib_ioctl,
614 .hw_params = rockchip_pcm_hw_params,
615 .hw_free = rockchip_pcm_hw_free,
616 .prepare = rockchip_pcm_prepare,
617 .trigger = rockchip_pcm_trigger,
618 .pointer = rockchip_pcm_pointer,
619 .mmap = rockchip_pcm_mmap,
622 static int rockchip_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
624 struct snd_pcm_substream *substream = pcm->streams[stream].substream;
625 struct snd_dma_buffer *buf = &substream->dma_buffer;
626 size_t size = rockchip_pcm_hardware.buffer_bytes_max;
628 DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
630 buf->dev.type = SNDRV_DMA_TYPE_DEV;
631 buf->dev.dev = pcm->card->dev;
632 buf->private_data = NULL;
633 buf->area = dma_alloc_writecombine(pcm->card->dev, size,
634 &buf->addr, GFP_KERNEL);
641 static void rockchip_pcm_free_dma_buffers(struct snd_pcm *pcm)
643 struct snd_pcm_substream *substream;
644 struct snd_dma_buffer *buf;
647 DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
649 for (stream = 0; stream < 2; stream++) {
650 substream = pcm->streams[stream].substream;
654 buf = &substream->dma_buffer;
658 dma_free_writecombine(pcm->card->dev, buf->bytes,
659 buf->area, buf->addr);
664 static u64 rockchip_pcm_dmamask = DMA_BIT_MASK(32);
666 static int rockchip_pcm_new(struct snd_card *card,
667 struct snd_soc_dai *dai, struct snd_pcm *pcm)
671 DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
673 #ifdef CONFIG_ANDROID_POWER
674 audio_lock.name = "rk-audio";
675 android_init_suspend_lock(&audio_lock);
678 if (!card->dev->dma_mask)
679 card->dev->dma_mask = &rockchip_pcm_dmamask;
680 if (!card->dev->coherent_dma_mask)
681 card->dev->coherent_dma_mask = 0xffffffff;
683 if (dai->playback.channels_min) {
684 ret = rockchip_pcm_preallocate_dma_buffer(pcm,
685 SNDRV_PCM_STREAM_PLAYBACK);
690 if (dai->capture.channels_min) {
691 ret = rockchip_pcm_preallocate_dma_buffer(pcm,
692 SNDRV_PCM_STREAM_CAPTURE);
700 struct snd_soc_platform rk29_soc_platform = {
701 .name = "rockchip-audio",
702 .pcm_ops = &rockchip_pcm_ops,
703 .pcm_new = rockchip_pcm_new,
704 .pcm_free = rockchip_pcm_free_dma_buffers,
706 EXPORT_SYMBOL_GPL(rk29_soc_platform);
708 static int __init rockchip_soc_platform_init(void)
710 DBG("Enter::%s, %d\n", __FUNCTION__, __LINE__);
711 return snd_soc_register_platform(&rk29_soc_platform);
713 module_init(rockchip_soc_platform_init);
715 static void __exit rockchip_soc_platform_exit(void)
717 snd_soc_unregister_platform(&rk29_soc_platform);
719 module_exit(rockchip_soc_platform_exit);
721 /* Module information */
722 MODULE_AUTHOR("rockchip");
723 MODULE_DESCRIPTION("ROCKCHIP PCM ASoC Interface");
724 MODULE_LICENSE("GPL");