Commit f46c3296 authored by Takashi Iwai's avatar Takashi Iwai

ALSA: hda - Fix index number conflicts of phantom jacks

Since some jack controls may be renamed as phantom jacks, the existing
check for index conflicts doesn't work because it simply compares the
name with the last used name, assuming that the controls with the same
name continue.  Thus, it would result in the duplicated controls when
two or more phantom jacks with the very same type exist, and the
driver gives up with an error.

This patch fixes the problem by checking the index number conflicts
more intensively (but dumbly).
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 7ae48b56
...@@ -314,9 +314,28 @@ int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, ...@@ -314,9 +314,28 @@ int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,
} }
EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctl); EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctl);
/* get the unique index number for the given kctl name */
static int get_unique_index(struct hda_codec *codec, const char *name, int idx)
{
struct hda_jack_tbl *jack;
int i, len = strlen(name);
again:
jack = codec->jacktbl.list;
for (i = 0; i < codec->jacktbl.used; i++, jack++) {
/* jack->kctl.id contains "XXX Jack" name string with index */
if (jack->kctl &&
!strncmp(name, jack->kctl->id.name, len) &&
!strcmp(" Jack", jack->kctl->id.name + len) &&
jack->kctl->id.index == idx) {
idx++;
goto again;
}
}
return idx;
}
static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid,
const struct auto_pin_cfg *cfg, const struct auto_pin_cfg *cfg)
char *lastname, int *lastidx)
{ {
unsigned int def_conf, conn; unsigned int def_conf, conn;
char name[44]; char name[44];
...@@ -336,10 +355,7 @@ static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, ...@@ -336,10 +355,7 @@ static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid,
if (phantom_jack) if (phantom_jack)
/* Example final name: "Internal Mic Phantom Jack" */ /* Example final name: "Internal Mic Phantom Jack" */
strncat(name, " Phantom", sizeof(name) - strlen(name) - 1); strncat(name, " Phantom", sizeof(name) - strlen(name) - 1);
if (!strcmp(name, lastname) && idx == *lastidx) idx = get_unique_index(codec, name, idx);
idx++;
strncpy(lastname, name, sizeof(name));
*lastidx = idx;
err = __snd_hda_jack_add_kctl(codec, nid, name, idx, phantom_jack); err = __snd_hda_jack_add_kctl(codec, nid, name, idx, phantom_jack);
if (err < 0) if (err < 0)
return err; return err;
...@@ -356,42 +372,41 @@ int snd_hda_jack_add_kctls(struct hda_codec *codec, ...@@ -356,42 +372,41 @@ int snd_hda_jack_add_kctls(struct hda_codec *codec,
const struct auto_pin_cfg *cfg) const struct auto_pin_cfg *cfg)
{ {
const hda_nid_t *p; const hda_nid_t *p;
int i, err, lastidx = 0; int i, err;
char lastname[44] = "";
for (i = 0, p = cfg->line_out_pins; i < cfg->line_outs; i++, p++) { for (i = 0, p = cfg->line_out_pins; i < cfg->line_outs; i++, p++) {
err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx); err = add_jack_kctl(codec, *p, cfg);
if (err < 0) if (err < 0)
return err; return err;
} }
for (i = 0, p = cfg->hp_pins; i < cfg->hp_outs; i++, p++) { for (i = 0, p = cfg->hp_pins; i < cfg->hp_outs; i++, p++) {
if (*p == *cfg->line_out_pins) /* might be duplicated */ if (*p == *cfg->line_out_pins) /* might be duplicated */
break; break;
err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx); err = add_jack_kctl(codec, *p, cfg);
if (err < 0) if (err < 0)
return err; return err;
} }
for (i = 0, p = cfg->speaker_pins; i < cfg->speaker_outs; i++, p++) { for (i = 0, p = cfg->speaker_pins; i < cfg->speaker_outs; i++, p++) {
if (*p == *cfg->line_out_pins) /* might be duplicated */ if (*p == *cfg->line_out_pins) /* might be duplicated */
break; break;
err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx); err = add_jack_kctl(codec, *p, cfg);
if (err < 0) if (err < 0)
return err; return err;
} }
for (i = 0; i < cfg->num_inputs; i++) { for (i = 0; i < cfg->num_inputs; i++) {
err = add_jack_kctl(codec, cfg->inputs[i].pin, cfg, lastname, &lastidx); err = add_jack_kctl(codec, cfg->inputs[i].pin, cfg);
if (err < 0) if (err < 0)
return err; return err;
} }
for (i = 0, p = cfg->dig_out_pins; i < cfg->dig_outs; i++, p++) { for (i = 0, p = cfg->dig_out_pins; i < cfg->dig_outs; i++, p++) {
err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx); err = add_jack_kctl(codec, *p, cfg);
if (err < 0) if (err < 0)
return err; return err;
} }
err = add_jack_kctl(codec, cfg->dig_in_pin, cfg, lastname, &lastidx); err = add_jack_kctl(codec, cfg->dig_in_pin, cfg);
if (err < 0) if (err < 0)
return err; return err;
err = add_jack_kctl(codec, cfg->mono_out_pin, cfg, lastname, &lastidx); err = add_jack_kctl(codec, cfg->mono_out_pin, cfg);
if (err < 0) if (err < 0)
return err; return err;
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment