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