···11+/*22+ * BIOS auto-parser helper functions for HD-audio33+ *44+ * Copyright (c) 2012 Takashi Iwai <tiwai@suse.de>55+ *66+ * This driver is free software; you can redistribute it and/or modify77+ * it under the terms of the GNU General Public License as published by88+ * the Free Software Foundation; either version 2 of the License, or99+ * (at your option) any later version.1010+ */1111+1212+#include <linux/slab.h>1313+#include <linux/export.h>1414+#include <sound/core.h>1515+#include "hda_codec.h"1616+#include "hda_local.h"1717+#include "hda_auto_parser.h"1818+1919+#define SFX "hda_codec: "2020+2121+/*2222+ * Helper for automatic pin configuration2323+ */2424+2525+static int is_in_nid_list(hda_nid_t nid, const hda_nid_t *list)2626+{2727+ for (; *list; list++)2828+ if (*list == nid)2929+ return 1;3030+ return 0;3131+}3232+3333+3434+/*3535+ * Sort an associated group of pins according to their sequence numbers.3636+ */3737+static void sort_pins_by_sequence(hda_nid_t *pins, short *sequences,3838+ int num_pins)3939+{4040+ int i, j;4141+ short seq;4242+ hda_nid_t nid;4343+4444+ for (i = 0; i < num_pins; i++) {4545+ for (j = i + 1; j < num_pins; j++) {4646+ if (sequences[i] > sequences[j]) {4747+ seq = sequences[i];4848+ sequences[i] = sequences[j];4949+ sequences[j] = seq;5050+ nid = pins[i];5151+ pins[i] = pins[j];5252+ pins[j] = nid;5353+ }5454+ }5555+ }5656+}5757+5858+5959+/* add the found input-pin to the cfg->inputs[] table */6060+static void add_auto_cfg_input_pin(struct auto_pin_cfg *cfg, hda_nid_t nid,6161+ int type)6262+{6363+ if (cfg->num_inputs < AUTO_CFG_MAX_INS) {6464+ cfg->inputs[cfg->num_inputs].pin = nid;6565+ cfg->inputs[cfg->num_inputs].type = type;6666+ cfg->num_inputs++;6767+ }6868+}6969+7070+/* sort inputs in the order of AUTO_PIN_* type */7171+static void sort_autocfg_input_pins(struct auto_pin_cfg *cfg)7272+{7373+ int i, j;7474+7575+ for (i = 0; i < cfg->num_inputs; i++) {7676+ for (j = i + 1; j < cfg->num_inputs; j++) {7777+ if (cfg->inputs[i].type > cfg->inputs[j].type) {7878+ struct auto_pin_cfg_item tmp;7979+ tmp = cfg->inputs[i];8080+ cfg->inputs[i] = cfg->inputs[j];8181+ cfg->inputs[j] = tmp;8282+ }8383+ }8484+ }8585+}8686+8787+/* Reorder the surround channels8888+ * ALSA sequence is front/surr/clfe/side8989+ * HDA sequence is:9090+ * 4-ch: front/surr => OK as it is9191+ * 6-ch: front/clfe/surr9292+ * 8-ch: front/clfe/rear/side|fc9393+ */9494+static void reorder_outputs(unsigned int nums, hda_nid_t *pins)9595+{9696+ hda_nid_t nid;9797+9898+ switch (nums) {9999+ case 3:100100+ case 4:101101+ nid = pins[1];102102+ pins[1] = pins[2];103103+ pins[2] = nid;104104+ break;105105+ }106106+}107107+108108+/*109109+ * Parse all pin widgets and store the useful pin nids to cfg110110+ *111111+ * The number of line-outs or any primary output is stored in line_outs,112112+ * and the corresponding output pins are assigned to line_out_pins[],113113+ * in the order of front, rear, CLFE, side, ...114114+ *115115+ * If more extra outputs (speaker and headphone) are found, the pins are116116+ * assisnged to hp_pins[] and speaker_pins[], respectively. If no line-out jack117117+ * is detected, one of speaker of HP pins is assigned as the primary118118+ * output, i.e. to line_out_pins[0]. So, line_outs is always positive119119+ * if any analog output exists.120120+ *121121+ * The analog input pins are assigned to inputs array.122122+ * The digital input/output pins are assigned to dig_in_pin and dig_out_pin,123123+ * respectively.124124+ */125125+int snd_hda_parse_pin_defcfg(struct hda_codec *codec,126126+ struct auto_pin_cfg *cfg,127127+ const hda_nid_t *ignore_nids,128128+ unsigned int cond_flags)129129+{130130+ hda_nid_t nid, end_nid;131131+ short seq, assoc_line_out;132132+ short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)];133133+ short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)];134134+ short sequences_hp[ARRAY_SIZE(cfg->hp_pins)];135135+ int i;136136+137137+ memset(cfg, 0, sizeof(*cfg));138138+139139+ memset(sequences_line_out, 0, sizeof(sequences_line_out));140140+ memset(sequences_speaker, 0, sizeof(sequences_speaker));141141+ memset(sequences_hp, 0, sizeof(sequences_hp));142142+ assoc_line_out = 0;143143+144144+ codec->ignore_misc_bit = true;145145+ end_nid = codec->start_nid + codec->num_nodes;146146+ for (nid = codec->start_nid; nid < end_nid; nid++) {147147+ unsigned int wid_caps = get_wcaps(codec, nid);148148+ unsigned int wid_type = get_wcaps_type(wid_caps);149149+ unsigned int def_conf;150150+ short assoc, loc, conn, dev;151151+152152+ /* read all default configuration for pin complex */153153+ if (wid_type != AC_WID_PIN)154154+ continue;155155+ /* ignore the given nids (e.g. pc-beep returns error) */156156+ if (ignore_nids && is_in_nid_list(nid, ignore_nids))157157+ continue;158158+159159+ def_conf = snd_hda_codec_get_pincfg(codec, nid);160160+ if (!(get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) &161161+ AC_DEFCFG_MISC_NO_PRESENCE))162162+ codec->ignore_misc_bit = false;163163+ conn = get_defcfg_connect(def_conf);164164+ if (conn == AC_JACK_PORT_NONE)165165+ continue;166166+ loc = get_defcfg_location(def_conf);167167+ dev = get_defcfg_device(def_conf);168168+169169+ /* workaround for buggy BIOS setups */170170+ if (dev == AC_JACK_LINE_OUT) {171171+ if (conn == AC_JACK_PORT_FIXED)172172+ dev = AC_JACK_SPEAKER;173173+ }174174+175175+ switch (dev) {176176+ case AC_JACK_LINE_OUT:177177+ seq = get_defcfg_sequence(def_conf);178178+ assoc = get_defcfg_association(def_conf);179179+180180+ if (!(wid_caps & AC_WCAP_STEREO))181181+ if (!cfg->mono_out_pin)182182+ cfg->mono_out_pin = nid;183183+ if (!assoc)184184+ continue;185185+ if (!assoc_line_out)186186+ assoc_line_out = assoc;187187+ else if (assoc_line_out != assoc)188188+ continue;189189+ if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins))190190+ continue;191191+ cfg->line_out_pins[cfg->line_outs] = nid;192192+ sequences_line_out[cfg->line_outs] = seq;193193+ cfg->line_outs++;194194+ break;195195+ case AC_JACK_SPEAKER:196196+ seq = get_defcfg_sequence(def_conf);197197+ assoc = get_defcfg_association(def_conf);198198+ if (cfg->speaker_outs >= ARRAY_SIZE(cfg->speaker_pins))199199+ continue;200200+ cfg->speaker_pins[cfg->speaker_outs] = nid;201201+ sequences_speaker[cfg->speaker_outs] = (assoc << 4) | seq;202202+ cfg->speaker_outs++;203203+ break;204204+ case AC_JACK_HP_OUT:205205+ seq = get_defcfg_sequence(def_conf);206206+ assoc = get_defcfg_association(def_conf);207207+ if (cfg->hp_outs >= ARRAY_SIZE(cfg->hp_pins))208208+ continue;209209+ cfg->hp_pins[cfg->hp_outs] = nid;210210+ sequences_hp[cfg->hp_outs] = (assoc << 4) | seq;211211+ cfg->hp_outs++;212212+ break;213213+ case AC_JACK_MIC_IN:214214+ add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_MIC);215215+ break;216216+ case AC_JACK_LINE_IN:217217+ add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_LINE_IN);218218+ break;219219+ case AC_JACK_CD:220220+ add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_CD);221221+ break;222222+ case AC_JACK_AUX:223223+ add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_AUX);224224+ break;225225+ case AC_JACK_SPDIF_OUT:226226+ case AC_JACK_DIG_OTHER_OUT:227227+ if (cfg->dig_outs >= ARRAY_SIZE(cfg->dig_out_pins))228228+ continue;229229+ cfg->dig_out_pins[cfg->dig_outs] = nid;230230+ cfg->dig_out_type[cfg->dig_outs] =231231+ (loc == AC_JACK_LOC_HDMI) ?232232+ HDA_PCM_TYPE_HDMI : HDA_PCM_TYPE_SPDIF;233233+ cfg->dig_outs++;234234+ break;235235+ case AC_JACK_SPDIF_IN:236236+ case AC_JACK_DIG_OTHER_IN:237237+ cfg->dig_in_pin = nid;238238+ if (loc == AC_JACK_LOC_HDMI)239239+ cfg->dig_in_type = HDA_PCM_TYPE_HDMI;240240+ else241241+ cfg->dig_in_type = HDA_PCM_TYPE_SPDIF;242242+ break;243243+ }244244+ }245245+246246+ /* FIX-UP:247247+ * If no line-out is defined but multiple HPs are found,248248+ * some of them might be the real line-outs.249249+ */250250+ if (!cfg->line_outs && cfg->hp_outs > 1 &&251251+ !(cond_flags & HDA_PINCFG_NO_HP_FIXUP)) {252252+ int i = 0;253253+ while (i < cfg->hp_outs) {254254+ /* The real HPs should have the sequence 0x0f */255255+ if ((sequences_hp[i] & 0x0f) == 0x0f) {256256+ i++;257257+ continue;258258+ }259259+ /* Move it to the line-out table */260260+ cfg->line_out_pins[cfg->line_outs] = cfg->hp_pins[i];261261+ sequences_line_out[cfg->line_outs] = sequences_hp[i];262262+ cfg->line_outs++;263263+ cfg->hp_outs--;264264+ memmove(cfg->hp_pins + i, cfg->hp_pins + i + 1,265265+ sizeof(cfg->hp_pins[0]) * (cfg->hp_outs - i));266266+ memmove(sequences_hp + i, sequences_hp + i + 1,267267+ sizeof(sequences_hp[0]) * (cfg->hp_outs - i));268268+ }269269+ memset(cfg->hp_pins + cfg->hp_outs, 0,270270+ sizeof(hda_nid_t) * (AUTO_CFG_MAX_OUTS - cfg->hp_outs));271271+ if (!cfg->hp_outs)272272+ cfg->line_out_type = AUTO_PIN_HP_OUT;273273+274274+ }275275+276276+ /* sort by sequence */277277+ sort_pins_by_sequence(cfg->line_out_pins, sequences_line_out,278278+ cfg->line_outs);279279+ sort_pins_by_sequence(cfg->speaker_pins, sequences_speaker,280280+ cfg->speaker_outs);281281+ sort_pins_by_sequence(cfg->hp_pins, sequences_hp,282282+ cfg->hp_outs);283283+284284+ /*285285+ * FIX-UP: if no line-outs are detected, try to use speaker or HP pin286286+ * as a primary output287287+ */288288+ if (!cfg->line_outs &&289289+ !(cond_flags & HDA_PINCFG_NO_LO_FIXUP)) {290290+ if (cfg->speaker_outs) {291291+ cfg->line_outs = cfg->speaker_outs;292292+ memcpy(cfg->line_out_pins, cfg->speaker_pins,293293+ sizeof(cfg->speaker_pins));294294+ cfg->speaker_outs = 0;295295+ memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));296296+ cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;297297+ } else if (cfg->hp_outs) {298298+ cfg->line_outs = cfg->hp_outs;299299+ memcpy(cfg->line_out_pins, cfg->hp_pins,300300+ sizeof(cfg->hp_pins));301301+ cfg->hp_outs = 0;302302+ memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));303303+ cfg->line_out_type = AUTO_PIN_HP_OUT;304304+ }305305+ }306306+307307+ reorder_outputs(cfg->line_outs, cfg->line_out_pins);308308+ reorder_outputs(cfg->hp_outs, cfg->hp_pins);309309+ reorder_outputs(cfg->speaker_outs, cfg->speaker_pins);310310+311311+ sort_autocfg_input_pins(cfg);312312+313313+ /*314314+ * debug prints of the parsed results315315+ */316316+ snd_printd("autoconfig: line_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x) type:%s\n",317317+ cfg->line_outs, cfg->line_out_pins[0], cfg->line_out_pins[1],318318+ cfg->line_out_pins[2], cfg->line_out_pins[3],319319+ cfg->line_out_pins[4],320320+ cfg->line_out_type == AUTO_PIN_HP_OUT ? "hp" :321321+ (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT ?322322+ "speaker" : "line"));323323+ snd_printd(" speaker_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",324324+ cfg->speaker_outs, cfg->speaker_pins[0],325325+ cfg->speaker_pins[1], cfg->speaker_pins[2],326326+ cfg->speaker_pins[3], cfg->speaker_pins[4]);327327+ snd_printd(" hp_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",328328+ cfg->hp_outs, cfg->hp_pins[0],329329+ cfg->hp_pins[1], cfg->hp_pins[2],330330+ cfg->hp_pins[3], cfg->hp_pins[4]);331331+ snd_printd(" mono: mono_out=0x%x\n", cfg->mono_out_pin);332332+ if (cfg->dig_outs)333333+ snd_printd(" dig-out=0x%x/0x%x\n",334334+ cfg->dig_out_pins[0], cfg->dig_out_pins[1]);335335+ snd_printd(" inputs:");336336+ for (i = 0; i < cfg->num_inputs; i++) {337337+ snd_printd(" %s=0x%x",338338+ hda_get_autocfg_input_label(codec, cfg, i),339339+ cfg->inputs[i].pin);340340+ }341341+ snd_printd("\n");342342+ if (cfg->dig_in_pin)343343+ snd_printd(" dig-in=0x%x\n", cfg->dig_in_pin);344344+345345+ return 0;346346+}347347+EXPORT_SYMBOL_HDA(snd_hda_parse_pin_defcfg);348348+349349+int snd_hda_get_input_pin_attr(unsigned int def_conf)350350+{351351+ unsigned int loc = get_defcfg_location(def_conf);352352+ unsigned int conn = get_defcfg_connect(def_conf);353353+ if (conn == AC_JACK_PORT_NONE)354354+ return INPUT_PIN_ATTR_UNUSED;355355+ /* Windows may claim the internal mic to be BOTH, too */356356+ if (conn == AC_JACK_PORT_FIXED || conn == AC_JACK_PORT_BOTH)357357+ return INPUT_PIN_ATTR_INT;358358+ if ((loc & 0x30) == AC_JACK_LOC_INTERNAL)359359+ return INPUT_PIN_ATTR_INT;360360+ if ((loc & 0x30) == AC_JACK_LOC_SEPARATE)361361+ return INPUT_PIN_ATTR_DOCK;362362+ if (loc == AC_JACK_LOC_REAR)363363+ return INPUT_PIN_ATTR_REAR;364364+ if (loc == AC_JACK_LOC_FRONT)365365+ return INPUT_PIN_ATTR_FRONT;366366+ return INPUT_PIN_ATTR_NORMAL;367367+}368368+EXPORT_SYMBOL_HDA(snd_hda_get_input_pin_attr);369369+370370+/**371371+ * hda_get_input_pin_label - Give a label for the given input pin372372+ *373373+ * When check_location is true, the function checks the pin location374374+ * for mic and line-in pins, and set an appropriate prefix like "Front",375375+ * "Rear", "Internal".376376+ */377377+378378+static const char *hda_get_input_pin_label(struct hda_codec *codec,379379+ hda_nid_t pin, bool check_location)380380+{381381+ unsigned int def_conf;382382+ static const char * const mic_names[] = {383383+ "Internal Mic", "Dock Mic", "Mic", "Front Mic", "Rear Mic",384384+ };385385+ int attr;386386+387387+ def_conf = snd_hda_codec_get_pincfg(codec, pin);388388+389389+ switch (get_defcfg_device(def_conf)) {390390+ case AC_JACK_MIC_IN:391391+ if (!check_location)392392+ return "Mic";393393+ attr = snd_hda_get_input_pin_attr(def_conf);394394+ if (!attr)395395+ return "None";396396+ return mic_names[attr - 1];397397+ case AC_JACK_LINE_IN:398398+ if (!check_location)399399+ return "Line";400400+ attr = snd_hda_get_input_pin_attr(def_conf);401401+ if (!attr)402402+ return "None";403403+ if (attr == INPUT_PIN_ATTR_DOCK)404404+ return "Dock Line";405405+ return "Line";406406+ case AC_JACK_AUX:407407+ return "Aux";408408+ case AC_JACK_CD:409409+ return "CD";410410+ case AC_JACK_SPDIF_IN:411411+ return "SPDIF In";412412+ case AC_JACK_DIG_OTHER_IN:413413+ return "Digital In";414414+ default:415415+ return "Misc";416416+ }417417+}418418+419419+/* Check whether the location prefix needs to be added to the label.420420+ * If all mic-jacks are in the same location (e.g. rear panel), we don't421421+ * have to put "Front" prefix to each label. In such a case, returns false.422422+ */423423+static int check_mic_location_need(struct hda_codec *codec,424424+ const struct auto_pin_cfg *cfg,425425+ int input)426426+{427427+ unsigned int defc;428428+ int i, attr, attr2;429429+430430+ defc = snd_hda_codec_get_pincfg(codec, cfg->inputs[input].pin);431431+ attr = snd_hda_get_input_pin_attr(defc);432432+ /* for internal or docking mics, we need locations */433433+ if (attr <= INPUT_PIN_ATTR_NORMAL)434434+ return 1;435435+436436+ attr = 0;437437+ for (i = 0; i < cfg->num_inputs; i++) {438438+ defc = snd_hda_codec_get_pincfg(codec, cfg->inputs[i].pin);439439+ attr2 = snd_hda_get_input_pin_attr(defc);440440+ if (attr2 >= INPUT_PIN_ATTR_NORMAL) {441441+ if (attr && attr != attr2)442442+ return 1; /* different locations found */443443+ attr = attr2;444444+ }445445+ }446446+ return 0;447447+}448448+449449+/**450450+ * hda_get_autocfg_input_label - Get a label for the given input451451+ *452452+ * Get a label for the given input pin defined by the autocfg item.453453+ * Unlike hda_get_input_pin_label(), this function checks all inputs454454+ * defined in autocfg and avoids the redundant mic/line prefix as much as455455+ * possible.456456+ */457457+const char *hda_get_autocfg_input_label(struct hda_codec *codec,458458+ const struct auto_pin_cfg *cfg,459459+ int input)460460+{461461+ int type = cfg->inputs[input].type;462462+ int has_multiple_pins = 0;463463+464464+ if ((input > 0 && cfg->inputs[input - 1].type == type) ||465465+ (input < cfg->num_inputs - 1 && cfg->inputs[input + 1].type == type))466466+ has_multiple_pins = 1;467467+ if (has_multiple_pins && type == AUTO_PIN_MIC)468468+ has_multiple_pins &= check_mic_location_need(codec, cfg, input);469469+ return hda_get_input_pin_label(codec, cfg->inputs[input].pin,470470+ has_multiple_pins);471471+}472472+EXPORT_SYMBOL_HDA(hda_get_autocfg_input_label);473473+474474+/* return the position of NID in the list, or -1 if not found */475475+static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)476476+{477477+ int i;478478+ for (i = 0; i < nums; i++)479479+ if (list[i] == nid)480480+ return i;481481+ return -1;482482+}483483+484484+/* get a unique suffix or an index number */485485+static const char *check_output_sfx(hda_nid_t nid, const hda_nid_t *pins,486486+ int num_pins, int *indexp)487487+{488488+ static const char * const channel_sfx[] = {489489+ " Front", " Surround", " CLFE", " Side"490490+ };491491+ int i;492492+493493+ i = find_idx_in_nid_list(nid, pins, num_pins);494494+ if (i < 0)495495+ return NULL;496496+ if (num_pins == 1)497497+ return "";498498+ if (num_pins > ARRAY_SIZE(channel_sfx)) {499499+ if (indexp)500500+ *indexp = i;501501+ return "";502502+ }503503+ return channel_sfx[i];504504+}505505+506506+static int fill_audio_out_name(struct hda_codec *codec, hda_nid_t nid,507507+ const struct auto_pin_cfg *cfg,508508+ const char *name, char *label, int maxlen,509509+ int *indexp)510510+{511511+ unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid);512512+ int attr = snd_hda_get_input_pin_attr(def_conf);513513+ const char *pfx = "", *sfx = "";514514+515515+ /* handle as a speaker if it's a fixed line-out */516516+ if (!strcmp(name, "Line Out") && attr == INPUT_PIN_ATTR_INT)517517+ name = "Speaker";518518+ /* check the location */519519+ switch (attr) {520520+ case INPUT_PIN_ATTR_DOCK:521521+ pfx = "Dock ";522522+ break;523523+ case INPUT_PIN_ATTR_FRONT:524524+ pfx = "Front ";525525+ break;526526+ }527527+ if (cfg) {528528+ /* try to give a unique suffix if needed */529529+ sfx = check_output_sfx(nid, cfg->line_out_pins, cfg->line_outs,530530+ indexp);531531+ if (!sfx)532532+ sfx = check_output_sfx(nid, cfg->speaker_pins, cfg->speaker_outs,533533+ indexp);534534+ if (!sfx) {535535+ /* don't add channel suffix for Headphone controls */536536+ int idx = find_idx_in_nid_list(nid, cfg->hp_pins,537537+ cfg->hp_outs);538538+ if (idx >= 0)539539+ *indexp = idx;540540+ sfx = "";541541+ }542542+ }543543+ snprintf(label, maxlen, "%s%s%s", pfx, name, sfx);544544+ return 1;545545+}546546+547547+/**548548+ * snd_hda_get_pin_label - Get a label for the given I/O pin549549+ *550550+ * Get a label for the given pin. This function works for both input and551551+ * output pins. When @cfg is given as non-NULL, the function tries to get552552+ * an optimized label using hda_get_autocfg_input_label().553553+ *554554+ * This function tries to give a unique label string for the pin as much as555555+ * possible. For example, when the multiple line-outs are present, it adds556556+ * the channel suffix like "Front", "Surround", etc (only when @cfg is given).557557+ * If no unique name with a suffix is available and @indexp is non-NULL, the558558+ * index number is stored in the pointer.559559+ */560560+int snd_hda_get_pin_label(struct hda_codec *codec, hda_nid_t nid,561561+ const struct auto_pin_cfg *cfg,562562+ char *label, int maxlen, int *indexp)563563+{564564+ unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid);565565+ const char *name = NULL;566566+ int i;567567+568568+ if (indexp)569569+ *indexp = 0;570570+ if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)571571+ return 0;572572+573573+ switch (get_defcfg_device(def_conf)) {574574+ case AC_JACK_LINE_OUT:575575+ return fill_audio_out_name(codec, nid, cfg, "Line Out",576576+ label, maxlen, indexp);577577+ case AC_JACK_SPEAKER:578578+ return fill_audio_out_name(codec, nid, cfg, "Speaker",579579+ label, maxlen, indexp);580580+ case AC_JACK_HP_OUT:581581+ return fill_audio_out_name(codec, nid, cfg, "Headphone",582582+ label, maxlen, indexp);583583+ case AC_JACK_SPDIF_OUT:584584+ case AC_JACK_DIG_OTHER_OUT:585585+ if (get_defcfg_location(def_conf) == AC_JACK_LOC_HDMI)586586+ name = "HDMI";587587+ else588588+ name = "SPDIF";589589+ if (cfg && indexp) {590590+ i = find_idx_in_nid_list(nid, cfg->dig_out_pins,591591+ cfg->dig_outs);592592+ if (i >= 0)593593+ *indexp = i;594594+ }595595+ break;596596+ default:597597+ if (cfg) {598598+ for (i = 0; i < cfg->num_inputs; i++) {599599+ if (cfg->inputs[i].pin != nid)600600+ continue;601601+ name = hda_get_autocfg_input_label(codec, cfg, i);602602+ if (name)603603+ break;604604+ }605605+ }606606+ if (!name)607607+ name = hda_get_input_pin_label(codec, nid, true);608608+ break;609609+ }610610+ if (!name)611611+ return 0;612612+ strlcpy(label, name, maxlen);613613+ return 1;614614+}615615+EXPORT_SYMBOL_HDA(snd_hda_get_pin_label);616616+617617+int snd_hda_gen_add_verbs(struct hda_gen_spec *spec,618618+ const struct hda_verb *list)619619+{620620+ const struct hda_verb **v;621621+ snd_array_init(&spec->verbs, sizeof(struct hda_verb *), 8);622622+ v = snd_array_new(&spec->verbs);623623+ if (!v)624624+ return -ENOMEM;625625+ *v = list;626626+ return 0;627627+}628628+EXPORT_SYMBOL_HDA(snd_hda_gen_add_verbs);629629+630630+void snd_hda_gen_apply_verbs(struct hda_codec *codec)631631+{632632+ struct hda_gen_spec *spec = codec->spec;633633+ int i;634634+ for (i = 0; i < spec->verbs.used; i++) {635635+ struct hda_verb **v = snd_array_elem(&spec->verbs, i);636636+ snd_hda_sequence_write(codec, *v);637637+ }638638+}639639+EXPORT_SYMBOL_HDA(snd_hda_gen_apply_verbs);640640+641641+void snd_hda_apply_pincfgs(struct hda_codec *codec,642642+ const struct hda_pintbl *cfg)643643+{644644+ for (; cfg->nid; cfg++)645645+ snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val);646646+}647647+EXPORT_SYMBOL_HDA(snd_hda_apply_pincfgs);648648+649649+void snd_hda_apply_fixup(struct hda_codec *codec, int action)650650+{651651+ struct hda_gen_spec *spec = codec->spec;652652+ int id = spec->fixup_id;653653+#ifdef CONFIG_SND_DEBUG_VERBOSE654654+ const char *modelname = spec->fixup_name;655655+#endif656656+ int depth = 0;657657+658658+ if (!spec->fixup_list)659659+ return;660660+661661+ while (id >= 0) {662662+ const struct hda_fixup *fix = spec->fixup_list + id;663663+664664+ switch (fix->type) {665665+ case HDA_FIXUP_PINS:666666+ if (action != HDA_FIXUP_ACT_PRE_PROBE || !fix->v.pins)667667+ break;668668+ snd_printdd(KERN_INFO SFX669669+ "%s: Apply pincfg for %s\n",670670+ codec->chip_name, modelname);671671+ snd_hda_apply_pincfgs(codec, fix->v.pins);672672+ break;673673+ case HDA_FIXUP_VERBS:674674+ if (action != HDA_FIXUP_ACT_PROBE || !fix->v.verbs)675675+ break;676676+ snd_printdd(KERN_INFO SFX677677+ "%s: Apply fix-verbs for %s\n",678678+ codec->chip_name, modelname);679679+ snd_hda_gen_add_verbs(codec->spec, fix->v.verbs);680680+ break;681681+ case HDA_FIXUP_FUNC:682682+ if (!fix->v.func)683683+ break;684684+ snd_printdd(KERN_INFO SFX685685+ "%s: Apply fix-func for %s\n",686686+ codec->chip_name, modelname);687687+ fix->v.func(codec, fix, action);688688+ break;689689+ default:690690+ snd_printk(KERN_ERR SFX691691+ "%s: Invalid fixup type %d\n",692692+ codec->chip_name, fix->type);693693+ break;694694+ }695695+ if (!fix->chained)696696+ break;697697+ if (++depth > 10)698698+ break;699699+ id = fix->chain_id;700700+ }701701+}702702+EXPORT_SYMBOL_HDA(snd_hda_apply_fixup);703703+704704+void snd_hda_pick_fixup(struct hda_codec *codec,705705+ const struct hda_model_fixup *models,706706+ const struct snd_pci_quirk *quirk,707707+ const struct hda_fixup *fixlist)708708+{709709+ struct hda_gen_spec *spec = codec->spec;710710+ const struct snd_pci_quirk *q;711711+ int id = -1;712712+ const char *name = NULL;713713+714714+ /* when model=nofixup is given, don't pick up any fixups */715715+ if (codec->modelname && !strcmp(codec->modelname, "nofixup")) {716716+ spec->fixup_list = NULL;717717+ spec->fixup_id = -1;718718+ return;719719+ }720720+721721+ if (codec->modelname && models) {722722+ while (models->name) {723723+ if (!strcmp(codec->modelname, models->name)) {724724+ id = models->id;725725+ name = models->name;726726+ break;727727+ }728728+ models++;729729+ }730730+ }731731+ if (id < 0) {732732+ q = snd_pci_quirk_lookup(codec->bus->pci, quirk);733733+ if (q) {734734+ id = q->value;735735+#ifdef CONFIG_SND_DEBUG_VERBOSE736736+ name = q->name;737737+#endif738738+ }739739+ }740740+ if (id < 0) {741741+ for (q = quirk; q->subvendor; q++) {742742+ unsigned int vendorid =743743+ q->subdevice | (q->subvendor << 16);744744+ if (vendorid == codec->subsystem_id) {745745+ id = q->value;746746+#ifdef CONFIG_SND_DEBUG_VERBOSE747747+ name = q->name;748748+#endif749749+ break;750750+ }751751+ }752752+ }753753+754754+ spec->fixup_id = id;755755+ if (id >= 0) {756756+ spec->fixup_list = fixlist;757757+ spec->fixup_name = name;758758+ }759759+}760760+EXPORT_SYMBOL_HDA(snd_hda_pick_fixup);
+160
sound/pci/hda/hda_auto_parser.h
···11+/*22+ * BIOS auto-parser helper functions for HD-audio33+ *44+ * Copyright (c) 2012 Takashi Iwai <tiwai@suse.de>55+ *66+ * This driver is free software; you can redistribute it and/or modify77+ * it under the terms of the GNU General Public License as published by88+ * the Free Software Foundation; either version 2 of the License, or99+ * (at your option) any later version.1010+ */1111+1212+#ifndef __SOUND_HDA_AUTO_PARSER_H1313+#define __SOUND_HDA_AUTO_PARSER_H1414+1515+/*1616+ * Helper for automatic pin configuration1717+ */1818+1919+enum {2020+ AUTO_PIN_MIC,2121+ AUTO_PIN_LINE_IN,2222+ AUTO_PIN_CD,2323+ AUTO_PIN_AUX,2424+ AUTO_PIN_LAST2525+};2626+2727+enum {2828+ AUTO_PIN_LINE_OUT,2929+ AUTO_PIN_SPEAKER_OUT,3030+ AUTO_PIN_HP_OUT3131+};3232+3333+#define AUTO_CFG_MAX_OUTS HDA_MAX_OUTS3434+#define AUTO_CFG_MAX_INS 83535+3636+struct auto_pin_cfg_item {3737+ hda_nid_t pin;3838+ int type;3939+};4040+4141+struct auto_pin_cfg;4242+const char *hda_get_autocfg_input_label(struct hda_codec *codec,4343+ const struct auto_pin_cfg *cfg,4444+ int input);4545+int snd_hda_get_pin_label(struct hda_codec *codec, hda_nid_t nid,4646+ const struct auto_pin_cfg *cfg,4747+ char *label, int maxlen, int *indexp);4848+4949+enum {5050+ INPUT_PIN_ATTR_UNUSED, /* pin not connected */5151+ INPUT_PIN_ATTR_INT, /* internal mic/line-in */5252+ INPUT_PIN_ATTR_DOCK, /* docking mic/line-in */5353+ INPUT_PIN_ATTR_NORMAL, /* mic/line-in jack */5454+ INPUT_PIN_ATTR_FRONT, /* mic/line-in jack in front */5555+ INPUT_PIN_ATTR_REAR, /* mic/line-in jack in rear */5656+};5757+5858+int snd_hda_get_input_pin_attr(unsigned int def_conf);5959+6060+struct auto_pin_cfg {6161+ int line_outs;6262+ /* sorted in the order of Front/Surr/CLFE/Side */6363+ hda_nid_t line_out_pins[AUTO_CFG_MAX_OUTS];6464+ int speaker_outs;6565+ hda_nid_t speaker_pins[AUTO_CFG_MAX_OUTS];6666+ int hp_outs;6767+ int line_out_type; /* AUTO_PIN_XXX_OUT */6868+ hda_nid_t hp_pins[AUTO_CFG_MAX_OUTS];6969+ int num_inputs;7070+ struct auto_pin_cfg_item inputs[AUTO_CFG_MAX_INS];7171+ int dig_outs;7272+ hda_nid_t dig_out_pins[2];7373+ hda_nid_t dig_in_pin;7474+ hda_nid_t mono_out_pin;7575+ int dig_out_type[2]; /* HDA_PCM_TYPE_XXX */7676+ int dig_in_type; /* HDA_PCM_TYPE_XXX */7777+};7878+7979+/* bit-flags for snd_hda_parse_pin_def_config() behavior */8080+#define HDA_PINCFG_NO_HP_FIXUP (1 << 0) /* no HP-split */8181+#define HDA_PINCFG_NO_LO_FIXUP (1 << 1) /* don't take other outs as LO */8282+8383+int snd_hda_parse_pin_defcfg(struct hda_codec *codec,8484+ struct auto_pin_cfg *cfg,8585+ const hda_nid_t *ignore_nids,8686+ unsigned int cond_flags);8787+8888+/* older function */8989+#define snd_hda_parse_pin_def_config(codec, cfg, ignore) \9090+ snd_hda_parse_pin_defcfg(codec, cfg, ignore, 0)9191+9292+/*9393+ */9494+9595+struct hda_gen_spec {9696+ /* fix-up list */9797+ int fixup_id;9898+ const struct hda_fixup *fixup_list;9999+ const char *fixup_name;100100+101101+ /* additional init verbs */102102+ struct snd_array verbs;103103+};104104+105105+106106+/*107107+ * Fix-up pin default configurations and add default verbs108108+ */109109+110110+struct hda_pintbl {111111+ hda_nid_t nid;112112+ u32 val;113113+};114114+115115+struct hda_model_fixup {116116+ const int id;117117+ const char *name;118118+};119119+120120+struct hda_fixup {121121+ int type;122122+ bool chained;123123+ int chain_id;124124+ union {125125+ const struct hda_pintbl *pins;126126+ const struct hda_verb *verbs;127127+ void (*func)(struct hda_codec *codec,128128+ const struct hda_fixup *fix,129129+ int action);130130+ } v;131131+};132132+133133+/* fixup types */134134+enum {135135+ HDA_FIXUP_INVALID,136136+ HDA_FIXUP_PINS,137137+ HDA_FIXUP_VERBS,138138+ HDA_FIXUP_FUNC,139139+};140140+141141+/* fixup action definitions */142142+enum {143143+ HDA_FIXUP_ACT_PRE_PROBE,144144+ HDA_FIXUP_ACT_PROBE,145145+ HDA_FIXUP_ACT_INIT,146146+ HDA_FIXUP_ACT_BUILD,147147+};148148+149149+int snd_hda_gen_add_verbs(struct hda_gen_spec *spec,150150+ const struct hda_verb *list);151151+void snd_hda_gen_apply_verbs(struct hda_codec *codec);152152+void snd_hda_apply_pincfgs(struct hda_codec *codec,153153+ const struct hda_pintbl *cfg);154154+void snd_hda_apply_fixup(struct hda_codec *codec, int action);155155+void snd_hda_pick_fixup(struct hda_codec *codec,156156+ const struct hda_model_fixup *models,157157+ const struct snd_pci_quirk *quirk,158158+ const struct hda_fixup *fixlist);159159+160160+#endif /* __SOUND_HDA_AUTO_PARSER_H */
+284-747
sound/pci/hda/hda_codec.c
···334334 return NULL;335335}336336337337-/**338338- * snd_hda_get_conn_list - get connection list339339- * @codec: the HDA codec340340- * @nid: NID to parse341341- * @listp: the pointer to store NID list342342- *343343- * Parses the connection list of the given widget and stores the list344344- * of NIDs.345345- *346346- * Returns the number of connections, or a negative error code.347347- */348348-int snd_hda_get_conn_list(struct hda_codec *codec, hda_nid_t nid,349349- const hda_nid_t **listp)337337+/* read the connection and add to the cache */338338+static int read_and_add_raw_conns(struct hda_codec *codec, hda_nid_t nid)350339{351351- struct snd_array *array = &codec->conn_lists;352352- int len, err;353340 hda_nid_t list[HDA_MAX_CONNECTIONS];354354- hda_nid_t *p;355355- bool added = false;341341+ int len;356342357357- again:358358- /* if the connection-list is already cached, read it */359359- p = lookup_conn_list(array, nid);360360- if (p) {361361- if (listp)362362- *listp = p + 2;363363- return p[1];364364- }365365- if (snd_BUG_ON(added))366366- return -EINVAL;367367-368368- /* read the connection and add to the cache */369369- len = snd_hda_get_raw_connections(codec, nid, list, HDA_MAX_CONNECTIONS);343343+ len = snd_hda_get_raw_connections(codec, nid, list, ARRAY_SIZE(list));370344 if (len < 0)371345 return len;372372- err = snd_hda_override_conn_list(codec, nid, len, list);373373- if (err < 0)374374- return err;375375- added = true;376376- goto again;346346+ return snd_hda_override_conn_list(codec, nid, len, list);377347}378378-EXPORT_SYMBOL_HDA(snd_hda_get_conn_list);379348380349/**381350 * snd_hda_get_connections - copy connection list382351 * @codec: the HDA codec383352 * @nid: NID to parse384384- * @conn_list: connection list array353353+ * @conn_list: connection list array; when NULL, checks only the size385354 * @max_conns: max. number of connections to store386355 *387356 * Parses the connection list of the given widget and stores the list···359390 * Returns the number of connections, or a negative error code.360391 */361392int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,362362- hda_nid_t *conn_list, int max_conns)393393+ hda_nid_t *conn_list, int max_conns)363394{364364- const hda_nid_t *list;365365- int len = snd_hda_get_conn_list(codec, nid, &list);395395+ struct snd_array *array = &codec->conn_lists;396396+ int len;397397+ hda_nid_t *p;398398+ bool added = false;366399367367- if (len <= 0)368368- return len;369369- if (len > max_conns) {370370- snd_printk(KERN_ERR "hda_codec: "371371- "Too many connections %d for NID 0x%x\n",372372- len, nid);373373- return -EINVAL;400400+ again:401401+ mutex_lock(&codec->hash_mutex);402402+ len = -1;403403+ /* if the connection-list is already cached, read it */404404+ p = lookup_conn_list(array, nid);405405+ if (p) {406406+ len = p[1];407407+ if (conn_list && len > max_conns) {408408+ snd_printk(KERN_ERR "hda_codec: "409409+ "Too many connections %d for NID 0x%x\n",410410+ len, nid);411411+ mutex_unlock(&codec->hash_mutex);412412+ return -EINVAL;413413+ }414414+ if (conn_list && len)415415+ memcpy(conn_list, p + 2, len * sizeof(hda_nid_t));374416 }375375- memcpy(conn_list, list, len * sizeof(hda_nid_t));376376- return len;417417+ mutex_unlock(&codec->hash_mutex);418418+ if (len >= 0)419419+ return len;420420+ if (snd_BUG_ON(added))421421+ return -EINVAL;422422+423423+ len = read_and_add_raw_conns(codec, nid);424424+ if (len < 0)425425+ return len;426426+ added = true;427427+ goto again;377428}378429EXPORT_SYMBOL_HDA(snd_hda_get_connections);379430···532543 hda_nid_t *p;533544 int i, old_used;534545546546+ mutex_lock(&codec->hash_mutex);535547 p = lookup_conn_list(array, nid);536548 if (p)537549 *p = -1; /* invalidate the old entry */···543553 for (i = 0; i < len; i++)544554 if (!add_conn_list(array, list[i]))545555 goto error_add;556556+ mutex_unlock(&codec->hash_mutex);546557 return 0;547558548559 error_add:549560 array->used = old_used;561561+ mutex_unlock(&codec->hash_mutex);550562 return -ENOMEM;551563}552564EXPORT_SYMBOL_HDA(snd_hda_override_conn_list);···12471255 codec->addr = codec_addr;12481256 mutex_init(&codec->spdif_mutex);12491257 mutex_init(&codec->control_mutex);12581258+ mutex_init(&codec->hash_mutex);12501259 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));12511260 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));12521261 snd_array_init(&codec->mixers, sizeof(struct hda_nid_item), 32);···12571264 snd_array_init(&codec->cvt_setups, sizeof(struct hda_cvt_setup), 8);12581265 snd_array_init(&codec->conn_lists, sizeof(hda_nid_t), 64);12591266 snd_array_init(&codec->spdif_out, sizeof(struct hda_spdif_out), 16);12601260- if (codec->bus->modelname) {12611261- codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL);12621262- if (!codec->modelname) {12631263- snd_hda_codec_free(codec);12641264- return -ENODEV;12651265- }12661266- }1267126712681268#ifdef CONFIG_SND_HDA_POWER_SAVE12691269+ spin_lock_init(&codec->power_lock);12691270 INIT_DELAYED_WORK(&codec->power_work, hda_power_work);12701271 /* snd_hda_codec_new() marks the codec as power-up, and leave it as is.12711272 * the caller has to power down appropriatley after initialization···12671280 */12681281 hda_keep_power_on(codec);12691282#endif12831283+12841284+ if (codec->bus->modelname) {12851285+ codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL);12861286+ if (!codec->modelname) {12871287+ snd_hda_codec_free(codec);12881288+ return -ENODEV;12891289+ }12901290+ }1270129112711292 list_add_tail(&codec->list, &bus->codec_list);12721293 bus->caddr_tbl[codec_addr] = codec;···15981603 return (struct hda_amp_info *)get_alloc_hash(&codec->amp_cache, key);15991604}1600160516061606+/* overwrite the value with the key in the caps hash */16071607+static int write_caps_hash(struct hda_codec *codec, u32 key, unsigned int val)16081608+{16091609+ struct hda_amp_info *info;16101610+16111611+ mutex_lock(&codec->hash_mutex);16121612+ info = get_alloc_amp_hash(codec, key);16131613+ if (!info) {16141614+ mutex_unlock(&codec->hash_mutex);16151615+ return -EINVAL;16161616+ }16171617+ info->amp_caps = val;16181618+ info->head.val |= INFO_AMP_CAPS;16191619+ mutex_unlock(&codec->hash_mutex);16201620+ return 0;16211621+}16221622+16231623+/* query the value from the caps hash; if not found, fetch the current16241624+ * value from the given function and store in the hash16251625+ */16261626+static unsigned int16271627+query_caps_hash(struct hda_codec *codec, hda_nid_t nid, int dir, u32 key,16281628+ unsigned int (*func)(struct hda_codec *, hda_nid_t, int))16291629+{16301630+ struct hda_amp_info *info;16311631+ unsigned int val;16321632+16331633+ mutex_lock(&codec->hash_mutex);16341634+ info = get_alloc_amp_hash(codec, key);16351635+ if (!info) {16361636+ mutex_unlock(&codec->hash_mutex);16371637+ return 0;16381638+ }16391639+ if (!(info->head.val & INFO_AMP_CAPS)) {16401640+ mutex_unlock(&codec->hash_mutex); /* for reentrance */16411641+ val = func(codec, nid, dir);16421642+ write_caps_hash(codec, key, val);16431643+ } else {16441644+ val = info->amp_caps;16451645+ mutex_unlock(&codec->hash_mutex);16461646+ }16471647+ return val;16481648+}16491649+16501650+static unsigned int read_amp_cap(struct hda_codec *codec, hda_nid_t nid,16511651+ int direction)16521652+{16531653+ if (!(get_wcaps(codec, nid) & AC_WCAP_AMP_OVRD))16541654+ nid = codec->afg;16551655+ return snd_hda_param_read(codec, nid,16561656+ direction == HDA_OUTPUT ?16571657+ AC_PAR_AMP_OUT_CAP : AC_PAR_AMP_IN_CAP);16581658+}16591659+16011660/**16021661 * query_amp_caps - query AMP capabilities16031662 * @codec: the HD-auio codec···16661617 */16671618u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)16681619{16691669- struct hda_amp_info *info;16701670-16711671- info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, 0));16721672- if (!info)16731673- return 0;16741674- if (!(info->head.val & INFO_AMP_CAPS)) {16751675- if (!(get_wcaps(codec, nid) & AC_WCAP_AMP_OVRD))16761676- nid = codec->afg;16771677- info->amp_caps = snd_hda_param_read(codec, nid,16781678- direction == HDA_OUTPUT ?16791679- AC_PAR_AMP_OUT_CAP :16801680- AC_PAR_AMP_IN_CAP);16811681- if (info->amp_caps)16821682- info->head.val |= INFO_AMP_CAPS;16831683- }16841684- return info->amp_caps;16201620+ return query_caps_hash(codec, nid, direction,16211621+ HDA_HASH_KEY(nid, direction, 0),16221622+ read_amp_cap);16851623}16861624EXPORT_SYMBOL_HDA(query_amp_caps);16871625···16881652int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,16891653 unsigned int caps)16901654{16911691- struct hda_amp_info *info;16921692-16931693- info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, dir, 0));16941694- if (!info)16951695- return -EINVAL;16961696- info->amp_caps = caps;16971697- info->head.val |= INFO_AMP_CAPS;16981698- return 0;16551655+ return write_caps_hash(codec, HDA_HASH_KEY(nid, dir, 0), caps);16991656}17001657EXPORT_SYMBOL_HDA(snd_hda_override_amp_caps);1701165817021702-static unsigned int17031703-query_caps_hash(struct hda_codec *codec, hda_nid_t nid, u32 key,17041704- unsigned int (*func)(struct hda_codec *, hda_nid_t))17051705-{17061706- struct hda_amp_info *info;17071707-17081708- info = get_alloc_amp_hash(codec, key);17091709- if (!info)17101710- return 0;17111711- if (!info->head.val) {17121712- info->head.val |= INFO_AMP_CAPS;17131713- info->amp_caps = func(codec, nid);17141714- }17151715- return info->amp_caps;17161716-}17171717-17181718-static unsigned int read_pin_cap(struct hda_codec *codec, hda_nid_t nid)16591659+static unsigned int read_pin_cap(struct hda_codec *codec, hda_nid_t nid,16601660+ int dir)17191661{17201662 return snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);17211663}···17111697 */17121698u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid)17131699{17141714- return query_caps_hash(codec, nid, HDA_HASH_PINCAP_KEY(nid),17001700+ return query_caps_hash(codec, nid, 0, HDA_HASH_PINCAP_KEY(nid),17151701 read_pin_cap);17161702}17171703EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps);···17291715int snd_hda_override_pin_caps(struct hda_codec *codec, hda_nid_t nid,17301716 unsigned int caps)17311717{17321732- struct hda_amp_info *info;17331733- info = get_alloc_amp_hash(codec, HDA_HASH_PINCAP_KEY(nid));17341734- if (!info)17351735- return -ENOMEM;17361736- info->amp_caps = caps;17371737- info->head.val |= INFO_AMP_CAPS;17381738- return 0;17181718+ return write_caps_hash(codec, HDA_HASH_PINCAP_KEY(nid), caps);17391719}17401720EXPORT_SYMBOL_HDA(snd_hda_override_pin_caps);1741172117421742-/*17431743- * read the current volume to info17441744- * if the cache exists, read the cache value.17221722+/* read or sync the hash value with the current value;17231723+ * call within hash_mutex17451724 */17461746-static unsigned int get_vol_mute(struct hda_codec *codec,17471747- struct hda_amp_info *info, hda_nid_t nid,17481748- int ch, int direction, int index)17251725+static struct hda_amp_info *17261726+update_amp_hash(struct hda_codec *codec, hda_nid_t nid, int ch,17271727+ int direction, int index)17491728{17501750- u32 val, parm;17291729+ struct hda_amp_info *info;17301730+ unsigned int parm, val = 0;17311731+ bool val_read = false;1751173217521752- if (info->head.val & INFO_AMP_VOL(ch))17531753- return info->vol[ch];17541754-17551755- parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT;17561756- parm |= direction == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT;17571757- parm |= index;17581758- val = snd_hda_codec_read(codec, nid, 0,17331733+ retry:17341734+ info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index));17351735+ if (!info)17361736+ return NULL;17371737+ if (!(info->head.val & INFO_AMP_VOL(ch))) {17381738+ if (!val_read) {17391739+ mutex_unlock(&codec->hash_mutex);17401740+ parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT;17411741+ parm |= direction == HDA_OUTPUT ?17421742+ AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT;17431743+ parm |= index;17441744+ val = snd_hda_codec_read(codec, nid, 0,17591745 AC_VERB_GET_AMP_GAIN_MUTE, parm);17601760- info->vol[ch] = val & 0xff;17611761- info->head.val |= INFO_AMP_VOL(ch);17621762- return info->vol[ch];17461746+ val &= 0xff;17471747+ val_read = true;17481748+ mutex_lock(&codec->hash_mutex);17491749+ goto retry;17501750+ }17511751+ info->vol[ch] = val;17521752+ info->head.val |= INFO_AMP_VOL(ch);17531753+ }17541754+ return info;17631755}1764175617651757/*17661766- * write the current volume in info to the h/w and update the cache17581758+ * write the current volume in info to the h/w17671759 */17681760static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,17691761 hda_nid_t nid, int ch, int direction, int index,···17861766 else17871767 parm |= val;17881768 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, parm);17891789- info->vol[ch] = val;17901769}1791177017921771/**···18021783 int direction, int index)18031784{18041785 struct hda_amp_info *info;18051805- info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index));18061806- if (!info)18071807- return 0;18081808- return get_vol_mute(codec, info, nid, ch, direction, index);17861786+ unsigned int val = 0;17871787+17881788+ mutex_lock(&codec->hash_mutex);17891789+ info = update_amp_hash(codec, nid, ch, direction, index);17901790+ if (info)17911791+ val = info->vol[ch];17921792+ mutex_unlock(&codec->hash_mutex);17931793+ return val;18091794}18101795EXPORT_SYMBOL_HDA(snd_hda_codec_amp_read);18111796···18311808{18321809 struct hda_amp_info *info;1833181018341834- info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx));18351835- if (!info)18361836- return 0;18371811 if (snd_BUG_ON(mask & ~0xff))18381812 mask &= 0xff;18391813 val &= mask;18401840- val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask;18411841- if (info->vol[ch] == val)18141814+18151815+ mutex_lock(&codec->hash_mutex);18161816+ info = update_amp_hash(codec, nid, ch, direction, idx);18171817+ if (!info) {18181818+ mutex_unlock(&codec->hash_mutex);18421819 return 0;18201820+ }18211821+ val |= info->vol[ch] & ~mask;18221822+ if (info->vol[ch] == val) {18231823+ mutex_unlock(&codec->hash_mutex);18241824+ return 0;18251825+ }18261826+ info->vol[ch] = val;18271827+ mutex_unlock(&codec->hash_mutex);18431828 put_vol_mute(codec, info, nid, ch, direction, idx, val);18441829 return 1;18451830}···22942263 /* OK, let it free */2295226422962265#ifdef CONFIG_SND_HDA_POWER_SAVE22972297- cancel_delayed_work(&codec->power_work);22662266+ cancel_delayed_work_sync(&codec->power_work);22672267+ codec->power_on = 0;22682268+ codec->power_transition = 0;22692269+ codec->power_jiffies = jiffies;22982270 flush_workqueue(codec->bus->workq);22992271#endif23002272 snd_hda_ctls_clear(codec);···28932859{28942860 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);28952861 int idx = kcontrol->private_value;28962896- struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx);28622862+ struct hda_spdif_out *spdif;2897286328642864+ mutex_lock(&codec->spdif_mutex);28652865+ spdif = snd_array_elem(&codec->spdif_out, idx);28982866 ucontrol->value.iec958.status[0] = spdif->status & 0xff;28992867 ucontrol->value.iec958.status[1] = (spdif->status >> 8) & 0xff;29002868 ucontrol->value.iec958.status[2] = (spdif->status >> 16) & 0xff;29012869 ucontrol->value.iec958.status[3] = (spdif->status >> 24) & 0xff;28702870+ mutex_unlock(&codec->spdif_mutex);2902287129032872 return 0;29042873}···29872950{29882951 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);29892952 int idx = kcontrol->private_value;29902990- struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx);29912991- hda_nid_t nid = spdif->nid;29532953+ struct hda_spdif_out *spdif;29542954+ hda_nid_t nid;29922955 unsigned short val;29932956 int change;2994295729952958 mutex_lock(&codec->spdif_mutex);29592959+ spdif = snd_array_elem(&codec->spdif_out, idx);29602960+ nid = spdif->nid;29962961 spdif->status = ucontrol->value.iec958.status[0] |29972962 ((unsigned int)ucontrol->value.iec958.status[1] << 8) |29982963 ((unsigned int)ucontrol->value.iec958.status[2] << 16) |···30162977{30172978 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);30182979 int idx = kcontrol->private_value;30193019- struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx);29802980+ struct hda_spdif_out *spdif;3020298129822982+ mutex_lock(&codec->spdif_mutex);29832983+ spdif = snd_array_elem(&codec->spdif_out, idx);30212984 ucontrol->value.integer.value[0] = spdif->ctls & AC_DIG1_ENABLE;29852985+ mutex_unlock(&codec->spdif_mutex);30222986 return 0;30232987}30242988···30412999{30423000 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);30433001 int idx = kcontrol->private_value;30443044- struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx);30453045- hda_nid_t nid = spdif->nid;30023002+ struct hda_spdif_out *spdif;30033003+ hda_nid_t nid;30463004 unsigned short val;30473005 int change;3048300630493007 mutex_lock(&codec->spdif_mutex);30083008+ spdif = snd_array_elem(&codec->spdif_out, idx);30093009+ nid = spdif->nid;30503010 val = spdif->ctls & ~AC_DIG1_ENABLE;30513011 if (ucontrol->value.integer.value[0])30523012 val |= AC_DIG1_ENABLE;···31363092}31373093EXPORT_SYMBOL_HDA(snd_hda_create_spdif_out_ctls);3138309430953095+/* get the hda_spdif_out entry from the given NID30963096+ * call within spdif_mutex lock30973097+ */31393098struct hda_spdif_out *snd_hda_spdif_out_of_nid(struct hda_codec *codec,31403099 hda_nid_t nid)31413100{···3155310831563109void snd_hda_spdif_ctls_unassign(struct hda_codec *codec, int idx)31573110{31583158- struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx);31113111+ struct hda_spdif_out *spdif;3159311231603113 mutex_lock(&codec->spdif_mutex);31143114+ spdif = snd_array_elem(&codec->spdif_out, idx);31613115 spdif->nid = (u16)-1;31623116 mutex_unlock(&codec->spdif_mutex);31633117}···3166311831673119void snd_hda_spdif_ctls_assign(struct hda_codec *codec, int idx, hda_nid_t nid)31683120{31693169- struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx);31213121+ struct hda_spdif_out *spdif;31703122 unsigned short val;3171312331723124 mutex_lock(&codec->spdif_mutex);31253125+ spdif = snd_array_elem(&codec->spdif_out, idx);31733126 if (spdif->nid != nid) {31743127 spdif->nid = nid;31753128 val = spdif->ctls;···35353486 codec->afg ? codec->afg : codec->mfg,35363487 AC_PWRST_D3);35373488#ifdef CONFIG_SND_HDA_POWER_SAVE35383538- snd_hda_update_power_acct(codec);35393489 cancel_delayed_work(&codec->power_work);34903490+ spin_lock(&codec->power_lock);34913491+ snd_hda_update_power_acct(codec);34923492+ trace_hda_power_down(codec);35403493 codec->power_on = 0;35413494 codec->power_transition = 0;35423495 codec->power_jiffies = jiffies;34963496+ spin_unlock(&codec->power_lock);35433497#endif35443498}35453499···35513499 */35523500static void hda_call_codec_resume(struct hda_codec *codec)35533501{35023502+ /* set as if powered on for avoiding re-entering the resume35033503+ * in the resume / power-save sequence35043504+ */35053505+ hda_keep_power_on(codec);35543506 hda_set_power_state(codec,35553507 codec->afg ? codec->afg : codec->mfg,35563508 AC_PWRST_D0);···35703514 snd_hda_codec_resume_amp(codec);35713515 snd_hda_codec_resume_cache(codec);35723516 }35173517+ snd_hda_power_down(codec); /* flag down before returning */35733518}35743519#endif /* CONFIG_PM */35753520···37223665}37233666EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format);3724366737253725-static unsigned int get_pcm_param(struct hda_codec *codec, hda_nid_t nid)36683668+static unsigned int get_pcm_param(struct hda_codec *codec, hda_nid_t nid,36693669+ int dir)37263670{37273671 unsigned int val = 0;37283672 if (nid != codec->afg &&···3738368037393681static unsigned int query_pcm_param(struct hda_codec *codec, hda_nid_t nid)37403682{37413741- return query_caps_hash(codec, nid, HDA_HASH_PARPCM_KEY(nid),36833683+ return query_caps_hash(codec, nid, 0, HDA_HASH_PARPCM_KEY(nid),37423684 get_pcm_param);37433685}3744368637453745-static unsigned int get_stream_param(struct hda_codec *codec, hda_nid_t nid)36873687+static unsigned int get_stream_param(struct hda_codec *codec, hda_nid_t nid,36883688+ int dir)37463689{37473690 unsigned int streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM);37483691 if (!streams || streams == -1)···3755369637563697static unsigned int query_stream_param(struct hda_codec *codec, hda_nid_t nid)37573698{37583758- return query_caps_hash(codec, nid, HDA_HASH_PARSTR_KEY(nid),36993699+ return query_caps_hash(codec, nid, 0, HDA_HASH_PARSTR_KEY(nid),37593700 get_stream_param);37603701}37613702···38343775 bps = 20;38353776 }38363777 }37783778+#if 0 /* FIXME: CS4206 doesn't work, which is the only codec supporting float */38373779 if (streams & AC_SUPFMT_FLOAT32) {38383780 formats |= SNDRV_PCM_FMTBIT_FLOAT_LE;38393781 if (!bps)38403782 bps = 32;38413783 }37843784+#endif38423785 if (streams == AC_SUPFMT_AC3) {38433786 /* should be exclusive */38443787 /* temporary hack: we have still no proper support···43444283 container_of(work, struct hda_codec, power_work.work);43454284 struct hda_bus *bus = codec->bus;4346428543474347- if (!codec->power_on || codec->power_count) {43484348- codec->power_transition = 0;42864286+ spin_lock(&codec->power_lock);42874287+ if (codec->power_transition > 0) { /* during power-up sequence? */42884288+ spin_unlock(&codec->power_lock);43494289 return;43504290 }42914291+ if (!codec->power_on || codec->power_count) {42924292+ codec->power_transition = 0;42934293+ spin_unlock(&codec->power_lock);42944294+ return;42954295+ }42964296+ spin_unlock(&codec->power_lock);4351429743524352- trace_hda_power_down(codec);43534298 hda_call_codec_suspend(codec);43544299 if (bus->ops.pm_notify)43554300 bus->ops.pm_notify(bus);···4363429643644297static void hda_keep_power_on(struct hda_codec *codec)43654298{42994299+ spin_lock(&codec->power_lock);43664300 codec->power_count++;43674301 codec->power_on = 1;43684302 codec->power_jiffies = jiffies;43034303+ spin_unlock(&codec->power_lock);43694304}4370430543714306/* update the power on/off account with the current jiffies */···43924323{43934324 struct hda_bus *bus = codec->bus;4394432543264326+ spin_lock(&codec->power_lock);43954327 codec->power_count++;43964396- if (codec->power_on || codec->power_transition)43284328+ if (codec->power_on || codec->power_transition > 0) {43294329+ spin_unlock(&codec->power_lock);43974330 return;43314331+ }43324332+ spin_unlock(&codec->power_lock);4398433343344334+ cancel_delayed_work_sync(&codec->power_work);43354335+43364336+ spin_lock(&codec->power_lock);43994337 trace_hda_power_up(codec);44004338 snd_hda_update_power_acct(codec);44014339 codec->power_on = 1;44024340 codec->power_jiffies = jiffies;43414341+ codec->power_transition = 1; /* avoid reentrance */43424342+ spin_unlock(&codec->power_lock);43434343+44034344 if (bus->ops.pm_notify)44044345 bus->ops.pm_notify(bus);44054346 hda_call_codec_resume(codec);44064406- cancel_delayed_work(&codec->power_work);43474347+43484348+ spin_lock(&codec->power_lock);44074349 codec->power_transition = 0;43504350+ spin_unlock(&codec->power_lock);44084351}44094352EXPORT_SYMBOL_HDA(snd_hda_power_up);44104353···44324351 */44334352void snd_hda_power_down(struct hda_codec *codec)44344353{43544354+ spin_lock(&codec->power_lock);44354355 --codec->power_count;44364436- if (!codec->power_on || codec->power_count || codec->power_transition)43564356+ if (!codec->power_on || codec->power_count || codec->power_transition) {43574357+ spin_unlock(&codec->power_lock);44374358 return;43594359+ }44384360 if (power_save(codec)) {44394439- codec->power_transition = 1; /* avoid reentrance */43614361+ codec->power_transition = -1; /* avoid reentrance */44404362 queue_delayed_work(codec->bus->workq, &codec->power_work,44414363 msecs_to_jiffies(power_save(codec) * 1000));44424364 }43654365+ spin_unlock(&codec->power_lock);44434366}44444367EXPORT_SYMBOL_HDA(snd_hda_power_down);44454368···47954710{47964711 const hda_nid_t *nids = mout->dac_nids;47974712 int chs = substream->runtime->channels;47984798- struct hda_spdif_out *spdif =47994799- snd_hda_spdif_out_of_nid(codec, mout->dig_out_nid);47134713+ struct hda_spdif_out *spdif;48004714 int i;4801471548024716 mutex_lock(&codec->spdif_mutex);47174717+ spdif = snd_hda_spdif_out_of_nid(codec, mout->dig_out_nid);48034718 if (mout->dig_out_nid && mout->share_spdif &&48044719 mout->dig_out_used != HDA_DIG_EXCLUSIVE) {48054720 if (chs == 2 &&···48804795}48814796EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_cleanup);4882479748834883-/*48844884- * Helper for automatic pin configuration48854885- */48864886-48874887-static int is_in_nid_list(hda_nid_t nid, const hda_nid_t *list)48884888-{48894889- for (; *list; list++)48904890- if (*list == nid)48914891- return 1;48924892- return 0;48934893-}48944894-48954895-48964896-/*48974897- * Sort an associated group of pins according to their sequence numbers.48984898- */48994899-static void sort_pins_by_sequence(hda_nid_t *pins, short *sequences,49004900- int num_pins)49014901-{49024902- int i, j;49034903- short seq;49044904- hda_nid_t nid;49054905-49064906- for (i = 0; i < num_pins; i++) {49074907- for (j = i + 1; j < num_pins; j++) {49084908- if (sequences[i] > sequences[j]) {49094909- seq = sequences[i];49104910- sequences[i] = sequences[j];49114911- sequences[j] = seq;49124912- nid = pins[i];49134913- pins[i] = pins[j];49144914- pins[j] = nid;49154915- }49164916- }49174917- }49184918-}49194919-49204920-49214921-/* add the found input-pin to the cfg->inputs[] table */49224922-static void add_auto_cfg_input_pin(struct auto_pin_cfg *cfg, hda_nid_t nid,49234923- int type)49244924-{49254925- if (cfg->num_inputs < AUTO_CFG_MAX_INS) {49264926- cfg->inputs[cfg->num_inputs].pin = nid;49274927- cfg->inputs[cfg->num_inputs].type = type;49284928- cfg->num_inputs++;49294929- }49304930-}49314931-49324932-/* sort inputs in the order of AUTO_PIN_* type */49334933-static void sort_autocfg_input_pins(struct auto_pin_cfg *cfg)49344934-{49354935- int i, j;49364936-49374937- for (i = 0; i < cfg->num_inputs; i++) {49384938- for (j = i + 1; j < cfg->num_inputs; j++) {49394939- if (cfg->inputs[i].type > cfg->inputs[j].type) {49404940- struct auto_pin_cfg_item tmp;49414941- tmp = cfg->inputs[i];49424942- cfg->inputs[i] = cfg->inputs[j];49434943- cfg->inputs[j] = tmp;49444944- }49454945- }49464946- }49474947-}49484948-49494949-/* Reorder the surround channels49504950- * ALSA sequence is front/surr/clfe/side49514951- * HDA sequence is:49524952- * 4-ch: front/surr => OK as it is49534953- * 6-ch: front/clfe/surr49544954- * 8-ch: front/clfe/rear/side|fc49554955- */49564956-static void reorder_outputs(unsigned int nums, hda_nid_t *pins)49574957-{49584958- hda_nid_t nid;49594959-49604960- switch (nums) {49614961- case 3:49624962- case 4:49634963- nid = pins[1];49644964- pins[1] = pins[2];49654965- pins[2] = nid;49664966- break;49674967- }49684968-}49694969-49704970-/*49714971- * Parse all pin widgets and store the useful pin nids to cfg49724972- *49734973- * The number of line-outs or any primary output is stored in line_outs,49744974- * and the corresponding output pins are assigned to line_out_pins[],49754975- * in the order of front, rear, CLFE, side, ...49764976- *49774977- * If more extra outputs (speaker and headphone) are found, the pins are49784978- * assisnged to hp_pins[] and speaker_pins[], respectively. If no line-out jack49794979- * is detected, one of speaker of HP pins is assigned as the primary49804980- * output, i.e. to line_out_pins[0]. So, line_outs is always positive49814981- * if any analog output exists.49824982- *49834983- * The analog input pins are assigned to inputs array.49844984- * The digital input/output pins are assigned to dig_in_pin and dig_out_pin,49854985- * respectively.49864986- */49874987-int snd_hda_parse_pin_defcfg(struct hda_codec *codec,49884988- struct auto_pin_cfg *cfg,49894989- const hda_nid_t *ignore_nids,49904990- unsigned int cond_flags)49914991-{49924992- hda_nid_t nid, end_nid;49934993- short seq, assoc_line_out;49944994- short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)];49954995- short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)];49964996- short sequences_hp[ARRAY_SIZE(cfg->hp_pins)];49974997- int i;49984998-49994999- memset(cfg, 0, sizeof(*cfg));50005000-50015001- memset(sequences_line_out, 0, sizeof(sequences_line_out));50025002- memset(sequences_speaker, 0, sizeof(sequences_speaker));50035003- memset(sequences_hp, 0, sizeof(sequences_hp));50045004- assoc_line_out = 0;50055005-50065006- codec->ignore_misc_bit = true;50075007- end_nid = codec->start_nid + codec->num_nodes;50085008- for (nid = codec->start_nid; nid < end_nid; nid++) {50095009- unsigned int wid_caps = get_wcaps(codec, nid);50105010- unsigned int wid_type = get_wcaps_type(wid_caps);50115011- unsigned int def_conf;50125012- short assoc, loc, conn, dev;50135013-50145014- /* read all default configuration for pin complex */50155015- if (wid_type != AC_WID_PIN)50165016- continue;50175017- /* ignore the given nids (e.g. pc-beep returns error) */50185018- if (ignore_nids && is_in_nid_list(nid, ignore_nids))50195019- continue;50205020-50215021- def_conf = snd_hda_codec_get_pincfg(codec, nid);50225022- if (!(get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) &50235023- AC_DEFCFG_MISC_NO_PRESENCE))50245024- codec->ignore_misc_bit = false;50255025- conn = get_defcfg_connect(def_conf);50265026- if (conn == AC_JACK_PORT_NONE)50275027- continue;50285028- loc = get_defcfg_location(def_conf);50295029- dev = get_defcfg_device(def_conf);50305030-50315031- /* workaround for buggy BIOS setups */50325032- if (dev == AC_JACK_LINE_OUT) {50335033- if (conn == AC_JACK_PORT_FIXED)50345034- dev = AC_JACK_SPEAKER;50355035- }50365036-50375037- switch (dev) {50385038- case AC_JACK_LINE_OUT:50395039- seq = get_defcfg_sequence(def_conf);50405040- assoc = get_defcfg_association(def_conf);50415041-50425042- if (!(wid_caps & AC_WCAP_STEREO))50435043- if (!cfg->mono_out_pin)50445044- cfg->mono_out_pin = nid;50455045- if (!assoc)50465046- continue;50475047- if (!assoc_line_out)50485048- assoc_line_out = assoc;50495049- else if (assoc_line_out != assoc)50505050- continue;50515051- if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins))50525052- continue;50535053- cfg->line_out_pins[cfg->line_outs] = nid;50545054- sequences_line_out[cfg->line_outs] = seq;50555055- cfg->line_outs++;50565056- break;50575057- case AC_JACK_SPEAKER:50585058- seq = get_defcfg_sequence(def_conf);50595059- assoc = get_defcfg_association(def_conf);50605060- if (cfg->speaker_outs >= ARRAY_SIZE(cfg->speaker_pins))50615061- continue;50625062- cfg->speaker_pins[cfg->speaker_outs] = nid;50635063- sequences_speaker[cfg->speaker_outs] = (assoc << 4) | seq;50645064- cfg->speaker_outs++;50655065- break;50665066- case AC_JACK_HP_OUT:50675067- seq = get_defcfg_sequence(def_conf);50685068- assoc = get_defcfg_association(def_conf);50695069- if (cfg->hp_outs >= ARRAY_SIZE(cfg->hp_pins))50705070- continue;50715071- cfg->hp_pins[cfg->hp_outs] = nid;50725072- sequences_hp[cfg->hp_outs] = (assoc << 4) | seq;50735073- cfg->hp_outs++;50745074- break;50755075- case AC_JACK_MIC_IN:50765076- add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_MIC);50775077- break;50785078- case AC_JACK_LINE_IN:50795079- add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_LINE_IN);50805080- break;50815081- case AC_JACK_CD:50825082- add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_CD);50835083- break;50845084- case AC_JACK_AUX:50855085- add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_AUX);50865086- break;50875087- case AC_JACK_SPDIF_OUT:50885088- case AC_JACK_DIG_OTHER_OUT:50895089- if (cfg->dig_outs >= ARRAY_SIZE(cfg->dig_out_pins))50905090- continue;50915091- cfg->dig_out_pins[cfg->dig_outs] = nid;50925092- cfg->dig_out_type[cfg->dig_outs] =50935093- (loc == AC_JACK_LOC_HDMI) ?50945094- HDA_PCM_TYPE_HDMI : HDA_PCM_TYPE_SPDIF;50955095- cfg->dig_outs++;50965096- break;50975097- case AC_JACK_SPDIF_IN:50985098- case AC_JACK_DIG_OTHER_IN:50995099- cfg->dig_in_pin = nid;51005100- if (loc == AC_JACK_LOC_HDMI)51015101- cfg->dig_in_type = HDA_PCM_TYPE_HDMI;51025102- else51035103- cfg->dig_in_type = HDA_PCM_TYPE_SPDIF;51045104- break;51055105- }51065106- }51075107-51085108- /* FIX-UP:51095109- * If no line-out is defined but multiple HPs are found,51105110- * some of them might be the real line-outs.51115111- */51125112- if (!cfg->line_outs && cfg->hp_outs > 1 &&51135113- !(cond_flags & HDA_PINCFG_NO_HP_FIXUP)) {51145114- int i = 0;51155115- while (i < cfg->hp_outs) {51165116- /* The real HPs should have the sequence 0x0f */51175117- if ((sequences_hp[i] & 0x0f) == 0x0f) {51185118- i++;51195119- continue;51205120- }51215121- /* Move it to the line-out table */51225122- cfg->line_out_pins[cfg->line_outs] = cfg->hp_pins[i];51235123- sequences_line_out[cfg->line_outs] = sequences_hp[i];51245124- cfg->line_outs++;51255125- cfg->hp_outs--;51265126- memmove(cfg->hp_pins + i, cfg->hp_pins + i + 1,51275127- sizeof(cfg->hp_pins[0]) * (cfg->hp_outs - i));51285128- memmove(sequences_hp + i, sequences_hp + i + 1,51295129- sizeof(sequences_hp[0]) * (cfg->hp_outs - i));51305130- }51315131- memset(cfg->hp_pins + cfg->hp_outs, 0,51325132- sizeof(hda_nid_t) * (AUTO_CFG_MAX_OUTS - cfg->hp_outs));51335133- if (!cfg->hp_outs)51345134- cfg->line_out_type = AUTO_PIN_HP_OUT;51355135-51365136- }51375137-51385138- /* sort by sequence */51395139- sort_pins_by_sequence(cfg->line_out_pins, sequences_line_out,51405140- cfg->line_outs);51415141- sort_pins_by_sequence(cfg->speaker_pins, sequences_speaker,51425142- cfg->speaker_outs);51435143- sort_pins_by_sequence(cfg->hp_pins, sequences_hp,51445144- cfg->hp_outs);51455145-51465146- /*51475147- * FIX-UP: if no line-outs are detected, try to use speaker or HP pin51485148- * as a primary output51495149- */51505150- if (!cfg->line_outs &&51515151- !(cond_flags & HDA_PINCFG_NO_LO_FIXUP)) {51525152- if (cfg->speaker_outs) {51535153- cfg->line_outs = cfg->speaker_outs;51545154- memcpy(cfg->line_out_pins, cfg->speaker_pins,51555155- sizeof(cfg->speaker_pins));51565156- cfg->speaker_outs = 0;51575157- memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));51585158- cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;51595159- } else if (cfg->hp_outs) {51605160- cfg->line_outs = cfg->hp_outs;51615161- memcpy(cfg->line_out_pins, cfg->hp_pins,51625162- sizeof(cfg->hp_pins));51635163- cfg->hp_outs = 0;51645164- memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));51655165- cfg->line_out_type = AUTO_PIN_HP_OUT;51665166- }51675167- }51685168-51695169- reorder_outputs(cfg->line_outs, cfg->line_out_pins);51705170- reorder_outputs(cfg->hp_outs, cfg->hp_pins);51715171- reorder_outputs(cfg->speaker_outs, cfg->speaker_pins);51725172-51735173- sort_autocfg_input_pins(cfg);51745174-51755175- /*51765176- * debug prints of the parsed results51775177- */51785178- snd_printd("autoconfig: line_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x) type:%s\n",51795179- cfg->line_outs, cfg->line_out_pins[0], cfg->line_out_pins[1],51805180- cfg->line_out_pins[2], cfg->line_out_pins[3],51815181- cfg->line_out_pins[4],51825182- cfg->line_out_type == AUTO_PIN_HP_OUT ? "hp" :51835183- (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT ?51845184- "speaker" : "line"));51855185- snd_printd(" speaker_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",51865186- cfg->speaker_outs, cfg->speaker_pins[0],51875187- cfg->speaker_pins[1], cfg->speaker_pins[2],51885188- cfg->speaker_pins[3], cfg->speaker_pins[4]);51895189- snd_printd(" hp_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",51905190- cfg->hp_outs, cfg->hp_pins[0],51915191- cfg->hp_pins[1], cfg->hp_pins[2],51925192- cfg->hp_pins[3], cfg->hp_pins[4]);51935193- snd_printd(" mono: mono_out=0x%x\n", cfg->mono_out_pin);51945194- if (cfg->dig_outs)51955195- snd_printd(" dig-out=0x%x/0x%x\n",51965196- cfg->dig_out_pins[0], cfg->dig_out_pins[1]);51975197- snd_printd(" inputs:");51985198- for (i = 0; i < cfg->num_inputs; i++) {51995199- snd_printd(" %s=0x%x",52005200- hda_get_autocfg_input_label(codec, cfg, i),52015201- cfg->inputs[i].pin);52025202- }52035203- snd_printd("\n");52045204- if (cfg->dig_in_pin)52055205- snd_printd(" dig-in=0x%x\n", cfg->dig_in_pin);52065206-52075207- return 0;52085208-}52095209-EXPORT_SYMBOL_HDA(snd_hda_parse_pin_defcfg);52105210-52115211-int snd_hda_get_input_pin_attr(unsigned int def_conf)52125212-{52135213- unsigned int loc = get_defcfg_location(def_conf);52145214- unsigned int conn = get_defcfg_connect(def_conf);52155215- if (conn == AC_JACK_PORT_NONE)52165216- return INPUT_PIN_ATTR_UNUSED;52175217- /* Windows may claim the internal mic to be BOTH, too */52185218- if (conn == AC_JACK_PORT_FIXED || conn == AC_JACK_PORT_BOTH)52195219- return INPUT_PIN_ATTR_INT;52205220- if ((loc & 0x30) == AC_JACK_LOC_INTERNAL)52215221- return INPUT_PIN_ATTR_INT;52225222- if ((loc & 0x30) == AC_JACK_LOC_SEPARATE)52235223- return INPUT_PIN_ATTR_DOCK;52245224- if (loc == AC_JACK_LOC_REAR)52255225- return INPUT_PIN_ATTR_REAR;52265226- if (loc == AC_JACK_LOC_FRONT)52275227- return INPUT_PIN_ATTR_FRONT;52285228- return INPUT_PIN_ATTR_NORMAL;52295229-}52305230-EXPORT_SYMBOL_HDA(snd_hda_get_input_pin_attr);52315231-52324798/**52335233- * hda_get_input_pin_label - Give a label for the given input pin47994799+ * snd_hda_get_default_vref - Get the default (mic) VREF pin bits52344800 *52355235- * When check_location is true, the function checks the pin location52365236- * for mic and line-in pins, and set an appropriate prefix like "Front",52375237- * "Rear", "Internal".48014801+ * Guess the suitable VREF pin bits to be set as the pin-control value.48024802+ * Note: the function doesn't set the AC_PINCTL_IN_EN bit.52384803 */52395239-52405240-static const char *hda_get_input_pin_label(struct hda_codec *codec,52415241- hda_nid_t pin, bool check_location)48044804+unsigned int snd_hda_get_default_vref(struct hda_codec *codec, hda_nid_t pin)52424805{52435243- unsigned int def_conf;52445244- static const char * const mic_names[] = {52455245- "Internal Mic", "Dock Mic", "Mic", "Front Mic", "Rear Mic",52465246- };52475247- int attr;52485248-52495249- def_conf = snd_hda_codec_get_pincfg(codec, pin);52505250-52515251- switch (get_defcfg_device(def_conf)) {52525252- case AC_JACK_MIC_IN:52535253- if (!check_location)52545254- return "Mic";52555255- attr = snd_hda_get_input_pin_attr(def_conf);52565256- if (!attr)52575257- return "None";52585258- return mic_names[attr - 1];52595259- case AC_JACK_LINE_IN:52605260- if (!check_location)52615261- return "Line";52625262- attr = snd_hda_get_input_pin_attr(def_conf);52635263- if (!attr)52645264- return "None";52655265- if (attr == INPUT_PIN_ATTR_DOCK)52665266- return "Dock Line";52675267- return "Line";52685268- case AC_JACK_AUX:52695269- return "Aux";52705270- case AC_JACK_CD:52715271- return "CD";52725272- case AC_JACK_SPDIF_IN:52735273- return "SPDIF In";52745274- case AC_JACK_DIG_OTHER_IN:52755275- return "Digital In";52765276- default:52775277- return "Misc";52785278- }48064806+ unsigned int pincap;48074807+ unsigned int oldval;48084808+ oldval = snd_hda_codec_read(codec, pin, 0,48094809+ AC_VERB_GET_PIN_WIDGET_CONTROL, 0);48104810+ pincap = snd_hda_query_pin_caps(codec, pin);48114811+ pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;48124812+ /* Exception: if the default pin setup is vref50, we give it priority */48134813+ if ((pincap & AC_PINCAP_VREF_80) && oldval != PIN_VREF50)48144814+ return AC_PINCTL_VREF_80;48154815+ else if (pincap & AC_PINCAP_VREF_50)48164816+ return AC_PINCTL_VREF_50;48174817+ else if (pincap & AC_PINCAP_VREF_100)48184818+ return AC_PINCTL_VREF_100;48194819+ else if (pincap & AC_PINCAP_VREF_GRD)48204820+ return AC_PINCTL_VREF_GRD;48214821+ return AC_PINCTL_VREF_HIZ;52794822}48234823+EXPORT_SYMBOL_HDA(snd_hda_get_default_vref);5280482452815281-/* Check whether the location prefix needs to be added to the label.52825282- * If all mic-jacks are in the same location (e.g. rear panel), we don't52835283- * have to put "Front" prefix to each label. In such a case, returns false.52845284- */52855285-static int check_mic_location_need(struct hda_codec *codec,52865286- const struct auto_pin_cfg *cfg,52875287- int input)48254825+int _snd_hda_set_pin_ctl(struct hda_codec *codec, hda_nid_t pin,48264826+ unsigned int val, bool cached)52884827{52895289- unsigned int defc;52905290- int i, attr, attr2;52915291-52925292- defc = snd_hda_codec_get_pincfg(codec, cfg->inputs[input].pin);52935293- attr = snd_hda_get_input_pin_attr(defc);52945294- /* for internal or docking mics, we need locations */52955295- if (attr <= INPUT_PIN_ATTR_NORMAL)52965296- return 1;52975297-52985298- attr = 0;52995299- for (i = 0; i < cfg->num_inputs; i++) {53005300- defc = snd_hda_codec_get_pincfg(codec, cfg->inputs[i].pin);53015301- attr2 = snd_hda_get_input_pin_attr(defc);53025302- if (attr2 >= INPUT_PIN_ATTR_NORMAL) {53035303- if (attr && attr != attr2)53045304- return 1; /* different locations found */53055305- attr = attr2;48284828+ if (val) {48294829+ unsigned int cap = snd_hda_query_pin_caps(codec, pin);48304830+ if (cap && (val & AC_PINCTL_OUT_EN)) {48314831+ if (!(cap & AC_PINCAP_OUT))48324832+ val &= ~(AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN);48334833+ else if ((val & AC_PINCTL_HP_EN) &&48344834+ !(cap & AC_PINCAP_HP_DRV))48354835+ val &= ~AC_PINCTL_HP_EN;48364836+ }48374837+ if (cap && (val & AC_PINCTL_IN_EN)) {48384838+ if (!(cap & AC_PINCAP_IN))48394839+ val &= ~(AC_PINCTL_IN_EN | AC_PINCTL_VREFEN);53064840 }53074841 }53085308- return 0;48424842+ if (cached)48434843+ return snd_hda_codec_update_cache(codec, pin, 0,48444844+ AC_VERB_SET_PIN_WIDGET_CONTROL, val);48454845+ else48464846+ return snd_hda_codec_write(codec, pin, 0,48474847+ AC_VERB_SET_PIN_WIDGET_CONTROL, val);53094848}53105310-53115311-/**53125312- * hda_get_autocfg_input_label - Get a label for the given input53135313- *53145314- * Get a label for the given input pin defined by the autocfg item.53155315- * Unlike hda_get_input_pin_label(), this function checks all inputs53165316- * defined in autocfg and avoids the redundant mic/line prefix as much as53175317- * possible.53185318- */53195319-const char *hda_get_autocfg_input_label(struct hda_codec *codec,53205320- const struct auto_pin_cfg *cfg,53215321- int input)53225322-{53235323- int type = cfg->inputs[input].type;53245324- int has_multiple_pins = 0;53255325-53265326- if ((input > 0 && cfg->inputs[input - 1].type == type) ||53275327- (input < cfg->num_inputs - 1 && cfg->inputs[input + 1].type == type))53285328- has_multiple_pins = 1;53295329- if (has_multiple_pins && type == AUTO_PIN_MIC)53305330- has_multiple_pins &= check_mic_location_need(codec, cfg, input);53315331- return hda_get_input_pin_label(codec, cfg->inputs[input].pin,53325332- has_multiple_pins);53335333-}53345334-EXPORT_SYMBOL_HDA(hda_get_autocfg_input_label);53355335-53365336-/* return the position of NID in the list, or -1 if not found */53375337-static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)53385338-{53395339- int i;53405340- for (i = 0; i < nums; i++)53415341- if (list[i] == nid)53425342- return i;53435343- return -1;53445344-}53455345-53465346-/* get a unique suffix or an index number */53475347-static const char *check_output_sfx(hda_nid_t nid, const hda_nid_t *pins,53485348- int num_pins, int *indexp)53495349-{53505350- static const char * const channel_sfx[] = {53515351- " Front", " Surround", " CLFE", " Side"53525352- };53535353- int i;53545354-53555355- i = find_idx_in_nid_list(nid, pins, num_pins);53565356- if (i < 0)53575357- return NULL;53585358- if (num_pins == 1)53595359- return "";53605360- if (num_pins > ARRAY_SIZE(channel_sfx)) {53615361- if (indexp)53625362- *indexp = i;53635363- return "";53645364- }53655365- return channel_sfx[i];53665366-}53675367-53685368-static int fill_audio_out_name(struct hda_codec *codec, hda_nid_t nid,53695369- const struct auto_pin_cfg *cfg,53705370- const char *name, char *label, int maxlen,53715371- int *indexp)53725372-{53735373- unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid);53745374- int attr = snd_hda_get_input_pin_attr(def_conf);53755375- const char *pfx = "", *sfx = "";53765376-53775377- /* handle as a speaker if it's a fixed line-out */53785378- if (!strcmp(name, "Line Out") && attr == INPUT_PIN_ATTR_INT)53795379- name = "Speaker";53805380- /* check the location */53815381- switch (attr) {53825382- case INPUT_PIN_ATTR_DOCK:53835383- pfx = "Dock ";53845384- break;53855385- case INPUT_PIN_ATTR_FRONT:53865386- pfx = "Front ";53875387- break;53885388- }53895389- if (cfg) {53905390- /* try to give a unique suffix if needed */53915391- sfx = check_output_sfx(nid, cfg->line_out_pins, cfg->line_outs,53925392- indexp);53935393- if (!sfx)53945394- sfx = check_output_sfx(nid, cfg->speaker_pins, cfg->speaker_outs,53955395- indexp);53965396- if (!sfx) {53975397- /* don't add channel suffix for Headphone controls */53985398- int idx = find_idx_in_nid_list(nid, cfg->hp_pins,53995399- cfg->hp_outs);54005400- if (idx >= 0)54015401- *indexp = idx;54025402- sfx = "";54035403- }54045404- }54055405- snprintf(label, maxlen, "%s%s%s", pfx, name, sfx);54065406- return 1;54075407-}54085408-54095409-/**54105410- * snd_hda_get_pin_label - Get a label for the given I/O pin54115411- *54125412- * Get a label for the given pin. This function works for both input and54135413- * output pins. When @cfg is given as non-NULL, the function tries to get54145414- * an optimized label using hda_get_autocfg_input_label().54155415- *54165416- * This function tries to give a unique label string for the pin as much as54175417- * possible. For example, when the multiple line-outs are present, it adds54185418- * the channel suffix like "Front", "Surround", etc (only when @cfg is given).54195419- * If no unique name with a suffix is available and @indexp is non-NULL, the54205420- * index number is stored in the pointer.54215421- */54225422-int snd_hda_get_pin_label(struct hda_codec *codec, hda_nid_t nid,54235423- const struct auto_pin_cfg *cfg,54245424- char *label, int maxlen, int *indexp)54255425-{54265426- unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid);54275427- const char *name = NULL;54285428- int i;54295429-54305430- if (indexp)54315431- *indexp = 0;54325432- if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)54335433- return 0;54345434-54355435- switch (get_defcfg_device(def_conf)) {54365436- case AC_JACK_LINE_OUT:54375437- return fill_audio_out_name(codec, nid, cfg, "Line Out",54385438- label, maxlen, indexp);54395439- case AC_JACK_SPEAKER:54405440- return fill_audio_out_name(codec, nid, cfg, "Speaker",54415441- label, maxlen, indexp);54425442- case AC_JACK_HP_OUT:54435443- return fill_audio_out_name(codec, nid, cfg, "Headphone",54445444- label, maxlen, indexp);54455445- case AC_JACK_SPDIF_OUT:54465446- case AC_JACK_DIG_OTHER_OUT:54475447- if (get_defcfg_location(def_conf) == AC_JACK_LOC_HDMI)54485448- name = "HDMI";54495449- else54505450- name = "SPDIF";54515451- if (cfg && indexp) {54525452- i = find_idx_in_nid_list(nid, cfg->dig_out_pins,54535453- cfg->dig_outs);54545454- if (i >= 0)54555455- *indexp = i;54565456- }54575457- break;54585458- default:54595459- if (cfg) {54605460- for (i = 0; i < cfg->num_inputs; i++) {54615461- if (cfg->inputs[i].pin != nid)54625462- continue;54635463- name = hda_get_autocfg_input_label(codec, cfg, i);54645464- if (name)54655465- break;54665466- }54675467- }54685468- if (!name)54695469- name = hda_get_input_pin_label(codec, nid, true);54705470- break;54715471- }54725472- if (!name)54735473- return 0;54745474- strlcpy(label, name, maxlen);54755475- return 1;54765476-}54775477-EXPORT_SYMBOL_HDA(snd_hda_get_pin_label);48494849+EXPORT_SYMBOL_HDA(_snd_hda_set_pin_ctl);5478485054794851/**54804852 * snd_hda_add_imux_item - Add an item to input_mux···49865444 list_for_each_entry(codec, &bus->codec_list, list) {49875445 if (hda_codec_is_power_on(codec))49885446 hda_call_codec_suspend(codec);49894989- if (codec->patch_ops.post_suspend)49904990- codec->patch_ops.post_suspend(codec);49915447 }49925448 return 0;49935449}···50055465 struct hda_codec *codec;5006546650075467 list_for_each_entry(codec, &bus->codec_list, list) {50085008- if (codec->patch_ops.pre_resume)50095009- codec->patch_ops.pre_resume(codec);50105010- if (snd_hda_codec_needs_resume(codec))50115011- hda_call_codec_resume(codec);54685468+ hda_call_codec_resume(codec);50125469 }50135470 return 0;50145471}
+8-7
sound/pci/hda/hda_codec.h
···704704 unsigned int power_state);705705#ifdef CONFIG_PM706706 int (*suspend)(struct hda_codec *codec, pm_message_t state);707707- int (*post_suspend)(struct hda_codec *codec);708708- int (*pre_resume)(struct hda_codec *codec);709707 int (*resume)(struct hda_codec *codec);710708#endif711709#ifdef CONFIG_SND_HDA_POWER_SAVE···827829828830 struct mutex spdif_mutex;829831 struct mutex control_mutex;832832+ struct mutex hash_mutex;830833 struct snd_array spdif_out;831834 unsigned int spdif_in_enable; /* SPDIF input enable? */832835 const hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */···860861 unsigned int no_jack_detect:1; /* Machine has no jack-detection */861862#ifdef CONFIG_SND_HDA_POWER_SAVE862863 unsigned int power_on :1; /* current (global) power-state */863863- unsigned int power_transition :1; /* power-state in transition */864864+ int power_transition; /* power-state in transition */864865 int power_count; /* current (global) power refcount */865866 struct delayed_work power_work; /* delayed task for powerdown */866867 unsigned long power_on_acct;867868 unsigned long power_off_acct;868869 unsigned long power_jiffies;870870+ spinlock_t power_lock;869871#endif870872871873 /* codec-specific additional proc output */···911911 hda_nid_t *start_id);912912int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,913913 hda_nid_t *conn_list, int max_conns);914914+static inline int915915+snd_hda_get_num_conns(struct hda_codec *codec, hda_nid_t nid)916916+{917917+ return snd_hda_get_connections(codec, nid, NULL, 0);918918+}914919int snd_hda_get_raw_connections(struct hda_codec *codec, hda_nid_t nid,915920 hda_nid_t *conn_list, int max_conns);916916-int snd_hda_get_conn_list(struct hda_codec *codec, hda_nid_t nid,917917- const hda_nid_t **listp);918921int snd_hda_override_conn_list(struct hda_codec *codec, hda_nid_t nid, int nums,919922 const hda_nid_t *list);920923int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux,···10541051#ifdef CONFIG_SND_HDA_POWER_SAVE10551052void snd_hda_power_up(struct hda_codec *codec);10561053void snd_hda_power_down(struct hda_codec *codec);10571057-#define snd_hda_codec_needs_resume(codec) codec->power_count10581054void snd_hda_update_power_acct(struct hda_codec *codec);10591055#else10601056static inline void snd_hda_power_up(struct hda_codec *codec) {}10611057static inline void snd_hda_power_down(struct hda_codec *codec) {}10621062-#define snd_hda_codec_needs_resume(codec) 110631058#endif1064105910651060#ifdef CONFIG_SND_HDA_PATCH_LOADER
+23-17
sound/pci/hda/hda_intel.c
···497497 AZX_DRIVER_NVIDIA,498498 AZX_DRIVER_TERA,499499 AZX_DRIVER_CTX,500500+ AZX_DRIVER_CTHDA,500501 AZX_DRIVER_GENERIC,501502 AZX_NUM_DRIVERS, /* keep this as last entry */502503};···519518#define AZX_DCAPS_OLD_SSYNC (1 << 20) /* Old SSYNC reg for ICH */520519#define AZX_DCAPS_BUFSIZE (1 << 21) /* no buffer size alignment */521520#define AZX_DCAPS_ALIGN_BUFSIZE (1 << 22) /* buffer size alignment */521521+#define AZX_DCAPS_4K_BDLE_BOUNDARY (1 << 23) /* BDLE in 4k boundary */522522523523/* quirks for ATI SB / AMD Hudson */524524#define AZX_DCAPS_PRESET_ATI_SB \···535533 (AZX_DCAPS_NVIDIA_SNOOP | AZX_DCAPS_RIRB_DELAY | AZX_DCAPS_NO_MSI |\536534 AZX_DCAPS_ALIGN_BUFSIZE)537535536536+#define AZX_DCAPS_PRESET_CTHDA \537537+ (AZX_DCAPS_NO_MSI | AZX_DCAPS_POSFIX_LPIB | AZX_DCAPS_4K_BDLE_BOUNDARY)538538+538539static char *driver_short_names[] __devinitdata = {539540 [AZX_DRIVER_ICH] = "HDA Intel",540541 [AZX_DRIVER_PCH] = "HDA Intel PCH",···551546 [AZX_DRIVER_NVIDIA] = "HDA NVidia",552547 [AZX_DRIVER_TERA] = "HDA Teradici", 553548 [AZX_DRIVER_CTX] = "HDA Creative", 549549+ [AZX_DRIVER_CTHDA] = "HDA Creative",554550 [AZX_DRIVER_GENERIC] = "HD-Audio Generic",555551};556552···12911285/*12921286 * set up a BDL entry12931287 */12941294-static int setup_bdle(struct snd_pcm_substream *substream,12881288+static int setup_bdle(struct azx *chip,12891289+ struct snd_pcm_substream *substream,12951290 struct azx_dev *azx_dev, u32 **bdlp,12961291 int ofs, int size, int with_ioc)12971292{···13111304 bdl[1] = cpu_to_le32(upper_32_bits(addr));13121305 /* program the size field of the BDL entry */13131306 chunk = snd_pcm_sgbuf_get_chunk_size(substream, ofs, size);13071307+ /* one BDLE cannot cross 4K boundary on CTHDA chips */13081308+ if (chip->driver_caps & AZX_DCAPS_4K_BDLE_BOUNDARY) {13091309+ u32 remain = 0x1000 - (ofs & 0xfff);13101310+ if (chunk > remain)13111311+ chunk = remain;13121312+ }13141313 bdl[2] = cpu_to_le32(chunk);13151314 /* program the IOC to enable interrupt13161315 * only when the whole fragment is processed···13691356 bdl_pos_adj[chip->dev_index]);13701357 pos_adj = 0;13711358 } else {13721372- ofs = setup_bdle(substream, azx_dev,13591359+ ofs = setup_bdle(chip, substream, azx_dev,13731360 &bdl, ofs, pos_adj,13741361 !substream->runtime->no_period_wakeup);13751362 if (ofs < 0)···13791366 pos_adj = 0;13801367 for (i = 0; i < periods; i++) {13811368 if (i == periods - 1 && pos_adj)13821382- ofs = setup_bdle(substream, azx_dev, &bdl, ofs,13691369+ ofs = setup_bdle(chip, substream, azx_dev, &bdl, ofs,13831370 period_bytes - pos_adj, 0);13841371 else13851385- ofs = setup_bdle(substream, azx_dev, &bdl, ofs,13721372+ ofs = setup_bdle(chip, substream, azx_dev, &bdl, ofs,13861373 period_bytes,13871374 !substream->runtime->no_period_wakeup);13881375 if (ofs < 0)···23662353 * power management23672354 */2368235523692369-static int snd_hda_codecs_inuse(struct hda_bus *bus)23702370-{23712371- struct hda_codec *codec;23722372-23732373- list_for_each_entry(codec, &bus->codec_list, list) {23742374- if (snd_hda_codec_needs_resume(codec))23752375- return 1;23762376- }23772377- return 0;23782378-}23792379-23802356static int azx_suspend(struct pci_dev *pci, pm_message_t state)23812357{23822358 struct snd_card *card = pci_get_drvdata(pci);···24122410 return -EIO;24132411 azx_init_pci(chip);2414241224152415- if (snd_hda_codecs_inuse(chip->bus))24162416- azx_init_chip(chip, 1);24132413+ azx_init_chip(chip, 1);2417241424182415 snd_hda_resume(chip->bus);24192416 snd_power_change_state(card, SNDRV_CTL_POWER_D0);···31313130 .driver_data = AZX_DRIVER_CTX | AZX_DCAPS_CTX_WORKAROUND |31323131 AZX_DCAPS_RIRB_PRE_DELAY | AZX_DCAPS_POSFIX_LPIB },31333132#endif31333133+ /* CTHDA chips */31343134+ { PCI_DEVICE(0x1102, 0x0010),31353135+ .driver_data = AZX_DRIVER_CTHDA | AZX_DCAPS_PRESET_CTHDA },31363136+ { PCI_DEVICE(0x1102, 0x0012),31373137+ .driver_data = AZX_DRIVER_CTHDA | AZX_DCAPS_PRESET_CTHDA },31343138 /* Vortex86MX */31353139 { PCI_DEVICE(0x17f3, 0x3010), .driver_data = AZX_DRIVER_GENERIC },31363140 /* VMware HDAudio */
···262262 const struct hda_input_mux *imux,263263 struct snd_ctl_elem_value *ucontrol, hda_nid_t nid,264264 unsigned int *cur_val);265265+int snd_hda_add_imux_item(struct hda_input_mux *imux, const char *label,266266+ int index, int *type_index_ret);265267266268/*267269 * Channel mode helper···395393 struct hda_bus *bus;396394};397395398398-/*399399- * Helper for automatic pin configuration400400- */401401-402402-enum {403403- AUTO_PIN_MIC,404404- AUTO_PIN_LINE_IN,405405- AUTO_PIN_CD,406406- AUTO_PIN_AUX,407407- AUTO_PIN_LAST408408-};409409-410410-enum {411411- AUTO_PIN_LINE_OUT,412412- AUTO_PIN_SPEAKER_OUT,413413- AUTO_PIN_HP_OUT414414-};415415-416416-#define AUTO_CFG_MAX_OUTS HDA_MAX_OUTS417417-#define AUTO_CFG_MAX_INS 8418418-419419-struct auto_pin_cfg_item {420420- hda_nid_t pin;421421- int type;422422-};423423-424424-struct auto_pin_cfg;425425-const char *hda_get_autocfg_input_label(struct hda_codec *codec,426426- const struct auto_pin_cfg *cfg,427427- int input);428428-int snd_hda_get_pin_label(struct hda_codec *codec, hda_nid_t nid,429429- const struct auto_pin_cfg *cfg,430430- char *label, int maxlen, int *indexp);431431-int snd_hda_add_imux_item(struct hda_input_mux *imux, const char *label,432432- int index, int *type_index_ret);433433-434434-enum {435435- INPUT_PIN_ATTR_UNUSED, /* pin not connected */436436- INPUT_PIN_ATTR_INT, /* internal mic/line-in */437437- INPUT_PIN_ATTR_DOCK, /* docking mic/line-in */438438- INPUT_PIN_ATTR_NORMAL, /* mic/line-in jack */439439- INPUT_PIN_ATTR_FRONT, /* mic/line-in jack in front */440440- INPUT_PIN_ATTR_REAR, /* mic/line-in jack in rear */441441-};442442-443443-int snd_hda_get_input_pin_attr(unsigned int def_conf);444444-445445-struct auto_pin_cfg {446446- int line_outs;447447- /* sorted in the order of Front/Surr/CLFE/Side */448448- hda_nid_t line_out_pins[AUTO_CFG_MAX_OUTS];449449- int speaker_outs;450450- hda_nid_t speaker_pins[AUTO_CFG_MAX_OUTS];451451- int hp_outs;452452- int line_out_type; /* AUTO_PIN_XXX_OUT */453453- hda_nid_t hp_pins[AUTO_CFG_MAX_OUTS];454454- int num_inputs;455455- struct auto_pin_cfg_item inputs[AUTO_CFG_MAX_INS];456456- int dig_outs;457457- hda_nid_t dig_out_pins[2];458458- hda_nid_t dig_in_pin;459459- hda_nid_t mono_out_pin;460460- int dig_out_type[2]; /* HDA_PCM_TYPE_XXX */461461- int dig_in_type; /* HDA_PCM_TYPE_XXX */462462-};463463-396396+/* helper macros to retrieve pin default-config values */464397#define get_defcfg_connect(cfg) \465398 ((cfg & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT)466399#define get_defcfg_association(cfg) \···408471 ((cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT)409472#define get_defcfg_misc(cfg) \410473 ((cfg & AC_DEFCFG_MISC) >> AC_DEFCFG_MISC_SHIFT)411411-412412-/* bit-flags for snd_hda_parse_pin_def_config() behavior */413413-#define HDA_PINCFG_NO_HP_FIXUP (1 << 0) /* no HP-split */414414-#define HDA_PINCFG_NO_LO_FIXUP (1 << 1) /* don't take other outs as LO */415415-416416-int snd_hda_parse_pin_defcfg(struct hda_codec *codec,417417- struct auto_pin_cfg *cfg,418418- const hda_nid_t *ignore_nids,419419- unsigned int cond_flags);420420-421421-/* older function */422422-#define snd_hda_parse_pin_def_config(codec, cfg, ignore) \423423- snd_hda_parse_pin_defcfg(codec, cfg, ignore, 0)424474425475/* amp values */426476#define AMP_IN_MUTE(idx) (0x7080 | ((idx)<<8))···425501#define PIN_OUT (AC_PINCTL_OUT_EN)426502#define PIN_HP (AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN)427503#define PIN_HP_AMP (AC_PINCTL_HP_EN)504504+505505+unsigned int snd_hda_get_default_vref(struct hda_codec *codec, hda_nid_t pin);506506+int _snd_hda_set_pin_ctl(struct hda_codec *codec, hda_nid_t pin,507507+ unsigned int val, bool cached);508508+509509+/**510510+ * _snd_hda_set_pin_ctl - Set a pin-control value safely511511+ * @codec: the codec instance512512+ * @pin: the pin NID to set the control513513+ * @val: the pin-control value (AC_PINCTL_* bits)514514+ *515515+ * This function sets the pin-control value to the given pin, but516516+ * filters out the invalid pin-control bits when the pin has no such517517+ * capabilities. For example, when PIN_HP is passed but the pin has no518518+ * HP-drive capability, the HP bit is omitted.519519+ *520520+ * The function doesn't check the input VREF capability bits, though.521521+ * Use snd_hda_get_default_vref() to guess the right value.522522+ * Also, this function is only for analog pins, not for HDMI pins.523523+ */524524+static inline int525525+snd_hda_set_pin_ctl(struct hda_codec *codec, hda_nid_t pin, unsigned int val)526526+{527527+ return _snd_hda_set_pin_ctl(codec, pin, val, false);528528+}529529+530530+/**531531+ * snd_hda_set_pin_ctl_cache - Set a pin-control value safely532532+ * @codec: the codec instance533533+ * @pin: the pin NID to set the control534534+ * @val: the pin-control value (AC_PINCTL_* bits)535535+ *536536+ * Just like snd_hda_set_pin_ctl() but write to cache as well.537537+ */538538+static inline int539539+snd_hda_set_pin_ctl_cache(struct hda_codec *codec, hda_nid_t pin,540540+ unsigned int val)541541+{542542+ return _snd_hda_set_pin_ctl(codec, pin, val, true);543543+}428544429545/*430546 * get widget capabilities
+8-6
sound/pci/hda/patch_analog.c
···2828#include <sound/core.h>2929#include "hda_codec.h"3030#include "hda_local.h"3131+#include "hda_auto_parser.h"3132#include "hda_beep.h"3233#include "hda_jack.h"3334···17431742 if (! ad198x_eapd_put(kcontrol, ucontrol))17441743 return 0;17451744 /* change speaker pin appropriately */17461746- snd_hda_codec_write(codec, 0x05, 0,17471747- AC_VERB_SET_PIN_WIDGET_CONTROL,17481748- spec->cur_eapd ? PIN_OUT : 0);17451745+ snd_hda_set_pin_ctl(codec, 0x05, spec->cur_eapd ? PIN_OUT : 0);17491746 /* toggle HP mute appropriately */17501747 snd_hda_codec_amp_stereo(codec, 0x06, HDA_OUTPUT, 0,17511748 HDA_AMP_MUTE,···31023103 int dac_idx)31033104{31043105 /* set as output */31053105- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);31063106+ snd_hda_set_pin_ctl(codec, nid, pin_type);31063107 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);31073108 switch (nid) {31083109 case 0x11: /* port-A - DAC 03 */···31563157 for (i = 0; i < cfg->num_inputs; i++) {31573158 hda_nid_t nid = cfg->inputs[i].pin;31583159 int type = cfg->inputs[i].type;31603160+ int val;31593161 switch (nid) {31603162 case 0x15: /* port-C */31613163 snd_hda_codec_write(codec, 0x33, 0, AC_VERB_SET_CONNECT_SEL, 0x0);···31653165 snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_CONNECT_SEL, 0x0);31663166 break;31673167 }31683168- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,31693169- type == AUTO_PIN_MIC ? PIN_VREF80 : PIN_IN);31683168+ val = PIN_IN;31693169+ if (type == AUTO_PIN_MIC)31703170+ val |= snd_hda_get_default_vref(codec, nid);31713171+ snd_hda_set_pin_ctl(codec, nid, val);31703172 if (nid != AD1988_PIN_CD_NID)31713173 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,31723174 AMP_OUT_MUTE);