162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *  Jack abstraction layer
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci *  Copyright 2008 Wolfson Microelectronics
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <linux/input.h>
962306a36Sopenharmony_ci#include <linux/slab.h>
1062306a36Sopenharmony_ci#include <linux/module.h>
1162306a36Sopenharmony_ci#include <linux/ctype.h>
1262306a36Sopenharmony_ci#include <linux/mm.h>
1362306a36Sopenharmony_ci#include <linux/debugfs.h>
1462306a36Sopenharmony_ci#include <sound/jack.h>
1562306a36Sopenharmony_ci#include <sound/core.h>
1662306a36Sopenharmony_ci#include <sound/control.h>
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_cistruct snd_jack_kctl {
1962306a36Sopenharmony_ci	struct snd_kcontrol *kctl;
2062306a36Sopenharmony_ci	struct list_head list;  /* list of controls belong to the same jack */
2162306a36Sopenharmony_ci	unsigned int mask_bits; /* only masked status bits are reported via kctl */
2262306a36Sopenharmony_ci	struct snd_jack *jack;  /* pointer to struct snd_jack */
2362306a36Sopenharmony_ci	bool sw_inject_enable;  /* allow to inject plug event via debugfs */
2462306a36Sopenharmony_ci#ifdef CONFIG_SND_JACK_INJECTION_DEBUG
2562306a36Sopenharmony_ci	struct dentry *jack_debugfs_root; /* jack_kctl debugfs root */
2662306a36Sopenharmony_ci#endif
2762306a36Sopenharmony_ci};
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci#ifdef CONFIG_SND_JACK_INPUT_DEV
3062306a36Sopenharmony_cistatic const int jack_switch_types[SND_JACK_SWITCH_TYPES] = {
3162306a36Sopenharmony_ci	SW_HEADPHONE_INSERT,
3262306a36Sopenharmony_ci	SW_MICROPHONE_INSERT,
3362306a36Sopenharmony_ci	SW_LINEOUT_INSERT,
3462306a36Sopenharmony_ci	SW_JACK_PHYSICAL_INSERT,
3562306a36Sopenharmony_ci	SW_VIDEOOUT_INSERT,
3662306a36Sopenharmony_ci	SW_LINEIN_INSERT,
3762306a36Sopenharmony_ci};
3862306a36Sopenharmony_ci#endif /* CONFIG_SND_JACK_INPUT_DEV */
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_cistatic int snd_jack_dev_disconnect(struct snd_device *device)
4162306a36Sopenharmony_ci{
4262306a36Sopenharmony_ci#ifdef CONFIG_SND_JACK_INPUT_DEV
4362306a36Sopenharmony_ci	struct snd_jack *jack = device->device_data;
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci	mutex_lock(&jack->input_dev_lock);
4662306a36Sopenharmony_ci	if (!jack->input_dev) {
4762306a36Sopenharmony_ci		mutex_unlock(&jack->input_dev_lock);
4862306a36Sopenharmony_ci		return 0;
4962306a36Sopenharmony_ci	}
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci	/* If the input device is registered with the input subsystem
5262306a36Sopenharmony_ci	 * then we need to use a different deallocator. */
5362306a36Sopenharmony_ci	if (jack->registered)
5462306a36Sopenharmony_ci		input_unregister_device(jack->input_dev);
5562306a36Sopenharmony_ci	else
5662306a36Sopenharmony_ci		input_free_device(jack->input_dev);
5762306a36Sopenharmony_ci	jack->input_dev = NULL;
5862306a36Sopenharmony_ci	mutex_unlock(&jack->input_dev_lock);
5962306a36Sopenharmony_ci#endif /* CONFIG_SND_JACK_INPUT_DEV */
6062306a36Sopenharmony_ci	return 0;
6162306a36Sopenharmony_ci}
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_cistatic int snd_jack_dev_free(struct snd_device *device)
6462306a36Sopenharmony_ci{
6562306a36Sopenharmony_ci	struct snd_jack *jack = device->device_data;
6662306a36Sopenharmony_ci	struct snd_card *card = device->card;
6762306a36Sopenharmony_ci	struct snd_jack_kctl *jack_kctl, *tmp_jack_kctl;
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	list_for_each_entry_safe(jack_kctl, tmp_jack_kctl, &jack->kctl_list, list) {
7062306a36Sopenharmony_ci		list_del_init(&jack_kctl->list);
7162306a36Sopenharmony_ci		snd_ctl_remove(card, jack_kctl->kctl);
7262306a36Sopenharmony_ci	}
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	if (jack->private_free)
7562306a36Sopenharmony_ci		jack->private_free(jack);
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	snd_jack_dev_disconnect(device);
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci	kfree(jack->id);
8062306a36Sopenharmony_ci	kfree(jack);
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	return 0;
8362306a36Sopenharmony_ci}
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci#ifdef CONFIG_SND_JACK_INPUT_DEV
8662306a36Sopenharmony_cistatic int snd_jack_dev_register(struct snd_device *device)
8762306a36Sopenharmony_ci{
8862306a36Sopenharmony_ci	struct snd_jack *jack = device->device_data;
8962306a36Sopenharmony_ci	struct snd_card *card = device->card;
9062306a36Sopenharmony_ci	int err, i;
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci	snprintf(jack->name, sizeof(jack->name), "%s %s",
9362306a36Sopenharmony_ci		 card->shortname, jack->id);
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci	mutex_lock(&jack->input_dev_lock);
9662306a36Sopenharmony_ci	if (!jack->input_dev) {
9762306a36Sopenharmony_ci		mutex_unlock(&jack->input_dev_lock);
9862306a36Sopenharmony_ci		return 0;
9962306a36Sopenharmony_ci	}
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci	jack->input_dev->name = jack->name;
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci	/* Default to the sound card device. */
10462306a36Sopenharmony_ci	if (!jack->input_dev->dev.parent)
10562306a36Sopenharmony_ci		jack->input_dev->dev.parent = snd_card_get_device_link(card);
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci	/* Add capabilities for any keys that are enabled */
10862306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(jack->key); i++) {
10962306a36Sopenharmony_ci		int testbit = SND_JACK_BTN_0 >> i;
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci		if (!(jack->type & testbit))
11262306a36Sopenharmony_ci			continue;
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci		if (!jack->key[i])
11562306a36Sopenharmony_ci			jack->key[i] = BTN_0 + i;
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci		input_set_capability(jack->input_dev, EV_KEY, jack->key[i]);
11862306a36Sopenharmony_ci	}
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci	err = input_register_device(jack->input_dev);
12162306a36Sopenharmony_ci	if (err == 0)
12262306a36Sopenharmony_ci		jack->registered = 1;
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci	mutex_unlock(&jack->input_dev_lock);
12562306a36Sopenharmony_ci	return err;
12662306a36Sopenharmony_ci}
12762306a36Sopenharmony_ci#endif /* CONFIG_SND_JACK_INPUT_DEV */
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci#ifdef CONFIG_SND_JACK_INJECTION_DEBUG
13062306a36Sopenharmony_cistatic void snd_jack_inject_report(struct snd_jack_kctl *jack_kctl, int status)
13162306a36Sopenharmony_ci{
13262306a36Sopenharmony_ci	struct snd_jack *jack;
13362306a36Sopenharmony_ci#ifdef CONFIG_SND_JACK_INPUT_DEV
13462306a36Sopenharmony_ci	int i;
13562306a36Sopenharmony_ci#endif
13662306a36Sopenharmony_ci	if (!jack_kctl)
13762306a36Sopenharmony_ci		return;
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci	jack = jack_kctl->jack;
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci	if (jack_kctl->sw_inject_enable)
14262306a36Sopenharmony_ci		snd_kctl_jack_report(jack->card, jack_kctl->kctl,
14362306a36Sopenharmony_ci				     status & jack_kctl->mask_bits);
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci#ifdef CONFIG_SND_JACK_INPUT_DEV
14662306a36Sopenharmony_ci	if (!jack->input_dev)
14762306a36Sopenharmony_ci		return;
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(jack->key); i++) {
15062306a36Sopenharmony_ci		int testbit = ((SND_JACK_BTN_0 >> i) & jack_kctl->mask_bits);
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci		if (jack->type & testbit)
15362306a36Sopenharmony_ci			input_report_key(jack->input_dev, jack->key[i],
15462306a36Sopenharmony_ci					 status & testbit);
15562306a36Sopenharmony_ci	}
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(jack_switch_types); i++) {
15862306a36Sopenharmony_ci		int testbit = ((1 << i) & jack_kctl->mask_bits);
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci		if (jack->type & testbit)
16162306a36Sopenharmony_ci			input_report_switch(jack->input_dev,
16262306a36Sopenharmony_ci					    jack_switch_types[i],
16362306a36Sopenharmony_ci					    status & testbit);
16462306a36Sopenharmony_ci	}
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ci	input_sync(jack->input_dev);
16762306a36Sopenharmony_ci#endif /* CONFIG_SND_JACK_INPUT_DEV */
16862306a36Sopenharmony_ci}
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_cistatic ssize_t sw_inject_enable_read(struct file *file,
17162306a36Sopenharmony_ci				     char __user *to, size_t count, loff_t *ppos)
17262306a36Sopenharmony_ci{
17362306a36Sopenharmony_ci	struct snd_jack_kctl *jack_kctl = file->private_data;
17462306a36Sopenharmony_ci	int len, ret;
17562306a36Sopenharmony_ci	char buf[128];
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci	len = scnprintf(buf, sizeof(buf), "%s: %s\t\t%s: %i\n", "Jack", jack_kctl->kctl->id.name,
17862306a36Sopenharmony_ci			"Inject Enabled", jack_kctl->sw_inject_enable);
17962306a36Sopenharmony_ci	ret = simple_read_from_buffer(to, count, ppos, buf, len);
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci	return ret;
18262306a36Sopenharmony_ci}
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_cistatic ssize_t sw_inject_enable_write(struct file *file,
18562306a36Sopenharmony_ci				      const char __user *from, size_t count, loff_t *ppos)
18662306a36Sopenharmony_ci{
18762306a36Sopenharmony_ci	struct snd_jack_kctl *jack_kctl = file->private_data;
18862306a36Sopenharmony_ci	int ret, err;
18962306a36Sopenharmony_ci	unsigned long enable;
19062306a36Sopenharmony_ci	char buf[8] = { 0 };
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci	ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, from, count);
19362306a36Sopenharmony_ci	err = kstrtoul(buf, 0, &enable);
19462306a36Sopenharmony_ci	if (err)
19562306a36Sopenharmony_ci		return err;
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci	if (jack_kctl->sw_inject_enable == (!!enable))
19862306a36Sopenharmony_ci		return ret;
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci	jack_kctl->sw_inject_enable = !!enable;
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci	if (!jack_kctl->sw_inject_enable)
20362306a36Sopenharmony_ci		snd_jack_report(jack_kctl->jack, jack_kctl->jack->hw_status_cache);
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci	return ret;
20662306a36Sopenharmony_ci}
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_cistatic ssize_t jackin_inject_write(struct file *file,
20962306a36Sopenharmony_ci				   const char __user *from, size_t count, loff_t *ppos)
21062306a36Sopenharmony_ci{
21162306a36Sopenharmony_ci	struct snd_jack_kctl *jack_kctl = file->private_data;
21262306a36Sopenharmony_ci	int ret, err;
21362306a36Sopenharmony_ci	unsigned long enable;
21462306a36Sopenharmony_ci	char buf[8] = { 0 };
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci	if (!jack_kctl->sw_inject_enable)
21762306a36Sopenharmony_ci		return -EINVAL;
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ci	ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, from, count);
22062306a36Sopenharmony_ci	err = kstrtoul(buf, 0, &enable);
22162306a36Sopenharmony_ci	if (err)
22262306a36Sopenharmony_ci		return err;
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci	snd_jack_inject_report(jack_kctl, !!enable ? jack_kctl->mask_bits : 0);
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci	return ret;
22762306a36Sopenharmony_ci}
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_cistatic ssize_t jack_kctl_id_read(struct file *file,
23062306a36Sopenharmony_ci				 char __user *to, size_t count, loff_t *ppos)
23162306a36Sopenharmony_ci{
23262306a36Sopenharmony_ci	struct snd_jack_kctl *jack_kctl = file->private_data;
23362306a36Sopenharmony_ci	char buf[64];
23462306a36Sopenharmony_ci	int len, ret;
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ci	len = scnprintf(buf, sizeof(buf), "%s\n", jack_kctl->kctl->id.name);
23762306a36Sopenharmony_ci	ret = simple_read_from_buffer(to, count, ppos, buf, len);
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ci	return ret;
24062306a36Sopenharmony_ci}
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_ci/* the bit definition is aligned with snd_jack_types in jack.h */
24362306a36Sopenharmony_cistatic const char * const jack_events_name[] = {
24462306a36Sopenharmony_ci	"HEADPHONE(0x0001)", "MICROPHONE(0x0002)", "LINEOUT(0x0004)",
24562306a36Sopenharmony_ci	"MECHANICAL(0x0008)", "VIDEOOUT(0x0010)", "LINEIN(0x0020)",
24662306a36Sopenharmony_ci	"", "", "", "BTN_5(0x0200)", "BTN_4(0x0400)", "BTN_3(0x0800)",
24762306a36Sopenharmony_ci	"BTN_2(0x1000)", "BTN_1(0x2000)", "BTN_0(0x4000)", "",
24862306a36Sopenharmony_ci};
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci/* the recommended buffer size is 256 */
25162306a36Sopenharmony_cistatic int parse_mask_bits(unsigned int mask_bits, char *buf, size_t buf_size)
25262306a36Sopenharmony_ci{
25362306a36Sopenharmony_ci	int i;
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci	scnprintf(buf, buf_size, "0x%04x", mask_bits);
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(jack_events_name); i++)
25862306a36Sopenharmony_ci		if (mask_bits & (1 << i)) {
25962306a36Sopenharmony_ci			strlcat(buf, " ", buf_size);
26062306a36Sopenharmony_ci			strlcat(buf, jack_events_name[i], buf_size);
26162306a36Sopenharmony_ci		}
26262306a36Sopenharmony_ci	strlcat(buf, "\n", buf_size);
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_ci	return strlen(buf);
26562306a36Sopenharmony_ci}
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_cistatic ssize_t jack_kctl_mask_bits_read(struct file *file,
26862306a36Sopenharmony_ci					char __user *to, size_t count, loff_t *ppos)
26962306a36Sopenharmony_ci{
27062306a36Sopenharmony_ci	struct snd_jack_kctl *jack_kctl = file->private_data;
27162306a36Sopenharmony_ci	char buf[256];
27262306a36Sopenharmony_ci	int len, ret;
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci	len = parse_mask_bits(jack_kctl->mask_bits, buf, sizeof(buf));
27562306a36Sopenharmony_ci	ret = simple_read_from_buffer(to, count, ppos, buf, len);
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_ci	return ret;
27862306a36Sopenharmony_ci}
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_cistatic ssize_t jack_kctl_status_read(struct file *file,
28162306a36Sopenharmony_ci				     char __user *to, size_t count, loff_t *ppos)
28262306a36Sopenharmony_ci{
28362306a36Sopenharmony_ci	struct snd_jack_kctl *jack_kctl = file->private_data;
28462306a36Sopenharmony_ci	char buf[16];
28562306a36Sopenharmony_ci	int len, ret;
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci	len = scnprintf(buf, sizeof(buf), "%s\n", jack_kctl->kctl->private_value ?
28862306a36Sopenharmony_ci			"Plugged" : "Unplugged");
28962306a36Sopenharmony_ci	ret = simple_read_from_buffer(to, count, ppos, buf, len);
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci	return ret;
29262306a36Sopenharmony_ci}
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci#ifdef CONFIG_SND_JACK_INPUT_DEV
29562306a36Sopenharmony_cistatic ssize_t jack_type_read(struct file *file,
29662306a36Sopenharmony_ci			      char __user *to, size_t count, loff_t *ppos)
29762306a36Sopenharmony_ci{
29862306a36Sopenharmony_ci	struct snd_jack_kctl *jack_kctl = file->private_data;
29962306a36Sopenharmony_ci	char buf[256];
30062306a36Sopenharmony_ci	int len, ret;
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci	len = parse_mask_bits(jack_kctl->jack->type, buf, sizeof(buf));
30362306a36Sopenharmony_ci	ret = simple_read_from_buffer(to, count, ppos, buf, len);
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci	return ret;
30662306a36Sopenharmony_ci}
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_cistatic const struct file_operations jack_type_fops = {
30962306a36Sopenharmony_ci	.open = simple_open,
31062306a36Sopenharmony_ci	.read = jack_type_read,
31162306a36Sopenharmony_ci	.llseek = default_llseek,
31262306a36Sopenharmony_ci};
31362306a36Sopenharmony_ci#endif
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_cistatic const struct file_operations sw_inject_enable_fops = {
31662306a36Sopenharmony_ci	.open = simple_open,
31762306a36Sopenharmony_ci	.read = sw_inject_enable_read,
31862306a36Sopenharmony_ci	.write = sw_inject_enable_write,
31962306a36Sopenharmony_ci	.llseek = default_llseek,
32062306a36Sopenharmony_ci};
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_cistatic const struct file_operations jackin_inject_fops = {
32362306a36Sopenharmony_ci	.open = simple_open,
32462306a36Sopenharmony_ci	.write = jackin_inject_write,
32562306a36Sopenharmony_ci	.llseek = default_llseek,
32662306a36Sopenharmony_ci};
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_cistatic const struct file_operations jack_kctl_id_fops = {
32962306a36Sopenharmony_ci	.open = simple_open,
33062306a36Sopenharmony_ci	.read = jack_kctl_id_read,
33162306a36Sopenharmony_ci	.llseek = default_llseek,
33262306a36Sopenharmony_ci};
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_cistatic const struct file_operations jack_kctl_mask_bits_fops = {
33562306a36Sopenharmony_ci	.open = simple_open,
33662306a36Sopenharmony_ci	.read = jack_kctl_mask_bits_read,
33762306a36Sopenharmony_ci	.llseek = default_llseek,
33862306a36Sopenharmony_ci};
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_cistatic const struct file_operations jack_kctl_status_fops = {
34162306a36Sopenharmony_ci	.open = simple_open,
34262306a36Sopenharmony_ci	.read = jack_kctl_status_read,
34362306a36Sopenharmony_ci	.llseek = default_llseek,
34462306a36Sopenharmony_ci};
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_cistatic int snd_jack_debugfs_add_inject_node(struct snd_jack *jack,
34762306a36Sopenharmony_ci					    struct snd_jack_kctl *jack_kctl)
34862306a36Sopenharmony_ci{
34962306a36Sopenharmony_ci	char *tname;
35062306a36Sopenharmony_ci	int i;
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ci	/* Don't create injection interface for Phantom jacks */
35362306a36Sopenharmony_ci	if (strstr(jack_kctl->kctl->id.name, "Phantom"))
35462306a36Sopenharmony_ci		return 0;
35562306a36Sopenharmony_ci
35662306a36Sopenharmony_ci	tname = kstrdup(jack_kctl->kctl->id.name, GFP_KERNEL);
35762306a36Sopenharmony_ci	if (!tname)
35862306a36Sopenharmony_ci		return -ENOMEM;
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_ci	/* replace the chars which are not suitable for folder's name with _ */
36162306a36Sopenharmony_ci	for (i = 0; tname[i]; i++)
36262306a36Sopenharmony_ci		if (!isalnum(tname[i]))
36362306a36Sopenharmony_ci			tname[i] = '_';
36462306a36Sopenharmony_ci
36562306a36Sopenharmony_ci	jack_kctl->jack_debugfs_root = debugfs_create_dir(tname, jack->card->debugfs_root);
36662306a36Sopenharmony_ci	kfree(tname);
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_ci	debugfs_create_file("sw_inject_enable", 0644, jack_kctl->jack_debugfs_root, jack_kctl,
36962306a36Sopenharmony_ci			    &sw_inject_enable_fops);
37062306a36Sopenharmony_ci
37162306a36Sopenharmony_ci	debugfs_create_file("jackin_inject", 0200, jack_kctl->jack_debugfs_root, jack_kctl,
37262306a36Sopenharmony_ci			    &jackin_inject_fops);
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ci	debugfs_create_file("kctl_id", 0444, jack_kctl->jack_debugfs_root, jack_kctl,
37562306a36Sopenharmony_ci			    &jack_kctl_id_fops);
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci	debugfs_create_file("mask_bits", 0444, jack_kctl->jack_debugfs_root, jack_kctl,
37862306a36Sopenharmony_ci			    &jack_kctl_mask_bits_fops);
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci	debugfs_create_file("status", 0444, jack_kctl->jack_debugfs_root, jack_kctl,
38162306a36Sopenharmony_ci			    &jack_kctl_status_fops);
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci#ifdef CONFIG_SND_JACK_INPUT_DEV
38462306a36Sopenharmony_ci	debugfs_create_file("type", 0444, jack_kctl->jack_debugfs_root, jack_kctl,
38562306a36Sopenharmony_ci			    &jack_type_fops);
38662306a36Sopenharmony_ci#endif
38762306a36Sopenharmony_ci	return 0;
38862306a36Sopenharmony_ci}
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_cistatic void snd_jack_debugfs_clear_inject_node(struct snd_jack_kctl *jack_kctl)
39162306a36Sopenharmony_ci{
39262306a36Sopenharmony_ci	debugfs_remove(jack_kctl->jack_debugfs_root);
39362306a36Sopenharmony_ci	jack_kctl->jack_debugfs_root = NULL;
39462306a36Sopenharmony_ci}
39562306a36Sopenharmony_ci#else /* CONFIG_SND_JACK_INJECTION_DEBUG */
39662306a36Sopenharmony_cistatic int snd_jack_debugfs_add_inject_node(struct snd_jack *jack,
39762306a36Sopenharmony_ci					    struct snd_jack_kctl *jack_kctl)
39862306a36Sopenharmony_ci{
39962306a36Sopenharmony_ci	return 0;
40062306a36Sopenharmony_ci}
40162306a36Sopenharmony_ci
40262306a36Sopenharmony_cistatic void snd_jack_debugfs_clear_inject_node(struct snd_jack_kctl *jack_kctl)
40362306a36Sopenharmony_ci{
40462306a36Sopenharmony_ci}
40562306a36Sopenharmony_ci#endif /* CONFIG_SND_JACK_INJECTION_DEBUG */
40662306a36Sopenharmony_ci
40762306a36Sopenharmony_cistatic void snd_jack_kctl_private_free(struct snd_kcontrol *kctl)
40862306a36Sopenharmony_ci{
40962306a36Sopenharmony_ci	struct snd_jack_kctl *jack_kctl;
41062306a36Sopenharmony_ci
41162306a36Sopenharmony_ci	jack_kctl = kctl->private_data;
41262306a36Sopenharmony_ci	if (jack_kctl) {
41362306a36Sopenharmony_ci		snd_jack_debugfs_clear_inject_node(jack_kctl);
41462306a36Sopenharmony_ci		list_del(&jack_kctl->list);
41562306a36Sopenharmony_ci		kfree(jack_kctl);
41662306a36Sopenharmony_ci	}
41762306a36Sopenharmony_ci}
41862306a36Sopenharmony_ci
41962306a36Sopenharmony_cistatic void snd_jack_kctl_add(struct snd_jack *jack, struct snd_jack_kctl *jack_kctl)
42062306a36Sopenharmony_ci{
42162306a36Sopenharmony_ci	jack_kctl->jack = jack;
42262306a36Sopenharmony_ci	list_add_tail(&jack_kctl->list, &jack->kctl_list);
42362306a36Sopenharmony_ci	snd_jack_debugfs_add_inject_node(jack, jack_kctl);
42462306a36Sopenharmony_ci}
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_cistatic struct snd_jack_kctl * snd_jack_kctl_new(struct snd_card *card, const char *name, unsigned int mask)
42762306a36Sopenharmony_ci{
42862306a36Sopenharmony_ci	struct snd_kcontrol *kctl;
42962306a36Sopenharmony_ci	struct snd_jack_kctl *jack_kctl;
43062306a36Sopenharmony_ci	int err;
43162306a36Sopenharmony_ci
43262306a36Sopenharmony_ci	kctl = snd_kctl_jack_new(name, card);
43362306a36Sopenharmony_ci	if (!kctl)
43462306a36Sopenharmony_ci		return NULL;
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_ci	err = snd_ctl_add(card, kctl);
43762306a36Sopenharmony_ci	if (err < 0)
43862306a36Sopenharmony_ci		return NULL;
43962306a36Sopenharmony_ci
44062306a36Sopenharmony_ci	jack_kctl = kzalloc(sizeof(*jack_kctl), GFP_KERNEL);
44162306a36Sopenharmony_ci
44262306a36Sopenharmony_ci	if (!jack_kctl)
44362306a36Sopenharmony_ci		goto error;
44462306a36Sopenharmony_ci
44562306a36Sopenharmony_ci	jack_kctl->kctl = kctl;
44662306a36Sopenharmony_ci	jack_kctl->mask_bits = mask;
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_ci	kctl->private_data = jack_kctl;
44962306a36Sopenharmony_ci	kctl->private_free = snd_jack_kctl_private_free;
45062306a36Sopenharmony_ci
45162306a36Sopenharmony_ci	return jack_kctl;
45262306a36Sopenharmony_cierror:
45362306a36Sopenharmony_ci	snd_ctl_free_one(kctl);
45462306a36Sopenharmony_ci	return NULL;
45562306a36Sopenharmony_ci}
45662306a36Sopenharmony_ci
45762306a36Sopenharmony_ci/**
45862306a36Sopenharmony_ci * snd_jack_add_new_kctl - Create a new snd_jack_kctl and add it to jack
45962306a36Sopenharmony_ci * @jack:  the jack instance which the kctl will attaching to
46062306a36Sopenharmony_ci * @name:  the name for the snd_kcontrol object
46162306a36Sopenharmony_ci * @mask:  a bitmask of enum snd_jack_type values that can be detected
46262306a36Sopenharmony_ci *         by this snd_jack_kctl object.
46362306a36Sopenharmony_ci *
46462306a36Sopenharmony_ci * Creates a new snd_kcontrol object and adds it to the jack kctl_list.
46562306a36Sopenharmony_ci *
46662306a36Sopenharmony_ci * Return: Zero if successful, or a negative error code on failure.
46762306a36Sopenharmony_ci */
46862306a36Sopenharmony_ciint snd_jack_add_new_kctl(struct snd_jack *jack, const char * name, int mask)
46962306a36Sopenharmony_ci{
47062306a36Sopenharmony_ci	struct snd_jack_kctl *jack_kctl;
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_ci	jack_kctl = snd_jack_kctl_new(jack->card, name, mask);
47362306a36Sopenharmony_ci	if (!jack_kctl)
47462306a36Sopenharmony_ci		return -ENOMEM;
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_ci	snd_jack_kctl_add(jack, jack_kctl);
47762306a36Sopenharmony_ci	return 0;
47862306a36Sopenharmony_ci}
47962306a36Sopenharmony_ciEXPORT_SYMBOL(snd_jack_add_new_kctl);
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_ci/**
48262306a36Sopenharmony_ci * snd_jack_new - Create a new jack
48362306a36Sopenharmony_ci * @card:  the card instance
48462306a36Sopenharmony_ci * @id:    an identifying string for this jack
48562306a36Sopenharmony_ci * @type:  a bitmask of enum snd_jack_type values that can be detected by
48662306a36Sopenharmony_ci *         this jack
48762306a36Sopenharmony_ci * @jjack: Used to provide the allocated jack object to the caller.
48862306a36Sopenharmony_ci * @initial_kctl: if true, create a kcontrol and add it to the jack list.
48962306a36Sopenharmony_ci * @phantom_jack: Don't create a input device for phantom jacks.
49062306a36Sopenharmony_ci *
49162306a36Sopenharmony_ci * Creates a new jack object.
49262306a36Sopenharmony_ci *
49362306a36Sopenharmony_ci * Return: Zero if successful, or a negative error code on failure.
49462306a36Sopenharmony_ci * On success @jjack will be initialised.
49562306a36Sopenharmony_ci */
49662306a36Sopenharmony_ciint snd_jack_new(struct snd_card *card, const char *id, int type,
49762306a36Sopenharmony_ci		 struct snd_jack **jjack, bool initial_kctl, bool phantom_jack)
49862306a36Sopenharmony_ci{
49962306a36Sopenharmony_ci	struct snd_jack *jack;
50062306a36Sopenharmony_ci	struct snd_jack_kctl *jack_kctl = NULL;
50162306a36Sopenharmony_ci	int err;
50262306a36Sopenharmony_ci	static const struct snd_device_ops ops = {
50362306a36Sopenharmony_ci		.dev_free = snd_jack_dev_free,
50462306a36Sopenharmony_ci#ifdef CONFIG_SND_JACK_INPUT_DEV
50562306a36Sopenharmony_ci		.dev_register = snd_jack_dev_register,
50662306a36Sopenharmony_ci		.dev_disconnect = snd_jack_dev_disconnect,
50762306a36Sopenharmony_ci#endif /* CONFIG_SND_JACK_INPUT_DEV */
50862306a36Sopenharmony_ci	};
50962306a36Sopenharmony_ci
51062306a36Sopenharmony_ci	if (initial_kctl) {
51162306a36Sopenharmony_ci		jack_kctl = snd_jack_kctl_new(card, id, type);
51262306a36Sopenharmony_ci		if (!jack_kctl)
51362306a36Sopenharmony_ci			return -ENOMEM;
51462306a36Sopenharmony_ci	}
51562306a36Sopenharmony_ci
51662306a36Sopenharmony_ci	jack = kzalloc(sizeof(struct snd_jack), GFP_KERNEL);
51762306a36Sopenharmony_ci	if (jack == NULL)
51862306a36Sopenharmony_ci		return -ENOMEM;
51962306a36Sopenharmony_ci
52062306a36Sopenharmony_ci	jack->id = kstrdup(id, GFP_KERNEL);
52162306a36Sopenharmony_ci	if (jack->id == NULL) {
52262306a36Sopenharmony_ci		kfree(jack);
52362306a36Sopenharmony_ci		return -ENOMEM;
52462306a36Sopenharmony_ci	}
52562306a36Sopenharmony_ci
52662306a36Sopenharmony_ci#ifdef CONFIG_SND_JACK_INPUT_DEV
52762306a36Sopenharmony_ci	mutex_init(&jack->input_dev_lock);
52862306a36Sopenharmony_ci
52962306a36Sopenharmony_ci	/* don't create input device for phantom jack */
53062306a36Sopenharmony_ci	if (!phantom_jack) {
53162306a36Sopenharmony_ci		int i;
53262306a36Sopenharmony_ci
53362306a36Sopenharmony_ci		jack->input_dev = input_allocate_device();
53462306a36Sopenharmony_ci		if (jack->input_dev == NULL) {
53562306a36Sopenharmony_ci			err = -ENOMEM;
53662306a36Sopenharmony_ci			goto fail_input;
53762306a36Sopenharmony_ci		}
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_ci		jack->input_dev->phys = "ALSA";
54062306a36Sopenharmony_ci
54162306a36Sopenharmony_ci		jack->type = type;
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_ci		for (i = 0; i < SND_JACK_SWITCH_TYPES; i++)
54462306a36Sopenharmony_ci			if (type & (1 << i))
54562306a36Sopenharmony_ci				input_set_capability(jack->input_dev, EV_SW,
54662306a36Sopenharmony_ci						     jack_switch_types[i]);
54762306a36Sopenharmony_ci
54862306a36Sopenharmony_ci	}
54962306a36Sopenharmony_ci#endif /* CONFIG_SND_JACK_INPUT_DEV */
55062306a36Sopenharmony_ci
55162306a36Sopenharmony_ci	err = snd_device_new(card, SNDRV_DEV_JACK, jack, &ops);
55262306a36Sopenharmony_ci	if (err < 0)
55362306a36Sopenharmony_ci		goto fail_input;
55462306a36Sopenharmony_ci
55562306a36Sopenharmony_ci	jack->card = card;
55662306a36Sopenharmony_ci	INIT_LIST_HEAD(&jack->kctl_list);
55762306a36Sopenharmony_ci
55862306a36Sopenharmony_ci	if (initial_kctl)
55962306a36Sopenharmony_ci		snd_jack_kctl_add(jack, jack_kctl);
56062306a36Sopenharmony_ci
56162306a36Sopenharmony_ci	*jjack = jack;
56262306a36Sopenharmony_ci
56362306a36Sopenharmony_ci	return 0;
56462306a36Sopenharmony_ci
56562306a36Sopenharmony_cifail_input:
56662306a36Sopenharmony_ci#ifdef CONFIG_SND_JACK_INPUT_DEV
56762306a36Sopenharmony_ci	input_free_device(jack->input_dev);
56862306a36Sopenharmony_ci#endif
56962306a36Sopenharmony_ci	kfree(jack->id);
57062306a36Sopenharmony_ci	kfree(jack);
57162306a36Sopenharmony_ci	return err;
57262306a36Sopenharmony_ci}
57362306a36Sopenharmony_ciEXPORT_SYMBOL(snd_jack_new);
57462306a36Sopenharmony_ci
57562306a36Sopenharmony_ci#ifdef CONFIG_SND_JACK_INPUT_DEV
57662306a36Sopenharmony_ci/**
57762306a36Sopenharmony_ci * snd_jack_set_parent - Set the parent device for a jack
57862306a36Sopenharmony_ci *
57962306a36Sopenharmony_ci * @jack:   The jack to configure
58062306a36Sopenharmony_ci * @parent: The device to set as parent for the jack.
58162306a36Sopenharmony_ci *
58262306a36Sopenharmony_ci * Set the parent for the jack devices in the device tree.  This
58362306a36Sopenharmony_ci * function is only valid prior to registration of the jack.  If no
58462306a36Sopenharmony_ci * parent is configured then the parent device will be the sound card.
58562306a36Sopenharmony_ci */
58662306a36Sopenharmony_civoid snd_jack_set_parent(struct snd_jack *jack, struct device *parent)
58762306a36Sopenharmony_ci{
58862306a36Sopenharmony_ci	WARN_ON(jack->registered);
58962306a36Sopenharmony_ci	mutex_lock(&jack->input_dev_lock);
59062306a36Sopenharmony_ci	if (!jack->input_dev) {
59162306a36Sopenharmony_ci		mutex_unlock(&jack->input_dev_lock);
59262306a36Sopenharmony_ci		return;
59362306a36Sopenharmony_ci	}
59462306a36Sopenharmony_ci
59562306a36Sopenharmony_ci	jack->input_dev->dev.parent = parent;
59662306a36Sopenharmony_ci	mutex_unlock(&jack->input_dev_lock);
59762306a36Sopenharmony_ci}
59862306a36Sopenharmony_ciEXPORT_SYMBOL(snd_jack_set_parent);
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_ci/**
60162306a36Sopenharmony_ci * snd_jack_set_key - Set a key mapping on a jack
60262306a36Sopenharmony_ci *
60362306a36Sopenharmony_ci * @jack:    The jack to configure
60462306a36Sopenharmony_ci * @type:    Jack report type for this key
60562306a36Sopenharmony_ci * @keytype: Input layer key type to be reported
60662306a36Sopenharmony_ci *
60762306a36Sopenharmony_ci * Map a SND_JACK_BTN_* button type to an input layer key, allowing
60862306a36Sopenharmony_ci * reporting of keys on accessories via the jack abstraction.  If no
60962306a36Sopenharmony_ci * mapping is provided but keys are enabled in the jack type then
61062306a36Sopenharmony_ci * BTN_n numeric buttons will be reported.
61162306a36Sopenharmony_ci *
61262306a36Sopenharmony_ci * If jacks are not reporting via the input API this call will have no
61362306a36Sopenharmony_ci * effect.
61462306a36Sopenharmony_ci *
61562306a36Sopenharmony_ci * Note that this is intended to be use by simple devices with small
61662306a36Sopenharmony_ci * numbers of keys that can be reported.  It is also possible to
61762306a36Sopenharmony_ci * access the input device directly - devices with complex input
61862306a36Sopenharmony_ci * capabilities on accessories should consider doing this rather than
61962306a36Sopenharmony_ci * using this abstraction.
62062306a36Sopenharmony_ci *
62162306a36Sopenharmony_ci * This function may only be called prior to registration of the jack.
62262306a36Sopenharmony_ci *
62362306a36Sopenharmony_ci * Return: Zero if successful, or a negative error code on failure.
62462306a36Sopenharmony_ci */
62562306a36Sopenharmony_ciint snd_jack_set_key(struct snd_jack *jack, enum snd_jack_types type,
62662306a36Sopenharmony_ci		     int keytype)
62762306a36Sopenharmony_ci{
62862306a36Sopenharmony_ci	int key = fls(SND_JACK_BTN_0) - fls(type);
62962306a36Sopenharmony_ci
63062306a36Sopenharmony_ci	WARN_ON(jack->registered);
63162306a36Sopenharmony_ci
63262306a36Sopenharmony_ci	if (!keytype || key >= ARRAY_SIZE(jack->key))
63362306a36Sopenharmony_ci		return -EINVAL;
63462306a36Sopenharmony_ci
63562306a36Sopenharmony_ci	jack->type |= type;
63662306a36Sopenharmony_ci	jack->key[key] = keytype;
63762306a36Sopenharmony_ci	return 0;
63862306a36Sopenharmony_ci}
63962306a36Sopenharmony_ciEXPORT_SYMBOL(snd_jack_set_key);
64062306a36Sopenharmony_ci#endif /* CONFIG_SND_JACK_INPUT_DEV */
64162306a36Sopenharmony_ci
64262306a36Sopenharmony_ci/**
64362306a36Sopenharmony_ci * snd_jack_report - Report the current status of a jack
64462306a36Sopenharmony_ci * Note: This function uses mutexes and should be called from a
64562306a36Sopenharmony_ci * context which can sleep (such as a workqueue).
64662306a36Sopenharmony_ci *
64762306a36Sopenharmony_ci * @jack:   The jack to report status for
64862306a36Sopenharmony_ci * @status: The current status of the jack
64962306a36Sopenharmony_ci */
65062306a36Sopenharmony_civoid snd_jack_report(struct snd_jack *jack, int status)
65162306a36Sopenharmony_ci{
65262306a36Sopenharmony_ci	struct snd_jack_kctl *jack_kctl;
65362306a36Sopenharmony_ci	unsigned int mask_bits = 0;
65462306a36Sopenharmony_ci#ifdef CONFIG_SND_JACK_INPUT_DEV
65562306a36Sopenharmony_ci	struct input_dev *idev;
65662306a36Sopenharmony_ci	int i;
65762306a36Sopenharmony_ci#endif
65862306a36Sopenharmony_ci
65962306a36Sopenharmony_ci	if (!jack)
66062306a36Sopenharmony_ci		return;
66162306a36Sopenharmony_ci
66262306a36Sopenharmony_ci	jack->hw_status_cache = status;
66362306a36Sopenharmony_ci
66462306a36Sopenharmony_ci	list_for_each_entry(jack_kctl, &jack->kctl_list, list)
66562306a36Sopenharmony_ci		if (jack_kctl->sw_inject_enable)
66662306a36Sopenharmony_ci			mask_bits |= jack_kctl->mask_bits;
66762306a36Sopenharmony_ci		else
66862306a36Sopenharmony_ci			snd_kctl_jack_report(jack->card, jack_kctl->kctl,
66962306a36Sopenharmony_ci					     status & jack_kctl->mask_bits);
67062306a36Sopenharmony_ci
67162306a36Sopenharmony_ci#ifdef CONFIG_SND_JACK_INPUT_DEV
67262306a36Sopenharmony_ci	idev = input_get_device(jack->input_dev);
67362306a36Sopenharmony_ci	if (!idev)
67462306a36Sopenharmony_ci		return;
67562306a36Sopenharmony_ci
67662306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(jack->key); i++) {
67762306a36Sopenharmony_ci		int testbit = ((SND_JACK_BTN_0 >> i) & ~mask_bits);
67862306a36Sopenharmony_ci
67962306a36Sopenharmony_ci		if (jack->type & testbit)
68062306a36Sopenharmony_ci			input_report_key(idev, jack->key[i],
68162306a36Sopenharmony_ci					 status & testbit);
68262306a36Sopenharmony_ci	}
68362306a36Sopenharmony_ci
68462306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(jack_switch_types); i++) {
68562306a36Sopenharmony_ci		int testbit = ((1 << i) & ~mask_bits);
68662306a36Sopenharmony_ci
68762306a36Sopenharmony_ci		if (jack->type & testbit)
68862306a36Sopenharmony_ci			input_report_switch(idev,
68962306a36Sopenharmony_ci					    jack_switch_types[i],
69062306a36Sopenharmony_ci					    status & testbit);
69162306a36Sopenharmony_ci	}
69262306a36Sopenharmony_ci
69362306a36Sopenharmony_ci	input_sync(idev);
69462306a36Sopenharmony_ci	input_put_device(idev);
69562306a36Sopenharmony_ci#endif /* CONFIG_SND_JACK_INPUT_DEV */
69662306a36Sopenharmony_ci}
69762306a36Sopenharmony_ciEXPORT_SYMBOL(snd_jack_report);
698