aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2011-12-07 11:20:30 -0500
committerTakashi Iwai <tiwai@suse.de>2011-12-07 11:32:24 -0500
commit0a34b42b6245ccc710be6759cded5b7fe41ea1f9 (patch)
tree22bcae44ec79d4cdac2b9f5548db63b3a776364f /sound
parentfbabc24619f7298626265a3f973786b471b8c29d (diff)
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 <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r--sound/pci/hda/patch_realtek.c37
1 files changed, 30 insertions, 7 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 214d4f91d6af..1d07e8fa2433 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -2906,7 +2906,7 @@ static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
2906 if (!nid) 2906 if (!nid)
2907 continue; 2907 continue;
2908 if (found_in_nid_list(nid, spec->multiout.dac_nids, 2908 if (found_in_nid_list(nid, spec->multiout.dac_nids,
2909 spec->multiout.num_dacs)) 2909 ARRAY_SIZE(spec->private_dac_nids)))
2910 continue; 2910 continue;
2911 if (found_in_nid_list(nid, spec->multiout.hp_out_nid, 2911 if (found_in_nid_list(nid, spec->multiout.hp_out_nid,
2912 ARRAY_SIZE(spec->multiout.hp_out_nid))) 2912 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)
2927 return 0; 2927 return 0;
2928} 2928}
2929 2929
2930/* return 0 if no possible DAC is found, 1 if one or more found */
2930static int alc_auto_fill_extra_dacs(struct hda_codec *codec, int num_outs, 2931static int alc_auto_fill_extra_dacs(struct hda_codec *codec, int num_outs,
2931 const hda_nid_t *pins, hda_nid_t *dacs) 2932 const hda_nid_t *pins, hda_nid_t *dacs)
2932{ 2933{
@@ -2944,7 +2945,7 @@ static int alc_auto_fill_extra_dacs(struct hda_codec *codec, int num_outs,
2944 if (!dacs[i]) 2945 if (!dacs[i])
2945 dacs[i] = alc_auto_look_for_dac(codec, pins[i]); 2946 dacs[i] = alc_auto_look_for_dac(codec, pins[i]);
2946 } 2947 }
2947 return 0; 2948 return 1;
2948} 2949}
2949 2950
2950static int alc_auto_fill_multi_ios(struct hda_codec *codec, 2951static 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,
2954static int alc_auto_fill_dac_nids(struct hda_codec *codec) 2955static int alc_auto_fill_dac_nids(struct hda_codec *codec)
2955{ 2956{
2956 struct alc_spec *spec = codec->spec; 2957 struct alc_spec *spec = codec->spec;
2957 const struct auto_pin_cfg *cfg = &spec->autocfg; 2958 struct auto_pin_cfg *cfg = &spec->autocfg;
2958 bool redone = false; 2959 bool redone = false;
2959 int i; 2960 int i;
2960 2961
@@ -2965,6 +2966,7 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec)
2965 spec->multiout.extra_out_nid[0] = 0; 2966 spec->multiout.extra_out_nid[0] = 0;
2966 memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids)); 2967 memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
2967 spec->multiout.dac_nids = spec->private_dac_nids; 2968 spec->multiout.dac_nids = spec->private_dac_nids;
2969 spec->multi_ios = 0;
2968 2970
2969 /* fill hard-wired DACs first */ 2971 /* fill hard-wired DACs first */
2970 if (!redone) { 2972 if (!redone) {
@@ -2998,10 +3000,12 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec)
2998 for (i = 0; i < cfg->line_outs; i++) { 3000 for (i = 0; i < cfg->line_outs; i++) {
2999 if (spec->private_dac_nids[i]) 3001 if (spec->private_dac_nids[i])
3000 spec->multiout.num_dacs++; 3002 spec->multiout.num_dacs++;
3001 else 3003 else {
3002 memmove(spec->private_dac_nids + i, 3004 memmove(spec->private_dac_nids + i,
3003 spec->private_dac_nids + i + 1, 3005 spec->private_dac_nids + i + 1,
3004 sizeof(hda_nid_t) * (cfg->line_outs - i - 1)); 3006 sizeof(hda_nid_t) * (cfg->line_outs - i - 1));
3007 spec->private_dac_nids[cfg->line_outs - 1] = 0;
3008 }
3005 } 3009 }
3006 3010
3007 if (cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { 3011 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)
3023 if (cfg->line_out_type != AUTO_PIN_HP_OUT) 3027 if (cfg->line_out_type != AUTO_PIN_HP_OUT)
3024 alc_auto_fill_extra_dacs(codec, cfg->hp_outs, cfg->hp_pins, 3028 alc_auto_fill_extra_dacs(codec, cfg->hp_outs, cfg->hp_pins,
3025 spec->multiout.hp_out_nid); 3029 spec->multiout.hp_out_nid);
3026 if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) 3030 if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
3027 alc_auto_fill_extra_dacs(codec, cfg->speaker_outs, cfg->speaker_pins, 3031 int err = alc_auto_fill_extra_dacs(codec, cfg->speaker_outs,
3028 spec->multiout.extra_out_nid); 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 }
3029 3052
3030 return 0; 3053 return 0;
3031} 3054}