lantiq: fix broadcasts and vlans in two iface mode
[oweals/openwrt.git] / target / linux / brcm2708 / patches-4.9 / 0117-pisound-improvements.patch
1 From 8ed8e29b19dba95a7a6c2364c2bb32d926601713 Mon Sep 17 00:00:00 2001
2 From: Giedrius Trainavicius <giedrius@blokas.io>
3 Date: Thu, 5 Jan 2017 02:38:16 +0200
4 Subject: [PATCH] pisound improvements:
5
6 * Added a writable sysfs object to enable scripts / user space software
7 to blink MIDI activity LEDs for variable duration.
8 * Improved hw_param constraints setting.
9 * Added compatibility with S16_LE sample format.
10 * Exposed some simple placeholder volume controls, so the card appears
11 in volumealsa widget.
12
13 Signed-off-by: Giedrius Trainavicius <giedrius@blokas.io>
14 ---
15  sound/soc/bcm/pisound.c | 175 ++++++++++++++++++++++++++++++++++++++++++------
16  1 file changed, 154 insertions(+), 21 deletions(-)
17
18 --- a/sound/soc/bcm/pisound.c
19 +++ b/sound/soc/bcm/pisound.c
20 @@ -36,6 +36,7 @@
21  #include <sound/jack.h>
22  #include <sound/rawmidi.h>
23  #include <sound/asequencer.h>
24 +#include <sound/control.h>
25  
26  static int pisnd_spi_init(struct device *dev);
27  static void pisnd_spi_uninit(void);
28 @@ -214,6 +215,9 @@ static char g_serial_num[11];
29  static char g_id[25];
30  static char g_version[5];
31  
32 +static uint8_t g_ledFlashDuration;
33 +static bool    g_ledFlashDurationChanged;
34 +
35  DEFINE_KFIFO(spi_fifo_in,  uint8_t, FIFO_SIZE);
36  DEFINE_KFIFO(spi_fifo_out, uint8_t, FIFO_SIZE);
37  
38 @@ -396,8 +400,13 @@ static void pisnd_work_handler(struct wo
39                         val = 0;
40                         tx = 0;
41  
42 -                       if (kfifo_get(&spi_fifo_out, &val))
43 +                       if (g_ledFlashDurationChanged) {
44 +                               tx = 0xf000 | g_ledFlashDuration;
45 +                               g_ledFlashDuration = 0;
46 +                               g_ledFlashDurationChanged = false;
47 +                       } else if (kfifo_get(&spi_fifo_out, &val)) {
48                                 tx = 0x0f00 | val;
49 +                       }
50  
51                         rx = spi_transfer16(tx);
52  
53 @@ -410,6 +419,7 @@ static void pisnd_work_handler(struct wo
54                 } while (rx != 0
55                         || !kfifo_is_empty(&spi_fifo_out)
56                         || pisnd_spi_has_more()
57 +                       || g_ledFlashDurationChanged
58                         );
59  
60                 if (!kfifo_is_empty(&spi_fifo_in) && g_recvCallback)
61 @@ -569,7 +579,7 @@ static int pisnd_spi_init(struct device
62         }
63  
64         /* Flash the LEDs. */
65 -       spi_transfer16(0xf000);
66 +       spi_transfer16(0xf008);
67  
68         ret = pisnd_spi_gpio_irq_init(dev);
69         if (ret < 0) {
70 @@ -610,6 +620,14 @@ static void pisnd_spi_uninit(void)
71         pisnd_spi_gpio_uninit();
72  }
73  
74 +static void pisnd_spi_flash_leds(uint8_t duration)
75 +{
76 +       g_ledFlashDuration = duration;
77 +       g_ledFlashDurationChanged = true;
78 +       printd("schedule from spi_flash_leds\n");
79 +       pisnd_schedule_process(TASK_PROCESS);
80 +}
81 +
82  static void pisnd_spi_send(uint8_t val)
83  {
84         kfifo_put(&spi_fifo_out, val);
85 @@ -658,6 +676,83 @@ static const struct of_device_id pisound
86         {},
87  };
88  
89 +enum {
90 +       SWITCH = 0,
91 +       VOLUME = 1,
92 +};
93 +
94 +static int pisnd_ctl_info(struct snd_kcontrol *kcontrol,
95 +       struct snd_ctl_elem_info *uinfo)
96 +{
97 +       if (kcontrol->private_value == SWITCH) {
98 +               uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
99 +               uinfo->count = 1;
100 +               uinfo->value.integer.min = 0;
101 +               uinfo->value.integer.max = 1;
102 +               return 0;
103 +       } else if (kcontrol->private_value == VOLUME) {
104 +               uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
105 +               uinfo->count = 1;
106 +               uinfo->value.integer.min = 0;
107 +               uinfo->value.integer.max = 100;
108 +               return 0;
109 +       }
110 +       return -EINVAL;
111 +}
112 +
113 +static int pisnd_ctl_get(struct snd_kcontrol *kcontrol,
114 +       struct snd_ctl_elem_value *ucontrol)
115 +{
116 +       if (kcontrol->private_value == SWITCH) {
117 +               ucontrol->value.integer.value[0] = 1;
118 +               return 0;
119 +       } else if (kcontrol->private_value == VOLUME) {
120 +               ucontrol->value.integer.value[0] = 100;
121 +               return 0;
122 +       }
123 +
124 +       return -EINVAL;
125 +}
126 +
127 +static struct snd_kcontrol_new pisnd_ctl[] = {
128 +       {
129 +               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
130 +               .name = "PCM Playback Switch",
131 +               .index = 0,
132 +               .private_value = SWITCH,
133 +               .access = SNDRV_CTL_ELEM_ACCESS_READ,
134 +               .info = pisnd_ctl_info,
135 +               .get = pisnd_ctl_get,
136 +       },
137 +       {
138 +               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
139 +               .name = "PCM Playback Volume",
140 +               .index = 0,
141 +               .private_value = VOLUME,
142 +               .access = SNDRV_CTL_ELEM_ACCESS_READ,
143 +               .info = pisnd_ctl_info,
144 +               .get = pisnd_ctl_get,
145 +       },
146 +};
147 +
148 +static int pisnd_ctl_init(struct snd_card *card)
149 +{
150 +       int err, i;
151 +
152 +       for (i = 0; i < ARRAY_SIZE(pisnd_ctl); ++i) {
153 +               err = snd_ctl_add(card, snd_ctl_new1(&pisnd_ctl[i], NULL));
154 +               if (err < 0)
155 +                       return err;
156 +       }
157 +
158 +       return 0;
159 +}
160 +
161 +static int pisnd_ctl_uninit(void)
162 +{
163 +       return 0;
164 +}
165 +
166  static struct gpio_desc *osr0, *osr1, *osr2;
167  static struct gpio_desc *reset;
168  static struct gpio_desc *button;
169 @@ -667,6 +762,14 @@ static int pisnd_hw_params(
170         struct snd_pcm_hw_params *params
171         )
172  {
173 +       struct snd_soc_pcm_runtime *rtd = substream->private_data;
174 +       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
175 +
176 +       /* pisound runs on fixed 32 clock counts per channel,
177 +        * as generated by the master ADC.
178 +        */
179 +       snd_soc_dai_set_bclk_ratio(cpu_dai, 32*2);
180 +
181         printd("rate   = %d\n", params_rate(params));
182         printd("ch     = %d\n", params_channels(params));
183         printd("bits   = %u\n",
184 @@ -711,16 +814,6 @@ static struct snd_pcm_hw_constraint_list
185         .mask = 0,
186  };
187  
188 -static unsigned int sample_bits[] = {
189 -       24, 32
190 -};
191 -
192 -static struct snd_pcm_hw_constraint_list constraints_sample_bits = {
193 -       .count = ARRAY_SIZE(sample_bits),
194 -       .list = sample_bits,
195 -       .mask = 0,
196 -};
197 -
198  static int pisnd_startup(struct snd_pcm_substream *substream)
199  {
200         int err = snd_pcm_hw_constraint_list(
201 @@ -733,11 +826,21 @@ static int pisnd_startup(struct snd_pcm_
202         if (err < 0)
203                 return err;
204  
205 -       err = snd_pcm_hw_constraint_list(
206 +       err = snd_pcm_hw_constraint_single(
207                 substream->runtime,
208 -               0,
209 -               SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
210 -               &constraints_sample_bits
211 +               SNDRV_PCM_HW_PARAM_CHANNELS,
212 +               2
213 +               );
214 +
215 +       if (err < 0)
216 +               return err;
217 +
218 +       err = snd_pcm_hw_constraint_mask64(
219 +               substream->runtime,
220 +               SNDRV_PCM_HW_PARAM_FORMAT,
221 +               SNDRV_PCM_FMTBIT_S16_LE |
222 +               SNDRV_PCM_FMTBIT_S24_LE |
223 +               SNDRV_PCM_FMTBIT_S32_LE
224                 );
225  
226         if (err < 0)
227 @@ -771,14 +874,23 @@ static int pisnd_card_probe(struct snd_s
228  {
229         int err = pisnd_midi_init(card->snd_card);
230  
231 -       if (err < 0)
232 +       if (err < 0) {
233                 printe("pisnd_midi_init failed: %d\n", err);
234 +               return err;
235 +       }
236  
237 -       return err;
238 +       err = pisnd_ctl_init(card->snd_card);
239 +       if (err < 0) {
240 +               printe("pisnd_ctl_init failed: %d\n", err);
241 +               return err;
242 +       }
243 +
244 +       return 0;
245  }
246  
247  static int pisnd_card_remove(struct snd_soc_card *card)
248  {
249 +       pisnd_ctl_uninit();
250         pisnd_midi_uninit();
251         return 0;
252  }
253 @@ -870,17 +982,38 @@ static ssize_t pisnd_version_show(
254         return sprintf(buf, "%s\n", pisnd_spi_get_version());
255  }
256  
257 +static ssize_t pisnd_led_store(
258 +       struct kobject *kobj,
259 +       struct kobj_attribute *attr,
260 +       const char *buf,
261 +       size_t length
262 +       )
263 +{
264 +       uint32_t timeout;
265 +       int err;
266 +
267 +       err = kstrtou32(buf, 10, &timeout);
268 +
269 +       if (err == 0 && timeout <= 255)
270 +               pisnd_spi_flash_leds(timeout);
271 +
272 +       return length;
273 +}
274 +
275  static struct kobj_attribute pisnd_serial_attribute =
276 -       __ATTR(serial, 0644, pisnd_serial_show, NULL);
277 +       __ATTR(serial, 0444, pisnd_serial_show, NULL);
278  static struct kobj_attribute pisnd_id_attribute =
279 -       __ATTR(id, 0644, pisnd_id_show, NULL);
280 +       __ATTR(id, 0444, pisnd_id_show, NULL);
281  static struct kobj_attribute pisnd_version_attribute =
282 -       __ATTR(version, 0644, pisnd_version_show, NULL);
283 +       __ATTR(version, 0444, pisnd_version_show, NULL);
284 +static struct kobj_attribute pisnd_led_attribute =
285 +       __ATTR(led, 0644, NULL, pisnd_led_store);
286  
287  static struct attribute *attrs[] = {
288         &pisnd_serial_attribute.attr,
289         &pisnd_id_attribute.attr,
290         &pisnd_version_attribute.attr,
291 +       &pisnd_led_attribute.attr,
292         NULL
293  };
294