ctljack.c 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Helper functions for jack-detection kcontrols
  4. *
  5. * Copyright (c) 2011 Takashi Iwai <tiwai@suse.de>
  6. */
  7. #include <linux/kernel.h>
  8. #include <linux/export.h>
  9. #include <sound/core.h>
  10. #include <sound/control.h>
  11. #define jack_detect_kctl_info snd_ctl_boolean_mono_info
  12. static int jack_detect_kctl_get(struct snd_kcontrol *kcontrol,
  13. struct snd_ctl_elem_value *ucontrol)
  14. {
  15. ucontrol->value.integer.value[0] = kcontrol->private_value;
  16. return 0;
  17. }
  18. static const struct snd_kcontrol_new jack_detect_kctl = {
  19. /* name is filled later */
  20. .iface = SNDRV_CTL_ELEM_IFACE_CARD,
  21. .access = SNDRV_CTL_ELEM_ACCESS_READ,
  22. .info = jack_detect_kctl_info,
  23. .get = jack_detect_kctl_get,
  24. };
  25. static int get_available_index(struct snd_card *card, const char *name)
  26. {
  27. struct snd_ctl_elem_id sid;
  28. memset(&sid, 0, sizeof(sid));
  29. sid.index = 0;
  30. sid.iface = SNDRV_CTL_ELEM_IFACE_CARD;
  31. strlcpy(sid.name, name, sizeof(sid.name));
  32. while (snd_ctl_find_id(card, &sid)) {
  33. sid.index++;
  34. /* reset numid; otherwise snd_ctl_find_id() hits this again */
  35. sid.numid = 0;
  36. }
  37. return sid.index;
  38. }
  39. static void jack_kctl_name_gen(char *name, const char *src_name, int size)
  40. {
  41. size_t count = strlen(src_name);
  42. bool need_cat = true;
  43. /* remove redundant " Jack" from src_name */
  44. if (count >= 5)
  45. need_cat = strncmp(&src_name[count - 5], " Jack", 5) ? true : false;
  46. snprintf(name, size, need_cat ? "%s Jack" : "%s", src_name);
  47. }
  48. struct snd_kcontrol *
  49. snd_kctl_jack_new(const char *name, struct snd_card *card)
  50. {
  51. struct snd_kcontrol *kctl;
  52. kctl = snd_ctl_new1(&jack_detect_kctl, NULL);
  53. if (!kctl)
  54. return NULL;
  55. jack_kctl_name_gen(kctl->id.name, name, sizeof(kctl->id.name));
  56. kctl->id.index = get_available_index(card, kctl->id.name);
  57. kctl->private_value = 0;
  58. return kctl;
  59. }
  60. void snd_kctl_jack_report(struct snd_card *card,
  61. struct snd_kcontrol *kctl, bool status)
  62. {
  63. if (kctl->private_value == status)
  64. return;
  65. kctl->private_value = status;
  66. snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);
  67. }