diff options
Diffstat (limited to 'sound/pci/hda/hda_codec.c')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 141 |
1 files changed, 108 insertions, 33 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index e57698f611ab..e050f893bf75 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -5066,61 +5066,136 @@ const char *hda_get_autocfg_input_label(struct hda_codec *codec, | |||
5066 | } | 5066 | } |
5067 | EXPORT_SYMBOL_HDA(hda_get_autocfg_input_label); | 5067 | EXPORT_SYMBOL_HDA(hda_get_autocfg_input_label); |
5068 | 5068 | ||
5069 | /* get a unique suffix or an index number */ | ||
5070 | static const char *check_output_sfx(hda_nid_t nid, const hda_nid_t *pins, | ||
5071 | int num_pins, int *indexp) | ||
5072 | { | ||
5073 | static const char * const channel_sfx[] = { | ||
5074 | " Front", " Surrount", " CLFE", " Side" | ||
5075 | }; | ||
5076 | int i; | ||
5077 | |||
5078 | for (i = 0; i < num_pins; i++) { | ||
5079 | if (pins[i] == nid) { | ||
5080 | if (num_pins == 1) | ||
5081 | return ""; | ||
5082 | if (num_pins > ARRAY_SIZE(channel_sfx)) { | ||
5083 | if (indexp) | ||
5084 | *indexp = i; | ||
5085 | return ""; | ||
5086 | } | ||
5087 | return channel_sfx[i]; | ||
5088 | } | ||
5089 | } | ||
5090 | return NULL; | ||
5091 | } | ||
5092 | |||
5093 | static int fill_audio_out_name(struct hda_codec *codec, hda_nid_t nid, | ||
5094 | const struct auto_pin_cfg *cfg, | ||
5095 | const char *name, char *label, int maxlen, | ||
5096 | int *indexp) | ||
5097 | { | ||
5098 | unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid); | ||
5099 | int attr = snd_hda_get_input_pin_attr(def_conf); | ||
5100 | const char *pfx = "", *sfx = ""; | ||
5101 | |||
5102 | /* handle as a speaker if it's a fixed line-out */ | ||
5103 | if (!strcmp(name, "Line-Out") && attr == INPUT_PIN_ATTR_INT) | ||
5104 | name = "Speaker"; | ||
5105 | /* check the location */ | ||
5106 | switch (attr) { | ||
5107 | case INPUT_PIN_ATTR_DOCK: | ||
5108 | pfx = "Dock "; | ||
5109 | break; | ||
5110 | case INPUT_PIN_ATTR_FRONT: | ||
5111 | pfx = "Front "; | ||
5112 | break; | ||
5113 | } | ||
5114 | if (cfg) { | ||
5115 | /* try to give a unique suffix if needed */ | ||
5116 | sfx = check_output_sfx(nid, cfg->line_out_pins, cfg->line_outs, | ||
5117 | indexp); | ||
5118 | if (!sfx) | ||
5119 | sfx = check_output_sfx(nid, cfg->hp_pins, cfg->hp_outs, | ||
5120 | indexp); | ||
5121 | if (!sfx) | ||
5122 | sfx = check_output_sfx(nid, cfg->speaker_pins, cfg->speaker_outs, | ||
5123 | indexp); | ||
5124 | if (!sfx) | ||
5125 | sfx = ""; | ||
5126 | } | ||
5127 | snprintf(label, maxlen, "%s%s%s", pfx, name, sfx); | ||
5128 | return 1; | ||
5129 | } | ||
5130 | |||
5069 | /** | 5131 | /** |
5070 | * snd_hda_get_pin_label - Get a label for the given I/O pin | 5132 | * snd_hda_get_pin_label - Get a label for the given I/O pin |
5071 | * | 5133 | * |
5072 | * Get a label for the given pin. This function works for both input and | 5134 | * Get a label for the given pin. This function works for both input and |
5073 | * output pins. When @cfg is given as non-NULL, the function tries to get | 5135 | * output pins. When @cfg is given as non-NULL, the function tries to get |
5074 | * an optimized label using hda_get_autocfg_input_label(). | 5136 | * an optimized label using hda_get_autocfg_input_label(). |
5137 | * | ||
5138 | * This function tries to give a unique label string for the pin as much as | ||
5139 | * possible. For example, when the multiple line-outs are present, it adds | ||
5140 | * the channel suffix like "Front", "Surround", etc (only when @cfg is given). | ||
5141 | * If no unique name with a suffix is available and @indexp is non-NULL, the | ||
5142 | * index number is stored in the pointer. | ||
5075 | */ | 5143 | */ |
5076 | const char *snd_hda_get_pin_label(struct hda_codec *codec, hda_nid_t nid, | 5144 | int snd_hda_get_pin_label(struct hda_codec *codec, hda_nid_t nid, |
5077 | const struct auto_pin_cfg *cfg) | 5145 | const struct auto_pin_cfg *cfg, |
5146 | char *label, int maxlen, int *indexp) | ||
5078 | { | 5147 | { |
5079 | unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid); | 5148 | unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid); |
5080 | int attr; | 5149 | const char *name = NULL; |
5081 | int i; | 5150 | int i; |
5082 | 5151 | ||
5152 | if (indexp) | ||
5153 | *indexp = 0; | ||
5083 | if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE) | 5154 | if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE) |
5084 | return NULL; | 5155 | return 0; |
5085 | 5156 | ||
5086 | attr = snd_hda_get_input_pin_attr(def_conf); | ||
5087 | switch (get_defcfg_device(def_conf)) { | 5157 | switch (get_defcfg_device(def_conf)) { |
5088 | case AC_JACK_LINE_OUT: | 5158 | case AC_JACK_LINE_OUT: |
5089 | switch (attr) { | 5159 | return fill_audio_out_name(codec, nid, cfg, "Line-Out", |
5090 | case INPUT_PIN_ATTR_INT: | 5160 | label, maxlen, indexp); |
5091 | return "Speaker"; | ||
5092 | case INPUT_PIN_ATTR_DOCK: | ||
5093 | return "Dock Line-Out"; | ||
5094 | case INPUT_PIN_ATTR_FRONT: | ||
5095 | return "Front Line-Out"; | ||
5096 | default: | ||
5097 | return "Line-Out"; | ||
5098 | } | ||
5099 | case AC_JACK_SPEAKER: | 5161 | case AC_JACK_SPEAKER: |
5100 | return "Speaker"; | 5162 | return fill_audio_out_name(codec, nid, cfg, "Speaker", |
5163 | label, maxlen, indexp); | ||
5101 | case AC_JACK_HP_OUT: | 5164 | case AC_JACK_HP_OUT: |
5102 | switch (attr) { | 5165 | return fill_audio_out_name(codec, nid, cfg, "Headphone", |
5103 | case INPUT_PIN_ATTR_DOCK: | 5166 | label, maxlen, indexp); |
5104 | return "Dock Headphone"; | ||
5105 | case INPUT_PIN_ATTR_FRONT: | ||
5106 | return "Front Headphone"; | ||
5107 | default: | ||
5108 | return "Headphone"; | ||
5109 | } | ||
5110 | case AC_JACK_SPDIF_OUT: | 5167 | case AC_JACK_SPDIF_OUT: |
5111 | case AC_JACK_DIG_OTHER_OUT: | 5168 | case AC_JACK_DIG_OTHER_OUT: |
5112 | if (get_defcfg_location(def_conf) == AC_JACK_LOC_HDMI) | 5169 | if (get_defcfg_location(def_conf) == AC_JACK_LOC_HDMI) |
5113 | return "HDMI"; | 5170 | name = "HDMI"; |
5114 | else | 5171 | else |
5115 | return "SPDIF"; | 5172 | name = "SPDIF"; |
5116 | } | 5173 | if (cfg && indexp) { |
5117 | 5174 | for (i = 0; i < cfg->dig_outs; i++) | |
5118 | if (cfg) { | 5175 | if (cfg->dig_out_pins[i] == nid) { |
5119 | for (i = 0; i < cfg->num_inputs; i++) | 5176 | *indexp = i; |
5120 | if (cfg->inputs[i].pin == nid) | 5177 | break; |
5121 | return hda_get_autocfg_input_label(codec, cfg, i); | 5178 | } |
5179 | } | ||
5180 | break; | ||
5181 | default: | ||
5182 | if (cfg) { | ||
5183 | for (i = 0; i < cfg->num_inputs; i++) { | ||
5184 | if (cfg->inputs[i].pin != nid) | ||
5185 | continue; | ||
5186 | name = hda_get_autocfg_input_label(codec, cfg, i); | ||
5187 | if (name) | ||
5188 | break; | ||
5189 | } | ||
5190 | } | ||
5191 | if (!name) | ||
5192 | name = hda_get_input_pin_label(codec, nid, true); | ||
5193 | break; | ||
5122 | } | 5194 | } |
5123 | return hda_get_input_pin_label(codec, nid, true); | 5195 | if (!name) |
5196 | return 0; | ||
5197 | strlcpy(label, name, maxlen); | ||
5198 | return 1; | ||
5124 | } | 5199 | } |
5125 | EXPORT_SYMBOL_HDA(snd_hda_get_pin_label); | 5200 | EXPORT_SYMBOL_HDA(snd_hda_get_pin_label); |
5126 | 5201 | ||