kernel: refresh patches
[15.05/openwrt.git] / target / linux / brcm2708 / patches-3.14 / 0010-alsa-add-mmap-support-and-some-cleanups-to-bcm2835-A.patch
1 From 00d2b7bf3cd58d9735f103ff4cc6982b7dc927fe Mon Sep 17 00:00:00 2001
2 From: popcornmix <popcornmix@gmail.com>
3 Date: Fri, 26 Apr 2013 10:08:31 -0700
4 Subject: [PATCH 10/54] alsa: add mmap support and some cleanups to bcm2835
5  ALSA driver
6
7 ---
8  sound/arm/bcm2835-pcm.c   | 69 ++++++++++++++++++++++--------------
9  sound/arm/bcm2835-vchiq.c | 89 +++++++++++++++++++++++++++++++++--------------
10  sound/arm/bcm2835.c       | 34 +++++++++---------
11  sound/arm/bcm2835.h       |  2 ++
12  4 files changed, 124 insertions(+), 70 deletions(-)
13
14 --- a/sound/arm/bcm2835-pcm.c
15 +++ b/sound/arm/bcm2835-pcm.c
16 @@ -19,7 +19,8 @@
17  
18  /* hardware definition */
19  static struct snd_pcm_hardware snd_bcm2835_playback_hw = {
20 -       .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER),
21 +       .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
22 +                SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),
23         .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
24         .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
25         .rate_min = 8000,
26 @@ -251,6 +252,12 @@ static int snd_bcm2835_pcm_prepare(struc
27  
28         audio_info(" .. IN\n");
29  
30 +       memset(&alsa_stream->pcm_indirect, 0, sizeof(alsa_stream->pcm_indirect));
31 +
32 +       alsa_stream->pcm_indirect.hw_buffer_size =
33 +       alsa_stream->pcm_indirect.sw_buffer_size =
34 +               snd_pcm_lib_buffer_bytes(substream);
35 +
36         alsa_stream->buffer_size = snd_pcm_lib_buffer_bytes(substream);
37         alsa_stream->period_size = snd_pcm_lib_period_bytes(substream);
38         alsa_stream->pos = 0;
39 @@ -263,6 +270,32 @@ static int snd_bcm2835_pcm_prepare(struc
40         return 0;
41  }
42  
43 +static void snd_bcm2835_pcm_transfer(struct snd_pcm_substream *substream,
44 +                                   struct snd_pcm_indirect *rec, size_t bytes)
45 +{
46 +       struct snd_pcm_runtime *runtime = substream->runtime;
47 +       bcm2835_alsa_stream_t *alsa_stream = runtime->private_data;
48 +       void *src = (void *)(substream->runtime->dma_area + rec->sw_data);
49 +       int err;
50 +
51 +       err = bcm2835_audio_write(alsa_stream, bytes, src);
52 +       if (err)
53 +               audio_error(" Failed to transfer to alsa device (%d)\n", err);
54 +
55 +}
56 +
57 +static int snd_bcm2835_pcm_ack(struct snd_pcm_substream *substream)
58 +{
59 +       struct snd_pcm_runtime *runtime = substream->runtime;
60 +       bcm2835_alsa_stream_t *alsa_stream = runtime->private_data;
61 +       struct snd_pcm_indirect *pcm_indirect = &alsa_stream->pcm_indirect;
62 +
63 +       pcm_indirect->hw_queue_size = runtime->hw.buffer_bytes_max;
64 +       snd_pcm_indirect_playback_transfer(substream, pcm_indirect,
65 +                                          snd_bcm2835_pcm_transfer);
66 +       return 0;
67 +}
68 +
69  /* trigger callback */
70  static int snd_bcm2835_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
71  {
72 @@ -279,6 +312,11 @@ static int snd_bcm2835_pcm_trigger(struc
73                 if (!alsa_stream->running) {
74                         err = bcm2835_audio_start(alsa_stream);
75                         if (err == 0) {
76 +                               alsa_stream->pcm_indirect.hw_io =
77 +                               alsa_stream->pcm_indirect.hw_data =
78 +                                       bytes_to_frames(runtime,
79 +                                                       alsa_stream->pos);
80 +                               substream->ops->ack(substream);
81                                 alsa_stream->running = 1;
82                                 alsa_stream->draining = 1;
83                         } else {
84 @@ -327,30 +365,9 @@ snd_bcm2835_pcm_pointer(struct snd_pcm_s
85                       alsa_stream->pos);
86  
87         audio_info(" .. OUT\n");
88 -       return bytes_to_frames(runtime, alsa_stream->pos);
89 -}
90 -
91 -static int snd_bcm2835_pcm_copy(struct snd_pcm_substream *substream,
92 -                               int channel, snd_pcm_uframes_t pos, void *src,
93 -                               snd_pcm_uframes_t count)
94 -{
95 -       int ret;
96 -       struct snd_pcm_runtime *runtime = substream->runtime;
97 -       bcm2835_alsa_stream_t *alsa_stream = runtime->private_data;
98 -
99 -       audio_info(" .. IN\n");
100 -       audio_debug("copy.......... (%d) hwptr=%d appl=%d pos=%d\n",
101 -                     frames_to_bytes(runtime, count), frames_to_bytes(runtime,
102 -                                                                      runtime->
103 -                                                                      status->
104 -                                                                      hw_ptr),
105 -                     frames_to_bytes(runtime, runtime->control->appl_ptr),
106 -                     alsa_stream->pos);
107 -       ret =
108 -           bcm2835_audio_write(alsa_stream, frames_to_bytes(runtime, count),
109 -                               src);
110 -       audio_info(" .. OUT\n");
111 -       return ret;
112 +       return snd_pcm_indirect_playback_pointer(substream,
113 +                                                &alsa_stream->pcm_indirect,
114 +                                                alsa_stream->pos);
115  }
116  
117  static int snd_bcm2835_pcm_lib_ioctl(struct snd_pcm_substream *substream,
118 @@ -372,7 +389,7 @@ static struct snd_pcm_ops snd_bcm2835_pl
119         .prepare = snd_bcm2835_pcm_prepare,
120         .trigger = snd_bcm2835_pcm_trigger,
121         .pointer = snd_bcm2835_pcm_pointer,
122 -       .copy = snd_bcm2835_pcm_copy,
123 +       .ack = snd_bcm2835_pcm_ack,
124  };
125  
126  /* create a pcm device */
127 --- a/sound/arm/bcm2835-vchiq.c
128 +++ b/sound/arm/bcm2835-vchiq.c
129 @@ -27,6 +27,7 @@
130  #include <linux/delay.h>
131  #include <linux/atomic.h>
132  #include <linux/module.h>
133 +#include <linux/completion.h>
134  
135  #include "bcm2835.h"
136  
137 @@ -37,6 +38,10 @@
138  
139  /* ---- Private Constants and Types ------------------------------------------ */
140  
141 +#define BCM2835_AUDIO_STOP           0
142 +#define BCM2835_AUDIO_START          1
143 +#define BCM2835_AUDIO_WRITE          2
144 +
145  /* Logging macros (for remapping to other logging mechanisms, i.e., printf) */
146  #ifdef AUDIO_DEBUG_ENABLE
147         #define LOG_ERR( fmt, arg... )   pr_err( "%s:%d " fmt, __func__, __LINE__, ##arg)
148 @@ -53,7 +58,7 @@
149  typedef struct opaque_AUDIO_INSTANCE_T {
150         uint32_t num_connections;
151         VCHI_SERVICE_HANDLE_T vchi_handle[VCHI_MAX_NUM_CONNECTIONS];
152 -       struct semaphore msg_avail_event;
153 +       struct completion msg_avail_comp;
154         struct mutex vchi_mutex;
155         bcm2835_alsa_stream_t *alsa_stream;
156         int32_t result;
157 @@ -70,27 +75,35 @@ bool force_bulk = false;
158  
159  static int bcm2835_audio_stop_worker(bcm2835_alsa_stream_t * alsa_stream);
160  static int bcm2835_audio_start_worker(bcm2835_alsa_stream_t * alsa_stream);
161 +static int bcm2835_audio_write_worker(bcm2835_alsa_stream_t *alsa_stream,
162 +                                     uint32_t count, void *src);
163  
164  typedef struct {
165         struct work_struct my_work;
166         bcm2835_alsa_stream_t *alsa_stream;
167 -       int x;
168 +       int cmd;
169 +       void *src;
170 +       uint32_t count;
171  } my_work_t;
172  
173  static void my_wq_function(struct work_struct *work)
174  {
175         my_work_t *w = (my_work_t *) work;
176         int ret = -9;
177 -       LOG_DBG(" .. IN %p:%d\n", w->alsa_stream, w->x);
178 -       switch (w->x) {
179 -       case 1:
180 +       LOG_DBG(" .. IN %p:%d\n", w->alsa_stream, w->cmd);
181 +       switch (w->cmd) {
182 +       case BCM2835_AUDIO_START:
183                 ret = bcm2835_audio_start_worker(w->alsa_stream);
184                 break;
185 -       case 2:
186 +       case BCM2835_AUDIO_STOP:
187                 ret = bcm2835_audio_stop_worker(w->alsa_stream);
188                 break;
189 +       case BCM2835_AUDIO_WRITE:
190 +               ret = bcm2835_audio_write_worker(w->alsa_stream, w->count,
191 +                                                w->src);
192 +               break;
193         default:
194 -               LOG_ERR(" Unexpected work: %p:%d\n", w->alsa_stream, w->x);
195 +               LOG_ERR(" Unexpected work: %p:%d\n", w->alsa_stream, w->cmd);
196                 break;
197         }
198         kfree((void *)work);
199 @@ -107,7 +120,7 @@ int bcm2835_audio_start(bcm2835_alsa_str
200                 if (work) {
201                         INIT_WORK((struct work_struct *)work, my_wq_function);
202                         work->alsa_stream = alsa_stream;
203 -                       work->x = 1;
204 +                       work->cmd = BCM2835_AUDIO_START;
205                         if (queue_work
206                             (alsa_stream->my_wq, (struct work_struct *)work))
207                                 ret = 0;
208 @@ -128,7 +141,31 @@ int bcm2835_audio_stop(bcm2835_alsa_stre
209                 if (work) {
210                         INIT_WORK((struct work_struct *)work, my_wq_function);
211                         work->alsa_stream = alsa_stream;
212 -                       work->x = 2;
213 +                       work->cmd = BCM2835_AUDIO_STOP;
214 +                       if (queue_work
215 +                           (alsa_stream->my_wq, (struct work_struct *)work))
216 +                               ret = 0;
217 +               } else
218 +                       LOG_ERR(" .. Error: NULL work kmalloc\n");
219 +       }
220 +       LOG_DBG(" .. OUT %d\n", ret);
221 +       return ret;
222 +}
223 +
224 +int bcm2835_audio_write(bcm2835_alsa_stream_t *alsa_stream,
225 +                       uint32_t count, void *src)
226 +{
227 +       int ret = -1;
228 +       LOG_DBG(" .. IN\n");
229 +       if (alsa_stream->my_wq) {
230 +               my_work_t *work = kmalloc(sizeof(my_work_t), GFP_ATOMIC);
231 +                /*--- Queue some work (item 1) ---*/
232 +               if (work) {
233 +                       INIT_WORK((struct work_struct *)work, my_wq_function);
234 +                       work->alsa_stream = alsa_stream;
235 +                       work->cmd = BCM2835_AUDIO_WRITE;
236 +                       work->src = src;
237 +                       work->count = count;
238                         if (queue_work
239                             (alsa_stream->my_wq, (struct work_struct *)work))
240                                 ret = 0;
241 @@ -178,7 +215,7 @@ static void audio_vchi_callback(void *pa
242                     (" .. instance=%p, m.type=VC_AUDIO_MSG_TYPE_RESULT, success=%d\n",
243                      instance, m.u.result.success);
244                 instance->result = m.u.result.success;
245 -               up(&instance->msg_avail_event);
246 +               complete(&instance->msg_avail_comp);
247         } else if (m.type == VC_AUDIO_MSG_TYPE_COMPLETE) {
248                 irq_handler_t callback = (irq_handler_t) m.u.complete.callback;
249                 LOG_DBG
250 @@ -435,8 +472,8 @@ static int bcm2835_audio_set_ctls_chan(b
251         m.u.control.dest = chip->dest;
252         m.u.control.volume = chip->volume;
253  
254 -       /* Create the message available event */
255 -       sema_init(&instance->msg_avail_event, 0);
256 +       /* Create the message available completion */
257 +       init_completion(&instance->msg_avail_comp);
258  
259         /* Send the message to the videocore */
260         success = vchi_msg_queue(instance->vchi_handle[0],
261 @@ -452,11 +489,10 @@ static int bcm2835_audio_set_ctls_chan(b
262         }
263  
264         /* We are expecting a reply from the videocore */
265 -       if (down_interruptible(&instance->msg_avail_event)) {
266 +       ret = wait_for_completion_interruptible(&instance->msg_avail_comp);
267 +       if (ret) {
268                 LOG_ERR("%s: failed on waiting for event (status=%d)\n",
269                         __func__, success);
270 -
271 -               ret = -1;
272                 goto unlock;
273         }
274  
275 @@ -539,8 +575,8 @@ int bcm2835_audio_set_params(bcm2835_als
276         m.u.config.samplerate = samplerate;
277         m.u.config.bps = bps;
278  
279 -       /* Create the message available event */
280 -       sema_init(&instance->msg_avail_event, 0);
281 +       /* Create the message available completion */
282 +       init_completion(&instance->msg_avail_comp);
283  
284         /* Send the message to the videocore */
285         success = vchi_msg_queue(instance->vchi_handle[0],
286 @@ -556,11 +592,10 @@ int bcm2835_audio_set_params(bcm2835_als
287         }
288  
289         /* We are expecting a reply from the videocore */
290 -       if (down_interruptible(&instance->msg_avail_event)) {
291 +       ret = wait_for_completion_interruptible(&instance->msg_avail_comp);
292 +       if (ret) {
293                 LOG_ERR("%s: failed on waiting for event (status=%d)\n",
294                         __func__, success);
295 -
296 -               ret = -1;
297                 goto unlock;
298         }
299  
300 @@ -688,8 +723,8 @@ int bcm2835_audio_close(bcm2835_alsa_str
301  
302         m.type = VC_AUDIO_MSG_TYPE_CLOSE;
303  
304 -       /* Create the message available event */
305 -       sema_init(&instance->msg_avail_event, 0);
306 +       /* Create the message available completion */
307 +       init_completion(&instance->msg_avail_comp);
308  
309         /* Send the message to the videocore */
310         success = vchi_msg_queue(instance->vchi_handle[0],
311 @@ -702,11 +737,11 @@ int bcm2835_audio_close(bcm2835_alsa_str
312                 ret = -1;
313                 goto unlock;
314         }
315 -       if (down_interruptible(&instance->msg_avail_event)) {
316 +
317 +       ret = wait_for_completion_interruptible(&instance->msg_avail_comp);
318 +       if (ret) {
319                 LOG_ERR("%s: failed on waiting for event (status=%d)",
320                         __func__, success);
321 -
322 -               ret = -1;
323                 goto unlock;
324         }
325         if (instance->result != 0) {
326 @@ -732,8 +767,8 @@ unlock:
327         return ret;
328  }
329  
330 -int bcm2835_audio_write(bcm2835_alsa_stream_t * alsa_stream, uint32_t count,
331 -                       void *src)
332 +int bcm2835_audio_write_worker(bcm2835_alsa_stream_t *alsa_stream,
333 +                              uint32_t count, void *src)
334  {
335         VC_AUDIO_MSG_T m;
336         AUDIO_INSTANCE_T *instance = alsa_stream->instance;
337 --- a/sound/arm/bcm2835.c
338 +++ b/sound/arm/bcm2835.c
339 @@ -110,20 +110,20 @@ static int snd_bcm2835_alsa_probe(struct
340  
341         err = snd_bcm2835_create(g_card, pdev, &chip);
342         if (err < 0) {
343 -               printk(KERN_ERR "Failed to create bcm2835 chip\n");
344 +               dev_err(&pdev->dev, "Failed to create bcm2835 chip\n");
345                 goto out_bcm2835_create;
346         }
347  
348         g_chip = chip;
349         err = snd_bcm2835_new_pcm(chip);
350         if (err < 0) {
351 -               printk(KERN_ERR "Failed to create new BCM2835 pcm device\n");
352 +               dev_err(&pdev->dev, "Failed to create new BCM2835 pcm device\n");
353                 goto out_bcm2835_new_pcm;
354         }
355  
356         err = snd_bcm2835_new_ctl(chip);
357         if (err < 0) {
358 -               printk(KERN_ERR "Failed to create new BCM2835 ctl\n");
359 +               dev_err(&pdev->dev, "Failed to create new BCM2835 ctl\n");
360                 goto out_bcm2835_new_ctl;
361         }
362  
363 @@ -139,14 +139,14 @@ add_register_map:
364         if (dev == 0) {
365                 err = snd_card_register(card);
366                 if (err < 0) {
367 -                       printk(KERN_ERR
368 -                              "Failed to register bcm2835 ALSA card \n");
369 +                       dev_err(&pdev->dev,
370 +                               "Failed to register bcm2835 ALSA card \n");
371                         goto out_card_register;
372                 }
373                 platform_set_drvdata(pdev, card);
374 -               printk(KERN_INFO "bcm2835 ALSA card created!\n");
375 +               audio_info("bcm2835 ALSA card created!\n");
376         } else {
377 -               printk(KERN_INFO "bcm2835 ALSA chip created!\n");
378 +               audio_info("bcm2835 ALSA chip created!\n");
379                 platform_set_drvdata(pdev, (void *)dev);
380         }
381  
382 @@ -160,11 +160,11 @@ out_bcm2835_new_pcm:
383  out_bcm2835_create:
384         BUG_ON(!g_card);
385         if (snd_card_free(g_card))
386 -               printk(KERN_ERR "Failed to free Registered alsa card\n");
387 +               dev_err(&pdev->dev, "Failed to free Registered alsa card\n");
388         g_card = NULL;
389  out:
390         dev = SNDRV_CARDS;      /* stop more avail_substreams from being probed */
391 -       printk(KERN_ERR "BCM2835 ALSA Probe failed !!\n");
392 +       dev_err(&pdev->dev, "BCM2835 ALSA Probe failed !!\n");
393         return err;
394  }
395  
396 @@ -326,49 +326,49 @@ static int bcm2835_alsa_device_init(void
397         int err;
398         err = platform_driver_register(&bcm2835_alsa0_driver);
399         if (err) {
400 -               printk("Error registering bcm2835_alsa0_driver %d .\n", err);
401 +               pr_err("Error registering bcm2835_alsa0_driver %d .\n", err);
402                 goto out;
403         }
404  
405         err = platform_driver_register(&bcm2835_alsa1_driver);
406         if (err) {
407 -               printk("Error registering bcm2835_alsa1_driver %d .\n", err);
408 +               pr_err("Error registering bcm2835_alsa0_driver %d .\n", err);
409                 goto unregister_0;
410         }
411  
412         err = platform_driver_register(&bcm2835_alsa2_driver);
413         if (err) {
414 -               printk("Error registering bcm2835_alsa2_driver %d .\n", err);
415 +               pr_err("Error registering bcm2835_alsa0_driver %d .\n", err);
416                 goto unregister_1;
417         }
418  
419         err = platform_driver_register(&bcm2835_alsa3_driver);
420         if (err) {
421 -               printk("Error registering bcm2835_alsa3_driver %d .\n", err);
422 +               pr_err("Error registering bcm2835_alsa0_driver %d .\n", err);
423                 goto unregister_2;
424         }
425  
426         err = platform_driver_register(&bcm2835_alsa4_driver);
427         if (err) {
428 -               printk("Error registering bcm2835_alsa4_driver %d .\n", err);
429 +               pr_err("Error registering bcm2835_alsa0_driver %d .\n", err);
430                 goto unregister_3;
431         }
432  
433         err = platform_driver_register(&bcm2835_alsa5_driver);
434         if (err) {
435 -               printk("Error registering bcm2835_alsa5_driver %d .\n", err);
436 +               pr_err("Error registering bcm2835_alsa0_driver %d .\n", err);
437                 goto unregister_4;
438         }
439  
440         err = platform_driver_register(&bcm2835_alsa6_driver);
441         if (err) {
442 -               printk("Error registering bcm2835_alsa6_driver %d .\n", err);
443 +               pr_err("Error registering bcm2835_alsa0_driver %d .\n", err);
444                 goto unregister_5;
445         }
446  
447         err = platform_driver_register(&bcm2835_alsa7_driver);
448         if (err) {
449 -               printk("Error registering bcm2835_alsa7_driver %d .\n", err);
450 +               pr_err("Error registering bcm2835_alsa0_driver %d .\n", err);
451                 goto unregister_6;
452         }
453  
454 --- a/sound/arm/bcm2835.h
455 +++ b/sound/arm/bcm2835.h
456 @@ -23,6 +23,7 @@
457  #include <sound/initval.h>
458  #include <sound/pcm.h>
459  #include <sound/pcm_params.h>
460 +#include <sound/pcm-indirect.h>
461  #include <linux/workqueue.h>
462  
463  /*
464 @@ -110,6 +111,7 @@ typedef struct bcm2835_chip {
465  typedef struct bcm2835_alsa_stream {
466         bcm2835_chip_t *chip;
467         struct snd_pcm_substream *substream;
468 +       struct snd_pcm_indirect pcm_indirect;
469  
470         struct semaphore buffers_update_sem;
471         struct semaphore control_sem;