xref: /openbmc/linux/sound/pci/hda/hda_jack.c (revision 01a61e12b4602c82bde9797d0e153f3e53c95b04)
11835a0f9STakashi Iwai /*
21835a0f9STakashi Iwai  * Jack-detection handling for HD-audio
31835a0f9STakashi Iwai  *
41835a0f9STakashi Iwai  * Copyright (c) 2011 Takashi Iwai <tiwai@suse.de>
51835a0f9STakashi Iwai  *
61835a0f9STakashi Iwai  * This driver is free software; you can redistribute it and/or modify
71835a0f9STakashi Iwai  * it under the terms of the GNU General Public License as published by
81835a0f9STakashi Iwai  * the Free Software Foundation; either version 2 of the License, or
91835a0f9STakashi Iwai  * (at your option) any later version.
101835a0f9STakashi Iwai  */
111835a0f9STakashi Iwai 
121835a0f9STakashi Iwai #include <linux/init.h>
131835a0f9STakashi Iwai #include <linux/slab.h>
141835a0f9STakashi Iwai #include <sound/core.h>
15*01a61e12STakashi Iwai #include <sound/control.h>
161835a0f9STakashi Iwai #include "hda_codec.h"
171835a0f9STakashi Iwai #include "hda_local.h"
181835a0f9STakashi Iwai #include "hda_jack.h"
191835a0f9STakashi Iwai 
201835a0f9STakashi Iwai /* execute pin sense measurement */
211835a0f9STakashi Iwai static u32 read_pin_sense(struct hda_codec *codec, hda_nid_t nid)
221835a0f9STakashi Iwai {
231835a0f9STakashi Iwai 	u32 pincap;
241835a0f9STakashi Iwai 
251835a0f9STakashi Iwai 	if (!codec->no_trigger_sense) {
261835a0f9STakashi Iwai 		pincap = snd_hda_query_pin_caps(codec, nid);
271835a0f9STakashi Iwai 		if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */
281835a0f9STakashi Iwai 			snd_hda_codec_read(codec, nid, 0,
291835a0f9STakashi Iwai 					AC_VERB_SET_PIN_SENSE, 0);
301835a0f9STakashi Iwai 	}
311835a0f9STakashi Iwai 	return snd_hda_codec_read(codec, nid, 0,
321835a0f9STakashi Iwai 				  AC_VERB_GET_PIN_SENSE, 0);
331835a0f9STakashi Iwai }
341835a0f9STakashi Iwai 
351835a0f9STakashi Iwai /**
361835a0f9STakashi Iwai  * snd_hda_jack_tbl_get - query the jack-table entry for the given NID
371835a0f9STakashi Iwai  */
381835a0f9STakashi Iwai struct hda_jack_tbl *
391835a0f9STakashi Iwai snd_hda_jack_tbl_get(struct hda_codec *codec, hda_nid_t nid)
401835a0f9STakashi Iwai {
411835a0f9STakashi Iwai 	struct hda_jack_tbl *jack = codec->jacktbl.list;
421835a0f9STakashi Iwai 	int i;
431835a0f9STakashi Iwai 
441835a0f9STakashi Iwai 	if (!nid || !jack)
451835a0f9STakashi Iwai 		return NULL;
461835a0f9STakashi Iwai 	for (i = 0; i < codec->jacktbl.used; i++, jack++)
471835a0f9STakashi Iwai 		if (jack->nid == nid)
481835a0f9STakashi Iwai 			return jack;
491835a0f9STakashi Iwai 	return NULL;
501835a0f9STakashi Iwai }
511835a0f9STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_jack_tbl_get);
521835a0f9STakashi Iwai 
531835a0f9STakashi Iwai /**
541835a0f9STakashi Iwai  * snd_hda_jack_tbl_new - create a jack-table entry for the given NID
551835a0f9STakashi Iwai  */
561835a0f9STakashi Iwai struct hda_jack_tbl *
571835a0f9STakashi Iwai snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid)
581835a0f9STakashi Iwai {
591835a0f9STakashi Iwai 	struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid);
601835a0f9STakashi Iwai 	if (jack)
611835a0f9STakashi Iwai 		return jack;
621835a0f9STakashi Iwai 	snd_array_init(&codec->jacktbl, sizeof(*jack), 16);
631835a0f9STakashi Iwai 	jack = snd_array_new(&codec->jacktbl);
641835a0f9STakashi Iwai 	if (!jack)
651835a0f9STakashi Iwai 		return NULL;
661835a0f9STakashi Iwai 	jack->nid = nid;
671835a0f9STakashi Iwai 	jack->jack_dirty = 1;
681835a0f9STakashi Iwai 	return jack;
691835a0f9STakashi Iwai }
701835a0f9STakashi Iwai 
711835a0f9STakashi Iwai void snd_hda_jack_tbl_clear(struct hda_codec *codec)
721835a0f9STakashi Iwai {
731835a0f9STakashi Iwai 	snd_array_free(&codec->jacktbl);
741835a0f9STakashi Iwai }
751835a0f9STakashi Iwai 
761835a0f9STakashi Iwai /* update the cached value and notification flag if needed */
771835a0f9STakashi Iwai static void jack_detect_update(struct hda_codec *codec,
781835a0f9STakashi Iwai 			       struct hda_jack_tbl *jack)
791835a0f9STakashi Iwai {
80*01a61e12STakashi Iwai 	if (jack->jack_dirty || !jack->jack_cachable) {
81*01a61e12STakashi Iwai 		unsigned int val = read_pin_sense(codec, jack->nid);
821835a0f9STakashi Iwai 		jack->jack_dirty = 0;
83*01a61e12STakashi Iwai 		if (val != jack->pin_sense) {
84*01a61e12STakashi Iwai 			jack->need_notify = 1;
85*01a61e12STakashi Iwai 			jack->pin_sense = val;
86*01a61e12STakashi Iwai 		}
871835a0f9STakashi Iwai 	}
881835a0f9STakashi Iwai }
891835a0f9STakashi Iwai 
901835a0f9STakashi Iwai /**
911835a0f9STakashi Iwai  * snd_hda_set_dirty_all - Mark all the cached as dirty
921835a0f9STakashi Iwai  *
931835a0f9STakashi Iwai  * This function sets the dirty flag to all entries of jack table.
941835a0f9STakashi Iwai  * It's called from the resume path in hda_codec.c.
951835a0f9STakashi Iwai  */
961835a0f9STakashi Iwai void snd_hda_jack_set_dirty_all(struct hda_codec *codec)
971835a0f9STakashi Iwai {
981835a0f9STakashi Iwai 	struct hda_jack_tbl *jack = codec->jacktbl.list;
991835a0f9STakashi Iwai 	int i;
1001835a0f9STakashi Iwai 
1011835a0f9STakashi Iwai 	for (i = 0; i < codec->jacktbl.used; i++, jack++)
1021835a0f9STakashi Iwai 		if (jack->nid)
1031835a0f9STakashi Iwai 			jack->jack_dirty = 1;
1041835a0f9STakashi Iwai }
1051835a0f9STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_jack_set_dirty_all);
1061835a0f9STakashi Iwai 
1071835a0f9STakashi Iwai /**
1081835a0f9STakashi Iwai  * snd_hda_pin_sense - execute pin sense measurement
1091835a0f9STakashi Iwai  * @codec: the CODEC to sense
1101835a0f9STakashi Iwai  * @nid: the pin NID to sense
1111835a0f9STakashi Iwai  *
1121835a0f9STakashi Iwai  * Execute necessary pin sense measurement and return its Presence Detect,
1131835a0f9STakashi Iwai  * Impedance, ELD Valid etc. status bits.
1141835a0f9STakashi Iwai  */
1151835a0f9STakashi Iwai u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid)
1161835a0f9STakashi Iwai {
1171835a0f9STakashi Iwai 	struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid);
1181835a0f9STakashi Iwai 	if (jack) {
1191835a0f9STakashi Iwai 		jack_detect_update(codec, jack);
1201835a0f9STakashi Iwai 		return jack->pin_sense;
1211835a0f9STakashi Iwai 	}
1221835a0f9STakashi Iwai 	return read_pin_sense(codec, nid);
1231835a0f9STakashi Iwai }
1241835a0f9STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_pin_sense);
1251835a0f9STakashi Iwai 
1261835a0f9STakashi Iwai /**
1271835a0f9STakashi Iwai  * snd_hda_jack_detect - query pin Presence Detect status
1281835a0f9STakashi Iwai  * @codec: the CODEC to sense
1291835a0f9STakashi Iwai  * @nid: the pin NID to sense
1301835a0f9STakashi Iwai  *
1311835a0f9STakashi Iwai  * Query and return the pin's Presence Detect status.
1321835a0f9STakashi Iwai  */
1331835a0f9STakashi Iwai int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid)
1341835a0f9STakashi Iwai {
1351835a0f9STakashi Iwai 	u32 sense = snd_hda_pin_sense(codec, nid);
1361835a0f9STakashi Iwai 	return !!(sense & AC_PINSENSE_PRESENCE);
1371835a0f9STakashi Iwai }
1381835a0f9STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_jack_detect);
1391835a0f9STakashi Iwai 
1401835a0f9STakashi Iwai /**
1411835a0f9STakashi Iwai  * snd_hda_jack_detect_enable - enable the jack-detection
1421835a0f9STakashi Iwai  */
1431835a0f9STakashi Iwai int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid,
1441835a0f9STakashi Iwai 			       unsigned int tag)
1451835a0f9STakashi Iwai {
1461835a0f9STakashi Iwai 	struct hda_jack_tbl *jack = snd_hda_jack_tbl_new(codec, nid);
1471835a0f9STakashi Iwai 	if (!jack)
1481835a0f9STakashi Iwai 		return -ENOMEM;
149*01a61e12STakashi Iwai 	if (jack->jack_cachable)
150*01a61e12STakashi Iwai 		return 0; /* already registered */
151*01a61e12STakashi Iwai 	jack->jack_cachable = 1;
1521835a0f9STakashi Iwai 	return snd_hda_codec_write_cache(codec, nid, 0,
1531835a0f9STakashi Iwai 					 AC_VERB_SET_UNSOLICITED_ENABLE,
1541835a0f9STakashi Iwai 					 AC_USRSP_EN | tag);
1551835a0f9STakashi Iwai }
1561835a0f9STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_jack_detect_enable);
157*01a61e12STakashi Iwai 
158*01a61e12STakashi Iwai /* queue the notification when needed */
159*01a61e12STakashi Iwai static void jack_detect_report(struct hda_codec *codec,
160*01a61e12STakashi Iwai 			       struct hda_jack_tbl *jack)
161*01a61e12STakashi Iwai {
162*01a61e12STakashi Iwai 	jack_detect_update(codec, jack);
163*01a61e12STakashi Iwai 	if (jack->need_notify) {
164*01a61e12STakashi Iwai 		snd_ctl_notify(codec->bus->card, SNDRV_CTL_EVENT_MASK_VALUE,
165*01a61e12STakashi Iwai 			       &jack->kctl->id);
166*01a61e12STakashi Iwai 		jack->need_notify = 0;
167*01a61e12STakashi Iwai 	}
168*01a61e12STakashi Iwai }
169*01a61e12STakashi Iwai 
170*01a61e12STakashi Iwai /**
171*01a61e12STakashi Iwai  * snd_hda_jack_report - notify kctl when the jack state was changed
172*01a61e12STakashi Iwai  */
173*01a61e12STakashi Iwai void snd_hda_jack_report(struct hda_codec *codec, hda_nid_t nid)
174*01a61e12STakashi Iwai {
175*01a61e12STakashi Iwai 	struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid);
176*01a61e12STakashi Iwai 
177*01a61e12STakashi Iwai 	if (jack)
178*01a61e12STakashi Iwai 		jack_detect_report(codec, jack);
179*01a61e12STakashi Iwai }
180*01a61e12STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_jack_report);
181*01a61e12STakashi Iwai 
182*01a61e12STakashi Iwai /**
183*01a61e12STakashi Iwai  * snd_hda_jack_report_sync - sync the states of all jacks and report if changed
184*01a61e12STakashi Iwai  */
185*01a61e12STakashi Iwai void snd_hda_jack_report_sync(struct hda_codec *codec)
186*01a61e12STakashi Iwai {
187*01a61e12STakashi Iwai 	struct hda_jack_tbl *jack = codec->jacktbl.list;
188*01a61e12STakashi Iwai 	int i;
189*01a61e12STakashi Iwai 
190*01a61e12STakashi Iwai 	for (i = 0; i < codec->jacktbl.used; i++, jack++)
191*01a61e12STakashi Iwai 		if (jack->nid) {
192*01a61e12STakashi Iwai 			jack_detect_update(codec, jack);
193*01a61e12STakashi Iwai 			jack_detect_report(codec, jack);
194*01a61e12STakashi Iwai 		}
195*01a61e12STakashi Iwai }
196*01a61e12STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_jack_report_sync);
197*01a61e12STakashi Iwai 
198*01a61e12STakashi Iwai /*
199*01a61e12STakashi Iwai  * jack-detection kcontrols
200*01a61e12STakashi Iwai  */
201*01a61e12STakashi Iwai 
202*01a61e12STakashi Iwai #define jack_detect_kctl_info	snd_ctl_boolean_mono_info
203*01a61e12STakashi Iwai 
204*01a61e12STakashi Iwai static int jack_detect_kctl_get(struct snd_kcontrol *kcontrol,
205*01a61e12STakashi Iwai 				struct snd_ctl_elem_value *ucontrol)
206*01a61e12STakashi Iwai {
207*01a61e12STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
208*01a61e12STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
209*01a61e12STakashi Iwai 
210*01a61e12STakashi Iwai 	ucontrol->value.integer.value[0] = snd_hda_jack_detect(codec, nid);
211*01a61e12STakashi Iwai 	return 0;
212*01a61e12STakashi Iwai }
213*01a61e12STakashi Iwai 
214*01a61e12STakashi Iwai static struct snd_kcontrol_new jack_detect_kctl = {
215*01a61e12STakashi Iwai 	/* name is filled later */
216*01a61e12STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_CARD,
217*01a61e12STakashi Iwai 	.access = SNDRV_CTL_ELEM_ACCESS_READ,
218*01a61e12STakashi Iwai 	.info = jack_detect_kctl_info,
219*01a61e12STakashi Iwai 	.get = jack_detect_kctl_get,
220*01a61e12STakashi Iwai };
221*01a61e12STakashi Iwai 
222*01a61e12STakashi Iwai /**
223*01a61e12STakashi Iwai  * snd_hda_jack_add_kctl - Add a kctl for the given pin
224*01a61e12STakashi Iwai  *
225*01a61e12STakashi Iwai  * This assigns a jack-detection kctl to the given pin.  The kcontrol
226*01a61e12STakashi Iwai  * will have the given name and index.
227*01a61e12STakashi Iwai  */
228*01a61e12STakashi Iwai int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,
229*01a61e12STakashi Iwai 			  const char *name, int idx)
230*01a61e12STakashi Iwai {
231*01a61e12STakashi Iwai 	struct hda_jack_tbl *jack;
232*01a61e12STakashi Iwai 	struct snd_kcontrol *kctl;
233*01a61e12STakashi Iwai 
234*01a61e12STakashi Iwai 	jack = snd_hda_jack_tbl_get(codec, nid);
235*01a61e12STakashi Iwai 	if (!jack)
236*01a61e12STakashi Iwai 		return 0;
237*01a61e12STakashi Iwai 	if (jack->kctl)
238*01a61e12STakashi Iwai 		return 0; /* already created */
239*01a61e12STakashi Iwai 	kctl = snd_ctl_new1(&jack_detect_kctl, codec);
240*01a61e12STakashi Iwai 	if (!kctl)
241*01a61e12STakashi Iwai 		return -ENOMEM;
242*01a61e12STakashi Iwai 	snprintf(kctl->id.name, sizeof(kctl->id.name), "%s Jack", name);
243*01a61e12STakashi Iwai 	kctl->id.index = idx;
244*01a61e12STakashi Iwai 	kctl->private_value = nid;
245*01a61e12STakashi Iwai 	if (snd_hda_ctl_add(codec, nid, kctl) < 0)
246*01a61e12STakashi Iwai 		return -ENOMEM;
247*01a61e12STakashi Iwai 	jack->kctl = kctl;
248*01a61e12STakashi Iwai 	return 0;
249*01a61e12STakashi Iwai }
250*01a61e12STakashi Iwai 
251*01a61e12STakashi Iwai static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, int idx,
252*01a61e12STakashi Iwai 			 const struct auto_pin_cfg *cfg)
253*01a61e12STakashi Iwai {
254*01a61e12STakashi Iwai 	if (!nid)
255*01a61e12STakashi Iwai 		return 0;
256*01a61e12STakashi Iwai 	if (!is_jack_detectable(codec, nid))
257*01a61e12STakashi Iwai 		return 0;
258*01a61e12STakashi Iwai 	return snd_hda_jack_add_kctl(codec, nid,
259*01a61e12STakashi Iwai 				     snd_hda_get_pin_label(codec, nid, cfg),
260*01a61e12STakashi Iwai 				     idx);
261*01a61e12STakashi Iwai }
262*01a61e12STakashi Iwai 
263*01a61e12STakashi Iwai /**
264*01a61e12STakashi Iwai  * snd_hda_jack_add_kctls - Add kctls for all pins included in the given pincfg
265*01a61e12STakashi Iwai  *
266*01a61e12STakashi Iwai  * As of now, it assigns only to the pins that enabled the detection.
267*01a61e12STakashi Iwai  * Usually this is called at the end of build_controls callback.
268*01a61e12STakashi Iwai  */
269*01a61e12STakashi Iwai int snd_hda_jack_add_kctls(struct hda_codec *codec,
270*01a61e12STakashi Iwai 			   const struct auto_pin_cfg *cfg)
271*01a61e12STakashi Iwai {
272*01a61e12STakashi Iwai 	const hda_nid_t *p;
273*01a61e12STakashi Iwai 	int i, err;
274*01a61e12STakashi Iwai 
275*01a61e12STakashi Iwai 	for (i = 0, p = cfg->line_out_pins; i < cfg->line_outs; i++, p++) {
276*01a61e12STakashi Iwai 		err = add_jack_kctl(codec, *p, i, cfg);
277*01a61e12STakashi Iwai 		if (err < 0)
278*01a61e12STakashi Iwai 			return err;
279*01a61e12STakashi Iwai 	}
280*01a61e12STakashi Iwai 	for (i = 0, p = cfg->hp_pins; i < cfg->hp_outs; i++, p++) {
281*01a61e12STakashi Iwai 		if (*p == *cfg->line_out_pins) /* might be duplicated */
282*01a61e12STakashi Iwai 			break;
283*01a61e12STakashi Iwai 		err = add_jack_kctl(codec, *p, i, cfg);
284*01a61e12STakashi Iwai 		if (err < 0)
285*01a61e12STakashi Iwai 			return err;
286*01a61e12STakashi Iwai 	}
287*01a61e12STakashi Iwai 	for (i = 0, p = cfg->speaker_pins; i < cfg->speaker_outs; i++, p++) {
288*01a61e12STakashi Iwai 		if (*p == *cfg->line_out_pins) /* might be duplicated */
289*01a61e12STakashi Iwai 			break;
290*01a61e12STakashi Iwai 		err = add_jack_kctl(codec, *p, i, cfg);
291*01a61e12STakashi Iwai 		if (err < 0)
292*01a61e12STakashi Iwai 			return err;
293*01a61e12STakashi Iwai 	}
294*01a61e12STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
295*01a61e12STakashi Iwai 		err = add_jack_kctl(codec, cfg->inputs[i].pin, 0, cfg);
296*01a61e12STakashi Iwai 		if (err < 0)
297*01a61e12STakashi Iwai 			return err;
298*01a61e12STakashi Iwai 	}
299*01a61e12STakashi Iwai 	for (i = 0, p = cfg->dig_out_pins; i < cfg->dig_outs; i++, p++) {
300*01a61e12STakashi Iwai 		err = add_jack_kctl(codec, *p, i, cfg);
301*01a61e12STakashi Iwai 		if (err < 0)
302*01a61e12STakashi Iwai 			return err;
303*01a61e12STakashi Iwai 	}
304*01a61e12STakashi Iwai 	err = add_jack_kctl(codec, cfg->dig_in_pin, 0, cfg);
305*01a61e12STakashi Iwai 	if (err < 0)
306*01a61e12STakashi Iwai 		return err;
307*01a61e12STakashi Iwai 	err = add_jack_kctl(codec, cfg->mono_out_pin, 0, cfg);
308*01a61e12STakashi Iwai 	if (err < 0)
309*01a61e12STakashi Iwai 		return err;
310*01a61e12STakashi Iwai 	return 0;
311*01a61e12STakashi Iwai }
312*01a61e12STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctls);
313