Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-or-later
2 : : /*
3 : : * Jack abstraction layer
4 : : *
5 : : * Copyright 2008 Wolfson Microelectronics
6 : : */
7 : :
8 : : #include <linux/input.h>
9 : : #include <linux/slab.h>
10 : : #include <linux/module.h>
11 : : #include <sound/jack.h>
12 : : #include <sound/core.h>
13 : : #include <sound/control.h>
14 : :
15 : : struct snd_jack_kctl {
16 : : struct snd_kcontrol *kctl;
17 : : struct list_head list; /* list of controls belong to the same jack */
18 : : unsigned int mask_bits; /* only masked status bits are reported via kctl */
19 : : };
20 : :
21 : : #ifdef CONFIG_SND_JACK_INPUT_DEV
22 : : static int jack_switch_types[SND_JACK_SWITCH_TYPES] = {
23 : : SW_HEADPHONE_INSERT,
24 : : SW_MICROPHONE_INSERT,
25 : : SW_LINEOUT_INSERT,
26 : : SW_JACK_PHYSICAL_INSERT,
27 : : SW_VIDEOOUT_INSERT,
28 : : SW_LINEIN_INSERT,
29 : : };
30 : : #endif /* CONFIG_SND_JACK_INPUT_DEV */
31 : :
32 : 0 : static int snd_jack_dev_disconnect(struct snd_device *device)
33 : : {
34 : : #ifdef CONFIG_SND_JACK_INPUT_DEV
35 : 0 : struct snd_jack *jack = device->device_data;
36 : :
37 [ # # ]: 0 : if (!jack->input_dev)
38 : : return 0;
39 : :
40 : : /* If the input device is registered with the input subsystem
41 : : * then we need to use a different deallocator. */
42 [ # # ]: 0 : if (jack->registered)
43 : 0 : input_unregister_device(jack->input_dev);
44 : : else
45 : 0 : input_free_device(jack->input_dev);
46 : 0 : jack->input_dev = NULL;
47 : : #endif /* CONFIG_SND_JACK_INPUT_DEV */
48 : 0 : return 0;
49 : : }
50 : :
51 : 0 : static int snd_jack_dev_free(struct snd_device *device)
52 : : {
53 : 0 : struct snd_jack *jack = device->device_data;
54 : 0 : struct snd_card *card = device->card;
55 : : struct snd_jack_kctl *jack_kctl, *tmp_jack_kctl;
56 : :
57 [ # # ]: 0 : list_for_each_entry_safe(jack_kctl, tmp_jack_kctl, &jack->kctl_list, list) {
58 : : list_del_init(&jack_kctl->list);
59 : 0 : snd_ctl_remove(card, jack_kctl->kctl);
60 : : }
61 [ # # ]: 0 : if (jack->private_free)
62 : 0 : jack->private_free(jack);
63 : :
64 : 0 : snd_jack_dev_disconnect(device);
65 : :
66 : 0 : kfree(jack->id);
67 : 0 : kfree(jack);
68 : :
69 : 0 : return 0;
70 : : }
71 : :
72 : : #ifdef CONFIG_SND_JACK_INPUT_DEV
73 : 0 : static int snd_jack_dev_register(struct snd_device *device)
74 : : {
75 : 0 : struct snd_jack *jack = device->device_data;
76 : 0 : struct snd_card *card = device->card;
77 : : int err, i;
78 : :
79 : 0 : snprintf(jack->name, sizeof(jack->name), "%s %s",
80 : 0 : card->shortname, jack->id);
81 : :
82 [ # # ]: 0 : if (!jack->input_dev)
83 : : return 0;
84 : :
85 : 0 : jack->input_dev->name = jack->name;
86 : :
87 : : /* Default to the sound card device. */
88 [ # # ]: 0 : if (!jack->input_dev->dev.parent)
89 : 0 : jack->input_dev->dev.parent = snd_card_get_device_link(card);
90 : :
91 : : /* Add capabilities for any keys that are enabled */
92 [ # # ]: 0 : for (i = 0; i < ARRAY_SIZE(jack->key); i++) {
93 : 0 : int testbit = SND_JACK_BTN_0 >> i;
94 : :
95 [ # # ]: 0 : if (!(jack->type & testbit))
96 : 0 : continue;
97 : :
98 [ # # ]: 0 : if (!jack->key[i])
99 : 0 : jack->key[i] = BTN_0 + i;
100 : :
101 : 0 : input_set_capability(jack->input_dev, EV_KEY, jack->key[i]);
102 : : }
103 : :
104 : 0 : err = input_register_device(jack->input_dev);
105 [ # # ]: 0 : if (err == 0)
106 : 0 : jack->registered = 1;
107 : :
108 : 0 : return err;
109 : : }
110 : : #endif /* CONFIG_SND_JACK_INPUT_DEV */
111 : :
112 : 0 : static void snd_jack_kctl_private_free(struct snd_kcontrol *kctl)
113 : : {
114 : : struct snd_jack_kctl *jack_kctl;
115 : :
116 : 0 : jack_kctl = kctl->private_data;
117 [ # # ]: 0 : if (jack_kctl) {
118 : : list_del(&jack_kctl->list);
119 : 0 : kfree(jack_kctl);
120 : : }
121 : 0 : }
122 : :
123 : : static void snd_jack_kctl_add(struct snd_jack *jack, struct snd_jack_kctl *jack_kctl)
124 : : {
125 : 0 : list_add_tail(&jack_kctl->list, &jack->kctl_list);
126 : : }
127 : :
128 : 0 : static struct snd_jack_kctl * snd_jack_kctl_new(struct snd_card *card, const char *name, unsigned int mask)
129 : : {
130 : : struct snd_kcontrol *kctl;
131 : : struct snd_jack_kctl *jack_kctl;
132 : : int err;
133 : :
134 : 0 : kctl = snd_kctl_jack_new(name, card);
135 [ # # ]: 0 : if (!kctl)
136 : : return NULL;
137 : :
138 : 0 : err = snd_ctl_add(card, kctl);
139 [ # # ]: 0 : if (err < 0)
140 : : return NULL;
141 : :
142 : 0 : jack_kctl = kzalloc(sizeof(*jack_kctl), GFP_KERNEL);
143 : :
144 [ # # ]: 0 : if (!jack_kctl)
145 : : goto error;
146 : :
147 : 0 : jack_kctl->kctl = kctl;
148 : 0 : jack_kctl->mask_bits = mask;
149 : :
150 : 0 : kctl->private_data = jack_kctl;
151 : 0 : kctl->private_free = snd_jack_kctl_private_free;
152 : :
153 : 0 : return jack_kctl;
154 : : error:
155 : 0 : snd_ctl_free_one(kctl);
156 : 0 : return NULL;
157 : : }
158 : :
159 : : /**
160 : : * snd_jack_add_new_kctl - Create a new snd_jack_kctl and add it to jack
161 : : * @jack: the jack instance which the kctl will attaching to
162 : : * @name: the name for the snd_kcontrol object
163 : : * @mask: a bitmask of enum snd_jack_type values that can be detected
164 : : * by this snd_jack_kctl object.
165 : : *
166 : : * Creates a new snd_kcontrol object and adds it to the jack kctl_list.
167 : : *
168 : : * Return: Zero if successful, or a negative error code on failure.
169 : : */
170 : 0 : int snd_jack_add_new_kctl(struct snd_jack *jack, const char * name, int mask)
171 : : {
172 : : struct snd_jack_kctl *jack_kctl;
173 : :
174 : 0 : jack_kctl = snd_jack_kctl_new(jack->card, name, mask);
175 [ # # ]: 0 : if (!jack_kctl)
176 : : return -ENOMEM;
177 : :
178 : : snd_jack_kctl_add(jack, jack_kctl);
179 : 0 : return 0;
180 : : }
181 : : EXPORT_SYMBOL(snd_jack_add_new_kctl);
182 : :
183 : : /**
184 : : * snd_jack_new - Create a new jack
185 : : * @card: the card instance
186 : : * @id: an identifying string for this jack
187 : : * @type: a bitmask of enum snd_jack_type values that can be detected by
188 : : * this jack
189 : : * @jjack: Used to provide the allocated jack object to the caller.
190 : : * @initial_kctl: if true, create a kcontrol and add it to the jack list.
191 : : * @phantom_jack: Don't create a input device for phantom jacks.
192 : : *
193 : : * Creates a new jack object.
194 : : *
195 : : * Return: Zero if successful, or a negative error code on failure.
196 : : * On success @jjack will be initialised.
197 : : */
198 : 0 : int snd_jack_new(struct snd_card *card, const char *id, int type,
199 : : struct snd_jack **jjack, bool initial_kctl, bool phantom_jack)
200 : : {
201 : : struct snd_jack *jack;
202 : : struct snd_jack_kctl *jack_kctl = NULL;
203 : : int err;
204 : : static struct snd_device_ops ops = {
205 : : .dev_free = snd_jack_dev_free,
206 : : #ifdef CONFIG_SND_JACK_INPUT_DEV
207 : : .dev_register = snd_jack_dev_register,
208 : : .dev_disconnect = snd_jack_dev_disconnect,
209 : : #endif /* CONFIG_SND_JACK_INPUT_DEV */
210 : : };
211 : :
212 [ # # ]: 0 : if (initial_kctl) {
213 : 0 : jack_kctl = snd_jack_kctl_new(card, id, type);
214 [ # # ]: 0 : if (!jack_kctl)
215 : : return -ENOMEM;
216 : : }
217 : :
218 : 0 : jack = kzalloc(sizeof(struct snd_jack), GFP_KERNEL);
219 [ # # ]: 0 : if (jack == NULL)
220 : : return -ENOMEM;
221 : :
222 : 0 : jack->id = kstrdup(id, GFP_KERNEL);
223 : :
224 : : /* don't creat input device for phantom jack */
225 [ # # ]: 0 : if (!phantom_jack) {
226 : : #ifdef CONFIG_SND_JACK_INPUT_DEV
227 : : int i;
228 : :
229 : 0 : jack->input_dev = input_allocate_device();
230 [ # # ]: 0 : if (jack->input_dev == NULL) {
231 : : err = -ENOMEM;
232 : : goto fail_input;
233 : : }
234 : :
235 : 0 : jack->input_dev->phys = "ALSA";
236 : :
237 : 0 : jack->type = type;
238 : :
239 [ # # ]: 0 : for (i = 0; i < SND_JACK_SWITCH_TYPES; i++)
240 [ # # ]: 0 : if (type & (1 << i))
241 : 0 : input_set_capability(jack->input_dev, EV_SW,
242 : 0 : jack_switch_types[i]);
243 : :
244 : : #endif /* CONFIG_SND_JACK_INPUT_DEV */
245 : : }
246 : :
247 : 0 : err = snd_device_new(card, SNDRV_DEV_JACK, jack, &ops);
248 [ # # ]: 0 : if (err < 0)
249 : : goto fail_input;
250 : :
251 : 0 : jack->card = card;
252 : 0 : INIT_LIST_HEAD(&jack->kctl_list);
253 : :
254 [ # # ]: 0 : if (initial_kctl)
255 : : snd_jack_kctl_add(jack, jack_kctl);
256 : :
257 : 0 : *jjack = jack;
258 : :
259 : 0 : return 0;
260 : :
261 : : fail_input:
262 : : #ifdef CONFIG_SND_JACK_INPUT_DEV
263 : 0 : input_free_device(jack->input_dev);
264 : : #endif
265 : 0 : kfree(jack->id);
266 : 0 : kfree(jack);
267 : 0 : return err;
268 : : }
269 : : EXPORT_SYMBOL(snd_jack_new);
270 : :
271 : : #ifdef CONFIG_SND_JACK_INPUT_DEV
272 : : /**
273 : : * snd_jack_set_parent - Set the parent device for a jack
274 : : *
275 : : * @jack: The jack to configure
276 : : * @parent: The device to set as parent for the jack.
277 : : *
278 : : * Set the parent for the jack devices in the device tree. This
279 : : * function is only valid prior to registration of the jack. If no
280 : : * parent is configured then the parent device will be the sound card.
281 : : */
282 : 0 : void snd_jack_set_parent(struct snd_jack *jack, struct device *parent)
283 : : {
284 [ # # ]: 0 : WARN_ON(jack->registered);
285 [ # # ]: 0 : if (!jack->input_dev)
286 : 0 : return;
287 : :
288 : 0 : jack->input_dev->dev.parent = parent;
289 : : }
290 : : EXPORT_SYMBOL(snd_jack_set_parent);
291 : :
292 : : /**
293 : : * snd_jack_set_key - Set a key mapping on a jack
294 : : *
295 : : * @jack: The jack to configure
296 : : * @type: Jack report type for this key
297 : : * @keytype: Input layer key type to be reported
298 : : *
299 : : * Map a SND_JACK_BTN_* button type to an input layer key, allowing
300 : : * reporting of keys on accessories via the jack abstraction. If no
301 : : * mapping is provided but keys are enabled in the jack type then
302 : : * BTN_n numeric buttons will be reported.
303 : : *
304 : : * If jacks are not reporting via the input API this call will have no
305 : : * effect.
306 : : *
307 : : * Note that this is intended to be use by simple devices with small
308 : : * numbers of keys that can be reported. It is also possible to
309 : : * access the input device directly - devices with complex input
310 : : * capabilities on accessories should consider doing this rather than
311 : : * using this abstraction.
312 : : *
313 : : * This function may only be called prior to registration of the jack.
314 : : *
315 : : * Return: Zero if successful, or a negative error code on failure.
316 : : */
317 : 0 : int snd_jack_set_key(struct snd_jack *jack, enum snd_jack_types type,
318 : : int keytype)
319 : : {
320 : 0 : int key = fls(SND_JACK_BTN_0) - fls(type);
321 : :
322 [ # # ]: 0 : WARN_ON(jack->registered);
323 : :
324 [ # # ]: 0 : if (!keytype || key >= ARRAY_SIZE(jack->key))
325 : : return -EINVAL;
326 : :
327 : 0 : jack->type |= type;
328 : 0 : jack->key[key] = keytype;
329 : 0 : return 0;
330 : : }
331 : : EXPORT_SYMBOL(snd_jack_set_key);
332 : : #endif /* CONFIG_SND_JACK_INPUT_DEV */
333 : :
334 : : /**
335 : : * snd_jack_report - Report the current status of a jack
336 : : *
337 : : * @jack: The jack to report status for
338 : : * @status: The current status of the jack
339 : : */
340 : 0 : void snd_jack_report(struct snd_jack *jack, int status)
341 : : {
342 : : struct snd_jack_kctl *jack_kctl;
343 : : #ifdef CONFIG_SND_JACK_INPUT_DEV
344 : : int i;
345 : : #endif
346 : :
347 [ # # ]: 0 : if (!jack)
348 : : return;
349 : :
350 [ # # ]: 0 : list_for_each_entry(jack_kctl, &jack->kctl_list, list)
351 : 0 : snd_kctl_jack_report(jack->card, jack_kctl->kctl,
352 : 0 : status & jack_kctl->mask_bits);
353 : :
354 : : #ifdef CONFIG_SND_JACK_INPUT_DEV
355 [ # # ]: 0 : if (!jack->input_dev)
356 : : return;
357 : :
358 [ # # ]: 0 : for (i = 0; i < ARRAY_SIZE(jack->key); i++) {
359 : 0 : int testbit = SND_JACK_BTN_0 >> i;
360 : :
361 [ # # ]: 0 : if (jack->type & testbit)
362 : 0 : input_report_key(jack->input_dev, jack->key[i],
363 : : status & testbit);
364 : : }
365 : :
366 [ # # ]: 0 : for (i = 0; i < ARRAY_SIZE(jack_switch_types); i++) {
367 : 0 : int testbit = 1 << i;
368 [ # # ]: 0 : if (jack->type & testbit)
369 : 0 : input_report_switch(jack->input_dev,
370 : 0 : jack_switch_types[i],
371 : : status & testbit);
372 : : }
373 : :
374 : 0 : input_sync(jack->input_dev);
375 : : #endif /* CONFIG_SND_JACK_INPUT_DEV */
376 : : }
377 : : EXPORT_SYMBOL(snd_jack_report);
|