blob: ac7e57c403981623d3a8cb21b3e914719c495d89 [file] [log] [blame]
Takashi Iwai1835a0f2011-10-27 22:12:46 +02001/*
2 * Jack-detection handling for HD-audio
3 *
4 * Copyright (c) 2011 Takashi Iwai <tiwai@suse.de>
5 *
6 * This driver is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#include <linux/init.h>
13#include <linux/slab.h>
Takashi Iwaibf815bf2011-11-16 14:28:33 +010014#include <linux/export.h>
Takashi Iwai1835a0f2011-10-27 22:12:46 +020015#include <sound/core.h>
Takashi Iwai01a61e12011-10-28 00:03:22 +020016#include <sound/control.h>
Takashi Iwaiaad37db2011-11-02 08:54:51 +010017#include <sound/jack.h>
Takashi Iwai1835a0f2011-10-27 22:12:46 +020018#include "hda_codec.h"
19#include "hda_local.h"
20#include "hda_jack.h"
21
Takashi Iwaia9c74172012-02-13 11:41:42 +010022bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid)
23{
24 if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_PRES_DETECT))
25 return false;
26 if (!codec->ignore_misc_bit &&
27 (get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) &
28 AC_DEFCFG_MISC_NO_PRESENCE))
29 return false;
30 if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP))
31 return false;
32 return true;
33}
34EXPORT_SYMBOL_HDA(is_jack_detectable);
35
Takashi Iwai1835a0f2011-10-27 22:12:46 +020036/* execute pin sense measurement */
37static u32 read_pin_sense(struct hda_codec *codec, hda_nid_t nid)
38{
39 u32 pincap;
40
41 if (!codec->no_trigger_sense) {
42 pincap = snd_hda_query_pin_caps(codec, nid);
43 if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */
44 snd_hda_codec_read(codec, nid, 0,
45 AC_VERB_SET_PIN_SENSE, 0);
46 }
47 return snd_hda_codec_read(codec, nid, 0,
48 AC_VERB_GET_PIN_SENSE, 0);
49}
50
51/**
52 * snd_hda_jack_tbl_get - query the jack-table entry for the given NID
53 */
54struct hda_jack_tbl *
55snd_hda_jack_tbl_get(struct hda_codec *codec, hda_nid_t nid)
56{
57 struct hda_jack_tbl *jack = codec->jacktbl.list;
58 int i;
59
60 if (!nid || !jack)
61 return NULL;
62 for (i = 0; i < codec->jacktbl.used; i++, jack++)
63 if (jack->nid == nid)
64 return jack;
65 return NULL;
66}
67EXPORT_SYMBOL_HDA(snd_hda_jack_tbl_get);
68
69/**
Takashi Iwai3a938972011-10-28 01:16:55 +020070 * snd_hda_jack_tbl_get_from_tag - query the jack-table entry for the given tag
71 */
72struct hda_jack_tbl *
73snd_hda_jack_tbl_get_from_tag(struct hda_codec *codec, unsigned char tag)
74{
75 struct hda_jack_tbl *jack = codec->jacktbl.list;
76 int i;
77
78 if (!tag || !jack)
79 return NULL;
80 for (i = 0; i < codec->jacktbl.used; i++, jack++)
81 if (jack->tag == tag)
82 return jack;
83 return NULL;
84}
85EXPORT_SYMBOL_HDA(snd_hda_jack_tbl_get_from_tag);
86
87/**
Takashi Iwai1835a0f2011-10-27 22:12:46 +020088 * snd_hda_jack_tbl_new - create a jack-table entry for the given NID
89 */
90struct hda_jack_tbl *
91snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid)
92{
93 struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid);
94 if (jack)
95 return jack;
96 snd_array_init(&codec->jacktbl, sizeof(*jack), 16);
97 jack = snd_array_new(&codec->jacktbl);
98 if (!jack)
99 return NULL;
100 jack->nid = nid;
101 jack->jack_dirty = 1;
Takashi Iwai3a938972011-10-28 01:16:55 +0200102 jack->tag = codec->jacktbl.used;
Takashi Iwai1835a0f2011-10-27 22:12:46 +0200103 return jack;
104}
David Henningssond1cb6202011-11-11 17:13:15 +0100105EXPORT_SYMBOL_HDA(snd_hda_jack_tbl_new);
Takashi Iwai1835a0f2011-10-27 22:12:46 +0200106
107void snd_hda_jack_tbl_clear(struct hda_codec *codec)
108{
Takashi Iwai31ef2252011-12-01 17:41:36 +0100109#ifdef CONFIG_SND_HDA_INPUT_JACK
110 /* free jack instances manually when clearing/reconfiguring */
111 if (!codec->bus->shutdown && codec->jacktbl.list) {
112 struct hda_jack_tbl *jack = codec->jacktbl.list;
113 int i;
114 for (i = 0; i < codec->jacktbl.used; i++, jack++) {
115 if (jack->jack)
116 snd_device_free(codec->bus->card, jack->jack);
117 }
118 }
119#endif
Takashi Iwai1835a0f2011-10-27 22:12:46 +0200120 snd_array_free(&codec->jacktbl);
121}
122
123/* update the cached value and notification flag if needed */
124static void jack_detect_update(struct hda_codec *codec,
125 struct hda_jack_tbl *jack)
126{
Takashi Iwai3a938972011-10-28 01:16:55 +0200127 if (jack->jack_dirty || !jack->jack_detect) {
Takashi Iwai35be5442011-11-02 08:36:06 +0100128 jack->pin_sense = read_pin_sense(codec, jack->nid);
Takashi Iwai1835a0f2011-10-27 22:12:46 +0200129 jack->jack_dirty = 0;
130 }
131}
132
133/**
134 * snd_hda_set_dirty_all - Mark all the cached as dirty
135 *
136 * This function sets the dirty flag to all entries of jack table.
137 * It's called from the resume path in hda_codec.c.
138 */
139void snd_hda_jack_set_dirty_all(struct hda_codec *codec)
140{
141 struct hda_jack_tbl *jack = codec->jacktbl.list;
142 int i;
143
144 for (i = 0; i < codec->jacktbl.used; i++, jack++)
145 if (jack->nid)
146 jack->jack_dirty = 1;
147}
148EXPORT_SYMBOL_HDA(snd_hda_jack_set_dirty_all);
149
150/**
151 * snd_hda_pin_sense - execute pin sense measurement
152 * @codec: the CODEC to sense
153 * @nid: the pin NID to sense
154 *
155 * Execute necessary pin sense measurement and return its Presence Detect,
156 * Impedance, ELD Valid etc. status bits.
157 */
158u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid)
159{
160 struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid);
161 if (jack) {
162 jack_detect_update(codec, jack);
163 return jack->pin_sense;
164 }
165 return read_pin_sense(codec, nid);
166}
167EXPORT_SYMBOL_HDA(snd_hda_pin_sense);
168
Takashi Iwai35be5442011-11-02 08:36:06 +0100169#define get_jack_plug_state(sense) !!(sense & AC_PINSENSE_PRESENCE)
170
Takashi Iwai1835a0f2011-10-27 22:12:46 +0200171/**
172 * snd_hda_jack_detect - query pin Presence Detect status
173 * @codec: the CODEC to sense
174 * @nid: the pin NID to sense
175 *
176 * Query and return the pin's Presence Detect status.
177 */
178int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid)
179{
180 u32 sense = snd_hda_pin_sense(codec, nid);
Takashi Iwai35be5442011-11-02 08:36:06 +0100181 return get_jack_plug_state(sense);
Takashi Iwai1835a0f2011-10-27 22:12:46 +0200182}
183EXPORT_SYMBOL_HDA(snd_hda_jack_detect);
184
185/**
186 * snd_hda_jack_detect_enable - enable the jack-detection
187 */
188int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid,
Takashi Iwai3a938972011-10-28 01:16:55 +0200189 unsigned char action)
Takashi Iwai1835a0f2011-10-27 22:12:46 +0200190{
191 struct hda_jack_tbl *jack = snd_hda_jack_tbl_new(codec, nid);
192 if (!jack)
193 return -ENOMEM;
Takashi Iwai3a938972011-10-28 01:16:55 +0200194 if (jack->jack_detect)
Takashi Iwai01a61e12011-10-28 00:03:22 +0200195 return 0; /* already registered */
Takashi Iwai3a938972011-10-28 01:16:55 +0200196 jack->jack_detect = 1;
197 if (action)
198 jack->action = action;
Takashi Iwai1835a0f2011-10-27 22:12:46 +0200199 return snd_hda_codec_write_cache(codec, nid, 0,
200 AC_VERB_SET_UNSOLICITED_ENABLE,
Takashi Iwai3a938972011-10-28 01:16:55 +0200201 AC_USRSP_EN | jack->tag);
Takashi Iwai1835a0f2011-10-27 22:12:46 +0200202}
203EXPORT_SYMBOL_HDA(snd_hda_jack_detect_enable);
Takashi Iwai01a61e12011-10-28 00:03:22 +0200204
Takashi Iwai01a61e12011-10-28 00:03:22 +0200205/**
Takashi Iwai01a61e12011-10-28 00:03:22 +0200206 * snd_hda_jack_report_sync - sync the states of all jacks and report if changed
207 */
208void snd_hda_jack_report_sync(struct hda_codec *codec)
209{
210 struct hda_jack_tbl *jack = codec->jacktbl.list;
Takashi Iwai35be5442011-11-02 08:36:06 +0100211 int i, state;
Takashi Iwai01a61e12011-10-28 00:03:22 +0200212
213 for (i = 0; i < codec->jacktbl.used; i++, jack++)
214 if (jack->nid) {
215 jack_detect_update(codec, jack);
Takashi Iwaicfc7c9d2011-11-11 17:53:03 +0100216 if (!jack->kctl)
217 continue;
Takashi Iwai35be5442011-11-02 08:36:06 +0100218 state = get_jack_plug_state(jack->pin_sense);
Takashi Iwaiaad37db2011-11-02 08:54:51 +0100219 snd_kctl_jack_report(codec->bus->card, jack->kctl, state);
Takashi Iwai31ef2252011-12-01 17:41:36 +0100220#ifdef CONFIG_SND_HDA_INPUT_JACK
221 if (jack->jack)
222 snd_jack_report(jack->jack,
223 state ? jack->type : 0);
224#endif
Takashi Iwai01a61e12011-10-28 00:03:22 +0200225 }
226}
227EXPORT_SYMBOL_HDA(snd_hda_jack_report_sync);
228
Takashi Iwai31ef2252011-12-01 17:41:36 +0100229#ifdef CONFIG_SND_HDA_INPUT_JACK
230/* guess the jack type from the pin-config */
231static int get_input_jack_type(struct hda_codec *codec, hda_nid_t nid)
232{
233 unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid);
234 switch (get_defcfg_device(def_conf)) {
235 case AC_JACK_LINE_OUT:
236 case AC_JACK_SPEAKER:
237 return SND_JACK_LINEOUT;
238 case AC_JACK_HP_OUT:
239 return SND_JACK_HEADPHONE;
240 case AC_JACK_SPDIF_OUT:
241 case AC_JACK_DIG_OTHER_OUT:
242 return SND_JACK_AVOUT;
243 case AC_JACK_MIC_IN:
244 return SND_JACK_MICROPHONE;
245 default:
246 return SND_JACK_LINEIN;
247 }
248}
249
250static void hda_free_jack_priv(struct snd_jack *jack)
251{
252 struct hda_jack_tbl *jacks = jack->private_data;
253 jacks->nid = 0;
254 jacks->jack = NULL;
255}
256#endif
257
Takashi Iwai01a61e12011-10-28 00:03:22 +0200258/**
259 * snd_hda_jack_add_kctl - Add a kctl for the given pin
260 *
261 * This assigns a jack-detection kctl to the given pin. The kcontrol
262 * will have the given name and index.
263 */
264int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,
265 const char *name, int idx)
266{
267 struct hda_jack_tbl *jack;
268 struct snd_kcontrol *kctl;
Takashi Iwai31ef2252011-12-01 17:41:36 +0100269 int err, state;
Takashi Iwai01a61e12011-10-28 00:03:22 +0200270
Takashi Iwai3a938972011-10-28 01:16:55 +0200271 jack = snd_hda_jack_tbl_new(codec, nid);
Takashi Iwai01a61e12011-10-28 00:03:22 +0200272 if (!jack)
273 return 0;
274 if (jack->kctl)
275 return 0; /* already created */
Takashi Iwai35be5442011-11-02 08:36:06 +0100276 kctl = snd_kctl_jack_new(name, idx, codec);
Takashi Iwai01a61e12011-10-28 00:03:22 +0200277 if (!kctl)
278 return -ENOMEM;
Takashi Iwai31ef2252011-12-01 17:41:36 +0100279 err = snd_hda_ctl_add(codec, nid, kctl);
280 if (err < 0)
281 return err;
Takashi Iwai01a61e12011-10-28 00:03:22 +0200282 jack->kctl = kctl;
Takashi Iwai31ef2252011-12-01 17:41:36 +0100283 state = snd_hda_jack_detect(codec, nid);
284 snd_kctl_jack_report(codec->bus->card, kctl, state);
285#ifdef CONFIG_SND_HDA_INPUT_JACK
286 jack->type = get_input_jack_type(codec, nid);
287 err = snd_jack_new(codec->bus->card, name, jack->type, &jack->jack);
288 if (err < 0)
289 return err;
290 jack->jack->private_data = jack;
291 jack->jack->private_free = hda_free_jack_priv;
292 snd_jack_report(jack->jack, state ? jack->type : 0);
293#endif
Takashi Iwai01a61e12011-10-28 00:03:22 +0200294 return 0;
295}
David Henningssond1cb6202011-11-11 17:13:15 +0100296EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctl);
Takashi Iwai01a61e12011-10-28 00:03:22 +0200297
Takashi Iwai201e06f2011-11-16 15:33:26 +0100298static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid,
David Henningsson05c3b362012-01-31 09:04:15 +0100299 const struct auto_pin_cfg *cfg,
300 char *lastname, int *lastidx)
Takashi Iwai01a61e12011-10-28 00:03:22 +0200301{
Takashi Iwai3a938972011-10-28 01:16:55 +0200302 unsigned int def_conf, conn;
Takashi Iwai201e06f2011-11-16 15:33:26 +0100303 char name[44];
304 int idx, err;
Takashi Iwai3a938972011-10-28 01:16:55 +0200305
Takashi Iwai01a61e12011-10-28 00:03:22 +0200306 if (!nid)
307 return 0;
308 if (!is_jack_detectable(codec, nid))
309 return 0;
Takashi Iwai3a938972011-10-28 01:16:55 +0200310 def_conf = snd_hda_codec_get_pincfg(codec, nid);
311 conn = get_defcfg_connect(def_conf);
312 if (conn != AC_JACK_PORT_COMPLEX)
313 return 0;
314
Takashi Iwai201e06f2011-11-16 15:33:26 +0100315 snd_hda_get_pin_label(codec, nid, cfg, name, sizeof(name), &idx);
David Henningsson05c3b362012-01-31 09:04:15 +0100316 if (!strcmp(name, lastname) && idx == *lastidx)
317 idx++;
318 strncpy(lastname, name, 44);
319 *lastidx = idx;
Takashi Iwai201e06f2011-11-16 15:33:26 +0100320 err = snd_hda_jack_add_kctl(codec, nid, name, idx);
Takashi Iwai3a938972011-10-28 01:16:55 +0200321 if (err < 0)
322 return err;
323 return snd_hda_jack_detect_enable(codec, nid, 0);
Takashi Iwai01a61e12011-10-28 00:03:22 +0200324}
325
326/**
327 * snd_hda_jack_add_kctls - Add kctls for all pins included in the given pincfg
Takashi Iwai01a61e12011-10-28 00:03:22 +0200328 */
329int snd_hda_jack_add_kctls(struct hda_codec *codec,
330 const struct auto_pin_cfg *cfg)
331{
332 const hda_nid_t *p;
David Henningsson05c3b362012-01-31 09:04:15 +0100333 int i, err, lastidx = 0;
334 char lastname[44] = "";
Takashi Iwai01a61e12011-10-28 00:03:22 +0200335
336 for (i = 0, p = cfg->line_out_pins; i < cfg->line_outs; i++, p++) {
David Henningsson05c3b362012-01-31 09:04:15 +0100337 err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx);
Takashi Iwai01a61e12011-10-28 00:03:22 +0200338 if (err < 0)
339 return err;
340 }
341 for (i = 0, p = cfg->hp_pins; i < cfg->hp_outs; i++, p++) {
342 if (*p == *cfg->line_out_pins) /* might be duplicated */
343 break;
David Henningsson05c3b362012-01-31 09:04:15 +0100344 err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx);
Takashi Iwai01a61e12011-10-28 00:03:22 +0200345 if (err < 0)
346 return err;
347 }
348 for (i = 0, p = cfg->speaker_pins; i < cfg->speaker_outs; i++, p++) {
349 if (*p == *cfg->line_out_pins) /* might be duplicated */
350 break;
David Henningsson05c3b362012-01-31 09:04:15 +0100351 err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx);
Takashi Iwai01a61e12011-10-28 00:03:22 +0200352 if (err < 0)
353 return err;
354 }
355 for (i = 0; i < cfg->num_inputs; i++) {
David Henningsson05c3b362012-01-31 09:04:15 +0100356 err = add_jack_kctl(codec, cfg->inputs[i].pin, cfg, lastname, &lastidx);
Takashi Iwai01a61e12011-10-28 00:03:22 +0200357 if (err < 0)
358 return err;
359 }
360 for (i = 0, p = cfg->dig_out_pins; i < cfg->dig_outs; i++, p++) {
David Henningsson05c3b362012-01-31 09:04:15 +0100361 err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx);
Takashi Iwai01a61e12011-10-28 00:03:22 +0200362 if (err < 0)
363 return err;
364 }
David Henningsson05c3b362012-01-31 09:04:15 +0100365 err = add_jack_kctl(codec, cfg->dig_in_pin, cfg, lastname, &lastidx);
Takashi Iwai01a61e12011-10-28 00:03:22 +0200366 if (err < 0)
367 return err;
David Henningsson05c3b362012-01-31 09:04:15 +0100368 err = add_jack_kctl(codec, cfg->mono_out_pin, cfg, lastname, &lastidx);
Takashi Iwai01a61e12011-10-28 00:03:22 +0200369 if (err < 0)
370 return err;
371 return 0;
372}
373EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctls);