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