/** * snd_hda_get_pin_label - Get a label for the given I/O pin * * Get a label for the given pin. This function works for both input and * output pins. When @cfg is given as non-NULL, the function tries to get * an optimized label using hda_get_autocfg_input_label(). * * This function tries to give a unique label string for the pin as much as * possible. For example, when the multiple line-outs are present, it adds * the channel suffix like "Front", "Surround", etc (only when @cfg is given). * If no unique name with a suffix is available and @indexp is non-NULL, the * index number is stored in the pointer. */ int snd_hda_get_pin_label(struct hda_codec *codec, hda_nid_t nid, const struct auto_pin_cfg *cfg, char *label, int maxlen, int *indexp) { unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid); const char *name = NULL; int i; if (indexp) *indexp = 0; if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE) return 0; switch (get_defcfg_device(def_conf)) { case AC_JACK_LINE_OUT: return fill_audio_out_name(codec, nid, cfg, "Line Out", label, maxlen, indexp); case AC_JACK_SPEAKER: return fill_audio_out_name(codec, nid, cfg, "Speaker", label, maxlen, indexp); case AC_JACK_HP_OUT: return fill_audio_out_name(codec, nid, cfg, "Headphone", label, maxlen, indexp); case AC_JACK_SPDIF_OUT: case AC_JACK_DIG_OTHER_OUT: if (get_defcfg_location(def_conf) == AC_JACK_LOC_HDMI) name = "HDMI"; else name = "SPDIF"; if (cfg && indexp) { i = find_idx_in_nid_list(nid, cfg->dig_out_pins, cfg->dig_outs); if (i >= 0) *indexp = i; } break; default: if (cfg) { for (i = 0; i < cfg->num_inputs; i++) { if (cfg->inputs[i].pin != nid) continue; name = hda_get_autocfg_input_label(codec, cfg, i); if (name) break; } } if (!name) name = hda_get_input_pin_label(codec, nid, true); break; } if (!name) return 0; strlcpy(label, name, maxlen); return 1; }
static int get_hp_label_index(struct hda_codec *codec, hda_nid_t nid, const hda_nid_t *pins, int num_pins) { int i, j, idx = 0; const char *pfx = check_output_pfx(codec, nid); i = find_idx_in_nid_list(nid, pins, num_pins); if (i < 0) return -1; for (j = 0; j < i; j++) if (pfx == check_output_pfx(codec, pins[j])) idx++; return idx; }
/* get a unique suffix or an index number */ static const char *check_output_sfx(hda_nid_t nid, const hda_nid_t *pins, int num_pins, int *indexp) { static const char * const channel_sfx[] = { " Front", " Surround", " CLFE", " Side" }; int i; i = find_idx_in_nid_list(nid, pins, num_pins); if (i < 0) return NULL; if (num_pins == 1) return ""; if (num_pins > ARRAY_SIZE(channel_sfx)) { if (indexp) *indexp = i; return ""; } return channel_sfx[i]; }
static int fill_audio_out_name(struct hda_codec *codec, hda_nid_t nid, const struct auto_pin_cfg *cfg, const char *name, char *label, int maxlen, int *indexp) { unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid); int attr = snd_hda_get_input_pin_attr(def_conf); const char *pfx = "", *sfx = ""; /* handle as a speaker if it's a fixed line-out */ if (!strcmp(name, "Line Out") && attr == INPUT_PIN_ATTR_INT) name = "Speaker"; /* check the location */ switch (attr) { case INPUT_PIN_ATTR_DOCK: pfx = "Dock "; break; case INPUT_PIN_ATTR_FRONT: pfx = "Front "; break; } if (cfg) { /* try to give a unique suffix if needed */ sfx = check_output_sfx(nid, cfg->line_out_pins, cfg->line_outs, indexp); if (!sfx) sfx = check_output_sfx(nid, cfg->speaker_pins, cfg->speaker_outs, indexp); if (!sfx) { /* don't add channel suffix for Headphone controls */ int idx = find_idx_in_nid_list(nid, cfg->hp_pins, cfg->hp_outs); if (idx >= 0) *indexp = idx; sfx = ""; } } snprintf(label, maxlen, "%s%s%s", pfx, name, sfx); return 1; }