18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Helper functions for jack-detection kcontrols
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (c) 2011 Takashi Iwai <tiwai@suse.de>
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <linux/kernel.h>
98c2ecf20Sopenharmony_ci#include <linux/export.h>
108c2ecf20Sopenharmony_ci#include <sound/core.h>
118c2ecf20Sopenharmony_ci#include <sound/control.h>
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#define jack_detect_kctl_info	snd_ctl_boolean_mono_info
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_cistatic int jack_detect_kctl_get(struct snd_kcontrol *kcontrol,
168c2ecf20Sopenharmony_ci				struct snd_ctl_elem_value *ucontrol)
178c2ecf20Sopenharmony_ci{
188c2ecf20Sopenharmony_ci	ucontrol->value.integer.value[0] = kcontrol->private_value;
198c2ecf20Sopenharmony_ci	return 0;
208c2ecf20Sopenharmony_ci}
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new jack_detect_kctl = {
238c2ecf20Sopenharmony_ci	/* name is filled later */
248c2ecf20Sopenharmony_ci	.iface = SNDRV_CTL_ELEM_IFACE_CARD,
258c2ecf20Sopenharmony_ci	.access = SNDRV_CTL_ELEM_ACCESS_READ,
268c2ecf20Sopenharmony_ci	.info = jack_detect_kctl_info,
278c2ecf20Sopenharmony_ci	.get = jack_detect_kctl_get,
288c2ecf20Sopenharmony_ci};
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_cistatic int get_available_index(struct snd_card *card, const char *name)
318c2ecf20Sopenharmony_ci{
328c2ecf20Sopenharmony_ci	struct snd_ctl_elem_id sid;
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci	memset(&sid, 0, sizeof(sid));
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci	sid.index = 0;
378c2ecf20Sopenharmony_ci	sid.iface = SNDRV_CTL_ELEM_IFACE_CARD;
388c2ecf20Sopenharmony_ci	strlcpy(sid.name, name, sizeof(sid.name));
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci	while (snd_ctl_find_id(card, &sid)) {
418c2ecf20Sopenharmony_ci		sid.index++;
428c2ecf20Sopenharmony_ci		/* reset numid; otherwise snd_ctl_find_id() hits this again */
438c2ecf20Sopenharmony_ci		sid.numid = 0;
448c2ecf20Sopenharmony_ci	}
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci	return sid.index;
478c2ecf20Sopenharmony_ci}
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_cistatic void jack_kctl_name_gen(char *name, const char *src_name, int size)
508c2ecf20Sopenharmony_ci{
518c2ecf20Sopenharmony_ci	size_t count = strlen(src_name);
528c2ecf20Sopenharmony_ci	bool need_cat = true;
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci	/* remove redundant " Jack" from src_name */
558c2ecf20Sopenharmony_ci	if (count >= 5)
568c2ecf20Sopenharmony_ci		need_cat = strncmp(&src_name[count - 5], " Jack", 5) ? true : false;
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci	snprintf(name, size, need_cat ? "%s Jack" : "%s", src_name);
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci}
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_cistruct snd_kcontrol *
638c2ecf20Sopenharmony_cisnd_kctl_jack_new(const char *name, struct snd_card *card)
648c2ecf20Sopenharmony_ci{
658c2ecf20Sopenharmony_ci	struct snd_kcontrol *kctl;
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci	kctl = snd_ctl_new1(&jack_detect_kctl, NULL);
688c2ecf20Sopenharmony_ci	if (!kctl)
698c2ecf20Sopenharmony_ci		return NULL;
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci	jack_kctl_name_gen(kctl->id.name, name, sizeof(kctl->id.name));
728c2ecf20Sopenharmony_ci	kctl->id.index = get_available_index(card, kctl->id.name);
738c2ecf20Sopenharmony_ci	kctl->private_value = 0;
748c2ecf20Sopenharmony_ci	return kctl;
758c2ecf20Sopenharmony_ci}
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_civoid snd_kctl_jack_report(struct snd_card *card,
788c2ecf20Sopenharmony_ci			  struct snd_kcontrol *kctl, bool status)
798c2ecf20Sopenharmony_ci{
808c2ecf20Sopenharmony_ci	if (kctl->private_value == status)
818c2ecf20Sopenharmony_ci		return;
828c2ecf20Sopenharmony_ci	kctl->private_value = status;
838c2ecf20Sopenharmony_ci	snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);
848c2ecf20Sopenharmony_ci}
85