| 1 | |
| 2 | |
| 3 | * Helper functions for jack-detection kcontrols
|
| 4 | *
|
| 5 | * Copyright (c) 2011 Takashi Iwai <[email protected]>
|
| 6 |
|
| 7 |
|
| 8 | #include <linux/kernel.h>
|
| 9 | #include <linux/export.h>
|
| 10 | #include <linux/string.h>
|
| 11 | #include <sound/core.h>
|
| 12 | #include <sound/control.h>
|
| 13 |
|
| 14 | #define jack_detect_kctl_info snd_ctl_boolean_mono_info
|
| 15 |
|
| 16 | static int jack_detect_kctl_get(struct snd_kcontrol *kcontrol,
|
| 17 | struct snd_ctl_elem_value *ucontrol)
|
| 18 | {
|
| 19 | ucontrol->value.integer.value[0] = kcontrol->private_value;
|
| 20 | return 0;
|
| 21 | }
|
| 22 |
|
| 23 | static const struct snd_kcontrol_new jack_detect_kctl = {
|
| 24 |
|
| 25 | .iface = SNDRV_CTL_ELEM_IFACE_CARD,
|
| 26 | .access = SNDRV_CTL_ELEM_ACCESS_READ,
|
| 27 | .info = jack_detect_kctl_info,
|
| 28 | .get = jack_detect_kctl_get,
|
| 29 | };
|
| 30 |
|
| 31 | static int get_available_index(struct snd_card *card, const char *name)
|
| 32 | {
|
| 33 | struct snd_ctl_elem_id sid;
|
| 34 |
|
| 35 | memset(&sid, 0, sizeof(sid));
|
| 36 |
|
| 37 | sid.index = 0;
|
| 38 | sid.iface = SNDRV_CTL_ELEM_IFACE_CARD;
|
| 39 | strscpy(sid.name, name, sizeof(sid.name));
|
| 40 |
|
| 41 | while (snd_ctl_find_id(card, &sid)) {
|
| 42 | sid.index++;
|
| 43 |
|
| 44 | sid.numid = 0;
|
| 45 | }
|
| 46 |
|
| 47 | return sid.index;
|
| 48 | }
|
| 49 |
|
| 50 | static void jack_kctl_name_gen(char *name, const char *src_name, size_t size)
|
| 51 | {
|
| 52 | size_t count = strlen(src_name);
|
| 53 | const char *suf = " Jack";
|
| 54 | size_t suf_len = strlen(suf);
|
| 55 | bool append_suf = true;
|
| 56 |
|
| 57 | if (count >= suf_len)
|
| 58 | append_suf = strncmp(&src_name[count - suf_len], suf, suf_len) != 0;
|
| 59 |
|
| 60 | if (append_suf)
|
| 61 | snprintf(name, size, "%s%s", src_name, suf);
|
| 62 | else
|
| 63 | strscpy(name, src_name, size);
|
| 64 | }
|
| 65 |
|
| 66 | struct snd_kcontrol *
|
| 67 | snd_kctl_jack_new(const char *name, struct snd_card *card)
|
| 68 | {
|
| 69 | struct snd_kcontrol *kctl;
|
| 70 |
|
| 71 | kctl = snd_ctl_new1(&jack_detect_kctl, NULL);
|
| 72 | if (!kctl)
|
| 73 | return NULL;
|
| 74 |
|
| 75 | jack_kctl_name_gen(kctl->id.name, name, sizeof(kctl->id.name));
|
| 76 | kctl->id.index = get_available_index(card, kctl->id.name);
|
| 77 | kctl->private_value = 0;
|
| 78 | return kctl;
|
| 79 | }
|
| 80 |
|
| 81 | void snd_kctl_jack_report(struct snd_card *card,
|
| 82 | struct snd_kcontrol *kctl, bool status)
|
| 83 | {
|
| 84 | if (kctl->private_value == status)
|
| 85 | return;
|
| 86 | kctl->private_value = status;
|
| 87 | snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);
|
| 88 | }
|