bedaf6f00a381c654ba043e8438f355efdd5502e
[firefly-linux-kernel-4.4.55.git] / sound / soc / rk2818 / rk2818_pcm.c
1 /*
2  * rk2818_pcm.c  --  ALSA SoC ROCKCHIP PCM Audio Layer Platform driver
3  *
4  * Driver for rockchip pcm audio
5  *  Copyright (C) 2009 lhh
6  *
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 as published by the
10  *  Free Software Foundation;  either version 2 of the  License, or (at your
11  *  option) any later version.
12  *
13  */
14 #include <linux/module.h>
15 #include <linux/init.h>
16 #include <linux/io.h>
17 #include <linux/platform_device.h>
18 #include <linux/slab.h>
19 #include <linux/dma-mapping.h>
20
21 #include <sound/core.h>
22 #include <sound/pcm.h>
23 #include <sound/pcm_params.h>
24 #include <sound/soc.h>
25
26 #include <asm/dma.h>
27 #include <mach/hardware.h>
28 #include <mach/dma.h>
29
30 #include "rk2818_pcm.h"
31
32 #ifdef CONFIG_ANDROID_POWER
33 #include <linux/android_power.h>
34 static android_suspend_lock_t audio_lock;
35 #endif
36
37 #if 0
38 #define DBG(x...) printk(KERN_INFO x)
39 #else
40 #define DBG(x...) do { } while (0)
41 #endif
42
43
44 static const struct snd_pcm_hardware rockchip_pcm_hardware = {
45         .info                   = SNDRV_PCM_INFO_INTERLEAVED |
46                                     SNDRV_PCM_INFO_BLOCK_TRANSFER |
47                                     SNDRV_PCM_INFO_MMAP |
48                                     SNDRV_PCM_INFO_MMAP_VALID |
49                                     SNDRV_PCM_INFO_PAUSE |
50                                     SNDRV_PCM_INFO_RESUME,
51         .formats                = SNDRV_PCM_FMTBIT_S16_LE |
52                                     SNDRV_PCM_FMTBIT_U16_LE |
53                                     SNDRV_PCM_FMTBIT_U8 |
54                                     SNDRV_PCM_FMTBIT_S8,
55         .channels_min           = 2,
56         .channels_max           = 2,
57         .buffer_bytes_max       = 128*1024,
58         .period_bytes_min       = 64,  ///PAGE_SIZE,
59         .period_bytes_max       = 2047*4,///PAGE_SIZE*2,
60         .periods_min            = 3,///2,
61         .periods_max            = 128,
62         .fifo_size              = 16,
63 };
64
65
66 struct rockchip_dma_buf_set {
67         struct rockchip_dma_buf_set     *next;
68         struct scatterlist sg;
69 };
70
71 struct rockchip_runtime_data {
72         spinlock_t lock;
73         int state;
74         int transfer_first;
75         unsigned int dma_loaded;
76         unsigned int dma_limit;
77         unsigned int dma_period;
78         dma_addr_t dma_start;
79         dma_addr_t dma_pos;
80         dma_addr_t dma_end;
81         struct rockchip_pcm_dma_params *params;
82         struct rockchip_dma_buf_set     *curr;          /* current dma buffer set */
83         struct rockchip_dma_buf_set     *next;          /* next buffer set to load */
84         struct rockchip_dma_buf_set     *end;           /* end of queue set*/
85 };
86
87
88 /* rockchip__dma_buf_enqueue
89  *
90  *queue an given buffer for dma transfer set.
91  *data       the physical address of the buffer data
92  *size       the size of the buffer in bytes
93 */
94 static int rockchip_dma_buffer_set_enqueue(struct rockchip_runtime_data *prtd, dma_addr_t data, int size)
95 {   
96         struct rockchip_dma_buf_set *sg_buf;
97         
98     DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
99         sg_buf = kzalloc(sizeof(struct rockchip_dma_buf_set), GFP_KERNEL);
100         
101         if (sg_buf == NULL) {
102                 DBG("scatter sg buffer allocate failed,no memory!\n");
103                 return -ENOMEM;
104         }
105         sg_buf->next = NULL;
106         sg_buf->sg.dma_address = data;
107         sg_buf->sg.length = size/4;  ////4;
108         if( prtd->curr == NULL) {
109                 prtd->curr = sg_buf;
110                 prtd->end  = sg_buf;
111                 prtd->next = NULL;
112         } else {
113                 if (prtd->end == NULL)
114                         DBG("prtd->end is NULL\n");
115                         prtd->end->next = sg_buf;
116                         prtd->end = sg_buf;
117         }
118         /* if necessary, update the next buffer field */
119         if (prtd->next == NULL)
120                 prtd->next = sg_buf;
121         return 0;
122 }
123
124 void rockchip_pcm_dma_irq(s32 ch, void *data);
125
126 void audio_start_dma(struct snd_pcm_substream *substream, int mode)
127 {
128         struct rockchip_runtime_data *prtd;
129         unsigned long flags;
130         struct rockchip_dma_buf_set *sg_buf;
131     
132     DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
133
134         prtd = substream->runtime->private_data;
135
136         switch (mode) {
137         case DMA_MODE_WRITE:
138                 if (prtd->transfer_first == 1) {
139                         prtd->transfer_first = 0;
140                 } else {
141                         sg_buf = prtd->curr;
142                         if (sg_buf != NULL) {
143                                 prtd->curr = sg_buf->next;
144                                 prtd->next = sg_buf->next;
145                                 sg_buf->next  = NULL;
146                                 kfree(sg_buf);
147                                 sg_buf = NULL;
148                         }
149                 }
150
151                 sg_buf = prtd->next;
152                 DBG("Enter::%s----%d---length=%x---dma_address=%x\n",__FUNCTION__,__LINE__,sg_buf->sg.length,sg_buf->sg.dma_address);           
153                 if (sg_buf) {                   
154                         spin_lock_irqsave(&prtd->lock, flags);
155                         disable_dma(prtd->params->channel);
156                         //set_dma_sg(prtd->params->channel, &(sg_buf->sg), 1);
157                         set_dma_mode(prtd->params->channel, DMA_MODE_WRITE);
158                         set_dma_handler(prtd->params->channel, rockchip_pcm_dma_irq, substream, DMA_IRQ_RIGHTNOW_MODE);
159                         __set_dma_addr(prtd->params->channel, (void *)(sg_buf->sg.dma_address));
160                         set_dma_count(prtd->params->channel, sg_buf->sg.length);
161                         enable_dma(prtd->params->channel);
162                         spin_unlock_irqrestore(&prtd->lock, flags);
163                 } else {
164                         DBG("next buffer is NULL for playback\n");
165                         return;
166                 }
167                 break;
168         case DMA_MODE_READ:
169                 if (prtd->transfer_first == 1) {
170                         prtd->transfer_first = 0;
171                 } else {
172                         sg_buf = prtd->curr;
173                         if (sg_buf != NULL) {
174                                 prtd->curr = sg_buf->next;
175                                 prtd->next = sg_buf->next;
176                                 sg_buf->next  = NULL;
177                                 kfree(sg_buf);
178                                 sg_buf = NULL;
179                         }
180                 }
181
182                 sg_buf = prtd->next;
183                 if (sg_buf) {                   
184                         spin_lock_irqsave(&prtd->lock, flags);
185                         disable_dma(prtd->params->channel);
186                         //set_dma_sg(prtd->params->channel, &(sg_buf->sg), 1);
187                         set_dma_mode(prtd->params->channel, DMA_MODE_READ);
188                         set_dma_handler(prtd->params->channel, rockchip_pcm_dma_irq, substream, DMA_IRQ_RIGHTNOW_MODE);                 
189                         __set_dma_addr(prtd->params->channel, (void *)(sg_buf->sg.dma_address));
190                         set_dma_count(prtd->params->channel, sg_buf->sg.length);
191                         enable_dma(prtd->params->channel);
192                         spin_unlock_irqrestore(&prtd->lock, flags);
193                 } else {
194                         DBG("next buffer is NULL for capture\n");
195                         return;
196                 }
197                 break;
198         }
199 }
200
201 /* rockchip_pcm_enqueue
202  *
203  * place a dma buffer onto the queue for the dma system
204  * to handle.
205 */
206 static void rockchip_pcm_enqueue(struct snd_pcm_substream *substream)
207 {
208         struct rockchip_runtime_data *prtd = substream->runtime->private_data;  
209         dma_addr_t pos = prtd->dma_pos;
210         int ret;
211     DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
212         
213     while (prtd->dma_loaded < prtd->dma_limit) {
214                 unsigned long len = prtd->dma_period;
215                 
216         DBG("dma_loaded: %d\n", prtd->dma_loaded);
217                 if ((pos + len) > prtd->dma_end) {
218                         len  = prtd->dma_end - pos;
219                 }
220                 ret = rockchip_dma_buffer_set_enqueue(prtd, pos, len);
221                 if (ret == 0) {
222                         prtd->dma_loaded++;
223                         pos += prtd->dma_period;
224                         if (pos >= prtd->dma_end)
225                                 pos = prtd->dma_start;
226                 } else 
227                         break;
228         }
229
230         prtd->dma_pos = pos;
231 }
232
233 void rockchip_pcm_dma_irq(s32 ch, void *data)
234 {    
235     struct snd_pcm_substream *substream = data;
236         struct rockchip_runtime_data *prtd;
237         unsigned long flags;
238         
239         DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
240
241         prtd = substream->runtime->private_data;
242         if (substream)
243                 snd_pcm_period_elapsed(substream);
244         spin_lock(&prtd->lock);
245         prtd->dma_loaded--;
246         if (prtd->state & ST_RUNNING) {
247                 rockchip_pcm_enqueue(substream);
248         }
249     spin_unlock(&prtd->lock);
250     local_irq_save(flags);
251         if (prtd->state & ST_RUNNING) {
252                 if (prtd->dma_loaded) {
253                         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
254                                 audio_start_dma(substream, DMA_MODE_WRITE);
255                         else
256                                 audio_start_dma(substream, DMA_MODE_READ);
257                 }
258         }
259         local_irq_restore(flags);   
260 }
261
262
263 static int rockchip_pcm_hw_params(struct snd_pcm_substream *substream,
264         struct snd_pcm_hw_params *params)
265 {
266         struct snd_pcm_runtime *runtime = substream->runtime;
267         struct rockchip_runtime_data *prtd = runtime->private_data;
268         struct snd_soc_pcm_runtime *rtd = substream->private_data;
269         struct rockchip_pcm_dma_params *dma = rtd->dai->cpu_dai->dma_data;
270         unsigned long totbytes = params_buffer_bytes(params);
271         int ret = 0;
272
273         DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
274         /*by Vincent Hsiung for EQ Vol Change*/
275         #define HW_PARAMS_FLAG_EQVOL_ON 0x21
276         #define HW_PARAMS_FLAG_EQVOL_OFF 0x22
277     if ((params->flags == HW_PARAMS_FLAG_EQVOL_ON)||(params->flags == HW_PARAMS_FLAG_EQVOL_OFF))
278         {
279                 return 0;
280         }
281
282         /* return if this is a bufferless transfer e.g.
283          * codec <--> BT codec or GSM modem -- lg FIXME */
284         if (!dma)
285                 return 0;
286
287         /* this may get called several times by oss emulation
288          * with different params -HW */
289         if (prtd->params == NULL) {
290                 /* prepare DMA */
291                 prtd->params = dma;
292
293                 DBG("params %p, client %p, channel %d\n", prtd->params,
294                         prtd->params->client, prtd->params->channel);
295
296                 ret = request_dma(prtd->params->channel, "i2s");  ///prtd->params->client->name);
297                 if(ret){
298                         for(prtd->params->channel=5;prtd->params->channel>0;prtd->params->channel--){
299                                 ret = request_dma(prtd->params->channel, "i2s");
300                                 if(!ret)break;
301                         }
302                 }
303                 if (ret) {
304                         DBG(KERN_ERR "failed to get dma channel\n");
305                         return ret;
306                 }
307         }
308
309
310         snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
311
312         runtime->dma_bytes = totbytes;
313
314         spin_lock_irq(&prtd->lock);
315         prtd->dma_loaded = 0;
316         prtd->dma_limit = runtime->hw.periods_min;
317         prtd->dma_period = params_period_bytes(params);
318         prtd->dma_start = runtime->dma_addr;
319         prtd->dma_pos = prtd->dma_start;
320         prtd->dma_end = prtd->dma_start + totbytes;
321         prtd->transfer_first = 1;
322         prtd->curr = NULL;
323         prtd->next = NULL;
324         prtd->end = NULL;
325         spin_unlock_irq(&prtd->lock);
326         return 0;
327 }
328
329 static int rockchip_pcm_hw_free(struct snd_pcm_substream *substream)
330 {
331         struct rockchip_runtime_data *prtd = substream->runtime->private_data;
332
333         DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
334         /* TODO - do we need to ensure DMA flushed */
335         snd_pcm_set_runtime_buffer(substream, NULL);
336
337         if (prtd->params) {
338                 free_dma(prtd->params->channel);
339                 prtd->params = NULL;
340         }
341
342         return 0;
343 }
344
345 static int rockchip_pcm_prepare(struct snd_pcm_substream *substream)
346 {
347         struct rockchip_runtime_data *prtd = substream->runtime->private_data;
348         int ret = 0;
349
350         DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
351
352         /* return if this is a bufferless transfer e.g.
353          * codec <--> BT codec or GSM modem -- lg FIXME */
354         if (!prtd->params)
355                 return 0;
356         prtd->dma_loaded = 0;
357         prtd->dma_pos = prtd->dma_start;
358
359         /* enqueue dma buffers */
360         rockchip_pcm_enqueue(substream);
361         return ret;
362 }
363
364 static int rockchip_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
365 {
366         struct rockchip_runtime_data *prtd = substream->runtime->private_data;
367         int ret = 0;
368
369         DBG("Enter::%s----%d---%d\n",__FUNCTION__,__LINE__,cmd);
370
371         spin_lock(&prtd->lock);
372
373         switch (cmd) {
374         case SNDRV_PCM_TRIGGER_START:
375                 DBG(" START \n");
376             prtd->state |= ST_RUNNING;
377             if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
378                     audio_start_dma(substream, DMA_MODE_WRITE);
379                 } else {
380                     audio_start_dma(substream, DMA_MODE_READ);
381                 }
382 #ifdef CONFIG_ANDROID_POWER        
383         android_lock_suspend(&audio_lock);
384         DBG("%s::start audio , lock system suspend\n" , __func__ );
385 #endif          
386                 break;
387         case SNDRV_PCM_TRIGGER_RESUME:
388             DBG(" RESUME \n");
389             break;
390         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
391                 DBG(" RESTART \n");
392                 break;
393
394         case SNDRV_PCM_TRIGGER_STOP:
395         case SNDRV_PCM_TRIGGER_SUSPEND:
396         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
397             DBG(" STOPS \n");
398                 prtd->state &= ~ST_RUNNING;
399                 disable_dma(prtd->params->channel);
400 #ifdef CONFIG_ANDROID_POWER        
401         android_unlock_suspend(&audio_lock );
402         DBG("%s::stop audio , unlock system suspend\n" , __func__ );
403 #endif
404                 
405                 break;
406         default:
407                 ret = -EINVAL;
408                 break;
409         }
410
411         spin_unlock(&prtd->lock);
412         return ret;
413 }
414
415
416 static snd_pcm_uframes_t
417 rockchip_pcm_pointer(struct snd_pcm_substream *substream)
418 {
419         struct snd_pcm_runtime *runtime = substream->runtime;
420         struct rockchip_runtime_data *prtd = runtime->private_data;
421         unsigned long res;
422         dma_addr_t src, dst;
423         snd_pcm_uframes_t ret;
424     
425         DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
426         spin_lock(&prtd->lock);
427
428     get_dma_position(prtd->params->channel, &src, &dst);                        
429         //dma_getposition(prtd->params->channel, &src, &dst);
430         
431         if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
432                 res = dst - prtd->dma_start;
433         else
434                 res = src - prtd->dma_start;
435
436         spin_unlock(&prtd->lock);
437
438         DBG("Pointer %x %x\n",src,dst); 
439
440         ret = bytes_to_frames(runtime, res);
441         if (ret == runtime->buffer_size)
442                 ret = 0;
443         return ret;     
444 }
445
446
447 static int rockchip_pcm_open(struct snd_pcm_substream *substream)
448 {
449         struct snd_pcm_runtime *runtime = substream->runtime;
450         struct rockchip_runtime_data *prtd;
451
452         DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
453
454         snd_soc_set_runtime_hwparams(substream, &rockchip_pcm_hardware);
455
456         prtd = kzalloc(sizeof(struct rockchip_runtime_data), GFP_KERNEL);
457         if (prtd == NULL)
458                 return -ENOMEM;
459
460         spin_lock_init(&prtd->lock);
461
462         runtime->private_data = prtd;
463         return 0;
464 }
465
466 static int rockchip_pcm_close(struct snd_pcm_substream *substream)
467 {
468         struct snd_pcm_runtime *runtime = substream->runtime;
469         struct rockchip_runtime_data *prtd = runtime->private_data;
470     struct rockchip_dma_buf_set *sg_buf = NULL;
471         DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
472
473         if (!prtd)
474                 DBG("rockchip_pcm_close called with prtd == NULL\n");
475     if (prtd) 
476                 sg_buf = prtd->curr;
477
478         while (sg_buf != NULL) {
479                 prtd->curr = sg_buf->next;
480                 prtd->next = sg_buf->next;
481                 sg_buf->next  = NULL;
482                 kfree(sg_buf);
483                 sg_buf = NULL;
484                 sg_buf = prtd->curr;
485         }
486         kfree(prtd);
487
488         return 0;
489 }
490
491 static int rockchip_pcm_mmap(struct snd_pcm_substream *substream,
492         struct vm_area_struct *vma)
493 {
494         struct snd_pcm_runtime *runtime = substream->runtime;
495
496         DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
497
498         return dma_mmap_writecombine(substream->pcm->card->dev, vma,
499                                      runtime->dma_area,
500                                      runtime->dma_addr,
501                                      runtime->dma_bytes);
502 }
503
504 static struct snd_pcm_ops rockchip_pcm_ops = {
505         .open           = rockchip_pcm_open,
506         .close          = rockchip_pcm_close,
507         .ioctl          = snd_pcm_lib_ioctl,
508         .hw_params      = rockchip_pcm_hw_params,
509         .hw_free        = rockchip_pcm_hw_free,
510         .prepare        = rockchip_pcm_prepare,
511         .trigger        = rockchip_pcm_trigger,
512         .pointer        = rockchip_pcm_pointer,
513         .mmap           = rockchip_pcm_mmap,
514 };
515
516 static int rockchip_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
517 {
518         struct snd_pcm_substream *substream = pcm->streams[stream].substream;
519         struct snd_dma_buffer *buf = &substream->dma_buffer;
520         size_t size = rockchip_pcm_hardware.buffer_bytes_max;
521
522         DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
523
524         buf->dev.type = SNDRV_DMA_TYPE_DEV;
525         buf->dev.dev = pcm->card->dev;
526         buf->private_data = NULL;
527         buf->area = dma_alloc_writecombine(pcm->card->dev, size,
528                                            &buf->addr, GFP_KERNEL);
529         if (!buf->area)
530                 return -ENOMEM;
531         buf->bytes = size;
532         return 0;
533 }
534
535 static void rockchip_pcm_free_dma_buffers(struct snd_pcm *pcm)
536 {
537         struct snd_pcm_substream *substream;
538         struct snd_dma_buffer *buf;
539         int stream;
540
541         DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
542
543         for (stream = 0; stream < 2; stream++) {
544                 substream = pcm->streams[stream].substream;
545                 if (!substream)
546                         continue;
547
548                 buf = &substream->dma_buffer;
549                 if (!buf->area)
550                         continue;
551
552                 dma_free_writecombine(pcm->card->dev, buf->bytes,
553                                       buf->area, buf->addr);
554                 buf->area = NULL;
555         }
556 }
557
558 static u64 rockchip_pcm_dmamask = DMA_BIT_MASK(32);
559
560 static int rockchip_pcm_new(struct snd_card *card,
561         struct snd_soc_dai *dai, struct snd_pcm *pcm)
562 {
563         int ret = 0;
564
565         DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
566
567 #ifdef CONFIG_ANDROID_POWER
568         audio_lock.name = "rk-audio";
569         android_init_suspend_lock(&audio_lock);
570 #endif
571
572         if (!card->dev->dma_mask)
573                 card->dev->dma_mask = &rockchip_pcm_dmamask;
574         if (!card->dev->coherent_dma_mask)
575                 card->dev->coherent_dma_mask = 0xffffffff;
576
577         if (dai->playback.channels_min) {
578                 ret = rockchip_pcm_preallocate_dma_buffer(pcm,
579                         SNDRV_PCM_STREAM_PLAYBACK);
580                 if (ret)
581                         goto out;
582         }
583
584         if (dai->capture.channels_min) {
585                 ret = rockchip_pcm_preallocate_dma_buffer(pcm,
586                         SNDRV_PCM_STREAM_CAPTURE);
587                 if (ret)
588                         goto out;
589         }
590  out:
591         return ret;
592 }
593
594 struct snd_soc_platform rk2818_soc_platform = {
595         .name           = "rockchip-audio",
596         .pcm_ops        = &rockchip_pcm_ops,
597         .pcm_new        = rockchip_pcm_new,
598         .pcm_free       = rockchip_pcm_free_dma_buffers,
599 };
600 EXPORT_SYMBOL_GPL(rk2818_soc_platform);
601
602 static int __init rockchip_soc_platform_init(void)
603 {
604         return snd_soc_register_platform(&rk2818_soc_platform);
605 }
606 module_init(rockchip_soc_platform_init);
607
608 static void __exit rockchip_soc_platform_exit(void)
609 {
610         snd_soc_unregister_platform(&rk2818_soc_platform);
611 }
612 module_exit(rockchip_soc_platform_exit);
613
614 /* Module information */
615 MODULE_AUTHOR("lhh lhh@rock-chips.com");
616 MODULE_DESCRIPTION("ROCKCHIP PCM ASoC Interface");
617 MODULE_LICENSE("GPL");
618