kernel: refresh patches
[oweals/openwrt.git] / target / linux / brcm2708 / patches-3.14 / 0032-snd-bcm2835-Add-support-for-spdif-hdmi-passthrough.patch
1 From 2172c6578ef13acb8fcf5cac643cb1ee8e824117 Mon Sep 17 00:00:00 2001
2 From: Julian Scheel <julian@jusst.de>
3 Date: Wed, 19 Feb 2014 16:06:59 +0100
4 Subject: [PATCH 32/54] snd-bcm2835: Add support for spdif/hdmi passthrough
5
6 This adds a dedicated subdevice which can be used for passthrough of non-audio
7 formats (ie encoded a52) through the hdmi audio link. In addition to this
8 driver extension an appropriate card config is required to make alsa-lib
9 support the AES parameters for this device.
10 ---
11  sound/arm/bcm2835-ctl.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++
12  sound/arm/bcm2835-pcm.c | 128 +++++++++++++++++++++++++++++++++++++++++-------
13  sound/arm/bcm2835.c     |   9 +++-
14  sound/arm/bcm2835.h     |   9 ++++
15  4 files changed, 250 insertions(+), 19 deletions(-)
16
17 --- a/sound/arm/bcm2835-ctl.c
18 +++ b/sound/arm/bcm2835-ctl.c
19 @@ -30,6 +30,7 @@
20  #include <sound/rawmidi.h>
21  #include <sound/initval.h>
22  #include <sound/tlv.h>
23 +#include <sound/asoundef.h>
24  
25  #include "bcm2835.h"
26  
27 @@ -183,6 +184,122 @@ static struct snd_kcontrol_new snd_bcm28
28         },
29  };
30  
31 +static int snd_bcm2835_spdif_default_info(struct snd_kcontrol *kcontrol,
32 +                                         struct snd_ctl_elem_info *uinfo)
33 +{
34 +       uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
35 +       uinfo->count = 1;
36 +       return 0;
37 +}
38 +
39 +static int snd_bcm2835_spdif_default_get(struct snd_kcontrol *kcontrol,
40 +                                        struct snd_ctl_elem_value *ucontrol)
41 +{
42 +       struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
43 +       int i;
44 +
45 +       for (i = 0; i < 4; i++)
46 +               ucontrol->value.iec958.status[i] =
47 +                       (chip->spdif_status >> (i * 8)) && 0xff;
48 +
49 +       return 0;
50 +}
51 +
52 +static int snd_bcm2835_spdif_default_put(struct snd_kcontrol *kcontrol,
53 +                                        struct snd_ctl_elem_value *ucontrol)
54 +{
55 +       struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
56 +       unsigned int val = 0;
57 +       int i, change;
58 +
59 +       for (i = 0; i < 4; i++)
60 +               val |= (unsigned int)ucontrol->value.iec958.status[i] << (i * 8);
61 +
62 +       change = val != chip->spdif_status;
63 +       chip->spdif_status = val;
64 +
65 +       return change;
66 +}
67 +
68 +static int snd_bcm2835_spdif_mask_info(struct snd_kcontrol *kcontrol,
69 +                                      struct snd_ctl_elem_info *uinfo)
70 +{
71 +       uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
72 +       uinfo->count = 1;
73 +       return 0;
74 +}
75 +
76 +static int snd_bcm2835_spdif_mask_get(struct snd_kcontrol *kcontrol,
77 +                                     struct snd_ctl_elem_value *ucontrol)
78 +{
79 +       /* bcm2835 supports only consumer mode and sets all other format flags
80 +        * automatically. So the only thing left is signalling non-audio
81 +        * content */
82 +       ucontrol->value.iec958.status[0] = IEC958_AES0_NONAUDIO;
83 +       return 0;
84 +}
85 +
86 +static int snd_bcm2835_spdif_stream_info(struct snd_kcontrol *kcontrol,
87 +                                        struct snd_ctl_elem_info *uinfo)
88 +{
89 +       uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
90 +       uinfo->count = 1;
91 +       return 0;
92 +}
93 +
94 +static int snd_bcm2835_spdif_stream_get(struct snd_kcontrol *kcontrol,
95 +                                       struct snd_ctl_elem_value *ucontrol)
96 +{
97 +       struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
98 +       int i;
99 +
100 +       for (i = 0; i < 4; i++)
101 +               ucontrol->value.iec958.status[i] =
102 +                       (chip->spdif_status >> (i * 8)) & 0xff;
103 +       return 0;
104 +}
105 +
106 +static int snd_bcm2835_spdif_stream_put(struct snd_kcontrol *kcontrol,
107 +                                       struct snd_ctl_elem_value *ucontrol)
108 +{
109 +       struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
110 +       unsigned int val = 0;
111 +       int i, change;
112 +
113 +       for (i = 0; i < 4; i++)
114 +               val |= (unsigned int)ucontrol->value.iec958.status[i] << (i * 8);
115 +       change = val != chip->spdif_status;
116 +       chip->spdif_status = val;
117 +
118 +       return change;
119 +}
120 +
121 +static struct snd_kcontrol_new snd_bcm2835_spdif[] = {
122 +       {
123 +               .iface = SNDRV_CTL_ELEM_IFACE_PCM,
124 +               .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
125 +               .info = snd_bcm2835_spdif_default_info,
126 +               .get = snd_bcm2835_spdif_default_get,
127 +               .put = snd_bcm2835_spdif_default_put
128 +       },
129 +       {
130 +               .access = SNDRV_CTL_ELEM_ACCESS_READ,
131 +               .iface = SNDRV_CTL_ELEM_IFACE_PCM,
132 +               .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, CON_MASK),
133 +               .info = snd_bcm2835_spdif_mask_info,
134 +               .get = snd_bcm2835_spdif_mask_get,
135 +       },
136 +       {
137 +               .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
138 +                       SNDRV_CTL_ELEM_ACCESS_INACTIVE,
139 +               .iface = SNDRV_CTL_ELEM_IFACE_PCM,
140 +               .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PCM_STREAM),
141 +               .info = snd_bcm2835_spdif_stream_info,
142 +               .get = snd_bcm2835_spdif_stream_get,
143 +               .put = snd_bcm2835_spdif_stream_put,
144 +       },
145 +};
146 +
147  int snd_bcm2835_new_ctl(bcm2835_chip_t * chip)
148  {
149         int err;
150 @@ -196,5 +313,11 @@ int snd_bcm2835_new_ctl(bcm2835_chip_t *
151                 if (err < 0)
152                         return err;
153         }
154 +       for (idx = 0; idx < ARRAY_SIZE(snd_bcm2835_spdif); idx++) {
155 +               err = snd_ctl_add(chip->card,
156 +                               snd_ctl_new1(&snd_bcm2835_spdif[idx], chip));
157 +               if (err < 0)
158 +                       return err;
159 +       }
160         return 0;
161  }
162 --- a/sound/arm/bcm2835-pcm.c
163 +++ b/sound/arm/bcm2835-pcm.c
164 @@ -15,6 +15,8 @@
165  #include <linux/interrupt.h>
166  #include <linux/slab.h>
167  
168 +#include <sound/asoundef.h>
169 +
170  #include "bcm2835.h"
171  
172  /* hardware definition */
173 @@ -34,6 +36,23 @@ static struct snd_pcm_hardware snd_bcm28
174         .periods_max = 128,
175  };
176  
177 +static struct snd_pcm_hardware snd_bcm2835_playback_spdif_hw = {
178 +       .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
179 +                SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),
180 +       .formats = SNDRV_PCM_FMTBIT_S16_LE,
181 +       .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_44100 |
182 +               SNDRV_PCM_RATE_48000,
183 +       .rate_min = 44100,
184 +       .rate_max = 48000,
185 +       .channels_min = 2,
186 +       .channels_max = 2,
187 +       .buffer_bytes_max = 128 * 1024,
188 +       .period_bytes_min =   1 * 1024,
189 +       .period_bytes_max = 128 * 1024,
190 +       .periods_min = 1,
191 +       .periods_max = 128,
192 +};
193 +
194  static void snd_bcm2835_playback_free(struct snd_pcm_runtime *runtime)
195  {
196         audio_info("Freeing up alsa stream here ..\n");
197 @@ -89,7 +108,8 @@ static irqreturn_t bcm2835_playback_fifo
198  }
199  
200  /* open callback */
201 -static int snd_bcm2835_playback_open(struct snd_pcm_substream *substream)
202 +static int snd_bcm2835_playback_open_generic(
203 +               struct snd_pcm_substream *substream, int spdif)
204  {
205         bcm2835_chip_t *chip = snd_pcm_substream_chip(substream);
206         struct snd_pcm_runtime *runtime = substream->runtime;
207 @@ -102,6 +122,11 @@ static int snd_bcm2835_playback_open(str
208         audio_info("Alsa open (%d)\n", substream->number);
209         idx = substream->number;
210  
211 +       if (spdif && chip->opened != 0)
212 +               return -EBUSY;
213 +       else if (!spdif && (chip->opened & (1 << idx)))
214 +               return -EBUSY;
215 +
216         if (idx > MAX_SUBSTREAMS) {
217                 audio_error
218                     ("substream(%d) device doesn't exist max(%d) substreams allowed\n",
219 @@ -143,13 +168,20 @@ static int snd_bcm2835_playback_open(str
220         }
221         runtime->private_data = alsa_stream;
222         runtime->private_free = snd_bcm2835_playback_free;
223 -       runtime->hw = snd_bcm2835_playback_hw;
224 +       if (spdif) {
225 +               runtime->hw = snd_bcm2835_playback_spdif_hw;
226 +       } else {
227 +               /* clear spdif status, as we are not in spdif mode */
228 +               chip->spdif_status = 0;
229 +               runtime->hw = snd_bcm2835_playback_hw;
230 +       }
231         /* minimum 16 bytes alignment (for vchiq bulk transfers) */
232         snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
233                                    16);
234  
235         chip->alsa_stream[idx] = alsa_stream;
236  
237 +       chip->opened |= (1 << idx);
238         alsa_stream->open = 1;
239         alsa_stream->draining = 1;
240  
241 @@ -159,6 +191,16 @@ out:
242         return err;
243  }
244  
245 +static int snd_bcm2835_playback_open(struct snd_pcm_substream *substream)
246 +{
247 +       return snd_bcm2835_playback_open_generic(substream, 0);
248 +}
249 +
250 +static int snd_bcm2835_playback_spdif_open(struct snd_pcm_substream *substream)
251 +{
252 +       return snd_bcm2835_playback_open_generic(substream, 1);
253 +}
254 +
255  /* close callback */
256  static int snd_bcm2835_playback_close(struct snd_pcm_substream *substream)
257  {
258 @@ -166,6 +208,7 @@ static int snd_bcm2835_playback_close(st
259  
260         struct snd_pcm_runtime *runtime = substream->runtime;
261         bcm2835_alsa_stream_t *alsa_stream = runtime->private_data;
262 +       bcm2835_chip_t *chip = snd_pcm_substream_chip(substream);
263  
264         audio_info(" .. IN\n");
265         audio_info("Alsa close\n");
266 @@ -196,6 +239,8 @@ static int snd_bcm2835_playback_close(st
267          * runtime->private_free callback we registered in *_open above
268          */
269  
270 +       chip->opened &= ~(1 << substream->number);
271 +
272         audio_info(" .. OUT\n");
273  
274         return 0;
275 @@ -205,10 +250,9 @@ static int snd_bcm2835_playback_close(st
276  static int snd_bcm2835_pcm_hw_params(struct snd_pcm_substream *substream,
277                                      struct snd_pcm_hw_params *params)
278  {
279 -       int err;
280         struct snd_pcm_runtime *runtime = substream->runtime;
281 -       bcm2835_alsa_stream_t *alsa_stream =
282 -           (bcm2835_alsa_stream_t *) runtime->private_data;
283 +       bcm2835_alsa_stream_t *alsa_stream = runtime->private_data;
284 +       int err;
285  
286         audio_info(" .. IN\n");
287  
288 @@ -219,19 +263,9 @@ static int snd_bcm2835_pcm_hw_params(str
289                 return err;
290         }
291  
292 -       err = bcm2835_audio_set_params(alsa_stream, params_channels(params),
293 -                                      params_rate(params),
294 -                                      snd_pcm_format_width(params_format
295 -                                                           (params)));
296 -       if (err < 0) {
297 -               audio_error(" error setting hw params\n");
298 -       }
299 -
300 -       bcm2835_audio_setup(alsa_stream);
301 -
302 -       /* in preparation of the stream, set the controls (volume level) of the stream */
303 -       bcm2835_audio_set_ctls(alsa_stream->chip);
304 -
305 +       alsa_stream->channels = params_channels(params);
306 +       alsa_stream->params_rate = params_rate(params);
307 +       alsa_stream->pcm_format_width = snd_pcm_format_width(params_format (params));
308         audio_info(" .. OUT\n");
309  
310         return err;
311 @@ -247,11 +281,35 @@ static int snd_bcm2835_pcm_hw_free(struc
312  /* prepare callback */
313  static int snd_bcm2835_pcm_prepare(struct snd_pcm_substream *substream)
314  {
315 +       bcm2835_chip_t *chip = snd_pcm_substream_chip(substream);
316         struct snd_pcm_runtime *runtime = substream->runtime;
317         bcm2835_alsa_stream_t *alsa_stream = runtime->private_data;
318 +       int channels;
319 +       int err;
320  
321         audio_info(" .. IN\n");
322  
323 +       /* notify the vchiq that it should enter spdif passthrough mode by
324 +        * setting channels=0 (see
325 +        * https://github.com/raspberrypi/linux/issues/528) */
326 +       if (chip->spdif_status & IEC958_AES0_NONAUDIO)
327 +               channels = 0;
328 +       else
329 +               channels = alsa_stream->channels;
330 +
331 +       err = bcm2835_audio_set_params(alsa_stream, channels,
332 +                                      alsa_stream->params_rate,
333 +                                      alsa_stream->pcm_format_width);
334 +       if (err < 0) {
335 +               audio_error(" error setting hw params\n");
336 +       }
337 +
338 +       bcm2835_audio_setup(alsa_stream);
339 +
340 +       /* in preparation of the stream, set the controls (volume level) of the stream */
341 +       bcm2835_audio_set_ctls(alsa_stream->chip);
342 +
343 +
344         memset(&alsa_stream->pcm_indirect, 0, sizeof(alsa_stream->pcm_indirect));
345  
346         alsa_stream->pcm_indirect.hw_buffer_size =
347 @@ -392,6 +450,18 @@ static struct snd_pcm_ops snd_bcm2835_pl
348         .ack = snd_bcm2835_pcm_ack,
349  };
350  
351 +static struct snd_pcm_ops snd_bcm2835_playback_spdif_ops = {
352 +       .open = snd_bcm2835_playback_spdif_open,
353 +       .close = snd_bcm2835_playback_close,
354 +       .ioctl = snd_bcm2835_pcm_lib_ioctl,
355 +       .hw_params = snd_bcm2835_pcm_hw_params,
356 +       .hw_free = snd_bcm2835_pcm_hw_free,
357 +       .prepare = snd_bcm2835_pcm_prepare,
358 +       .trigger = snd_bcm2835_pcm_trigger,
359 +       .pointer = snd_bcm2835_pcm_pointer,
360 +       .ack = snd_bcm2835_pcm_ack,
361 +};
362 +
363  /* create a pcm device */
364  int snd_bcm2835_new_pcm(bcm2835_chip_t * chip)
365  {
366 @@ -424,3 +494,25 @@ int snd_bcm2835_new_pcm(bcm2835_chip_t *
367  
368         return 0;
369  }
370 +
371 +int snd_bcm2835_new_spdif_pcm(bcm2835_chip_t * chip)
372 +{
373 +       struct snd_pcm *pcm;
374 +       int err;
375 +
376 +       err = snd_pcm_new(chip->card, "bcm2835 ALSA", 1, 1, 0, &pcm);
377 +       if (err < 0)
378 +               return err;
379 +
380 +       pcm->private_data = chip;
381 +       strcpy(pcm->name, "bcm2835 IEC958/HDMI");
382 +       chip->pcm_spdif = pcm;
383 +       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
384 +                       &snd_bcm2835_playback_spdif_ops);
385 +
386 +       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
387 +                                             snd_dma_continuous_data (GFP_KERNEL),
388 +                                             64 * 1024, 64 * 1024);
389 +
390 +       return 0;
391 +}
392 --- a/sound/arm/bcm2835.c
393 +++ b/sound/arm/bcm2835.c
394 @@ -104,7 +104,7 @@ static int snd_bcm2835_alsa_probe(struct
395                 goto out;
396  
397         snd_card_set_dev(g_card, &pdev->dev);
398 -       strcpy(g_card->driver, "BRCM bcm2835 ALSA Driver");
399 +       strcpy(g_card->driver, "bcm2835");
400         strcpy(g_card->shortname, "bcm2835 ALSA");
401         sprintf(g_card->longname, "%s", g_card->shortname);
402  
403 @@ -121,6 +121,12 @@ static int snd_bcm2835_alsa_probe(struct
404                 goto out_bcm2835_new_pcm;
405         }
406  
407 +       err = snd_bcm2835_new_spdif_pcm(chip);
408 +       if (err < 0) {
409 +               dev_err(&pdev->dev, "Failed to create new BCM2835 spdif pcm device\n");
410 +               goto out_bcm2835_new_spdif;
411 +       }
412 +
413         err = snd_bcm2835_new_ctl(chip);
414         if (err < 0) {
415                 dev_err(&pdev->dev, "Failed to create new BCM2835 ctl\n");
416 @@ -156,6 +162,7 @@ add_register_map:
417  
418  out_card_register:
419  out_bcm2835_new_ctl:
420 +out_bcm2835_new_spdif:
421  out_bcm2835_new_pcm:
422  out_bcm2835_create:
423         BUG_ON(!g_card);
424 --- a/sound/arm/bcm2835.h
425 +++ b/sound/arm/bcm2835.h
426 @@ -97,6 +97,7 @@ typedef enum {
427  typedef struct bcm2835_chip {
428         struct snd_card *card;
429         struct snd_pcm *pcm;
430 +       struct snd_pcm *pcm_spdif;
431         /* Bitmat for valid reg_base and irq numbers */
432         uint32_t avail_substreams;
433         struct platform_device *pdev[MAX_SUBSTREAMS];
434 @@ -106,6 +107,9 @@ typedef struct bcm2835_chip {
435         int old_volume; /* stores the volume value whist muted */
436         int dest;
437         int mute;
438 +
439 +       unsigned int opened;
440 +       unsigned int spdif_status;
441  } bcm2835_chip_t;
442  
443  typedef struct bcm2835_alsa_stream {
444 @@ -123,6 +127,10 @@ typedef struct bcm2835_alsa_stream {
445         int running;
446         int draining;
447  
448 +       int channels;
449 +       int params_rate;
450 +       int pcm_format_width;
451 +
452         unsigned int pos;
453         unsigned int buffer_size;
454         unsigned int period_size;
455 @@ -138,6 +146,7 @@ typedef struct bcm2835_alsa_stream {
456  
457  int snd_bcm2835_new_ctl(bcm2835_chip_t * chip);
458  int snd_bcm2835_new_pcm(bcm2835_chip_t * chip);
459 +int snd_bcm2835_new_spdif_pcm(bcm2835_chip_t * chip);
460  
461  int bcm2835_audio_open(bcm2835_alsa_stream_t * alsa_stream);
462  int bcm2835_audio_close(bcm2835_alsa_stream_t * alsa_stream);