Branch data Line data Source code
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 : : 8 : : #include <linux/kernel.h> 9 : : #include <linux/export.h> 10 : : #include <sound/core.h> 11 : : #include <sound/control.h> 12 : : 13 : : #define jack_detect_kctl_info snd_ctl_boolean_mono_info 14 : : 15 : 0 : static int jack_detect_kctl_get(struct snd_kcontrol *kcontrol, 16 : : struct snd_ctl_elem_value *ucontrol) 17 : : { 18 : 0 : ucontrol->value.integer.value[0] = kcontrol->private_value; 19 : 0 : return 0; 20 : : } 21 : : 22 : : static const struct snd_kcontrol_new jack_detect_kctl = { 23 : : /* name is filled later */ 24 : : .iface = SNDRV_CTL_ELEM_IFACE_CARD, 25 : : .access = SNDRV_CTL_ELEM_ACCESS_READ, 26 : : .info = jack_detect_kctl_info, 27 : : .get = jack_detect_kctl_get, 28 : : }; 29 : : 30 : 0 : static int get_available_index(struct snd_card *card, const char *name) 31 : : { 32 : : struct snd_ctl_elem_id sid; 33 : : 34 : 0 : memset(&sid, 0, sizeof(sid)); 35 : : 36 : : sid.index = 0; 37 : : sid.iface = SNDRV_CTL_ELEM_IFACE_CARD; 38 : 0 : strlcpy(sid.name, name, sizeof(sid.name)); 39 : : 40 : 0 : while (snd_ctl_find_id(card, &sid)) { 41 : 0 : sid.index++; 42 : : /* reset numid; otherwise snd_ctl_find_id() hits this again */ 43 : 0 : sid.numid = 0; 44 : : } 45 : : 46 : 0 : return sid.index; 47 : : } 48 : : 49 : 0 : static void jack_kctl_name_gen(char *name, const char *src_name, int size) 50 : : { 51 : 0 : size_t count = strlen(src_name); 52 : : bool need_cat = true; 53 : : 54 : : /* remove redundant " Jack" from src_name */ 55 : 0 : if (count >= 5) 56 : 0 : need_cat = strncmp(&src_name[count - 5], " Jack", 5) ? true : false; 57 : : 58 : 0 : snprintf(name, size, need_cat ? "%s Jack" : "%s", src_name); 59 : : 60 : 0 : } 61 : : 62 : : struct snd_kcontrol * 63 : 0 : snd_kctl_jack_new(const char *name, struct snd_card *card) 64 : : { 65 : : struct snd_kcontrol *kctl; 66 : : 67 : 0 : kctl = snd_ctl_new1(&jack_detect_kctl, NULL); 68 : 0 : if (!kctl) 69 : : return NULL; 70 : : 71 : 0 : jack_kctl_name_gen(kctl->id.name, name, sizeof(kctl->id.name)); 72 : 0 : kctl->id.index = get_available_index(card, kctl->id.name); 73 : 0 : kctl->private_value = 0; 74 : 0 : return kctl; 75 : : } 76 : : 77 : 0 : void snd_kctl_jack_report(struct snd_card *card, 78 : : struct snd_kcontrol *kctl, bool status) 79 : : { 80 : 0 : if (kctl->private_value == status) 81 : 0 : return; 82 : 0 : kctl->private_value = status; 83 : 0 : snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id); 84 : : }