Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * BIOS auto-parser helper functions for HD-audio
0004  *
0005  * Copyright (c) 2012 Takashi Iwai <tiwai@suse.de>
0006  */
0007 
0008 #include <linux/slab.h>
0009 #include <linux/export.h>
0010 #include <linux/sort.h>
0011 #include <sound/core.h>
0012 #include <sound/hda_codec.h>
0013 #include "hda_local.h"
0014 #include "hda_auto_parser.h"
0015 
0016 /*
0017  * Helper for automatic pin configuration
0018  */
0019 
0020 static int is_in_nid_list(hda_nid_t nid, const hda_nid_t *list)
0021 {
0022     for (; *list; list++)
0023         if (*list == nid)
0024             return 1;
0025     return 0;
0026 }
0027 
0028 /* a pair of input pin and its sequence */
0029 struct auto_out_pin {
0030     hda_nid_t pin;
0031     short seq;
0032 };
0033 
0034 static int compare_seq(const void *ap, const void *bp)
0035 {
0036     const struct auto_out_pin *a = ap;
0037     const struct auto_out_pin *b = bp;
0038     return (int)(a->seq - b->seq);
0039 }
0040 
0041 /*
0042  * Sort an associated group of pins according to their sequence numbers.
0043  * then store it to a pin array.
0044  */
0045 static void sort_pins_by_sequence(hda_nid_t *pins, struct auto_out_pin *list,
0046                   int num_pins)
0047 {
0048     int i;
0049     sort(list, num_pins, sizeof(list[0]), compare_seq, NULL);
0050     for (i = 0; i < num_pins; i++)
0051         pins[i] = list[i].pin;
0052 }
0053 
0054 
0055 /* add the found input-pin to the cfg->inputs[] table */
0056 static void add_auto_cfg_input_pin(struct hda_codec *codec, struct auto_pin_cfg *cfg,
0057                    hda_nid_t nid, int type)
0058 {
0059     if (cfg->num_inputs < AUTO_CFG_MAX_INS) {
0060         cfg->inputs[cfg->num_inputs].pin = nid;
0061         cfg->inputs[cfg->num_inputs].type = type;
0062         cfg->inputs[cfg->num_inputs].has_boost_on_pin =
0063             nid_has_volume(codec, nid, HDA_INPUT);
0064         cfg->num_inputs++;
0065     }
0066 }
0067 
0068 static int compare_input_type(const void *ap, const void *bp)
0069 {
0070     const struct auto_pin_cfg_item *a = ap;
0071     const struct auto_pin_cfg_item *b = bp;
0072     if (a->type != b->type)
0073         return (int)(a->type - b->type);
0074 
0075     /* If has both hs_mic and hp_mic, pick the hs_mic ahead of hp_mic. */
0076     if (a->is_headset_mic && b->is_headphone_mic)
0077         return -1; /* don't swap */
0078     else if (a->is_headphone_mic && b->is_headset_mic)
0079         return 1; /* swap */
0080 
0081     /* In case one has boost and the other one has not,
0082        pick the one with boost first. */
0083     return (int)(b->has_boost_on_pin - a->has_boost_on_pin);
0084 }
0085 
0086 /* Reorder the surround channels
0087  * ALSA sequence is front/surr/clfe/side
0088  * HDA sequence is:
0089  *    4-ch: front/surr  =>  OK as it is
0090  *    6-ch: front/clfe/surr
0091  *    8-ch: front/clfe/rear/side|fc
0092  */
0093 static void reorder_outputs(unsigned int nums, hda_nid_t *pins)
0094 {
0095     switch (nums) {
0096     case 3:
0097     case 4:
0098         swap(pins[1], pins[2]);
0099         break;
0100     }
0101 }
0102 
0103 /* check whether the given pin has a proper pin I/O capability bit */
0104 static bool check_pincap_validity(struct hda_codec *codec, hda_nid_t pin,
0105                   unsigned int dev)
0106 {
0107     unsigned int pincap = snd_hda_query_pin_caps(codec, pin);
0108 
0109     /* some old hardware don't return the proper pincaps */
0110     if (!pincap)
0111         return true;
0112 
0113     switch (dev) {
0114     case AC_JACK_LINE_OUT:
0115     case AC_JACK_SPEAKER:
0116     case AC_JACK_HP_OUT:
0117     case AC_JACK_SPDIF_OUT:
0118     case AC_JACK_DIG_OTHER_OUT:
0119         return !!(pincap & AC_PINCAP_OUT);
0120     default:
0121         return !!(pincap & AC_PINCAP_IN);
0122     }
0123 }
0124 
0125 static bool can_be_headset_mic(struct hda_codec *codec,
0126                    struct auto_pin_cfg_item *item,
0127                    int seq_number)
0128 {
0129     int attr;
0130     unsigned int def_conf;
0131     if (item->type != AUTO_PIN_MIC)
0132         return false;
0133 
0134     if (item->is_headset_mic || item->is_headphone_mic)
0135         return false; /* Already assigned */
0136 
0137     def_conf = snd_hda_codec_get_pincfg(codec, item->pin);
0138     attr = snd_hda_get_input_pin_attr(def_conf);
0139     if (attr <= INPUT_PIN_ATTR_DOCK)
0140         return false;
0141 
0142     if (seq_number >= 0) {
0143         int seq = get_defcfg_sequence(def_conf);
0144         if (seq != seq_number)
0145             return false;
0146     }
0147 
0148     return true;
0149 }
0150 
0151 /*
0152  * Parse all pin widgets and store the useful pin nids to cfg
0153  *
0154  * The number of line-outs or any primary output is stored in line_outs,
0155  * and the corresponding output pins are assigned to line_out_pins[],
0156  * in the order of front, rear, CLFE, side, ...
0157  *
0158  * If more extra outputs (speaker and headphone) are found, the pins are
0159  * assisnged to hp_pins[] and speaker_pins[], respectively.  If no line-out jack
0160  * is detected, one of speaker of HP pins is assigned as the primary
0161  * output, i.e. to line_out_pins[0].  So, line_outs is always positive
0162  * if any analog output exists.
0163  *
0164  * The analog input pins are assigned to inputs array.
0165  * The digital input/output pins are assigned to dig_in_pin and dig_out_pin,
0166  * respectively.
0167  */
0168 int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
0169                  struct auto_pin_cfg *cfg,
0170                  const hda_nid_t *ignore_nids,
0171                  unsigned int cond_flags)
0172 {
0173     hda_nid_t nid;
0174     short seq, assoc_line_out;
0175     struct auto_out_pin line_out[ARRAY_SIZE(cfg->line_out_pins)];
0176     struct auto_out_pin speaker_out[ARRAY_SIZE(cfg->speaker_pins)];
0177     struct auto_out_pin hp_out[ARRAY_SIZE(cfg->hp_pins)];
0178     int i;
0179 
0180     if (!snd_hda_get_int_hint(codec, "parser_flags", &i))
0181         cond_flags = i;
0182 
0183     memset(cfg, 0, sizeof(*cfg));
0184 
0185     memset(line_out, 0, sizeof(line_out));
0186     memset(speaker_out, 0, sizeof(speaker_out));
0187     memset(hp_out, 0, sizeof(hp_out));
0188     assoc_line_out = 0;
0189 
0190     for_each_hda_codec_node(nid, codec) {
0191         unsigned int wid_caps = get_wcaps(codec, nid);
0192         unsigned int wid_type = get_wcaps_type(wid_caps);
0193         unsigned int def_conf;
0194         short assoc, loc, conn, dev;
0195 
0196         /* read all default configuration for pin complex */
0197         if (wid_type != AC_WID_PIN)
0198             continue;
0199         /* ignore the given nids (e.g. pc-beep returns error) */
0200         if (ignore_nids && is_in_nid_list(nid, ignore_nids))
0201             continue;
0202 
0203         def_conf = snd_hda_codec_get_pincfg(codec, nid);
0204         conn = get_defcfg_connect(def_conf);
0205         if (conn == AC_JACK_PORT_NONE)
0206             continue;
0207         loc = get_defcfg_location(def_conf);
0208         dev = get_defcfg_device(def_conf);
0209 
0210         /* workaround for buggy BIOS setups */
0211         if (dev == AC_JACK_LINE_OUT) {
0212             if (conn == AC_JACK_PORT_FIXED ||
0213                 conn == AC_JACK_PORT_BOTH)
0214                 dev = AC_JACK_SPEAKER;
0215         }
0216 
0217         if (!check_pincap_validity(codec, nid, dev))
0218             continue;
0219 
0220         switch (dev) {
0221         case AC_JACK_LINE_OUT:
0222             seq = get_defcfg_sequence(def_conf);
0223             assoc = get_defcfg_association(def_conf);
0224 
0225             if (!(wid_caps & AC_WCAP_STEREO))
0226                 if (!cfg->mono_out_pin)
0227                     cfg->mono_out_pin = nid;
0228             if (!assoc)
0229                 continue;
0230             if (!assoc_line_out)
0231                 assoc_line_out = assoc;
0232             else if (assoc_line_out != assoc) {
0233                 codec_info(codec,
0234                        "ignore pin 0x%x with mismatching assoc# 0x%x vs 0x%x\n",
0235                        nid, assoc, assoc_line_out);
0236                 continue;
0237             }
0238             if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins)) {
0239                 codec_info(codec,
0240                        "ignore pin 0x%x, too many assigned pins\n",
0241                        nid);
0242                 continue;
0243             }
0244             line_out[cfg->line_outs].pin = nid;
0245             line_out[cfg->line_outs].seq = seq;
0246             cfg->line_outs++;
0247             break;
0248         case AC_JACK_SPEAKER:
0249             seq = get_defcfg_sequence(def_conf);
0250             assoc = get_defcfg_association(def_conf);
0251             if (cfg->speaker_outs >= ARRAY_SIZE(cfg->speaker_pins)) {
0252                 codec_info(codec,
0253                        "ignore pin 0x%x, too many assigned pins\n",
0254                        nid);
0255                 continue;
0256             }
0257             speaker_out[cfg->speaker_outs].pin = nid;
0258             speaker_out[cfg->speaker_outs].seq = (assoc << 4) | seq;
0259             cfg->speaker_outs++;
0260             break;
0261         case AC_JACK_HP_OUT:
0262             seq = get_defcfg_sequence(def_conf);
0263             assoc = get_defcfg_association(def_conf);
0264             if (cfg->hp_outs >= ARRAY_SIZE(cfg->hp_pins)) {
0265                 codec_info(codec,
0266                        "ignore pin 0x%x, too many assigned pins\n",
0267                        nid);
0268                 continue;
0269             }
0270             hp_out[cfg->hp_outs].pin = nid;
0271             hp_out[cfg->hp_outs].seq = (assoc << 4) | seq;
0272             cfg->hp_outs++;
0273             break;
0274         case AC_JACK_MIC_IN:
0275             add_auto_cfg_input_pin(codec, cfg, nid, AUTO_PIN_MIC);
0276             break;
0277         case AC_JACK_LINE_IN:
0278             add_auto_cfg_input_pin(codec, cfg, nid, AUTO_PIN_LINE_IN);
0279             break;
0280         case AC_JACK_CD:
0281             add_auto_cfg_input_pin(codec, cfg, nid, AUTO_PIN_CD);
0282             break;
0283         case AC_JACK_AUX:
0284             add_auto_cfg_input_pin(codec, cfg, nid, AUTO_PIN_AUX);
0285             break;
0286         case AC_JACK_SPDIF_OUT:
0287         case AC_JACK_DIG_OTHER_OUT:
0288             if (cfg->dig_outs >= ARRAY_SIZE(cfg->dig_out_pins)) {
0289                 codec_info(codec,
0290                        "ignore pin 0x%x, too many assigned pins\n",
0291                        nid);
0292                 continue;
0293             }
0294             cfg->dig_out_pins[cfg->dig_outs] = nid;
0295             cfg->dig_out_type[cfg->dig_outs] =
0296                 (loc == AC_JACK_LOC_HDMI) ?
0297                 HDA_PCM_TYPE_HDMI : HDA_PCM_TYPE_SPDIF;
0298             cfg->dig_outs++;
0299             break;
0300         case AC_JACK_SPDIF_IN:
0301         case AC_JACK_DIG_OTHER_IN:
0302             cfg->dig_in_pin = nid;
0303             if (loc == AC_JACK_LOC_HDMI)
0304                 cfg->dig_in_type = HDA_PCM_TYPE_HDMI;
0305             else
0306                 cfg->dig_in_type = HDA_PCM_TYPE_SPDIF;
0307             break;
0308         }
0309     }
0310 
0311     /* Find a pin that could be a headset or headphone mic */
0312     if (cond_flags & HDA_PINCFG_HEADSET_MIC || cond_flags & HDA_PINCFG_HEADPHONE_MIC) {
0313         bool hsmic = !!(cond_flags & HDA_PINCFG_HEADSET_MIC);
0314         bool hpmic = !!(cond_flags & HDA_PINCFG_HEADPHONE_MIC);
0315         for (i = 0; (hsmic || hpmic) && (i < cfg->num_inputs); i++)
0316             if (hsmic && can_be_headset_mic(codec, &cfg->inputs[i], 0xc)) {
0317                 cfg->inputs[i].is_headset_mic = 1;
0318                 hsmic = false;
0319             } else if (hpmic && can_be_headset_mic(codec, &cfg->inputs[i], 0xd)) {
0320                 cfg->inputs[i].is_headphone_mic = 1;
0321                 hpmic = false;
0322             }
0323 
0324         /* If we didn't find our sequence number mark, fall back to any sequence number */
0325         for (i = 0; (hsmic || hpmic) && (i < cfg->num_inputs); i++) {
0326             if (!can_be_headset_mic(codec, &cfg->inputs[i], -1))
0327                 continue;
0328             if (hsmic) {
0329                 cfg->inputs[i].is_headset_mic = 1;
0330                 hsmic = false;
0331             } else if (hpmic) {
0332                 cfg->inputs[i].is_headphone_mic = 1;
0333                 hpmic = false;
0334             }
0335         }
0336 
0337         if (hsmic)
0338             codec_dbg(codec, "Told to look for a headset mic, but didn't find any.\n");
0339         if (hpmic)
0340             codec_dbg(codec, "Told to look for a headphone mic, but didn't find any.\n");
0341     }
0342 
0343     /* FIX-UP:
0344      * If no line-out is defined but multiple HPs are found,
0345      * some of them might be the real line-outs.
0346      */
0347     if (!cfg->line_outs && cfg->hp_outs > 1 &&
0348         !(cond_flags & HDA_PINCFG_NO_HP_FIXUP)) {
0349         i = 0;
0350         while (i < cfg->hp_outs) {
0351             /* The real HPs should have the sequence 0x0f */
0352             if ((hp_out[i].seq & 0x0f) == 0x0f) {
0353                 i++;
0354                 continue;
0355             }
0356             /* Move it to the line-out table */
0357             line_out[cfg->line_outs++] = hp_out[i];
0358             cfg->hp_outs--;
0359             memmove(hp_out + i, hp_out + i + 1,
0360                 sizeof(hp_out[0]) * (cfg->hp_outs - i));
0361         }
0362         memset(hp_out + cfg->hp_outs, 0,
0363                sizeof(hp_out[0]) * (AUTO_CFG_MAX_OUTS - cfg->hp_outs));
0364         if (!cfg->hp_outs)
0365             cfg->line_out_type = AUTO_PIN_HP_OUT;
0366 
0367     }
0368 
0369     /* sort by sequence */
0370     sort_pins_by_sequence(cfg->line_out_pins, line_out, cfg->line_outs);
0371     sort_pins_by_sequence(cfg->speaker_pins, speaker_out,
0372                   cfg->speaker_outs);
0373     sort_pins_by_sequence(cfg->hp_pins, hp_out, cfg->hp_outs);
0374 
0375     /*
0376      * FIX-UP: if no line-outs are detected, try to use speaker or HP pin
0377      * as a primary output
0378      */
0379     if (!cfg->line_outs &&
0380         !(cond_flags & HDA_PINCFG_NO_LO_FIXUP)) {
0381         if (cfg->speaker_outs) {
0382             cfg->line_outs = cfg->speaker_outs;
0383             memcpy(cfg->line_out_pins, cfg->speaker_pins,
0384                    sizeof(cfg->speaker_pins));
0385             cfg->speaker_outs = 0;
0386             memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
0387             cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
0388         } else if (cfg->hp_outs) {
0389             cfg->line_outs = cfg->hp_outs;
0390             memcpy(cfg->line_out_pins, cfg->hp_pins,
0391                    sizeof(cfg->hp_pins));
0392             cfg->hp_outs = 0;
0393             memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
0394             cfg->line_out_type = AUTO_PIN_HP_OUT;
0395         }
0396     }
0397 
0398     reorder_outputs(cfg->line_outs, cfg->line_out_pins);
0399     reorder_outputs(cfg->hp_outs, cfg->hp_pins);
0400     reorder_outputs(cfg->speaker_outs, cfg->speaker_pins);
0401 
0402     /* sort inputs in the order of AUTO_PIN_* type */
0403     sort(cfg->inputs, cfg->num_inputs, sizeof(cfg->inputs[0]),
0404          compare_input_type, NULL);
0405 
0406     /*
0407      * debug prints of the parsed results
0408      */
0409     codec_info(codec, "autoconfig for %s: line_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x) type:%s\n",
0410            codec->core.chip_name, cfg->line_outs, cfg->line_out_pins[0],
0411            cfg->line_out_pins[1], cfg->line_out_pins[2],
0412            cfg->line_out_pins[3], cfg->line_out_pins[4],
0413            cfg->line_out_type == AUTO_PIN_HP_OUT ? "hp" :
0414            (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT ?
0415             "speaker" : "line"));
0416     codec_info(codec, "   speaker_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
0417            cfg->speaker_outs, cfg->speaker_pins[0],
0418            cfg->speaker_pins[1], cfg->speaker_pins[2],
0419            cfg->speaker_pins[3], cfg->speaker_pins[4]);
0420     codec_info(codec, "   hp_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
0421            cfg->hp_outs, cfg->hp_pins[0],
0422            cfg->hp_pins[1], cfg->hp_pins[2],
0423            cfg->hp_pins[3], cfg->hp_pins[4]);
0424     codec_info(codec, "   mono: mono_out=0x%x\n", cfg->mono_out_pin);
0425     if (cfg->dig_outs)
0426         codec_info(codec, "   dig-out=0x%x/0x%x\n",
0427                cfg->dig_out_pins[0], cfg->dig_out_pins[1]);
0428     codec_info(codec, "   inputs:\n");
0429     for (i = 0; i < cfg->num_inputs; i++) {
0430         codec_info(codec, "     %s=0x%x\n",
0431                 hda_get_autocfg_input_label(codec, cfg, i),
0432                 cfg->inputs[i].pin);
0433     }
0434     if (cfg->dig_in_pin)
0435         codec_info(codec, "   dig-in=0x%x\n", cfg->dig_in_pin);
0436 
0437     return 0;
0438 }
0439 EXPORT_SYMBOL_GPL(snd_hda_parse_pin_defcfg);
0440 
0441 /**
0442  * snd_hda_get_input_pin_attr - Get the input pin attribute from pin config
0443  * @def_conf: pin configuration value
0444  *
0445  * Guess the input pin attribute (INPUT_PIN_ATTR_XXX) from the given
0446  * default pin configuration value.
0447  */
0448 int snd_hda_get_input_pin_attr(unsigned int def_conf)
0449 {
0450     unsigned int loc = get_defcfg_location(def_conf);
0451     unsigned int conn = get_defcfg_connect(def_conf);
0452     if (conn == AC_JACK_PORT_NONE)
0453         return INPUT_PIN_ATTR_UNUSED;
0454     /* Windows may claim the internal mic to be BOTH, too */
0455     if (conn == AC_JACK_PORT_FIXED || conn == AC_JACK_PORT_BOTH)
0456         return INPUT_PIN_ATTR_INT;
0457     if ((loc & 0x30) == AC_JACK_LOC_INTERNAL)
0458         return INPUT_PIN_ATTR_INT;
0459     if ((loc & 0x30) == AC_JACK_LOC_SEPARATE)
0460         return INPUT_PIN_ATTR_DOCK;
0461     if (loc == AC_JACK_LOC_REAR)
0462         return INPUT_PIN_ATTR_REAR;
0463     if (loc == AC_JACK_LOC_FRONT)
0464         return INPUT_PIN_ATTR_FRONT;
0465     return INPUT_PIN_ATTR_NORMAL;
0466 }
0467 EXPORT_SYMBOL_GPL(snd_hda_get_input_pin_attr);
0468 
0469 /**
0470  * hda_get_input_pin_label - Give a label for the given input pin
0471  * @codec: the HDA codec
0472  * @item: ping config item to refer
0473  * @pin: the pin NID
0474  * @check_location: flag to add the jack location prefix
0475  *
0476  * When @check_location is true, the function checks the pin location
0477  * for mic and line-in pins, and set an appropriate prefix like "Front",
0478  * "Rear", "Internal".
0479  */
0480 static const char *hda_get_input_pin_label(struct hda_codec *codec,
0481                        const struct auto_pin_cfg_item *item,
0482                        hda_nid_t pin, bool check_location)
0483 {
0484     unsigned int def_conf;
0485     static const char * const mic_names[] = {
0486         "Internal Mic", "Dock Mic", "Mic", "Rear Mic", "Front Mic"
0487     };
0488     int attr;
0489 
0490     def_conf = snd_hda_codec_get_pincfg(codec, pin);
0491 
0492     switch (get_defcfg_device(def_conf)) {
0493     case AC_JACK_MIC_IN:
0494         if (item && item->is_headset_mic)
0495             return "Headset Mic";
0496         if (item && item->is_headphone_mic)
0497             return "Headphone Mic";
0498         if (!check_location)
0499             return "Mic";
0500         attr = snd_hda_get_input_pin_attr(def_conf);
0501         if (!attr)
0502             return "None";
0503         return mic_names[attr - 1];
0504     case AC_JACK_LINE_IN:
0505         if (!check_location)
0506             return "Line";
0507         attr = snd_hda_get_input_pin_attr(def_conf);
0508         if (!attr)
0509             return "None";
0510         if (attr == INPUT_PIN_ATTR_DOCK)
0511             return "Dock Line";
0512         return "Line";
0513     case AC_JACK_AUX:
0514         return "Aux";
0515     case AC_JACK_CD:
0516         return "CD";
0517     case AC_JACK_SPDIF_IN:
0518         return "SPDIF In";
0519     case AC_JACK_DIG_OTHER_IN:
0520         return "Digital In";
0521     case AC_JACK_HP_OUT:
0522         return "Headphone Mic";
0523     default:
0524         return "Misc";
0525     }
0526 }
0527 
0528 /* Check whether the location prefix needs to be added to the label.
0529  * If all mic-jacks are in the same location (e.g. rear panel), we don't
0530  * have to put "Front" prefix to each label.  In such a case, returns false.
0531  */
0532 static int check_mic_location_need(struct hda_codec *codec,
0533                    const struct auto_pin_cfg *cfg,
0534                    int input)
0535 {
0536     unsigned int defc;
0537     int i, attr, attr2;
0538 
0539     defc = snd_hda_codec_get_pincfg(codec, cfg->inputs[input].pin);
0540     attr = snd_hda_get_input_pin_attr(defc);
0541     /* for internal or docking mics, we need locations */
0542     if (attr <= INPUT_PIN_ATTR_NORMAL)
0543         return 1;
0544 
0545     attr = 0;
0546     for (i = 0; i < cfg->num_inputs; i++) {
0547         defc = snd_hda_codec_get_pincfg(codec, cfg->inputs[i].pin);
0548         attr2 = snd_hda_get_input_pin_attr(defc);
0549         if (attr2 >= INPUT_PIN_ATTR_NORMAL) {
0550             if (attr && attr != attr2)
0551                 return 1; /* different locations found */
0552             attr = attr2;
0553         }
0554     }
0555     return 0;
0556 }
0557 
0558 /**
0559  * hda_get_autocfg_input_label - Get a label for the given input
0560  * @codec: the HDA codec
0561  * @cfg: the parsed pin configuration
0562  * @input: the input index number
0563  *
0564  * Get a label for the given input pin defined by the autocfg item.
0565  * Unlike hda_get_input_pin_label(), this function checks all inputs
0566  * defined in autocfg and avoids the redundant mic/line prefix as much as
0567  * possible.
0568  */
0569 const char *hda_get_autocfg_input_label(struct hda_codec *codec,
0570                     const struct auto_pin_cfg *cfg,
0571                     int input)
0572 {
0573     int type = cfg->inputs[input].type;
0574     int has_multiple_pins = 0;
0575 
0576     if ((input > 0 && cfg->inputs[input - 1].type == type) ||
0577         (input < cfg->num_inputs - 1 && cfg->inputs[input + 1].type == type))
0578         has_multiple_pins = 1;
0579     if (has_multiple_pins && type == AUTO_PIN_MIC)
0580         has_multiple_pins &= check_mic_location_need(codec, cfg, input);
0581     has_multiple_pins |= codec->force_pin_prefix;
0582     return hda_get_input_pin_label(codec, &cfg->inputs[input],
0583                        cfg->inputs[input].pin,
0584                        has_multiple_pins);
0585 }
0586 EXPORT_SYMBOL_GPL(hda_get_autocfg_input_label);
0587 
0588 /* return the position of NID in the list, or -1 if not found */
0589 static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
0590 {
0591     int i;
0592     for (i = 0; i < nums; i++)
0593         if (list[i] == nid)
0594             return i;
0595     return -1;
0596 }
0597 
0598 /* get a unique suffix or an index number */
0599 static const char *check_output_sfx(hda_nid_t nid, const hda_nid_t *pins,
0600                     int num_pins, int *indexp)
0601 {
0602     static const char * const channel_sfx[] = {
0603         " Front", " Surround", " CLFE", " Side"
0604     };
0605     int i;
0606 
0607     i = find_idx_in_nid_list(nid, pins, num_pins);
0608     if (i < 0)
0609         return NULL;
0610     if (num_pins == 1)
0611         return "";
0612     if (num_pins > ARRAY_SIZE(channel_sfx)) {
0613         if (indexp)
0614             *indexp = i;
0615         return "";
0616     }
0617     return channel_sfx[i];
0618 }
0619 
0620 static const char *check_output_pfx(struct hda_codec *codec, hda_nid_t nid)
0621 {
0622     unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid);
0623     int attr = snd_hda_get_input_pin_attr(def_conf);
0624 
0625     /* check the location */
0626     switch (attr) {
0627     case INPUT_PIN_ATTR_DOCK:
0628         return "Dock ";
0629     case INPUT_PIN_ATTR_FRONT:
0630         return "Front ";
0631     }
0632     return "";
0633 }
0634 
0635 static int get_hp_label_index(struct hda_codec *codec, hda_nid_t nid,
0636                   const hda_nid_t *pins, int num_pins)
0637 {
0638     int i, j, idx = 0;
0639 
0640     const char *pfx = check_output_pfx(codec, nid);
0641 
0642     i = find_idx_in_nid_list(nid, pins, num_pins);
0643     if (i < 0)
0644         return -1;
0645     for (j = 0; j < i; j++)
0646         if (pfx == check_output_pfx(codec, pins[j]))
0647             idx++;
0648 
0649     return idx;
0650 }
0651 
0652 static int fill_audio_out_name(struct hda_codec *codec, hda_nid_t nid,
0653                    const struct auto_pin_cfg *cfg,
0654                    const char *name, char *label, int maxlen,
0655                    int *indexp)
0656 {
0657     unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid);
0658     int attr = snd_hda_get_input_pin_attr(def_conf);
0659     const char *pfx, *sfx = "";
0660 
0661     /* handle as a speaker if it's a fixed line-out */
0662     if (!strcmp(name, "Line Out") && attr == INPUT_PIN_ATTR_INT)
0663         name = "Speaker";
0664     pfx = check_output_pfx(codec, nid);
0665 
0666     if (cfg) {
0667         /* try to give a unique suffix if needed */
0668         sfx = check_output_sfx(nid, cfg->line_out_pins, cfg->line_outs,
0669                        indexp);
0670         if (!sfx)
0671             sfx = check_output_sfx(nid, cfg->speaker_pins, cfg->speaker_outs,
0672                            indexp);
0673         if (!sfx) {
0674             /* don't add channel suffix for Headphone controls */
0675             int idx = get_hp_label_index(codec, nid, cfg->hp_pins,
0676                              cfg->hp_outs);
0677             if (idx >= 0 && indexp)
0678                 *indexp = idx;
0679             sfx = "";
0680         }
0681     }
0682     snprintf(label, maxlen, "%s%s%s", pfx, name, sfx);
0683     return 1;
0684 }
0685 
0686 #define is_hdmi_cfg(conf) \
0687     (get_defcfg_location(conf) == AC_JACK_LOC_HDMI)
0688 
0689 /**
0690  * snd_hda_get_pin_label - Get a label for the given I/O pin
0691  * @codec: the HDA codec
0692  * @nid: pin NID
0693  * @cfg: the parsed pin configuration
0694  * @label: the string buffer to store
0695  * @maxlen: the max length of string buffer (including termination)
0696  * @indexp: the pointer to return the index number (for multiple ctls)
0697  *
0698  * Get a label for the given pin.  This function works for both input and
0699  * output pins.  When @cfg is given as non-NULL, the function tries to get
0700  * an optimized label using hda_get_autocfg_input_label().
0701  *
0702  * This function tries to give a unique label string for the pin as much as
0703  * possible.  For example, when the multiple line-outs are present, it adds
0704  * the channel suffix like "Front", "Surround", etc (only when @cfg is given).
0705  * If no unique name with a suffix is available and @indexp is non-NULL, the
0706  * index number is stored in the pointer.
0707  */
0708 int snd_hda_get_pin_label(struct hda_codec *codec, hda_nid_t nid,
0709               const struct auto_pin_cfg *cfg,
0710               char *label, int maxlen, int *indexp)
0711 {
0712     unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid);
0713     const char *name = NULL;
0714     int i;
0715     bool hdmi;
0716 
0717     if (indexp)
0718         *indexp = 0;
0719     if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
0720         return 0;
0721 
0722     switch (get_defcfg_device(def_conf)) {
0723     case AC_JACK_LINE_OUT:
0724         return fill_audio_out_name(codec, nid, cfg, "Line Out",
0725                        label, maxlen, indexp);
0726     case AC_JACK_SPEAKER:
0727         return fill_audio_out_name(codec, nid, cfg, "Speaker",
0728                        label, maxlen, indexp);
0729     case AC_JACK_HP_OUT:
0730         return fill_audio_out_name(codec, nid, cfg, "Headphone",
0731                        label, maxlen, indexp);
0732     case AC_JACK_SPDIF_OUT:
0733     case AC_JACK_DIG_OTHER_OUT:
0734         hdmi = is_hdmi_cfg(def_conf);
0735         name = hdmi ? "HDMI" : "SPDIF";
0736         if (cfg && indexp)
0737             for (i = 0; i < cfg->dig_outs; i++) {
0738                 hda_nid_t pin = cfg->dig_out_pins[i];
0739                 unsigned int c;
0740                 if (pin == nid)
0741                     break;
0742                 c = snd_hda_codec_get_pincfg(codec, pin);
0743                 if (hdmi == is_hdmi_cfg(c))
0744                     (*indexp)++;
0745             }
0746         break;
0747     default:
0748         if (cfg) {
0749             for (i = 0; i < cfg->num_inputs; i++) {
0750                 if (cfg->inputs[i].pin != nid)
0751                     continue;
0752                 name = hda_get_autocfg_input_label(codec, cfg, i);
0753                 if (name)
0754                     break;
0755             }
0756         }
0757         if (!name)
0758             name = hda_get_input_pin_label(codec, NULL, nid, true);
0759         break;
0760     }
0761     if (!name)
0762         return 0;
0763     strscpy(label, name, maxlen);
0764     return 1;
0765 }
0766 EXPORT_SYMBOL_GPL(snd_hda_get_pin_label);
0767 
0768 /**
0769  * snd_hda_add_verbs - Add verbs to the init list
0770  * @codec: the HDA codec
0771  * @list: zero-terminated verb list to add
0772  *
0773  * Append the given verb list to the execution list.  The verbs will be
0774  * performed at init and resume time via snd_hda_apply_verbs().
0775  */
0776 int snd_hda_add_verbs(struct hda_codec *codec,
0777               const struct hda_verb *list)
0778 {
0779     const struct hda_verb **v;
0780     v = snd_array_new(&codec->verbs);
0781     if (!v)
0782         return -ENOMEM;
0783     *v = list;
0784     return 0;
0785 }
0786 EXPORT_SYMBOL_GPL(snd_hda_add_verbs);
0787 
0788 /**
0789  * snd_hda_apply_verbs - Execute the init verb lists
0790  * @codec: the HDA codec
0791  */
0792 void snd_hda_apply_verbs(struct hda_codec *codec)
0793 {
0794     const struct hda_verb **v;
0795     int i;
0796 
0797     snd_array_for_each(&codec->verbs, i, v)
0798         snd_hda_sequence_write(codec, *v);
0799 }
0800 EXPORT_SYMBOL_GPL(snd_hda_apply_verbs);
0801 
0802 /**
0803  * snd_hda_apply_pincfgs - Set each pin config in the given list
0804  * @codec: the HDA codec
0805  * @cfg: NULL-terminated pin config table
0806  */
0807 void snd_hda_apply_pincfgs(struct hda_codec *codec,
0808                const struct hda_pintbl *cfg)
0809 {
0810     for (; cfg->nid; cfg++)
0811         snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val);
0812 }
0813 EXPORT_SYMBOL_GPL(snd_hda_apply_pincfgs);
0814 
0815 static void set_pin_targets(struct hda_codec *codec,
0816                 const struct hda_pintbl *cfg)
0817 {
0818     for (; cfg->nid; cfg++)
0819         snd_hda_set_pin_ctl_cache(codec, cfg->nid, cfg->val);
0820 }
0821 
0822 void __snd_hda_apply_fixup(struct hda_codec *codec, int id, int action, int depth)
0823 {
0824     const char *modelname = codec->fixup_name;
0825 
0826     while (id >= 0) {
0827         const struct hda_fixup *fix = codec->fixup_list + id;
0828 
0829         if (++depth > 10)
0830             break;
0831         if (fix->chained_before)
0832             __snd_hda_apply_fixup(codec, fix->chain_id, action, depth + 1);
0833 
0834         switch (fix->type) {
0835         case HDA_FIXUP_PINS:
0836             if (action != HDA_FIXUP_ACT_PRE_PROBE || !fix->v.pins)
0837                 break;
0838             codec_dbg(codec, "%s: Apply pincfg for %s\n",
0839                     codec->core.chip_name, modelname);
0840             snd_hda_apply_pincfgs(codec, fix->v.pins);
0841             break;
0842         case HDA_FIXUP_VERBS:
0843             if (action != HDA_FIXUP_ACT_PROBE || !fix->v.verbs)
0844                 break;
0845             codec_dbg(codec, "%s: Apply fix-verbs for %s\n",
0846                     codec->core.chip_name, modelname);
0847             snd_hda_add_verbs(codec, fix->v.verbs);
0848             break;
0849         case HDA_FIXUP_FUNC:
0850             if (!fix->v.func)
0851                 break;
0852             codec_dbg(codec, "%s: Apply fix-func for %s\n",
0853                     codec->core.chip_name, modelname);
0854             fix->v.func(codec, fix, action);
0855             break;
0856         case HDA_FIXUP_PINCTLS:
0857             if (action != HDA_FIXUP_ACT_PROBE || !fix->v.pins)
0858                 break;
0859             codec_dbg(codec, "%s: Apply pinctl for %s\n",
0860                     codec->core.chip_name, modelname);
0861             set_pin_targets(codec, fix->v.pins);
0862             break;
0863         default:
0864             codec_err(codec, "%s: Invalid fixup type %d\n",
0865                    codec->core.chip_name, fix->type);
0866             break;
0867         }
0868         if (!fix->chained || fix->chained_before)
0869             break;
0870         id = fix->chain_id;
0871     }
0872 }
0873 EXPORT_SYMBOL_GPL(__snd_hda_apply_fixup);
0874 
0875 /**
0876  * snd_hda_apply_fixup - Apply the fixup chain with the given action
0877  * @codec: the HDA codec
0878  * @action: fixup action (HDA_FIXUP_ACT_XXX)
0879  */
0880 void snd_hda_apply_fixup(struct hda_codec *codec, int action)
0881 {
0882     if (codec->fixup_list)
0883         __snd_hda_apply_fixup(codec, codec->fixup_id, action, 0);
0884 }
0885 EXPORT_SYMBOL_GPL(snd_hda_apply_fixup);
0886 
0887 #define IGNORE_SEQ_ASSOC (~(AC_DEFCFG_SEQUENCE | AC_DEFCFG_DEF_ASSOC))
0888 
0889 static bool pin_config_match(struct hda_codec *codec,
0890                  const struct hda_pintbl *pins,
0891                  bool match_all_pins)
0892 {
0893     const struct hda_pincfg *pin;
0894     int i;
0895 
0896     snd_array_for_each(&codec->init_pins, i, pin) {
0897         hda_nid_t nid = pin->nid;
0898         u32 cfg = pin->cfg;
0899         const struct hda_pintbl *t_pins;
0900         int found;
0901 
0902         t_pins = pins;
0903         found = 0;
0904         for (; t_pins->nid; t_pins++) {
0905             if (t_pins->nid == nid) {
0906                 found = 1;
0907                 if ((t_pins->val & IGNORE_SEQ_ASSOC) == (cfg & IGNORE_SEQ_ASSOC))
0908                     break;
0909                 else if ((cfg & 0xf0000000) == 0x40000000 && (t_pins->val & 0xf0000000) == 0x40000000)
0910                     break;
0911                 else
0912                     return false;
0913             }
0914         }
0915         if (match_all_pins &&
0916             !found && (cfg & 0xf0000000) != 0x40000000)
0917             return false;
0918     }
0919 
0920     return true;
0921 }
0922 
0923 /**
0924  * snd_hda_pick_pin_fixup - Pick up a fixup matching with the pin quirk list
0925  * @codec: the HDA codec
0926  * @pin_quirk: zero-terminated pin quirk list
0927  * @fixlist: the fixup list
0928  * @match_all_pins: all valid pins must match with the table entries
0929  */
0930 void snd_hda_pick_pin_fixup(struct hda_codec *codec,
0931                 const struct snd_hda_pin_quirk *pin_quirk,
0932                 const struct hda_fixup *fixlist,
0933                 bool match_all_pins)
0934 {
0935     const struct snd_hda_pin_quirk *pq;
0936 
0937     if (codec->fixup_id != HDA_FIXUP_ID_NOT_SET)
0938         return;
0939 
0940     for (pq = pin_quirk; pq->subvendor; pq++) {
0941         if ((codec->core.subsystem_id & 0xffff0000) != (pq->subvendor << 16))
0942             continue;
0943         if (codec->core.vendor_id != pq->codec)
0944             continue;
0945         if (pin_config_match(codec, pq->pins, match_all_pins)) {
0946             codec->fixup_id = pq->value;
0947 #ifdef CONFIG_SND_DEBUG_VERBOSE
0948             codec->fixup_name = pq->name;
0949             codec_dbg(codec, "%s: picked fixup %s (pin match)\n",
0950                   codec->core.chip_name, codec->fixup_name);
0951 #endif
0952             codec->fixup_list = fixlist;
0953             return;
0954         }
0955     }
0956 }
0957 EXPORT_SYMBOL_GPL(snd_hda_pick_pin_fixup);
0958 
0959 /**
0960  * snd_hda_pick_fixup - Pick up a fixup matching with PCI/codec SSID or model string
0961  * @codec: the HDA codec
0962  * @models: NULL-terminated model string list
0963  * @quirk: zero-terminated PCI/codec SSID quirk list
0964  * @fixlist: the fixup list
0965  *
0966  * Pick up a fixup entry matching with the given model string or SSID.
0967  * If a fixup was already set beforehand, the function doesn't do anything.
0968  * When a special model string "nofixup" is given, also no fixup is applied.
0969  *
0970  * The function tries to find the matching model name at first, if given.
0971  * If the model string contains the SSID alias, try to look up with the given
0972  * alias ID.
0973  * If nothing matched, try to look up the PCI SSID.
0974  * If still nothing matched, try to look up the codec SSID.
0975  */
0976 void snd_hda_pick_fixup(struct hda_codec *codec,
0977             const struct hda_model_fixup *models,
0978             const struct snd_pci_quirk *quirk,
0979             const struct hda_fixup *fixlist)
0980 {
0981     const struct snd_pci_quirk *q;
0982     int id = HDA_FIXUP_ID_NOT_SET;
0983     const char *name = NULL;
0984     const char *type = NULL;
0985     unsigned int vendor, device;
0986 
0987     if (codec->fixup_id != HDA_FIXUP_ID_NOT_SET)
0988         return;
0989 
0990     /* when model=nofixup is given, don't pick up any fixups */
0991     if (codec->modelname && !strcmp(codec->modelname, "nofixup")) {
0992         id = HDA_FIXUP_ID_NO_FIXUP;
0993         fixlist = NULL;
0994         codec_dbg(codec, "%s: picked no fixup (nofixup specified)\n",
0995               codec->core.chip_name);
0996         goto found;
0997     }
0998 
0999     /* match with the model name string */
1000     if (codec->modelname && models) {
1001         while (models->name) {
1002             if (!strcmp(codec->modelname, models->name)) {
1003                 id = models->id;
1004                 name = models->name;
1005                 codec_dbg(codec, "%s: picked fixup %s (model specified)\n",
1006                       codec->core.chip_name, codec->fixup_name);
1007                 goto found;
1008             }
1009             models++;
1010         }
1011     }
1012 
1013     if (!quirk)
1014         return;
1015 
1016     /* match with the SSID alias given by the model string "XXXX:YYYY" */
1017     if (codec->modelname &&
1018         sscanf(codec->modelname, "%04x:%04x", &vendor, &device) == 2) {
1019         q = snd_pci_quirk_lookup_id(vendor, device, quirk);
1020         if (q) {
1021             type = "alias SSID";
1022             goto found_device;
1023         }
1024     }
1025 
1026     /* match with the PCI SSID */
1027     q = snd_pci_quirk_lookup(codec->bus->pci, quirk);
1028     if (q) {
1029         type = "PCI SSID";
1030         goto found_device;
1031     }
1032 
1033     /* match with the codec SSID */
1034     q = snd_pci_quirk_lookup_id(codec->core.subsystem_id >> 16,
1035                     codec->core.subsystem_id & 0xffff,
1036                     quirk);
1037     if (q) {
1038         type = "codec SSID";
1039         goto found_device;
1040     }
1041 
1042     return; /* no matching */
1043 
1044  found_device:
1045     id = q->value;
1046 #ifdef CONFIG_SND_DEBUG_VERBOSE
1047     name = q->name;
1048 #endif
1049     codec_dbg(codec, "%s: picked fixup %s for %s %04x:%04x\n",
1050           codec->core.chip_name, name ? name : "",
1051           type, q->subvendor, q->subdevice);
1052  found:
1053     codec->fixup_id = id;
1054     codec->fixup_list = fixlist;
1055     codec->fixup_name = name;
1056 }
1057 EXPORT_SYMBOL_GPL(snd_hda_pick_fixup);