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 } 90*d1cb6200SDavid 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); 19735be544aSTakashi Iwai state = get_jack_plug_state(jack->pin_sense); 198aad37dbdSTakashi Iwai snd_kctl_jack_report(codec->bus->card, jack->kctl, state); 19901a61e12STakashi Iwai } 20001a61e12STakashi Iwai } 20101a61e12STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_jack_report_sync); 20201a61e12STakashi Iwai 20301a61e12STakashi Iwai /** 20401a61e12STakashi Iwai * snd_hda_jack_add_kctl - Add a kctl for the given pin 20501a61e12STakashi Iwai * 20601a61e12STakashi Iwai * This assigns a jack-detection kctl to the given pin. The kcontrol 20701a61e12STakashi Iwai * will have the given name and index. 20801a61e12STakashi Iwai */ 20901a61e12STakashi Iwai int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, 21001a61e12STakashi Iwai const char *name, int idx) 21101a61e12STakashi Iwai { 21201a61e12STakashi Iwai struct hda_jack_tbl *jack; 21301a61e12STakashi Iwai struct snd_kcontrol *kctl; 21401a61e12STakashi Iwai 2153a93897eSTakashi Iwai jack = snd_hda_jack_tbl_new(codec, nid); 21601a61e12STakashi Iwai if (!jack) 21701a61e12STakashi Iwai return 0; 21801a61e12STakashi Iwai if (jack->kctl) 21901a61e12STakashi Iwai return 0; /* already created */ 22035be544aSTakashi Iwai kctl = snd_kctl_jack_new(name, idx, codec); 22101a61e12STakashi Iwai if (!kctl) 22201a61e12STakashi Iwai return -ENOMEM; 22301a61e12STakashi Iwai if (snd_hda_ctl_add(codec, nid, kctl) < 0) 22401a61e12STakashi Iwai return -ENOMEM; 22501a61e12STakashi Iwai jack->kctl = kctl; 22601a61e12STakashi Iwai return 0; 22701a61e12STakashi Iwai } 228*d1cb6200SDavid Henningsson EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctl); 22901a61e12STakashi Iwai 23001a61e12STakashi Iwai static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, int idx, 23101a61e12STakashi Iwai const struct auto_pin_cfg *cfg) 23201a61e12STakashi Iwai { 2333a93897eSTakashi Iwai unsigned int def_conf, conn; 2343a93897eSTakashi Iwai int err; 2353a93897eSTakashi Iwai 23601a61e12STakashi Iwai if (!nid) 23701a61e12STakashi Iwai return 0; 23801a61e12STakashi Iwai if (!is_jack_detectable(codec, nid)) 23901a61e12STakashi Iwai return 0; 2403a93897eSTakashi Iwai def_conf = snd_hda_codec_get_pincfg(codec, nid); 2413a93897eSTakashi Iwai conn = get_defcfg_connect(def_conf); 2423a93897eSTakashi Iwai if (conn != AC_JACK_PORT_COMPLEX) 2433a93897eSTakashi Iwai return 0; 2443a93897eSTakashi Iwai 2453a93897eSTakashi Iwai err = snd_hda_jack_add_kctl(codec, nid, 24601a61e12STakashi Iwai snd_hda_get_pin_label(codec, nid, cfg), 24701a61e12STakashi Iwai idx); 2483a93897eSTakashi Iwai if (err < 0) 2493a93897eSTakashi Iwai return err; 2503a93897eSTakashi Iwai return snd_hda_jack_detect_enable(codec, nid, 0); 25101a61e12STakashi Iwai } 25201a61e12STakashi Iwai 25301a61e12STakashi Iwai /** 25401a61e12STakashi Iwai * snd_hda_jack_add_kctls - Add kctls for all pins included in the given pincfg 25501a61e12STakashi Iwai */ 25601a61e12STakashi Iwai int snd_hda_jack_add_kctls(struct hda_codec *codec, 25701a61e12STakashi Iwai const struct auto_pin_cfg *cfg) 25801a61e12STakashi Iwai { 25901a61e12STakashi Iwai const hda_nid_t *p; 26001a61e12STakashi Iwai int i, err; 26101a61e12STakashi Iwai 26201a61e12STakashi Iwai for (i = 0, p = cfg->line_out_pins; i < cfg->line_outs; i++, p++) { 26301a61e12STakashi Iwai err = add_jack_kctl(codec, *p, i, cfg); 26401a61e12STakashi Iwai if (err < 0) 26501a61e12STakashi Iwai return err; 26601a61e12STakashi Iwai } 26701a61e12STakashi Iwai for (i = 0, p = cfg->hp_pins; i < cfg->hp_outs; i++, p++) { 26801a61e12STakashi Iwai if (*p == *cfg->line_out_pins) /* might be duplicated */ 26901a61e12STakashi Iwai break; 27001a61e12STakashi Iwai err = add_jack_kctl(codec, *p, i, cfg); 27101a61e12STakashi Iwai if (err < 0) 27201a61e12STakashi Iwai return err; 27301a61e12STakashi Iwai } 27401a61e12STakashi Iwai for (i = 0, p = cfg->speaker_pins; i < cfg->speaker_outs; i++, p++) { 27501a61e12STakashi Iwai if (*p == *cfg->line_out_pins) /* might be duplicated */ 27601a61e12STakashi Iwai break; 27701a61e12STakashi Iwai err = add_jack_kctl(codec, *p, i, cfg); 27801a61e12STakashi Iwai if (err < 0) 27901a61e12STakashi Iwai return err; 28001a61e12STakashi Iwai } 28101a61e12STakashi Iwai for (i = 0; i < cfg->num_inputs; i++) { 28201a61e12STakashi Iwai err = add_jack_kctl(codec, cfg->inputs[i].pin, 0, cfg); 28301a61e12STakashi Iwai if (err < 0) 28401a61e12STakashi Iwai return err; 28501a61e12STakashi Iwai } 28601a61e12STakashi Iwai for (i = 0, p = cfg->dig_out_pins; i < cfg->dig_outs; i++, p++) { 28701a61e12STakashi Iwai err = add_jack_kctl(codec, *p, i, cfg); 28801a61e12STakashi Iwai if (err < 0) 28901a61e12STakashi Iwai return err; 29001a61e12STakashi Iwai } 29101a61e12STakashi Iwai err = add_jack_kctl(codec, cfg->dig_in_pin, 0, cfg); 29201a61e12STakashi Iwai if (err < 0) 29301a61e12STakashi Iwai return err; 29401a61e12STakashi Iwai err = add_jack_kctl(codec, cfg->mono_out_pin, 0, cfg); 29501a61e12STakashi Iwai if (err < 0) 29601a61e12STakashi Iwai return err; 29701a61e12STakashi Iwai return 0; 29801a61e12STakashi Iwai } 29901a61e12STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctls); 300aad37dbdSTakashi Iwai 301aad37dbdSTakashi Iwai #ifdef CONFIG_SND_HDA_INPUT_JACK 302aad37dbdSTakashi Iwai /* 303aad37dbdSTakashi Iwai * Input-jack notification support 304aad37dbdSTakashi Iwai */ 305aad37dbdSTakashi Iwai static const char *get_jack_default_name(struct hda_codec *codec, hda_nid_t nid, 306aad37dbdSTakashi Iwai int type) 307aad37dbdSTakashi Iwai { 308aad37dbdSTakashi Iwai switch (type) { 309aad37dbdSTakashi Iwai case SND_JACK_HEADPHONE: 310aad37dbdSTakashi Iwai return "Headphone"; 311aad37dbdSTakashi Iwai case SND_JACK_MICROPHONE: 312aad37dbdSTakashi Iwai return "Mic"; 313aad37dbdSTakashi Iwai case SND_JACK_LINEOUT: 314aad37dbdSTakashi Iwai return "Line-out"; 315aad37dbdSTakashi Iwai case SND_JACK_LINEIN: 316aad37dbdSTakashi Iwai return "Line-in"; 317aad37dbdSTakashi Iwai case SND_JACK_HEADSET: 318aad37dbdSTakashi Iwai return "Headset"; 319aad37dbdSTakashi Iwai case SND_JACK_VIDEOOUT: 320aad37dbdSTakashi Iwai return "HDMI/DP"; 321aad37dbdSTakashi Iwai default: 322aad37dbdSTakashi Iwai return "Misc"; 323aad37dbdSTakashi Iwai } 324aad37dbdSTakashi Iwai } 325aad37dbdSTakashi Iwai 326aad37dbdSTakashi Iwai static void hda_free_jack_priv(struct snd_jack *jack) 327aad37dbdSTakashi Iwai { 328aad37dbdSTakashi Iwai struct hda_jack_tbl *jacks = jack->private_data; 329aad37dbdSTakashi Iwai jacks->nid = 0; 330aad37dbdSTakashi Iwai jacks->jack = NULL; 331aad37dbdSTakashi Iwai } 332aad37dbdSTakashi Iwai 333aad37dbdSTakashi Iwai int snd_hda_input_jack_add(struct hda_codec *codec, hda_nid_t nid, int type, 334aad37dbdSTakashi Iwai const char *name) 335aad37dbdSTakashi Iwai { 336aad37dbdSTakashi Iwai struct hda_jack_tbl *jack = snd_hda_jack_tbl_new(codec, nid); 337aad37dbdSTakashi Iwai int err; 338aad37dbdSTakashi Iwai 339aad37dbdSTakashi Iwai if (!jack) 340aad37dbdSTakashi Iwai return -ENOMEM; 341aad37dbdSTakashi Iwai if (!name) 342aad37dbdSTakashi Iwai name = get_jack_default_name(codec, nid, type); 343aad37dbdSTakashi Iwai err = snd_jack_new(codec->bus->card, name, type, &jack->jack); 344aad37dbdSTakashi Iwai if (err < 0) 345aad37dbdSTakashi Iwai return err; 346aad37dbdSTakashi Iwai jack->jack->private_data = jack; 347aad37dbdSTakashi Iwai jack->jack->private_free = hda_free_jack_priv; 348aad37dbdSTakashi Iwai return 0; 349aad37dbdSTakashi Iwai } 350aad37dbdSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_input_jack_add); 351aad37dbdSTakashi Iwai 352aad37dbdSTakashi Iwai void snd_hda_input_jack_report(struct hda_codec *codec, hda_nid_t nid) 353aad37dbdSTakashi Iwai { 354aad37dbdSTakashi Iwai struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid); 355aad37dbdSTakashi Iwai unsigned int pin_ctl; 356aad37dbdSTakashi Iwai unsigned int present; 357aad37dbdSTakashi Iwai int type; 358aad37dbdSTakashi Iwai 359aad37dbdSTakashi Iwai if (!jack) 360aad37dbdSTakashi Iwai return; 361aad37dbdSTakashi Iwai 362aad37dbdSTakashi Iwai present = snd_hda_jack_detect(codec, nid); 363aad37dbdSTakashi Iwai type = jack->type; 364aad37dbdSTakashi Iwai if (type == (SND_JACK_HEADPHONE | SND_JACK_LINEOUT)) { 365aad37dbdSTakashi Iwai pin_ctl = snd_hda_codec_read(codec, nid, 0, 366aad37dbdSTakashi Iwai AC_VERB_GET_PIN_WIDGET_CONTROL, 0); 367aad37dbdSTakashi Iwai type = (pin_ctl & AC_PINCTL_HP_EN) ? 368aad37dbdSTakashi Iwai SND_JACK_HEADPHONE : SND_JACK_LINEOUT; 369aad37dbdSTakashi Iwai } 370aad37dbdSTakashi Iwai snd_jack_report(jack->jack, present ? type : 0); 371aad37dbdSTakashi Iwai } 372aad37dbdSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_input_jack_report); 373aad37dbdSTakashi Iwai 374aad37dbdSTakashi Iwai /* free jack instances manually when clearing/reconfiguring */ 375aad37dbdSTakashi Iwai static void snd_hda_input_jack_free(struct hda_codec *codec) 376aad37dbdSTakashi Iwai { 377aad37dbdSTakashi Iwai if (!codec->bus->shutdown && codec->jacktbl.list) { 378aad37dbdSTakashi Iwai struct hda_jack_tbl *jack = codec->jacktbl.list; 379aad37dbdSTakashi Iwai int i; 380aad37dbdSTakashi Iwai for (i = 0; i < codec->jacktbl.used; i++, jack++) { 381aad37dbdSTakashi Iwai if (jack->jack) 382aad37dbdSTakashi Iwai snd_device_free(codec->bus->card, jack->jack); 383aad37dbdSTakashi Iwai } 384aad37dbdSTakashi Iwai } 385aad37dbdSTakashi Iwai } 386aad37dbdSTakashi Iwai #endif /* CONFIG_SND_HDA_INPUT_JACK */ 387