Skip to content

Commit 0a34b42

Browse files
committed
ALSA: hda/realtek - Fix lost speaker volume controls
When there are the same or more number of HP pins are available, HP pins are used as the primary outputs instead of the speaker pins. But, in some cases (especially with ALC663 & co), some DACs are available only with a later pin and it's assigned to a speaker, and since the driver parses the pins from the lower NID, such a DAC was skipped eventually without assignments. This resulted in a regression, the missing speaker volume control in the new parser. As a workaround for this, now the driver retries the pin->DAC mapping again after restoring the speaker-pins as primary. This is still an ad hoc fix, but it works so far for most of Realtek codecs. Signed-off-by: Takashi Iwai <[email protected]>
1 parent fbabc24 commit 0a34b42

File tree

1 file changed

+30
-7
lines changed

1 file changed

+30
-7
lines changed

sound/pci/hda/patch_realtek.c

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2906,7 +2906,7 @@ static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
29062906
if (!nid)
29072907
continue;
29082908
if (found_in_nid_list(nid, spec->multiout.dac_nids,
2909-
spec->multiout.num_dacs))
2909+
ARRAY_SIZE(spec->private_dac_nids)))
29102910
continue;
29112911
if (found_in_nid_list(nid, spec->multiout.hp_out_nid,
29122912
ARRAY_SIZE(spec->multiout.hp_out_nid)))
@@ -2927,6 +2927,7 @@ static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin)
29272927
return 0;
29282928
}
29292929

2930+
/* return 0 if no possible DAC is found, 1 if one or more found */
29302931
static int alc_auto_fill_extra_dacs(struct hda_codec *codec, int num_outs,
29312932
const hda_nid_t *pins, hda_nid_t *dacs)
29322933
{
@@ -2944,7 +2945,7 @@ static int alc_auto_fill_extra_dacs(struct hda_codec *codec, int num_outs,
29442945
if (!dacs[i])
29452946
dacs[i] = alc_auto_look_for_dac(codec, pins[i]);
29462947
}
2947-
return 0;
2948+
return 1;
29482949
}
29492950

29502951
static int alc_auto_fill_multi_ios(struct hda_codec *codec,
@@ -2954,7 +2955,7 @@ static int alc_auto_fill_multi_ios(struct hda_codec *codec,
29542955
static int alc_auto_fill_dac_nids(struct hda_codec *codec)
29552956
{
29562957
struct alc_spec *spec = codec->spec;
2957-
const struct auto_pin_cfg *cfg = &spec->autocfg;
2958+
struct auto_pin_cfg *cfg = &spec->autocfg;
29582959
bool redone = false;
29592960
int i;
29602961

@@ -2965,6 +2966,7 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec)
29652966
spec->multiout.extra_out_nid[0] = 0;
29662967
memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
29672968
spec->multiout.dac_nids = spec->private_dac_nids;
2969+
spec->multi_ios = 0;
29682970

29692971
/* fill hard-wired DACs first */
29702972
if (!redone) {
@@ -2998,10 +3000,12 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec)
29983000
for (i = 0; i < cfg->line_outs; i++) {
29993001
if (spec->private_dac_nids[i])
30003002
spec->multiout.num_dacs++;
3001-
else
3003+
else {
30023004
memmove(spec->private_dac_nids + i,
30033005
spec->private_dac_nids + i + 1,
30043006
sizeof(hda_nid_t) * (cfg->line_outs - i - 1));
3007+
spec->private_dac_nids[cfg->line_outs - 1] = 0;
3008+
}
30053009
}
30063010

30073011
if (cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
@@ -3023,9 +3027,28 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec)
30233027
if (cfg->line_out_type != AUTO_PIN_HP_OUT)
30243028
alc_auto_fill_extra_dacs(codec, cfg->hp_outs, cfg->hp_pins,
30253029
spec->multiout.hp_out_nid);
3026-
if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
3027-
alc_auto_fill_extra_dacs(codec, cfg->speaker_outs, cfg->speaker_pins,
3028-
spec->multiout.extra_out_nid);
3030+
if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
3031+
int err = alc_auto_fill_extra_dacs(codec, cfg->speaker_outs,
3032+
cfg->speaker_pins,
3033+
spec->multiout.extra_out_nid);
3034+
/* if no speaker volume is assigned, try again as the primary
3035+
* output
3036+
*/
3037+
if (!err && cfg->speaker_outs > 0 &&
3038+
cfg->line_out_type == AUTO_PIN_HP_OUT) {
3039+
cfg->hp_outs = cfg->line_outs;
3040+
memcpy(cfg->hp_pins, cfg->line_out_pins,
3041+
sizeof(cfg->hp_pins));
3042+
cfg->line_outs = cfg->speaker_outs;
3043+
memcpy(cfg->line_out_pins, cfg->speaker_pins,
3044+
sizeof(cfg->speaker_pins));
3045+
cfg->speaker_outs = 0;
3046+
memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
3047+
cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
3048+
redone = false;
3049+
goto again;
3050+
}
3051+
}
30293052

30303053
return 0;
30313054
}

0 commit comments

Comments
 (0)