85 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Helper functions for jack-detection kcontrols4 *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_info14 15static int jack_detect_kctl_get(struct snd_kcontrol *kcontrol,16 struct snd_ctl_elem_value *ucontrol)17{18 ucontrol->value.integer.value[0] = kcontrol->private_value;19 return 0;20}21 22static 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 30static int get_available_index(struct snd_card *card, const char *name)31{32 struct snd_ctl_elem_id sid;33 34 memset(&sid, 0, sizeof(sid));35 36 sid.index = 0;37 sid.iface = SNDRV_CTL_ELEM_IFACE_CARD;38 strscpy(sid.name, name, sizeof(sid.name));39 40 while (snd_ctl_find_id(card, &sid)) {41 sid.index++;42 /* reset numid; otherwise snd_ctl_find_id() hits this again */43 sid.numid = 0;44 }45 46 return sid.index;47}48 49static void jack_kctl_name_gen(char *name, const char *src_name, int size)50{51 size_t count = strlen(src_name);52 bool need_cat = true;53 54 /* remove redundant " Jack" from src_name */55 if (count >= 5)56 need_cat = strncmp(&src_name[count - 5], " Jack", 5) ? true : false;57 58 snprintf(name, size, need_cat ? "%s Jack" : "%s", src_name);59 60}61 62struct snd_kcontrol *63snd_kctl_jack_new(const char *name, struct snd_card *card)64{65 struct snd_kcontrol *kctl;66 67 kctl = snd_ctl_new1(&jack_detect_kctl, NULL);68 if (!kctl)69 return NULL;70 71 jack_kctl_name_gen(kctl->id.name, name, sizeof(kctl->id.name));72 kctl->id.index = get_available_index(card, kctl->id.name);73 kctl->private_value = 0;74 return kctl;75}76 77void snd_kctl_jack_report(struct snd_card *card,78 struct snd_kcontrol *kctl, bool status)79{80 if (kctl->private_value == status)81 return;82 kctl->private_value = status;83 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);84}85