Lines Matching +full:led +full:- +full:s

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * LED state routines for driver control interface
14 MODULE_DESCRIPTION("ALSA control interface to LED trigger code.");
17 #define MAX_LED (((SNDRV_CTL_ELEM_ACCESS_MIC_LED - SNDRV_CTL_ELEM_ACCESS_SPK_LED) \
33 struct snd_ctl_led *led; member
60 .group = (SNDRV_CTL_ELEM_ACCESS_SPK_LED >> SNDRV_CTL_ELEM_ACCESS_LED_SHIFT) - 1,
66 .group = (SNDRV_CTL_ELEM_ACCESS_MIC_LED >> SNDRV_CTL_ELEM_ACCESS_LED_SHIFT) - 1,
85 SNDRV_CTL_ELEM_ACCESS_LED_SHIFT) - 1; in access_to_group()
109 struct snd_kcontrol *kctl = lctl->kctl; in snd_ctl_led_get()
114 info.id = kctl->id; in snd_ctl_led_get()
115 info.id.index += lctl->index_offset; in snd_ctl_led_get()
116 info.id.numid += lctl->index_offset; in snd_ctl_led_get()
117 result = kctl->info(kctl, &info); in snd_ctl_led_get()
119 return -1; in snd_ctl_led_get()
122 result = kctl->get(kctl, &value); in snd_ctl_led_get()
124 return -1; in snd_ctl_led_get()
141 struct snd_ctl_led *led; in snd_ctl_led_set_state() local
146 led = snd_ctl_led_get_by_access(access); in snd_ctl_led_set_state()
147 if (!led) in snd_ctl_led_set_state()
149 route = -1; in snd_ctl_led_set_state()
153 if (card && !snd_ctl_led_card_valid[card->number]) in snd_ctl_led_set_state()
155 list_for_each_entry(lctl, &led->controls, list) { in snd_ctl_led_set_state()
156 if (lctl->kctl == kctl && lctl->index_offset == ioff) in snd_ctl_led_set_state()
163 lctl->card = card; in snd_ctl_led_set_state()
164 lctl->access = access; in snd_ctl_led_set_state()
165 lctl->kctl = kctl; in snd_ctl_led_set_state()
166 lctl->index_offset = ioff; in snd_ctl_led_set_state()
167 list_add(&lctl->list, &led->controls); in snd_ctl_led_set_state()
172 switch (led->mode) { in snd_ctl_led_set_state()
179 struct led_trigger *trig = snd_ctl_ledtrig_audio[led->trigger_type]; in snd_ctl_led_set_state()
194 if (lctl->kctl == kctl && lctl->index_offset == ioff) in snd_ctl_led_find()
208 if (lctl && (access == 0 || access != lctl->access)) { in snd_ctl_led_remove()
209 ret = lctl->access; in snd_ctl_led_remove()
210 list_del(&lctl->list); in snd_ctl_led_remove()
227 vd = &kctl->vd[ioff]; in snd_ctl_led_notify()
228 access = vd->access & SNDRV_CTL_ELEM_ACCESS_LED_MASK; in snd_ctl_led_notify()
236 vd = &kctl->vd[ioff]; in snd_ctl_led_notify()
237 access = vd->access & SNDRV_CTL_ELEM_ACCESS_LED_MASK; in snd_ctl_led_notify()
255 return -ENXIO; in DEFINE_FREE()
256 guard(rwsem_write)(&card->controls_rwsem); in DEFINE_FREE()
259 return -ENOENT; in DEFINE_FREE()
261 vd = &kctl->vd[ioff]; in DEFINE_FREE()
262 access = vd->access & SNDRV_CTL_ELEM_ACCESS_LED_MASK; in DEFINE_FREE()
264 return -EXDEV; in DEFINE_FREE()
265 new_access = vd->access & ~SNDRV_CTL_ELEM_ACCESS_LED_MASK; in DEFINE_FREE()
268 if (new_access != vd->access) { in DEFINE_FREE()
269 vd->access = new_access; in DEFINE_FREE()
285 list_del(&lctl->list); in snd_ctl_led_ctl_destroy()
293 struct snd_ctl_led *led; in snd_ctl_led_clean() local
296 led = &snd_ctl_leds[group]; in snd_ctl_led_clean()
297 list_for_each_entry_safe(lctl, _lctl, &led->controls, list) in snd_ctl_led_clean()
298 if (!card || lctl->card == card) in snd_ctl_led_clean()
307 struct snd_ctl_led *led; in snd_ctl_led_reset() local
313 return -ENXIO; in snd_ctl_led_reset()
317 return -ENXIO; in snd_ctl_led_reset()
318 led = &snd_ctl_leds[group]; in snd_ctl_led_reset()
319 list_for_each_entry_safe(lctl, _lctl, &led->controls, list) in snd_ctl_led_reset()
320 if (lctl->card == card) { in snd_ctl_led_reset()
321 vd = &lctl->kctl->vd[lctl->index_offset]; in snd_ctl_led_reset()
322 vd->access &= ~group_to_access(group); in snd_ctl_led_reset()
337 if (snd_BUG_ON(card->number < 0 || in snd_ctl_led_register()
338 card->number >= ARRAY_SIZE(snd_ctl_led_card_valid))) in snd_ctl_led_register()
341 snd_ctl_led_card_valid[card->number] = true; in snd_ctl_led_register()
342 /* the register callback is already called with held card->controls_rwsem */ in snd_ctl_led_register()
343 list_for_each_entry(kctl, &card->controls, list) in snd_ctl_led_register()
344 for (ioff = 0; ioff < kctl->count; ioff++) in snd_ctl_led_register()
354 snd_ctl_led_card_valid[card->number] = false; in snd_ctl_led_disconnect()
382 struct snd_ctl_led *led = container_of(dev, struct snd_ctl_led, dev); in mode_show() local
385 switch (led->mode) { in mode_show()
386 case MODE_FOLLOW_MUTE: str = "follow-mute"; break; in mode_show()
387 case MODE_FOLLOW_ROUTE: str = "follow-route"; break; in mode_show()
391 return sysfs_emit(buf, "%s\n", str); in mode_show()
398 struct snd_ctl_led *led = container_of(dev, struct snd_ctl_led, dev); in mode_store() local
400 size_t l = min(count, sizeof(_buf) - 1); in mode_store()
417 led->mode = mode; in mode_store()
419 snd_ctl_led_set_state(NULL, group_to_access(led->group), NULL, 0); in mode_store()
426 struct snd_ctl_led *led = container_of(dev, struct snd_ctl_led, dev); in brightness_show() local
427 struct led_trigger *trig = snd_ctl_ledtrig_audio[led->trigger_type]; in brightness_show()
450 static char *find_eos(char *s) in find_eos() argument
452 while (*s && *s != ',') in find_eos()
453 s++; in find_eos()
454 if (*s) in find_eos()
455 s++; in find_eos()
456 return s; in find_eos()
459 static char *parse_uint(char *s, unsigned int *val) in parse_uint() argument
462 if (kstrtoull(s, 10, &res)) in parse_uint()
465 return find_eos(s); in parse_uint()
468 static char *parse_string(char *s, char *val, size_t val_size) in parse_string() argument
470 if (*s == '"' || *s == '\'') { in parse_string()
471 char c = *s; in parse_string()
472 s++; in parse_string()
473 while (*s && *s != c) { in parse_string()
475 *val++ = *s; in parse_string()
476 val_size--; in parse_string()
478 s++; in parse_string()
481 while (*s && *s != ',') { in parse_string()
483 *val++ = *s; in parse_string()
484 val_size--; in parse_string()
486 s++; in parse_string()
490 if (*s) in parse_string()
491 s++; in parse_string()
492 return s; in parse_string()
495 static char *parse_iface(char *s, snd_ctl_elem_iface_t *val) in parse_iface() argument
497 if (!strncasecmp(s, "card", 4)) in parse_iface()
499 else if (!strncasecmp(s, "mixer", 5)) in parse_iface()
501 return find_eos(s); in parse_iface()
507 * unsigned integer - numid (equivaled to numid=UINT)
508 * string - basic mixer name (equivalent to iface=MIXER,name=STR)
515 char buf2[256], *s, *os; in set_led_id() local
520 return -E2BIG; in set_led_id()
523 s = buf2; in set_led_id()
524 while (*s) { in set_led_id()
525 os = s; in set_led_id()
526 if (!strncasecmp(s, "numid=", 6)) { in set_led_id()
527 s = parse_uint(s + 6, &id.numid); in set_led_id()
528 } else if (!strncasecmp(s, "iface=", 6)) { in set_led_id()
529 s = parse_iface(s + 6, &id.iface); in set_led_id()
530 } else if (!strncasecmp(s, "device=", 7)) { in set_led_id()
531 s = parse_uint(s + 7, &id.device); in set_led_id()
532 } else if (!strncasecmp(s, "subdevice=", 10)) { in set_led_id()
533 s = parse_uint(s + 10, &id.subdevice); in set_led_id()
534 } else if (!strncasecmp(s, "name=", 5)) { in set_led_id()
535 s = parse_string(s + 5, id.name, sizeof(id.name)); in set_led_id()
536 } else if (!strncasecmp(s, "index=", 6)) { in set_led_id()
537 s = parse_uint(s + 6, &id.index); in set_led_id()
538 } else if (s == buf2) { in set_led_id()
539 while (*s) { in set_led_id()
540 if (*s < '0' || *s > '9') in set_led_id()
542 s++; in set_led_id()
544 if (*s == '\0') in set_led_id()
547 for (; *s >= ' '; s++); in set_led_id()
548 *s = '\0'; in set_led_id()
553 if (*s == ',') in set_led_id()
554 s++; in set_led_id()
555 if (s == os) in set_led_id()
559 err = snd_ctl_led_set_id(led_card->number, &id, led_card->led->group, attach); in set_led_id()
590 err = snd_ctl_led_reset(led_card->number, led_card->led->group); in reset_store()
605 card = snd_card_ref(led_card->number); in list_show()
607 return -ENXIO; in list_show()
608 guard(rwsem_read)(&card->controls_rwsem); in list_show()
610 if (snd_ctl_led_card_valid[led_card->number]) { in list_show()
611 list_for_each_entry(lctl, &led_card->led->controls, list) { in list_show()
612 if (lctl->card != card) in list_show()
617 lctl->kctl->id.numid + lctl->index_offset); in list_show()
651 struct snd_ctl_led *led; in snd_ctl_led_sysfs_add() local
655 led = &snd_ctl_leds[group]; in snd_ctl_led_sysfs_add()
659 led_card->number = card->number; in snd_ctl_led_sysfs_add()
660 led_card->led = led; in snd_ctl_led_sysfs_add()
661 device_initialize(&led_card->dev); in snd_ctl_led_sysfs_add()
662 led_card->dev.release = snd_ctl_led_card_release; in snd_ctl_led_sysfs_add()
663 if (dev_set_name(&led_card->dev, "card%d", card->number) < 0) in snd_ctl_led_sysfs_add()
665 led_card->dev.parent = &led->dev; in snd_ctl_led_sysfs_add()
666 led_card->dev.groups = snd_ctl_led_card_attr_groups; in snd_ctl_led_sysfs_add()
667 if (device_add(&led_card->dev)) in snd_ctl_led_sysfs_add()
669 led->cards[card->number] = led_card; in snd_ctl_led_sysfs_add()
670 snprintf(link_name, sizeof(link_name), "led-%s", led->name); in snd_ctl_led_sysfs_add()
671 WARN(sysfs_create_link(&card->ctl_dev->kobj, &led_card->dev.kobj, link_name), in snd_ctl_led_sysfs_add()
672 "can't create symlink to controlC%i device\n", card->number); in snd_ctl_led_sysfs_add()
673 WARN(sysfs_create_link(&led_card->dev.kobj, &card->card_dev.kobj, "card"), in snd_ctl_led_sysfs_add()
674 "can't create symlink to card%i\n", card->number); in snd_ctl_led_sysfs_add()
678 put_device(&led_card->dev); in snd_ctl_led_sysfs_add()
680 dev_err(card->dev, "snd_ctl_led: unable to add card%d", card->number); in snd_ctl_led_sysfs_add()
688 struct snd_ctl_led *led; in snd_ctl_led_sysfs_remove() local
692 led = &snd_ctl_leds[group]; in snd_ctl_led_sysfs_remove()
693 led_card = led->cards[card->number]; in snd_ctl_led_sysfs_remove()
696 snprintf(link_name, sizeof(link_name), "led-%s", led->name); in snd_ctl_led_sysfs_remove()
697 sysfs_remove_link(&card->ctl_dev->kobj, link_name); in snd_ctl_led_sysfs_remove()
698 sysfs_remove_link(&led_card->dev.kobj, "card"); in snd_ctl_led_sysfs_remove()
699 device_unregister(&led_card->dev); in snd_ctl_led_sysfs_remove()
700 led->cards[card->number] = NULL; in snd_ctl_led_sysfs_remove()
716 struct snd_ctl_led *led; in snd_ctl_led_init() local
719 led_trigger_register_simple("audio-mute", &snd_ctl_ledtrig_audio[LED_AUDIO_MUTE]); in snd_ctl_led_init()
720 led_trigger_register_simple("audio-micmute", &snd_ctl_ledtrig_audio[LED_AUDIO_MICMUTE]); in snd_ctl_led_init()
725 dev_set_name(&snd_ctl_led_dev, "ctl-led"); in snd_ctl_led_init()
728 return -ENOMEM; in snd_ctl_led_init()
731 led = &snd_ctl_leds[group]; in snd_ctl_led_init()
732 INIT_LIST_HEAD(&led->controls); in snd_ctl_led_init()
733 device_initialize(&led->dev); in snd_ctl_led_init()
734 led->dev.parent = &snd_ctl_led_dev; in snd_ctl_led_init()
735 led->dev.release = snd_ctl_led_release; in snd_ctl_led_init()
736 led->dev.groups = snd_ctl_led_dev_attr_groups; in snd_ctl_led_init()
737 dev_set_name(&led->dev, led->name); in snd_ctl_led_init()
738 if (device_add(&led->dev)) { in snd_ctl_led_init()
739 put_device(&led->dev); in snd_ctl_led_init()
740 for (; group > 0; group--) { in snd_ctl_led_init()
741 led = &snd_ctl_leds[group - 1]; in snd_ctl_led_init()
742 device_unregister(&led->dev); in snd_ctl_led_init()
745 return -ENOMEM; in snd_ctl_led_init()
754 struct snd_ctl_led *led; in snd_ctl_led_exit() local
769 led = &snd_ctl_leds[group]; in snd_ctl_led_exit()
770 device_unregister(&led->dev); in snd_ctl_led_exit()
782 MODULE_ALIAS("ledtrig:audio-mute");
783 MODULE_ALIAS("ledtrig:audio-micmute");