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> 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 /** 543a93897eSTakashi Iwai * snd_hda_jack_tbl_get_from_tag - query the jack-table entry for the given tag 553a93897eSTakashi Iwai */ 563a93897eSTakashi Iwai struct hda_jack_tbl * 573a93897eSTakashi Iwai snd_hda_jack_tbl_get_from_tag(struct hda_codec *codec, unsigned char tag) 583a93897eSTakashi Iwai { 593a93897eSTakashi Iwai struct hda_jack_tbl *jack = codec->jacktbl.list; 603a93897eSTakashi Iwai int i; 613a93897eSTakashi Iwai 623a93897eSTakashi Iwai if (!tag || !jack) 633a93897eSTakashi Iwai return NULL; 643a93897eSTakashi Iwai for (i = 0; i < codec->jacktbl.used; i++, jack++) 653a93897eSTakashi Iwai if (jack->tag == tag) 663a93897eSTakashi Iwai return jack; 673a93897eSTakashi Iwai return NULL; 683a93897eSTakashi Iwai } 693a93897eSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_jack_tbl_get_from_tag); 703a93897eSTakashi Iwai 713a93897eSTakashi Iwai /** 721835a0f9STakashi Iwai * snd_hda_jack_tbl_new - create a jack-table entry for the given NID 731835a0f9STakashi Iwai */ 741835a0f9STakashi Iwai struct hda_jack_tbl * 751835a0f9STakashi Iwai snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid) 761835a0f9STakashi Iwai { 771835a0f9STakashi Iwai struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid); 781835a0f9STakashi Iwai if (jack) 791835a0f9STakashi Iwai return jack; 801835a0f9STakashi Iwai snd_array_init(&codec->jacktbl, sizeof(*jack), 16); 811835a0f9STakashi Iwai jack = snd_array_new(&codec->jacktbl); 821835a0f9STakashi Iwai if (!jack) 831835a0f9STakashi Iwai return NULL; 841835a0f9STakashi Iwai jack->nid = nid; 851835a0f9STakashi Iwai jack->jack_dirty = 1; 863a93897eSTakashi Iwai jack->tag = codec->jacktbl.used; 871835a0f9STakashi Iwai return jack; 881835a0f9STakashi Iwai } 891835a0f9STakashi Iwai 901835a0f9STakashi Iwai void snd_hda_jack_tbl_clear(struct hda_codec *codec) 911835a0f9STakashi Iwai { 921835a0f9STakashi Iwai snd_array_free(&codec->jacktbl); 931835a0f9STakashi Iwai } 941835a0f9STakashi Iwai 951835a0f9STakashi Iwai /* update the cached value and notification flag if needed */ 961835a0f9STakashi Iwai static void jack_detect_update(struct hda_codec *codec, 971835a0f9STakashi Iwai struct hda_jack_tbl *jack) 981835a0f9STakashi Iwai { 993a93897eSTakashi Iwai if (jack->jack_dirty || !jack->jack_detect) { 100*35be544aSTakashi Iwai jack->pin_sense = read_pin_sense(codec, jack->nid); 1011835a0f9STakashi Iwai jack->jack_dirty = 0; 1021835a0f9STakashi Iwai } 1031835a0f9STakashi Iwai } 1041835a0f9STakashi Iwai 1051835a0f9STakashi Iwai /** 1061835a0f9STakashi Iwai * snd_hda_set_dirty_all - Mark all the cached as dirty 1071835a0f9STakashi Iwai * 1081835a0f9STakashi Iwai * This function sets the dirty flag to all entries of jack table. 1091835a0f9STakashi Iwai * It's called from the resume path in hda_codec.c. 1101835a0f9STakashi Iwai */ 1111835a0f9STakashi Iwai void snd_hda_jack_set_dirty_all(struct hda_codec *codec) 1121835a0f9STakashi Iwai { 1131835a0f9STakashi Iwai struct hda_jack_tbl *jack = codec->jacktbl.list; 1141835a0f9STakashi Iwai int i; 1151835a0f9STakashi Iwai 1161835a0f9STakashi Iwai for (i = 0; i < codec->jacktbl.used; i++, jack++) 1171835a0f9STakashi Iwai if (jack->nid) 1181835a0f9STakashi Iwai jack->jack_dirty = 1; 1191835a0f9STakashi Iwai } 1201835a0f9STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_jack_set_dirty_all); 1211835a0f9STakashi Iwai 1221835a0f9STakashi Iwai /** 1231835a0f9STakashi Iwai * snd_hda_pin_sense - execute pin sense measurement 1241835a0f9STakashi Iwai * @codec: the CODEC to sense 1251835a0f9STakashi Iwai * @nid: the pin NID to sense 1261835a0f9STakashi Iwai * 1271835a0f9STakashi Iwai * Execute necessary pin sense measurement and return its Presence Detect, 1281835a0f9STakashi Iwai * Impedance, ELD Valid etc. status bits. 1291835a0f9STakashi Iwai */ 1301835a0f9STakashi Iwai u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid) 1311835a0f9STakashi Iwai { 1321835a0f9STakashi Iwai struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid); 1331835a0f9STakashi Iwai if (jack) { 1341835a0f9STakashi Iwai jack_detect_update(codec, jack); 1351835a0f9STakashi Iwai return jack->pin_sense; 1361835a0f9STakashi Iwai } 1371835a0f9STakashi Iwai return read_pin_sense(codec, nid); 1381835a0f9STakashi Iwai } 1391835a0f9STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_pin_sense); 1401835a0f9STakashi Iwai 141*35be544aSTakashi Iwai #define get_jack_plug_state(sense) !!(sense & AC_PINSENSE_PRESENCE) 142*35be544aSTakashi Iwai 1431835a0f9STakashi Iwai /** 1441835a0f9STakashi Iwai * snd_hda_jack_detect - query pin Presence Detect status 1451835a0f9STakashi Iwai * @codec: the CODEC to sense 1461835a0f9STakashi Iwai * @nid: the pin NID to sense 1471835a0f9STakashi Iwai * 1481835a0f9STakashi Iwai * Query and return the pin's Presence Detect status. 1491835a0f9STakashi Iwai */ 1501835a0f9STakashi Iwai int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid) 1511835a0f9STakashi Iwai { 1521835a0f9STakashi Iwai u32 sense = snd_hda_pin_sense(codec, nid); 153*35be544aSTakashi Iwai return get_jack_plug_state(sense); 1541835a0f9STakashi Iwai } 1551835a0f9STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_jack_detect); 1561835a0f9STakashi Iwai 1571835a0f9STakashi Iwai /** 1581835a0f9STakashi Iwai * snd_hda_jack_detect_enable - enable the jack-detection 1591835a0f9STakashi Iwai */ 1601835a0f9STakashi Iwai int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid, 1613a93897eSTakashi Iwai unsigned char action) 1621835a0f9STakashi Iwai { 1631835a0f9STakashi Iwai struct hda_jack_tbl *jack = snd_hda_jack_tbl_new(codec, nid); 1641835a0f9STakashi Iwai if (!jack) 1651835a0f9STakashi Iwai return -ENOMEM; 1663a93897eSTakashi Iwai if (jack->jack_detect) 16701a61e12STakashi Iwai return 0; /* already registered */ 1683a93897eSTakashi Iwai jack->jack_detect = 1; 1693a93897eSTakashi Iwai if (action) 1703a93897eSTakashi Iwai jack->action = action; 1711835a0f9STakashi Iwai return snd_hda_codec_write_cache(codec, nid, 0, 1721835a0f9STakashi Iwai AC_VERB_SET_UNSOLICITED_ENABLE, 1733a93897eSTakashi Iwai AC_USRSP_EN | jack->tag); 1741835a0f9STakashi Iwai } 1751835a0f9STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_jack_detect_enable); 17601a61e12STakashi Iwai 17701a61e12STakashi Iwai /** 17801a61e12STakashi Iwai * snd_hda_jack_report_sync - sync the states of all jacks and report if changed 17901a61e12STakashi Iwai */ 18001a61e12STakashi Iwai void snd_hda_jack_report_sync(struct hda_codec *codec) 18101a61e12STakashi Iwai { 18201a61e12STakashi Iwai struct hda_jack_tbl *jack = codec->jacktbl.list; 183*35be544aSTakashi Iwai int i, state; 18401a61e12STakashi Iwai 18501a61e12STakashi Iwai for (i = 0; i < codec->jacktbl.used; i++, jack++) 18601a61e12STakashi Iwai if (jack->nid) { 18701a61e12STakashi Iwai jack_detect_update(codec, jack); 188*35be544aSTakashi Iwai state = get_jack_plug_state(jack->pin_sense); 189*35be544aSTakashi Iwai snd_kctl_jack_notify(codec->bus->card, jack->kctl, state); 19001a61e12STakashi Iwai } 19101a61e12STakashi Iwai } 19201a61e12STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_jack_report_sync); 19301a61e12STakashi Iwai 19401a61e12STakashi Iwai /** 19501a61e12STakashi Iwai * snd_hda_jack_add_kctl - Add a kctl for the given pin 19601a61e12STakashi Iwai * 19701a61e12STakashi Iwai * This assigns a jack-detection kctl to the given pin. The kcontrol 19801a61e12STakashi Iwai * will have the given name and index. 19901a61e12STakashi Iwai */ 20001a61e12STakashi Iwai int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, 20101a61e12STakashi Iwai const char *name, int idx) 20201a61e12STakashi Iwai { 20301a61e12STakashi Iwai struct hda_jack_tbl *jack; 20401a61e12STakashi Iwai struct snd_kcontrol *kctl; 20501a61e12STakashi Iwai 2063a93897eSTakashi Iwai jack = snd_hda_jack_tbl_new(codec, nid); 20701a61e12STakashi Iwai if (!jack) 20801a61e12STakashi Iwai return 0; 20901a61e12STakashi Iwai if (jack->kctl) 21001a61e12STakashi Iwai return 0; /* already created */ 211*35be544aSTakashi Iwai kctl = snd_kctl_jack_new(name, idx, codec); 21201a61e12STakashi Iwai if (!kctl) 21301a61e12STakashi Iwai return -ENOMEM; 21401a61e12STakashi Iwai if (snd_hda_ctl_add(codec, nid, kctl) < 0) 21501a61e12STakashi Iwai return -ENOMEM; 21601a61e12STakashi Iwai jack->kctl = kctl; 21701a61e12STakashi Iwai return 0; 21801a61e12STakashi Iwai } 21901a61e12STakashi Iwai 22001a61e12STakashi Iwai static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, int idx, 22101a61e12STakashi Iwai const struct auto_pin_cfg *cfg) 22201a61e12STakashi Iwai { 2233a93897eSTakashi Iwai unsigned int def_conf, conn; 2243a93897eSTakashi Iwai int err; 2253a93897eSTakashi Iwai 22601a61e12STakashi Iwai if (!nid) 22701a61e12STakashi Iwai return 0; 22801a61e12STakashi Iwai if (!is_jack_detectable(codec, nid)) 22901a61e12STakashi Iwai return 0; 2303a93897eSTakashi Iwai def_conf = snd_hda_codec_get_pincfg(codec, nid); 2313a93897eSTakashi Iwai conn = get_defcfg_connect(def_conf); 2323a93897eSTakashi Iwai if (conn != AC_JACK_PORT_COMPLEX) 2333a93897eSTakashi Iwai return 0; 2343a93897eSTakashi Iwai 2353a93897eSTakashi Iwai err = snd_hda_jack_add_kctl(codec, nid, 23601a61e12STakashi Iwai snd_hda_get_pin_label(codec, nid, cfg), 23701a61e12STakashi Iwai idx); 2383a93897eSTakashi Iwai if (err < 0) 2393a93897eSTakashi Iwai return err; 2403a93897eSTakashi Iwai return snd_hda_jack_detect_enable(codec, nid, 0); 24101a61e12STakashi Iwai } 24201a61e12STakashi Iwai 24301a61e12STakashi Iwai /** 24401a61e12STakashi Iwai * snd_hda_jack_add_kctls - Add kctls for all pins included in the given pincfg 24501a61e12STakashi Iwai */ 24601a61e12STakashi Iwai int snd_hda_jack_add_kctls(struct hda_codec *codec, 24701a61e12STakashi Iwai const struct auto_pin_cfg *cfg) 24801a61e12STakashi Iwai { 24901a61e12STakashi Iwai const hda_nid_t *p; 25001a61e12STakashi Iwai int i, err; 25101a61e12STakashi Iwai 25201a61e12STakashi Iwai for (i = 0, p = cfg->line_out_pins; i < cfg->line_outs; i++, p++) { 25301a61e12STakashi Iwai err = add_jack_kctl(codec, *p, i, cfg); 25401a61e12STakashi Iwai if (err < 0) 25501a61e12STakashi Iwai return err; 25601a61e12STakashi Iwai } 25701a61e12STakashi Iwai for (i = 0, p = cfg->hp_pins; i < cfg->hp_outs; i++, p++) { 25801a61e12STakashi Iwai if (*p == *cfg->line_out_pins) /* might be duplicated */ 25901a61e12STakashi Iwai break; 26001a61e12STakashi Iwai err = add_jack_kctl(codec, *p, i, cfg); 26101a61e12STakashi Iwai if (err < 0) 26201a61e12STakashi Iwai return err; 26301a61e12STakashi Iwai } 26401a61e12STakashi Iwai for (i = 0, p = cfg->speaker_pins; i < cfg->speaker_outs; i++, p++) { 26501a61e12STakashi Iwai if (*p == *cfg->line_out_pins) /* might be duplicated */ 26601a61e12STakashi Iwai break; 26701a61e12STakashi Iwai err = add_jack_kctl(codec, *p, i, cfg); 26801a61e12STakashi Iwai if (err < 0) 26901a61e12STakashi Iwai return err; 27001a61e12STakashi Iwai } 27101a61e12STakashi Iwai for (i = 0; i < cfg->num_inputs; i++) { 27201a61e12STakashi Iwai err = add_jack_kctl(codec, cfg->inputs[i].pin, 0, cfg); 27301a61e12STakashi Iwai if (err < 0) 27401a61e12STakashi Iwai return err; 27501a61e12STakashi Iwai } 27601a61e12STakashi Iwai for (i = 0, p = cfg->dig_out_pins; i < cfg->dig_outs; i++, p++) { 27701a61e12STakashi Iwai err = add_jack_kctl(codec, *p, i, cfg); 27801a61e12STakashi Iwai if (err < 0) 27901a61e12STakashi Iwai return err; 28001a61e12STakashi Iwai } 28101a61e12STakashi Iwai err = add_jack_kctl(codec, cfg->dig_in_pin, 0, cfg); 28201a61e12STakashi Iwai if (err < 0) 28301a61e12STakashi Iwai return err; 28401a61e12STakashi Iwai err = add_jack_kctl(codec, cfg->mono_out_pin, 0, cfg); 28501a61e12STakashi Iwai if (err < 0) 28601a61e12STakashi Iwai return err; 28701a61e12STakashi Iwai return 0; 28801a61e12STakashi Iwai } 28901a61e12STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctls); 290