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> 1501a61e12STakashi Iwai #include <sound/control.h> 16aad37dbdSTakashi Iwai #include <sound/jack.h> 171835a0f9STakashi Iwai #include "hda_codec.h" 181835a0f9STakashi Iwai #include "hda_local.h" 191835a0f9STakashi Iwai #include "hda_jack.h" 201835a0f9STakashi Iwai 211835a0f9STakashi Iwai /* execute pin sense measurement */ 221835a0f9STakashi Iwai static u32 read_pin_sense(struct hda_codec *codec, hda_nid_t nid) 231835a0f9STakashi Iwai { 241835a0f9STakashi Iwai u32 pincap; 251835a0f9STakashi Iwai 261835a0f9STakashi Iwai if (!codec->no_trigger_sense) { 271835a0f9STakashi Iwai pincap = snd_hda_query_pin_caps(codec, nid); 281835a0f9STakashi Iwai if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */ 291835a0f9STakashi Iwai snd_hda_codec_read(codec, nid, 0, 301835a0f9STakashi Iwai AC_VERB_SET_PIN_SENSE, 0); 311835a0f9STakashi Iwai } 321835a0f9STakashi Iwai return snd_hda_codec_read(codec, nid, 0, 331835a0f9STakashi Iwai AC_VERB_GET_PIN_SENSE, 0); 341835a0f9STakashi Iwai } 351835a0f9STakashi Iwai 361835a0f9STakashi Iwai /** 371835a0f9STakashi Iwai * snd_hda_jack_tbl_get - query the jack-table entry for the given NID 381835a0f9STakashi Iwai */ 391835a0f9STakashi Iwai struct hda_jack_tbl * 401835a0f9STakashi Iwai snd_hda_jack_tbl_get(struct hda_codec *codec, hda_nid_t nid) 411835a0f9STakashi Iwai { 421835a0f9STakashi Iwai struct hda_jack_tbl *jack = codec->jacktbl.list; 431835a0f9STakashi Iwai int i; 441835a0f9STakashi Iwai 451835a0f9STakashi Iwai if (!nid || !jack) 461835a0f9STakashi Iwai return NULL; 471835a0f9STakashi Iwai for (i = 0; i < codec->jacktbl.used; i++, jack++) 481835a0f9STakashi Iwai if (jack->nid == nid) 491835a0f9STakashi Iwai return jack; 501835a0f9STakashi Iwai return NULL; 511835a0f9STakashi Iwai } 521835a0f9STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_jack_tbl_get); 531835a0f9STakashi Iwai 541835a0f9STakashi Iwai /** 553a93897eSTakashi Iwai * snd_hda_jack_tbl_get_from_tag - query the jack-table entry for the given tag 563a93897eSTakashi Iwai */ 573a93897eSTakashi Iwai struct hda_jack_tbl * 583a93897eSTakashi Iwai snd_hda_jack_tbl_get_from_tag(struct hda_codec *codec, unsigned char tag) 593a93897eSTakashi Iwai { 603a93897eSTakashi Iwai struct hda_jack_tbl *jack = codec->jacktbl.list; 613a93897eSTakashi Iwai int i; 623a93897eSTakashi Iwai 633a93897eSTakashi Iwai if (!tag || !jack) 643a93897eSTakashi Iwai return NULL; 653a93897eSTakashi Iwai for (i = 0; i < codec->jacktbl.used; i++, jack++) 663a93897eSTakashi Iwai if (jack->tag == tag) 673a93897eSTakashi Iwai return jack; 683a93897eSTakashi Iwai return NULL; 693a93897eSTakashi Iwai } 703a93897eSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_jack_tbl_get_from_tag); 713a93897eSTakashi Iwai 723a93897eSTakashi Iwai /** 731835a0f9STakashi Iwai * snd_hda_jack_tbl_new - create a jack-table entry for the given NID 741835a0f9STakashi Iwai */ 751835a0f9STakashi Iwai struct hda_jack_tbl * 761835a0f9STakashi Iwai snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid) 771835a0f9STakashi Iwai { 781835a0f9STakashi Iwai struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid); 791835a0f9STakashi Iwai if (jack) 801835a0f9STakashi Iwai return jack; 811835a0f9STakashi Iwai snd_array_init(&codec->jacktbl, sizeof(*jack), 16); 821835a0f9STakashi Iwai jack = snd_array_new(&codec->jacktbl); 831835a0f9STakashi Iwai if (!jack) 841835a0f9STakashi Iwai return NULL; 851835a0f9STakashi Iwai jack->nid = nid; 861835a0f9STakashi Iwai jack->jack_dirty = 1; 873a93897eSTakashi Iwai jack->tag = codec->jacktbl.used; 881835a0f9STakashi Iwai return jack; 891835a0f9STakashi Iwai } 90d1cb6200SDavid Henningsson EXPORT_SYMBOL_HDA(snd_hda_jack_tbl_new); 911835a0f9STakashi Iwai 92aad37dbdSTakashi Iwai #ifdef CONFIG_SND_HDA_INPUT_JACK 93aad37dbdSTakashi Iwai static void snd_hda_input_jack_free(struct hda_codec *codec); 94aad37dbdSTakashi Iwai #else 95aad37dbdSTakashi Iwai #define snd_hda_input_jack_free(codec) 96aad37dbdSTakashi Iwai #endif 97aad37dbdSTakashi Iwai 981835a0f9STakashi Iwai void snd_hda_jack_tbl_clear(struct hda_codec *codec) 991835a0f9STakashi Iwai { 100aad37dbdSTakashi Iwai snd_hda_input_jack_free(codec); 1011835a0f9STakashi Iwai snd_array_free(&codec->jacktbl); 1021835a0f9STakashi Iwai } 1031835a0f9STakashi Iwai 1041835a0f9STakashi Iwai /* update the cached value and notification flag if needed */ 1051835a0f9STakashi Iwai static void jack_detect_update(struct hda_codec *codec, 1061835a0f9STakashi Iwai struct hda_jack_tbl *jack) 1071835a0f9STakashi Iwai { 1083a93897eSTakashi Iwai if (jack->jack_dirty || !jack->jack_detect) { 10935be544aSTakashi Iwai jack->pin_sense = read_pin_sense(codec, jack->nid); 1101835a0f9STakashi Iwai jack->jack_dirty = 0; 1111835a0f9STakashi Iwai } 1121835a0f9STakashi Iwai } 1131835a0f9STakashi Iwai 1141835a0f9STakashi Iwai /** 1151835a0f9STakashi Iwai * snd_hda_set_dirty_all - Mark all the cached as dirty 1161835a0f9STakashi Iwai * 1171835a0f9STakashi Iwai * This function sets the dirty flag to all entries of jack table. 1181835a0f9STakashi Iwai * It's called from the resume path in hda_codec.c. 1191835a0f9STakashi Iwai */ 1201835a0f9STakashi Iwai void snd_hda_jack_set_dirty_all(struct hda_codec *codec) 1211835a0f9STakashi Iwai { 1221835a0f9STakashi Iwai struct hda_jack_tbl *jack = codec->jacktbl.list; 1231835a0f9STakashi Iwai int i; 1241835a0f9STakashi Iwai 1251835a0f9STakashi Iwai for (i = 0; i < codec->jacktbl.used; i++, jack++) 1261835a0f9STakashi Iwai if (jack->nid) 1271835a0f9STakashi Iwai jack->jack_dirty = 1; 1281835a0f9STakashi Iwai } 1291835a0f9STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_jack_set_dirty_all); 1301835a0f9STakashi Iwai 1311835a0f9STakashi Iwai /** 1321835a0f9STakashi Iwai * snd_hda_pin_sense - execute pin sense measurement 1331835a0f9STakashi Iwai * @codec: the CODEC to sense 1341835a0f9STakashi Iwai * @nid: the pin NID to sense 1351835a0f9STakashi Iwai * 1361835a0f9STakashi Iwai * Execute necessary pin sense measurement and return its Presence Detect, 1371835a0f9STakashi Iwai * Impedance, ELD Valid etc. status bits. 1381835a0f9STakashi Iwai */ 1391835a0f9STakashi Iwai u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid) 1401835a0f9STakashi Iwai { 1411835a0f9STakashi Iwai struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid); 1421835a0f9STakashi Iwai if (jack) { 1431835a0f9STakashi Iwai jack_detect_update(codec, jack); 1441835a0f9STakashi Iwai return jack->pin_sense; 1451835a0f9STakashi Iwai } 1461835a0f9STakashi Iwai return read_pin_sense(codec, nid); 1471835a0f9STakashi Iwai } 1481835a0f9STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_pin_sense); 1491835a0f9STakashi Iwai 15035be544aSTakashi Iwai #define get_jack_plug_state(sense) !!(sense & AC_PINSENSE_PRESENCE) 15135be544aSTakashi Iwai 1521835a0f9STakashi Iwai /** 1531835a0f9STakashi Iwai * snd_hda_jack_detect - query pin Presence Detect status 1541835a0f9STakashi Iwai * @codec: the CODEC to sense 1551835a0f9STakashi Iwai * @nid: the pin NID to sense 1561835a0f9STakashi Iwai * 1571835a0f9STakashi Iwai * Query and return the pin's Presence Detect status. 1581835a0f9STakashi Iwai */ 1591835a0f9STakashi Iwai int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid) 1601835a0f9STakashi Iwai { 1611835a0f9STakashi Iwai u32 sense = snd_hda_pin_sense(codec, nid); 16235be544aSTakashi Iwai return get_jack_plug_state(sense); 1631835a0f9STakashi Iwai } 1641835a0f9STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_jack_detect); 1651835a0f9STakashi Iwai 1661835a0f9STakashi Iwai /** 1671835a0f9STakashi Iwai * snd_hda_jack_detect_enable - enable the jack-detection 1681835a0f9STakashi Iwai */ 1691835a0f9STakashi Iwai int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid, 1703a93897eSTakashi Iwai unsigned char action) 1711835a0f9STakashi Iwai { 1721835a0f9STakashi Iwai struct hda_jack_tbl *jack = snd_hda_jack_tbl_new(codec, nid); 1731835a0f9STakashi Iwai if (!jack) 1741835a0f9STakashi Iwai return -ENOMEM; 1753a93897eSTakashi Iwai if (jack->jack_detect) 17601a61e12STakashi Iwai return 0; /* already registered */ 1773a93897eSTakashi Iwai jack->jack_detect = 1; 1783a93897eSTakashi Iwai if (action) 1793a93897eSTakashi Iwai jack->action = action; 1801835a0f9STakashi Iwai return snd_hda_codec_write_cache(codec, nid, 0, 1811835a0f9STakashi Iwai AC_VERB_SET_UNSOLICITED_ENABLE, 1823a93897eSTakashi Iwai AC_USRSP_EN | jack->tag); 1831835a0f9STakashi Iwai } 1841835a0f9STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_jack_detect_enable); 18501a61e12STakashi Iwai 18601a61e12STakashi Iwai /** 18701a61e12STakashi Iwai * snd_hda_jack_report_sync - sync the states of all jacks and report if changed 18801a61e12STakashi Iwai */ 18901a61e12STakashi Iwai void snd_hda_jack_report_sync(struct hda_codec *codec) 19001a61e12STakashi Iwai { 19101a61e12STakashi Iwai struct hda_jack_tbl *jack = codec->jacktbl.list; 19235be544aSTakashi Iwai int i, state; 19301a61e12STakashi Iwai 19401a61e12STakashi Iwai for (i = 0; i < codec->jacktbl.used; i++, jack++) 19501a61e12STakashi Iwai if (jack->nid) { 19601a61e12STakashi Iwai jack_detect_update(codec, jack); 197*cfc7c9d3STakashi Iwai if (!jack->kctl) 198*cfc7c9d3STakashi Iwai continue; 19935be544aSTakashi Iwai state = get_jack_plug_state(jack->pin_sense); 200aad37dbdSTakashi Iwai snd_kctl_jack_report(codec->bus->card, jack->kctl, state); 20101a61e12STakashi Iwai } 20201a61e12STakashi Iwai } 20301a61e12STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_jack_report_sync); 20401a61e12STakashi Iwai 20501a61e12STakashi Iwai /** 20601a61e12STakashi Iwai * snd_hda_jack_add_kctl - Add a kctl for the given pin 20701a61e12STakashi Iwai * 20801a61e12STakashi Iwai * This assigns a jack-detection kctl to the given pin. The kcontrol 20901a61e12STakashi Iwai * will have the given name and index. 21001a61e12STakashi Iwai */ 21101a61e12STakashi Iwai int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, 21201a61e12STakashi Iwai const char *name, int idx) 21301a61e12STakashi Iwai { 21401a61e12STakashi Iwai struct hda_jack_tbl *jack; 21501a61e12STakashi Iwai struct snd_kcontrol *kctl; 21601a61e12STakashi Iwai 2173a93897eSTakashi Iwai jack = snd_hda_jack_tbl_new(codec, nid); 21801a61e12STakashi Iwai if (!jack) 21901a61e12STakashi Iwai return 0; 22001a61e12STakashi Iwai if (jack->kctl) 22101a61e12STakashi Iwai return 0; /* already created */ 22235be544aSTakashi Iwai kctl = snd_kctl_jack_new(name, idx, codec); 22301a61e12STakashi Iwai if (!kctl) 22401a61e12STakashi Iwai return -ENOMEM; 22501a61e12STakashi Iwai if (snd_hda_ctl_add(codec, nid, kctl) < 0) 22601a61e12STakashi Iwai return -ENOMEM; 22701a61e12STakashi Iwai jack->kctl = kctl; 22801a61e12STakashi Iwai return 0; 22901a61e12STakashi Iwai } 230d1cb6200SDavid Henningsson EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctl); 23101a61e12STakashi Iwai 23201a61e12STakashi Iwai static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, int idx, 23301a61e12STakashi Iwai const struct auto_pin_cfg *cfg) 23401a61e12STakashi Iwai { 2353a93897eSTakashi Iwai unsigned int def_conf, conn; 2363a93897eSTakashi Iwai int err; 2373a93897eSTakashi Iwai 23801a61e12STakashi Iwai if (!nid) 23901a61e12STakashi Iwai return 0; 24001a61e12STakashi Iwai if (!is_jack_detectable(codec, nid)) 24101a61e12STakashi Iwai return 0; 2423a93897eSTakashi Iwai def_conf = snd_hda_codec_get_pincfg(codec, nid); 2433a93897eSTakashi Iwai conn = get_defcfg_connect(def_conf); 2443a93897eSTakashi Iwai if (conn != AC_JACK_PORT_COMPLEX) 2453a93897eSTakashi Iwai return 0; 2463a93897eSTakashi Iwai 2473a93897eSTakashi Iwai err = snd_hda_jack_add_kctl(codec, nid, 24801a61e12STakashi Iwai snd_hda_get_pin_label(codec, nid, cfg), 24901a61e12STakashi Iwai idx); 2503a93897eSTakashi Iwai if (err < 0) 2513a93897eSTakashi Iwai return err; 2523a93897eSTakashi Iwai return snd_hda_jack_detect_enable(codec, nid, 0); 25301a61e12STakashi Iwai } 25401a61e12STakashi Iwai 25501a61e12STakashi Iwai /** 25601a61e12STakashi Iwai * snd_hda_jack_add_kctls - Add kctls for all pins included in the given pincfg 25701a61e12STakashi Iwai */ 25801a61e12STakashi Iwai int snd_hda_jack_add_kctls(struct hda_codec *codec, 25901a61e12STakashi Iwai const struct auto_pin_cfg *cfg) 26001a61e12STakashi Iwai { 26101a61e12STakashi Iwai const hda_nid_t *p; 26201a61e12STakashi Iwai int i, err; 26301a61e12STakashi Iwai 26401a61e12STakashi Iwai for (i = 0, p = cfg->line_out_pins; i < cfg->line_outs; i++, p++) { 26501a61e12STakashi Iwai err = add_jack_kctl(codec, *p, i, cfg); 26601a61e12STakashi Iwai if (err < 0) 26701a61e12STakashi Iwai return err; 26801a61e12STakashi Iwai } 26901a61e12STakashi Iwai for (i = 0, p = cfg->hp_pins; i < cfg->hp_outs; i++, p++) { 27001a61e12STakashi Iwai if (*p == *cfg->line_out_pins) /* might be duplicated */ 27101a61e12STakashi Iwai break; 27201a61e12STakashi Iwai err = add_jack_kctl(codec, *p, i, cfg); 27301a61e12STakashi Iwai if (err < 0) 27401a61e12STakashi Iwai return err; 27501a61e12STakashi Iwai } 27601a61e12STakashi Iwai for (i = 0, p = cfg->speaker_pins; i < cfg->speaker_outs; i++, p++) { 27701a61e12STakashi Iwai if (*p == *cfg->line_out_pins) /* might be duplicated */ 27801a61e12STakashi Iwai break; 27901a61e12STakashi Iwai err = add_jack_kctl(codec, *p, i, cfg); 28001a61e12STakashi Iwai if (err < 0) 28101a61e12STakashi Iwai return err; 28201a61e12STakashi Iwai } 28301a61e12STakashi Iwai for (i = 0; i < cfg->num_inputs; i++) { 28401a61e12STakashi Iwai err = add_jack_kctl(codec, cfg->inputs[i].pin, 0, cfg); 28501a61e12STakashi Iwai if (err < 0) 28601a61e12STakashi Iwai return err; 28701a61e12STakashi Iwai } 28801a61e12STakashi Iwai for (i = 0, p = cfg->dig_out_pins; i < cfg->dig_outs; i++, p++) { 28901a61e12STakashi Iwai err = add_jack_kctl(codec, *p, i, cfg); 29001a61e12STakashi Iwai if (err < 0) 29101a61e12STakashi Iwai return err; 29201a61e12STakashi Iwai } 29301a61e12STakashi Iwai err = add_jack_kctl(codec, cfg->dig_in_pin, 0, cfg); 29401a61e12STakashi Iwai if (err < 0) 29501a61e12STakashi Iwai return err; 29601a61e12STakashi Iwai err = add_jack_kctl(codec, cfg->mono_out_pin, 0, cfg); 29701a61e12STakashi Iwai if (err < 0) 29801a61e12STakashi Iwai return err; 29901a61e12STakashi Iwai return 0; 30001a61e12STakashi Iwai } 30101a61e12STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctls); 302aad37dbdSTakashi Iwai 303aad37dbdSTakashi Iwai #ifdef CONFIG_SND_HDA_INPUT_JACK 304aad37dbdSTakashi Iwai /* 305aad37dbdSTakashi Iwai * Input-jack notification support 306aad37dbdSTakashi Iwai */ 307aad37dbdSTakashi Iwai static const char *get_jack_default_name(struct hda_codec *codec, hda_nid_t nid, 308aad37dbdSTakashi Iwai int type) 309aad37dbdSTakashi Iwai { 310aad37dbdSTakashi Iwai switch (type) { 311aad37dbdSTakashi Iwai case SND_JACK_HEADPHONE: 312aad37dbdSTakashi Iwai return "Headphone"; 313aad37dbdSTakashi Iwai case SND_JACK_MICROPHONE: 314aad37dbdSTakashi Iwai return "Mic"; 315aad37dbdSTakashi Iwai case SND_JACK_LINEOUT: 316aad37dbdSTakashi Iwai return "Line-out"; 317aad37dbdSTakashi Iwai case SND_JACK_LINEIN: 318aad37dbdSTakashi Iwai return "Line-in"; 319aad37dbdSTakashi Iwai case SND_JACK_HEADSET: 320aad37dbdSTakashi Iwai return "Headset"; 321aad37dbdSTakashi Iwai case SND_JACK_VIDEOOUT: 322aad37dbdSTakashi Iwai return "HDMI/DP"; 323aad37dbdSTakashi Iwai default: 324aad37dbdSTakashi Iwai return "Misc"; 325aad37dbdSTakashi Iwai } 326aad37dbdSTakashi Iwai } 327aad37dbdSTakashi Iwai 328aad37dbdSTakashi Iwai static void hda_free_jack_priv(struct snd_jack *jack) 329aad37dbdSTakashi Iwai { 330aad37dbdSTakashi Iwai struct hda_jack_tbl *jacks = jack->private_data; 331aad37dbdSTakashi Iwai jacks->nid = 0; 332aad37dbdSTakashi Iwai jacks->jack = NULL; 333aad37dbdSTakashi Iwai } 334aad37dbdSTakashi Iwai 335aad37dbdSTakashi Iwai int snd_hda_input_jack_add(struct hda_codec *codec, hda_nid_t nid, int type, 336aad37dbdSTakashi Iwai const char *name) 337aad37dbdSTakashi Iwai { 338aad37dbdSTakashi Iwai struct hda_jack_tbl *jack = snd_hda_jack_tbl_new(codec, nid); 339aad37dbdSTakashi Iwai int err; 340aad37dbdSTakashi Iwai 341aad37dbdSTakashi Iwai if (!jack) 342aad37dbdSTakashi Iwai return -ENOMEM; 343aad37dbdSTakashi Iwai if (!name) 344aad37dbdSTakashi Iwai name = get_jack_default_name(codec, nid, type); 345aad37dbdSTakashi Iwai err = snd_jack_new(codec->bus->card, name, type, &jack->jack); 346aad37dbdSTakashi Iwai if (err < 0) 347aad37dbdSTakashi Iwai return err; 348aad37dbdSTakashi Iwai jack->jack->private_data = jack; 349aad37dbdSTakashi Iwai jack->jack->private_free = hda_free_jack_priv; 350aad37dbdSTakashi Iwai return 0; 351aad37dbdSTakashi Iwai } 352aad37dbdSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_input_jack_add); 353aad37dbdSTakashi Iwai 354aad37dbdSTakashi Iwai void snd_hda_input_jack_report(struct hda_codec *codec, hda_nid_t nid) 355aad37dbdSTakashi Iwai { 356aad37dbdSTakashi Iwai struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid); 357aad37dbdSTakashi Iwai unsigned int pin_ctl; 358aad37dbdSTakashi Iwai unsigned int present; 359aad37dbdSTakashi Iwai int type; 360aad37dbdSTakashi Iwai 361*cfc7c9d3STakashi Iwai if (!jack || !jack->jack) 362aad37dbdSTakashi Iwai return; 363aad37dbdSTakashi Iwai 364aad37dbdSTakashi Iwai present = snd_hda_jack_detect(codec, nid); 365aad37dbdSTakashi Iwai type = jack->type; 366aad37dbdSTakashi Iwai if (type == (SND_JACK_HEADPHONE | SND_JACK_LINEOUT)) { 367aad37dbdSTakashi Iwai pin_ctl = snd_hda_codec_read(codec, nid, 0, 368aad37dbdSTakashi Iwai AC_VERB_GET_PIN_WIDGET_CONTROL, 0); 369aad37dbdSTakashi Iwai type = (pin_ctl & AC_PINCTL_HP_EN) ? 370aad37dbdSTakashi Iwai SND_JACK_HEADPHONE : SND_JACK_LINEOUT; 371aad37dbdSTakashi Iwai } 372aad37dbdSTakashi Iwai snd_jack_report(jack->jack, present ? type : 0); 373aad37dbdSTakashi Iwai } 374aad37dbdSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_input_jack_report); 375aad37dbdSTakashi Iwai 376aad37dbdSTakashi Iwai /* free jack instances manually when clearing/reconfiguring */ 377aad37dbdSTakashi Iwai static void snd_hda_input_jack_free(struct hda_codec *codec) 378aad37dbdSTakashi Iwai { 379aad37dbdSTakashi Iwai if (!codec->bus->shutdown && codec->jacktbl.list) { 380aad37dbdSTakashi Iwai struct hda_jack_tbl *jack = codec->jacktbl.list; 381aad37dbdSTakashi Iwai int i; 382aad37dbdSTakashi Iwai for (i = 0; i < codec->jacktbl.used; i++, jack++) { 383aad37dbdSTakashi Iwai if (jack->jack) 384aad37dbdSTakashi Iwai snd_device_free(codec->bus->card, jack->jack); 385aad37dbdSTakashi Iwai } 386aad37dbdSTakashi Iwai } 387aad37dbdSTakashi Iwai } 388aad37dbdSTakashi Iwai #endif /* CONFIG_SND_HDA_INPUT_JACK */ 389