xref: /openbmc/linux/sound/core/control_led.c (revision 1519c84c)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *  LED state routines for driver control interface
4  *  Copyright (c) 2021 by Jaroslav Kysela <perex@perex.cz>
5  */
6 
7 #include <linux/slab.h>
8 #include <linux/module.h>
9 #include <linux/leds.h>
10 #include <sound/core.h>
11 #include <sound/control.h>
12 
13 MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
14 MODULE_DESCRIPTION("ALSA control interface to LED trigger code.");
15 MODULE_LICENSE("GPL");
16 
17 #define MAX_LED (((SNDRV_CTL_ELEM_ACCESS_MIC_LED - SNDRV_CTL_ELEM_ACCESS_SPK_LED) \
18 			>> SNDRV_CTL_ELEM_ACCESS_LED_SHIFT) + 1)
19 
20 enum snd_ctl_led_mode {
21 	 MODE_FOLLOW_MUTE = 0,
22 	 MODE_FOLLOW_ROUTE,
23 	 MODE_OFF,
24 	 MODE_ON,
25 };
26 
27 struct snd_ctl_led_card {
28 	struct device dev;
29 	int number;
30 	struct snd_ctl_led *led;
31 };
32 
33 struct snd_ctl_led {
34 	struct device dev;
35 	struct list_head controls;
36 	const char *name;
37 	unsigned int group;
38 	enum led_audio trigger_type;
39 	enum snd_ctl_led_mode mode;
40 	struct snd_ctl_led_card *cards[SNDRV_CARDS];
41 };
42 
43 struct snd_ctl_led_ctl {
44 	struct list_head list;
45 	struct snd_card *card;
46 	unsigned int access;
47 	struct snd_kcontrol *kctl;
48 	unsigned int index_offset;
49 };
50 
51 static DEFINE_MUTEX(snd_ctl_led_mutex);
52 static bool snd_ctl_led_card_valid[SNDRV_CARDS];
53 static struct snd_ctl_led snd_ctl_leds[MAX_LED] = {
54 	{
55 		.name = "speaker",
56 		.group = (SNDRV_CTL_ELEM_ACCESS_SPK_LED >> SNDRV_CTL_ELEM_ACCESS_LED_SHIFT) - 1,
57 		.trigger_type = LED_AUDIO_MUTE,
58 		.mode = MODE_FOLLOW_MUTE,
59 	},
60 	{
61 		.name = "mic",
62 		.group = (SNDRV_CTL_ELEM_ACCESS_MIC_LED >> SNDRV_CTL_ELEM_ACCESS_LED_SHIFT) - 1,
63 		.trigger_type = LED_AUDIO_MICMUTE,
64 		.mode = MODE_FOLLOW_MUTE,
65 	},
66 };
67 
68 static void snd_ctl_led_sysfs_add(struct snd_card *card);
69 static void snd_ctl_led_sysfs_remove(struct snd_card *card);
70 
71 #define UPDATE_ROUTE(route, cb) \
72 	do { \
73 		int route2 = (cb); \
74 		if (route2 >= 0) \
75 			route = route < 0 ? route2 : (route | route2); \
76 	} while (0)
77 
78 static inline unsigned int access_to_group(unsigned int access)
79 {
80 	return ((access & SNDRV_CTL_ELEM_ACCESS_LED_MASK) >>
81 				SNDRV_CTL_ELEM_ACCESS_LED_SHIFT) - 1;
82 }
83 
84 static inline unsigned int group_to_access(unsigned int group)
85 {
86 	return (group + 1) << SNDRV_CTL_ELEM_ACCESS_LED_SHIFT;
87 }
88 
89 static struct snd_ctl_led *snd_ctl_led_get_by_access(unsigned int access)
90 {
91 	unsigned int group = access_to_group(access);
92 	if (group >= MAX_LED)
93 		return NULL;
94 	return &snd_ctl_leds[group];
95 }
96 
97 /*
98  * A note for callers:
99  *   The two static variables info and value are protected using snd_ctl_led_mutex.
100  */
101 static int snd_ctl_led_get(struct snd_ctl_led_ctl *lctl)
102 {
103 	static struct snd_ctl_elem_info info;
104 	static struct snd_ctl_elem_value value;
105 	struct snd_kcontrol *kctl = lctl->kctl;
106 	unsigned int i;
107 	int result;
108 
109 	memset(&info, 0, sizeof(info));
110 	info.id = kctl->id;
111 	info.id.index += lctl->index_offset;
112 	info.id.numid += lctl->index_offset;
113 	result = kctl->info(kctl, &info);
114 	if (result < 0)
115 		return -1;
116 	memset(&value, 0, sizeof(value));
117 	value.id = info.id;
118 	result = kctl->get(kctl, &value);
119 	if (result < 0)
120 		return -1;
121 	if (info.type == SNDRV_CTL_ELEM_TYPE_BOOLEAN ||
122 	    info.type == SNDRV_CTL_ELEM_TYPE_INTEGER) {
123 		for (i = 0; i < info.count; i++)
124 			if (value.value.integer.value[i] != info.value.integer.min)
125 				return 1;
126 	} else if (info.type == SNDRV_CTL_ELEM_TYPE_INTEGER64) {
127 		for (i = 0; i < info.count; i++)
128 			if (value.value.integer64.value[i] != info.value.integer64.min)
129 				return 1;
130 	}
131 	return 0;
132 }
133 
134 static void snd_ctl_led_set_state(struct snd_card *card, unsigned int access,
135 				  struct snd_kcontrol *kctl, unsigned int ioff)
136 {
137 	struct snd_ctl_led *led;
138 	struct snd_ctl_led_ctl *lctl;
139 	int route;
140 	bool found;
141 
142 	led = snd_ctl_led_get_by_access(access);
143 	if (!led)
144 		return;
145 	route = -1;
146 	found = false;
147 	mutex_lock(&snd_ctl_led_mutex);
148 	/* the card may not be registered (active) at this point */
149 	if (card && !snd_ctl_led_card_valid[card->number]) {
150 		mutex_unlock(&snd_ctl_led_mutex);
151 		return;
152 	}
153 	list_for_each_entry(lctl, &led->controls, list) {
154 		if (lctl->kctl == kctl && lctl->index_offset == ioff)
155 			found = true;
156 		UPDATE_ROUTE(route, snd_ctl_led_get(lctl));
157 	}
158 	if (!found && kctl && card) {
159 		lctl = kzalloc(sizeof(*lctl), GFP_KERNEL);
160 		if (lctl) {
161 			lctl->card = card;
162 			lctl->access = access;
163 			lctl->kctl = kctl;
164 			lctl->index_offset = ioff;
165 			list_add(&lctl->list, &led->controls);
166 			UPDATE_ROUTE(route, snd_ctl_led_get(lctl));
167 		}
168 	}
169 	mutex_unlock(&snd_ctl_led_mutex);
170 	switch (led->mode) {
171 	case MODE_OFF:		route = 1; break;
172 	case MODE_ON:		route = 0; break;
173 	case MODE_FOLLOW_ROUTE:	if (route >= 0) route ^= 1; break;
174 	case MODE_FOLLOW_MUTE:	/* noop */ break;
175 	}
176 	if (route >= 0)
177 		ledtrig_audio_set(led->trigger_type, route ? LED_OFF : LED_ON);
178 }
179 
180 static struct snd_ctl_led_ctl *snd_ctl_led_find(struct snd_kcontrol *kctl, unsigned int ioff)
181 {
182 	struct list_head *controls;
183 	struct snd_ctl_led_ctl *lctl;
184 	unsigned int group;
185 
186 	for (group = 0; group < MAX_LED; group++) {
187 		controls = &snd_ctl_leds[group].controls;
188 		list_for_each_entry(lctl, controls, list)
189 			if (lctl->kctl == kctl && lctl->index_offset == ioff)
190 				return lctl;
191 	}
192 	return NULL;
193 }
194 
195 static unsigned int snd_ctl_led_remove(struct snd_kcontrol *kctl, unsigned int ioff,
196 				       unsigned int access)
197 {
198 	struct snd_ctl_led_ctl *lctl;
199 	unsigned int ret = 0;
200 
201 	mutex_lock(&snd_ctl_led_mutex);
202 	lctl = snd_ctl_led_find(kctl, ioff);
203 	if (lctl && (access == 0 || access != lctl->access)) {
204 		ret = lctl->access;
205 		list_del(&lctl->list);
206 		kfree(lctl);
207 	}
208 	mutex_unlock(&snd_ctl_led_mutex);
209 	return ret;
210 }
211 
212 static void snd_ctl_led_notify(struct snd_card *card, unsigned int mask,
213 			       struct snd_kcontrol *kctl, unsigned int ioff)
214 {
215 	struct snd_kcontrol_volatile *vd;
216 	unsigned int access, access2;
217 
218 	if (mask == SNDRV_CTL_EVENT_MASK_REMOVE) {
219 		access = snd_ctl_led_remove(kctl, ioff, 0);
220 		if (access)
221 			snd_ctl_led_set_state(card, access, NULL, 0);
222 	} else if (mask & SNDRV_CTL_EVENT_MASK_INFO) {
223 		vd = &kctl->vd[ioff];
224 		access = vd->access & SNDRV_CTL_ELEM_ACCESS_LED_MASK;
225 		access2 = snd_ctl_led_remove(kctl, ioff, access);
226 		if (access2)
227 			snd_ctl_led_set_state(card, access2, NULL, 0);
228 		if (access)
229 			snd_ctl_led_set_state(card, access, kctl, ioff);
230 	} else if ((mask & (SNDRV_CTL_EVENT_MASK_ADD |
231 			    SNDRV_CTL_EVENT_MASK_VALUE)) != 0) {
232 		vd = &kctl->vd[ioff];
233 		access = vd->access & SNDRV_CTL_ELEM_ACCESS_LED_MASK;
234 		if (access)
235 			snd_ctl_led_set_state(card, access, kctl, ioff);
236 	}
237 }
238 
239 static int snd_ctl_led_set_id(int card_number, struct snd_ctl_elem_id *id,
240 			      unsigned int group, bool set)
241 {
242 	struct snd_card *card;
243 	struct snd_kcontrol *kctl;
244 	struct snd_kcontrol_volatile *vd;
245 	unsigned int ioff, access, new_access;
246 	int err = 0;
247 
248 	card = snd_card_ref(card_number);
249 	if (card) {
250 		down_write(&card->controls_rwsem);
251 		kctl = snd_ctl_find_id(card, id);
252 		if (kctl) {
253 			ioff = snd_ctl_get_ioff(kctl, id);
254 			vd = &kctl->vd[ioff];
255 			access = vd->access & SNDRV_CTL_ELEM_ACCESS_LED_MASK;
256 			if (access != 0 && access != group_to_access(group)) {
257 				err = -EXDEV;
258 				goto unlock;
259 			}
260 			new_access = vd->access & ~SNDRV_CTL_ELEM_ACCESS_LED_MASK;
261 			if (set)
262 				new_access |= group_to_access(group);
263 			if (new_access != vd->access) {
264 				vd->access = new_access;
265 				snd_ctl_led_notify(card, SNDRV_CTL_EVENT_MASK_INFO, kctl, ioff);
266 			}
267 		} else {
268 			err = -ENOENT;
269 		}
270 unlock:
271 		up_write(&card->controls_rwsem);
272 		snd_card_unref(card);
273 	} else {
274 		err = -ENXIO;
275 	}
276 	return err;
277 }
278 
279 static void snd_ctl_led_refresh(void)
280 {
281 	unsigned int group;
282 
283 	for (group = 0; group < MAX_LED; group++)
284 		snd_ctl_led_set_state(NULL, group_to_access(group), NULL, 0);
285 }
286 
287 static void snd_ctl_led_ctl_destroy(struct snd_ctl_led_ctl *lctl)
288 {
289 	list_del(&lctl->list);
290 	kfree(lctl);
291 }
292 
293 static void snd_ctl_led_clean(struct snd_card *card)
294 {
295 	unsigned int group;
296 	struct snd_ctl_led *led;
297 	struct snd_ctl_led_ctl *lctl;
298 
299 	for (group = 0; group < MAX_LED; group++) {
300 		led = &snd_ctl_leds[group];
301 repeat:
302 		list_for_each_entry(lctl, &led->controls, list)
303 			if (!card || lctl->card == card) {
304 				snd_ctl_led_ctl_destroy(lctl);
305 				goto repeat;
306 			}
307 	}
308 }
309 
310 static int snd_ctl_led_reset(int card_number, unsigned int group)
311 {
312 	struct snd_card *card;
313 	struct snd_ctl_led *led;
314 	struct snd_ctl_led_ctl *lctl;
315 	struct snd_kcontrol_volatile *vd;
316 	bool change = false;
317 
318 	card = snd_card_ref(card_number);
319 	if (!card)
320 		return -ENXIO;
321 
322 	mutex_lock(&snd_ctl_led_mutex);
323 	if (!snd_ctl_led_card_valid[card_number]) {
324 		mutex_unlock(&snd_ctl_led_mutex);
325 		snd_card_unref(card);
326 		return -ENXIO;
327 	}
328 	led = &snd_ctl_leds[group];
329 repeat:
330 	list_for_each_entry(lctl, &led->controls, list)
331 		if (lctl->card == card) {
332 			vd = &lctl->kctl->vd[lctl->index_offset];
333 			vd->access &= ~group_to_access(group);
334 			snd_ctl_led_ctl_destroy(lctl);
335 			change = true;
336 			goto repeat;
337 		}
338 	mutex_unlock(&snd_ctl_led_mutex);
339 	if (change)
340 		snd_ctl_led_set_state(NULL, group_to_access(group), NULL, 0);
341 	snd_card_unref(card);
342 	return 0;
343 }
344 
345 static void snd_ctl_led_register(struct snd_card *card)
346 {
347 	struct snd_kcontrol *kctl;
348 	unsigned int ioff;
349 
350 	if (snd_BUG_ON(card->number < 0 ||
351 		       card->number >= ARRAY_SIZE(snd_ctl_led_card_valid)))
352 		return;
353 	mutex_lock(&snd_ctl_led_mutex);
354 	snd_ctl_led_card_valid[card->number] = true;
355 	mutex_unlock(&snd_ctl_led_mutex);
356 	/* the register callback is already called with held card->controls_rwsem */
357 	list_for_each_entry(kctl, &card->controls, list)
358 		for (ioff = 0; ioff < kctl->count; ioff++)
359 			snd_ctl_led_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, kctl, ioff);
360 	snd_ctl_led_refresh();
361 	snd_ctl_led_sysfs_add(card);
362 }
363 
364 static void snd_ctl_led_disconnect(struct snd_card *card)
365 {
366 	snd_ctl_led_sysfs_remove(card);
367 	mutex_lock(&snd_ctl_led_mutex);
368 	snd_ctl_led_card_valid[card->number] = false;
369 	snd_ctl_led_clean(card);
370 	mutex_unlock(&snd_ctl_led_mutex);
371 	snd_ctl_led_refresh();
372 }
373 
374 /*
375  * sysfs
376  */
377 
378 static ssize_t mode_show(struct device *dev,
379 			 struct device_attribute *attr, char *buf)
380 {
381 	struct snd_ctl_led *led = container_of(dev, struct snd_ctl_led, dev);
382 	const char *str;
383 
384 	switch (led->mode) {
385 	case MODE_FOLLOW_MUTE:	str = "follow-mute"; break;
386 	case MODE_FOLLOW_ROUTE:	str = "follow-route"; break;
387 	case MODE_ON:		str = "on"; break;
388 	case MODE_OFF:		str = "off"; break;
389 	}
390 	return sprintf(buf, "%s\n", str);
391 }
392 
393 static ssize_t mode_store(struct device *dev,
394 			  struct device_attribute *attr,
395 			  const char *buf, size_t count)
396 {
397 	struct snd_ctl_led *led = container_of(dev, struct snd_ctl_led, dev);
398 	char _buf[16];
399 	size_t l = min(count, sizeof(_buf) - 1);
400 	enum snd_ctl_led_mode mode;
401 
402 	memcpy(_buf, buf, l);
403 	_buf[l] = '\0';
404 	if (strstr(_buf, "mute"))
405 		mode = MODE_FOLLOW_MUTE;
406 	else if (strstr(_buf, "route"))
407 		mode = MODE_FOLLOW_ROUTE;
408 	else if (strncmp(_buf, "off", 3) == 0 || strncmp(_buf, "0", 1) == 0)
409 		mode = MODE_OFF;
410 	else if (strncmp(_buf, "on", 2) == 0 || strncmp(_buf, "1", 1) == 0)
411 		mode = MODE_ON;
412 	else
413 		return count;
414 
415 	mutex_lock(&snd_ctl_led_mutex);
416 	led->mode = mode;
417 	mutex_unlock(&snd_ctl_led_mutex);
418 
419 	snd_ctl_led_set_state(NULL, group_to_access(led->group), NULL, 0);
420 	return count;
421 }
422 
423 static ssize_t brightness_show(struct device *dev,
424 			       struct device_attribute *attr, char *buf)
425 {
426 	struct snd_ctl_led *led = container_of(dev, struct snd_ctl_led, dev);
427 
428 	return sprintf(buf, "%u\n", ledtrig_audio_get(led->trigger_type));
429 }
430 
431 static DEVICE_ATTR_RW(mode);
432 static DEVICE_ATTR_RO(brightness);
433 
434 static struct attribute *snd_ctl_led_dev_attrs[] = {
435 	&dev_attr_mode.attr,
436 	&dev_attr_brightness.attr,
437 	NULL,
438 };
439 
440 static const struct attribute_group snd_ctl_led_dev_attr_group = {
441 	.attrs = snd_ctl_led_dev_attrs,
442 };
443 
444 static const struct attribute_group *snd_ctl_led_dev_attr_groups[] = {
445 	&snd_ctl_led_dev_attr_group,
446 	NULL,
447 };
448 
449 static char *find_eos(char *s)
450 {
451 	while (*s && *s != ',')
452 		s++;
453 	if (*s)
454 		s++;
455 	return s;
456 }
457 
458 static char *parse_uint(char *s, unsigned int *val)
459 {
460 	unsigned long long res;
461 	if (kstrtoull(s, 10, &res))
462 		res = 0;
463 	*val = res;
464 	return find_eos(s);
465 }
466 
467 static char *parse_string(char *s, char *val, size_t val_size)
468 {
469 	if (*s == '"' || *s == '\'') {
470 		char c = *s;
471 		s++;
472 		while (*s && *s != c) {
473 			if (val_size > 1) {
474 				*val++ = *s;
475 				val_size--;
476 			}
477 			s++;
478 		}
479 	} else {
480 		while (*s && *s != ',') {
481 			if (val_size > 1) {
482 				*val++ = *s;
483 				val_size--;
484 			}
485 			s++;
486 		}
487 	}
488 	*val = '\0';
489 	if (*s)
490 		s++;
491 	return s;
492 }
493 
494 static char *parse_iface(char *s, unsigned int *val)
495 {
496 	if (!strncasecmp(s, "card", 4))
497 		*val = SNDRV_CTL_ELEM_IFACE_CARD;
498 	else if (!strncasecmp(s, "mixer", 5))
499 		*val = SNDRV_CTL_ELEM_IFACE_MIXER;
500 	return find_eos(s);
501 }
502 
503 /*
504  * These types of input strings are accepted:
505  *
506  *   unsigned integer - numid (equivaled to numid=UINT)
507  *   string - basic mixer name (equivalent to iface=MIXER,name=STR)
508  *   numid=UINT
509  *   [iface=MIXER,][device=UINT,][subdevice=UINT,]name=STR[,index=UINT]
510  */
511 static ssize_t set_led_id(struct snd_ctl_led_card *led_card, const char *buf, size_t count,
512 			  bool attach)
513 {
514 	char buf2[256], *s, *os;
515 	size_t len = max(sizeof(s) - 1, count);
516 	struct snd_ctl_elem_id id;
517 	int err;
518 
519 	strncpy(buf2, buf, len);
520 	buf2[len] = '\0';
521 	memset(&id, 0, sizeof(id));
522 	id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
523 	s = buf2;
524 	while (*s) {
525 		os = s;
526 		if (!strncasecmp(s, "numid=", 6)) {
527 			s = parse_uint(s + 6, &id.numid);
528 		} else if (!strncasecmp(s, "iface=", 6)) {
529 			s = parse_iface(s + 6, &id.iface);
530 		} else if (!strncasecmp(s, "device=", 7)) {
531 			s = parse_uint(s + 7, &id.device);
532 		} else if (!strncasecmp(s, "subdevice=", 10)) {
533 			s = parse_uint(s + 10, &id.subdevice);
534 		} else if (!strncasecmp(s, "name=", 5)) {
535 			s = parse_string(s + 5, id.name, sizeof(id.name));
536 		} else if (!strncasecmp(s, "index=", 6)) {
537 			s = parse_uint(s + 6, &id.index);
538 		} else if (s == buf2) {
539 			while (*s) {
540 				if (*s < '0' || *s > '9')
541 					break;
542 				s++;
543 			}
544 			if (*s == '\0')
545 				parse_uint(buf2, &id.numid);
546 			else {
547 				for (; *s >= ' '; s++);
548 				*s = '\0';
549 				strlcpy(id.name, buf2, sizeof(id.name));
550 			}
551 			break;
552 		}
553 		if (*s == ',')
554 			s++;
555 		if (s == os)
556 			break;
557 	}
558 
559 	err = snd_ctl_led_set_id(led_card->number, &id, led_card->led->group, attach);
560 	if (err < 0)
561 		return err;
562 
563 	return count;
564 }
565 
566 static ssize_t attach_store(struct device *dev,
567 			    struct device_attribute *attr,
568 			    const char *buf, size_t count)
569 {
570 	struct snd_ctl_led_card *led_card = container_of(dev, struct snd_ctl_led_card, dev);
571 	return set_led_id(led_card, buf, count, true);
572 }
573 
574 static ssize_t detach_store(struct device *dev,
575 			    struct device_attribute *attr,
576 			    const char *buf, size_t count)
577 {
578 	struct snd_ctl_led_card *led_card = container_of(dev, struct snd_ctl_led_card, dev);
579 	return set_led_id(led_card, buf, count, false);
580 }
581 
582 static ssize_t reset_store(struct device *dev,
583 			   struct device_attribute *attr,
584 			   const char *buf, size_t count)
585 {
586 	struct snd_ctl_led_card *led_card = container_of(dev, struct snd_ctl_led_card, dev);
587 	int err;
588 
589 	if (count > 0 && buf[0] == '1') {
590 		err = snd_ctl_led_reset(led_card->number, led_card->led->group);
591 		if (err < 0)
592 			return err;
593 	}
594 	return count;
595 }
596 
597 static ssize_t list_show(struct device *dev,
598 			 struct device_attribute *attr, char *buf)
599 {
600 	struct snd_ctl_led_card *led_card = container_of(dev, struct snd_ctl_led_card, dev);
601 	struct snd_card *card;
602 	struct snd_ctl_led_ctl *lctl;
603 	char *buf2 = buf;
604 	size_t l;
605 
606 	card = snd_card_ref(led_card->number);
607 	if (!card)
608 		return -ENXIO;
609 	down_read(&card->controls_rwsem);
610 	mutex_lock(&snd_ctl_led_mutex);
611 	if (snd_ctl_led_card_valid[led_card->number]) {
612 		list_for_each_entry(lctl, &led_card->led->controls, list)
613 			if (lctl->card == card) {
614 				if (buf2 - buf > PAGE_SIZE - 16)
615 					break;
616 				if (buf2 != buf)
617 					*buf2++ = ' ';
618 				l = scnprintf(buf2, 15, "%u",
619 						lctl->kctl->id.numid +
620 							lctl->index_offset);
621 				buf2[l] = '\0';
622 				buf2 += l + 1;
623 			}
624 	}
625 	mutex_unlock(&snd_ctl_led_mutex);
626 	up_read(&card->controls_rwsem);
627 	snd_card_unref(card);
628 	return buf2 - buf;
629 }
630 
631 static DEVICE_ATTR_WO(attach);
632 static DEVICE_ATTR_WO(detach);
633 static DEVICE_ATTR_WO(reset);
634 static DEVICE_ATTR_RO(list);
635 
636 static struct attribute *snd_ctl_led_card_attrs[] = {
637 	&dev_attr_attach.attr,
638 	&dev_attr_detach.attr,
639 	&dev_attr_reset.attr,
640 	&dev_attr_list.attr,
641 	NULL,
642 };
643 
644 static const struct attribute_group snd_ctl_led_card_attr_group = {
645 	.attrs = snd_ctl_led_card_attrs,
646 };
647 
648 static const struct attribute_group *snd_ctl_led_card_attr_groups[] = {
649 	&snd_ctl_led_card_attr_group,
650 	NULL,
651 };
652 
653 static struct device snd_ctl_led_dev;
654 
655 static void snd_ctl_led_sysfs_add(struct snd_card *card)
656 {
657 	unsigned int group;
658 	struct snd_ctl_led_card *led_card;
659 	struct snd_ctl_led *led;
660 	char link_name[32];
661 
662 	for (group = 0; group < MAX_LED; group++) {
663 		led = &snd_ctl_leds[group];
664 		led_card = kzalloc(sizeof(*led_card), GFP_KERNEL);
665 		if (!led_card)
666 			goto cerr2;
667 		led_card->number = card->number;
668 		led_card->led = led;
669 		device_initialize(&led_card->dev);
670 		if (dev_set_name(&led_card->dev, "card%d", card->number) < 0)
671 			goto cerr;
672 		led_card->dev.parent = &led->dev;
673 		led_card->dev.groups = snd_ctl_led_card_attr_groups;
674 		if (device_add(&led_card->dev))
675 			goto cerr;
676 		led->cards[card->number] = led_card;
677 		snprintf(link_name, sizeof(link_name), "led-%s", led->name);
678 		WARN(sysfs_create_link(&card->ctl_dev.kobj, &led_card->dev.kobj, link_name),
679 			"can't create symlink to controlC%i device\n", card->number);
680 		WARN(sysfs_create_link(&led_card->dev.kobj, &card->card_dev.kobj, "card"),
681 			"can't create symlink to card%i\n", card->number);
682 
683 		continue;
684 cerr:
685 		put_device(&led_card->dev);
686 cerr2:
687 		printk(KERN_ERR "snd_ctl_led: unable to add card%d", card->number);
688 		kfree(led_card);
689 	}
690 }
691 
692 static void snd_ctl_led_sysfs_remove(struct snd_card *card)
693 {
694 	unsigned int group;
695 	struct snd_ctl_led_card *led_card;
696 	struct snd_ctl_led *led;
697 	char link_name[32];
698 
699 	for (group = 0; group < MAX_LED; group++) {
700 		led = &snd_ctl_leds[group];
701 		led_card = led->cards[card->number];
702 		if (!led_card)
703 			continue;
704 		snprintf(link_name, sizeof(link_name), "led-%s", led->name);
705 		sysfs_remove_link(&card->ctl_dev.kobj, link_name);
706 		sysfs_remove_link(&led_card->dev.kobj, "card");
707 		device_del(&led_card->dev);
708 		kfree(led_card);
709 		led->cards[card->number] = NULL;
710 	}
711 }
712 
713 /*
714  * Control layer registration
715  */
716 static struct snd_ctl_layer_ops snd_ctl_led_lops = {
717 	.module_name = SND_CTL_LAYER_MODULE_LED,
718 	.lregister = snd_ctl_led_register,
719 	.ldisconnect = snd_ctl_led_disconnect,
720 	.lnotify = snd_ctl_led_notify,
721 };
722 
723 static int __init snd_ctl_led_init(void)
724 {
725 	struct snd_ctl_led *led;
726 	unsigned int group;
727 
728 	device_initialize(&snd_ctl_led_dev);
729 	snd_ctl_led_dev.class = sound_class;
730 	dev_set_name(&snd_ctl_led_dev, "ctl-led");
731 	if (device_add(&snd_ctl_led_dev)) {
732 		put_device(&snd_ctl_led_dev);
733 		return -ENOMEM;
734 	}
735 	for (group = 0; group < MAX_LED; group++) {
736 		led = &snd_ctl_leds[group];
737 		INIT_LIST_HEAD(&led->controls);
738 		device_initialize(&led->dev);
739 		led->dev.parent = &snd_ctl_led_dev;
740 		led->dev.groups = snd_ctl_led_dev_attr_groups;
741 		dev_set_name(&led->dev, led->name);
742 		if (device_add(&led->dev)) {
743 			put_device(&led->dev);
744 			for (; group > 0; group--) {
745 				led = &snd_ctl_leds[group - 1];
746 				device_del(&led->dev);
747 			}
748 			device_del(&snd_ctl_led_dev);
749 			return -ENOMEM;
750 		}
751 	}
752 	snd_ctl_register_layer(&snd_ctl_led_lops);
753 	return 0;
754 }
755 
756 static void __exit snd_ctl_led_exit(void)
757 {
758 	struct snd_ctl_led *led;
759 	struct snd_card *card;
760 	unsigned int group, card_number;
761 
762 	snd_ctl_disconnect_layer(&snd_ctl_led_lops);
763 	for (card_number = 0; card_number < SNDRV_CARDS; card_number++) {
764 		if (!snd_ctl_led_card_valid[card_number])
765 			continue;
766 		card = snd_card_ref(card_number);
767 		if (card) {
768 			snd_ctl_led_sysfs_remove(card);
769 			snd_card_unref(card);
770 		}
771 	}
772 	for (group = 0; group < MAX_LED; group++) {
773 		led = &snd_ctl_leds[group];
774 		device_del(&led->dev);
775 	}
776 	device_del(&snd_ctl_led_dev);
777 	snd_ctl_led_clean(NULL);
778 }
779 
780 module_init(snd_ctl_led_init)
781 module_exit(snd_ctl_led_exit)
782