At Wed, 7 Oct 2009 15:34:59 -0500 (CDT), manoj.iyer@canonical.com wrote:
Takashi San,
Like I reported earlier, the patch you mailed me (See patch below) breaks sound on Toshiba NB200/205 again, even with my quirk.
This can't be. The patch I sent changes only the auto-parser, so with the quirk it must be skipped.
Any chance that we can work on getting this fixed? If you point me in the right direction I can dig into this some, also, mainline http://kernel.ubuntu.com/~kernel-ppa/mainline/v2.6.32-rc1/ does not work. iirc, you mentioned that this patch made it into mainline as well.
Try 2.6.32-rc3 as is. If it doesn't work, please give alsa-info.sh output back.
thanks,
Takashi
Thanks
On Thu, 1 Oct 2009, Takashi Iwai wrote:
At Thu, 01 Oct 2009 10:26:05 +0200, I wrote:
At Thu, 1 Oct 2009 02:11:35 -0500 (CDT), manoj.iyer@canonical.com wrote:
2.6.31.x is way too old for testing the new stuff :) Any chance to test 2.6.32-rc1?
http://kernel.ubuntu.com/~kernel-ppa/mainline/v2.6.32-rc1/
I tried the 2.6.32-rc1 today, and sound does not work for me on the NB200.
OK, thanks for checking. After looking at the code a bit more deeply, it turned out that the BIOS auto-parser doesn't work with this particular configuration (the speaker with mono pin 0x17).
I'm going to fix it later, but I applied your patch as the quick fix for the time being.
Could you try the patch below with model=auto? This will make the auto-parser working, hopefully.
thanks,
Takashi
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 87da5e8..7810d3d 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -17146,70 +17146,145 @@ static struct alc_config_preset alc662_presets[] = {
- BIOS auto configuration
*/
+/* convert from MIX nid to DAC */ +static inline hda_nid_t alc662_mix_to_dac(hda_nid_t nid) +{
- if (nid == 0x0f)
return 0x02;
- else if (nid >= 0x0c && nid <= 0x0e)
return nid - 0x0c + 0x02;
- else
return 0;
+}
+/* get MIX nid connected to the given pin targeted to DAC */ +static hda_nid_t alc662_dac_to_mix(struct hda_codec *codec, hda_nid_t pin,
hda_nid_t dac)
+{
- hda_nid_t mix[4];
- int i, num;
- num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
- for (i = 0; i < num; i++) {
if (alc662_mix_to_dac(mix[i]) == dac)
return mix[i];
- }
- return 0;
+}
+/* look for an empty DAC slot */ +static hda_nid_t alc662_look_for_dac(struct hda_codec *codec, hda_nid_t pin) +{
- struct alc_spec *spec = codec->spec;
- hda_nid_t srcs[5];
- int i, j, num;
- num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs));
- if (num < 0)
return 0;
- for (i = 0; i < num; i++) {
hda_nid_t nid = alc662_mix_to_dac(srcs[i]);
if (!nid)
continue;
for (j = 0; j < spec->multiout.num_dacs; j++)
if (spec->multiout.dac_nids[j] == nid)
break;
if (j >= spec->multiout.num_dacs)
return nid;
- }
- return 0;
+}
+/* fill in the dac_nids table from the parsed pin configuration */ +static int alc662_auto_fill_dac_nids(struct hda_codec *codec,
const struct auto_pin_cfg *cfg)
+{
- struct alc_spec *spec = codec->spec;
- int i;
- hda_nid_t dac;
- spec->multiout.dac_nids = spec->private_dac_nids;
- for (i = 0; i < cfg->line_outs; i++) {
dac = alc662_look_for_dac(codec, cfg->line_out_pins[i]);
if (!dac)
continue;
spec->multiout.dac_nids[spec->multiout.num_dacs++] = dac;
- }
- return 0;
+}
+static int alc662_add_vol_ctl(struct alc_spec *spec, const char *pfx,
hda_nid_t nid, unsigned int chs)
+{
- char name[32];
- sprintf(name, "%s Playback Volume", pfx);
- return add_control(spec, ALC_CTL_WIDGET_VOL, name,
HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));
+}
+static int alc662_add_sw_ctl(struct alc_spec *spec, const char *pfx,
hda_nid_t nid, unsigned int chs)
+{
- char name[32];
- sprintf(name, "%s Playback Switch", pfx);
- return add_control(spec, ALC_CTL_WIDGET_MUTE, name,
HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_INPUT));
+}
+#define alc662_add_stereo_vol(spec, pfx, nid) \
- alc662_add_vol_ctl(spec, pfx, nid, 3)
+#define alc662_add_stereo_sw(spec, pfx, nid) \
- alc662_add_sw_ctl(spec, pfx, nid, 3)
/* add playback controls from the parsed DAC table */ -static int alc662_auto_create_multi_out_ctls(struct alc_spec *spec, +static int alc662_auto_create_multi_out_ctls(struct hda_codec *codec, const struct auto_pin_cfg *cfg) {
- char name[32];
- struct alc_spec *spec = codec->spec; static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" };
- hda_nid_t nid;
hda_nid_t nid, mix; int i, err;
for (i = 0; i < cfg->line_outs; i++) {
if (!spec->multiout.dac_nids[i])
nid = spec->multiout.dac_nids[i];
if (!nid)
continue;
mix = alc662_dac_to_mix(codec, cfg->line_out_pins[i], nid);
if (!mix) continue;
if (i == 2) { /* Center/LFE */nid = alc880_idx_to_dac(i);
err = add_control(spec, ALC_CTL_WIDGET_VOL,
"Center Playback Volume",
HDA_COMPOSE_AMP_VAL(nid, 1, 0,
HDA_OUTPUT));
err = alc662_add_vol_ctl(spec, "Center", nid, 1); if (err < 0) return err;
err = add_control(spec, ALC_CTL_WIDGET_VOL,
"LFE Playback Volume",
HDA_COMPOSE_AMP_VAL(nid, 2, 0,
HDA_OUTPUT));
err = alc662_add_vol_ctl(spec, "LFE", nid, 2); if (err < 0) return err;
err = add_control(spec, ALC_CTL_WIDGET_MUTE,
"Center Playback Switch",
HDA_COMPOSE_AMP_VAL(0x0e, 1, 0,
HDA_INPUT));
err = alc662_add_sw_ctl(spec, "Center", mix, 1); if (err < 0) return err;
err = add_control(spec, ALC_CTL_WIDGET_MUTE,
"LFE Playback Switch",
HDA_COMPOSE_AMP_VAL(0x0e, 2, 0,
HDA_INPUT));
} else { const char *pfx; if (cfg->line_outs == 1 && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {err = alc662_add_sw_ctl(spec, "LFE", mix, 2); if (err < 0) return err;
if (!cfg->hp_pins)
if (cfg->hp_outs) pfx = "Speaker"; else pfx = "PCM"; } else pfx = chname[i];
sprintf(name, "%s Playback Volume", pfx);
err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
HDA_COMPOSE_AMP_VAL(nid, 3, 0,
HDA_OUTPUT));
err = alc662_add_vol_ctl(spec, pfx, nid, 3); if (err < 0) return err; if (cfg->line_outs == 1 && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) pfx = "Speaker";
sprintf(name, "%s Playback Switch", pfx);
err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
HDA_COMPOSE_AMP_VAL(alc880_idx_to_mixer(i),
3, 0, HDA_INPUT));
}err = alc662_add_sw_ctl(spec, pfx, mix, 3); if (err < 0) return err;
@@ -17218,54 +17293,38 @@ static int alc662_auto_create_multi_out_ctls(struct alc_spec *spec, }
/* add playback controls for speaker and HP outputs */ -static int alc662_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin, +/* return DAC nid if any new DAC is assigned */ +static int alc662_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin, const char *pfx) {
- hda_nid_t nid;
- struct alc_spec *spec = codec->spec;
- hda_nid_t nid, mix; int err;
char name[32];
if (!pin) return 0;
if (pin == 0x17) {
/* ALC663 has a mono output pin on 0x17 */
- nid = alc662_look_for_dac(codec, pin);
- if (!nid) {
char name[32];
/* the corresponding DAC is already occupied */
if (!(get_wcaps(codec, pin) & AC_WCAP_OUT_AMP))
return 0; /* no way */
sprintf(name, "%s Playback Switch", pfx);/* create a switch only */
err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
HDA_COMPOSE_AMP_VAL(pin, 2, 0, HDA_OUTPUT));
return err;
return add_control(spec, ALC_CTL_WIDGET_MUTE, name,
}HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
- if (alc880_is_fixed_pin(pin)) {
nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
/* printk(KERN_DEBUG "DAC nid=%x\n",nid); */
/* specify the DAC as the extra output */
if (!spec->multiout.hp_nid)
spec->multiout.hp_nid = nid;
else
spec->multiout.extra_out_nid[0] = nid;
/* control HP volume/switch on the output mixer amp */
nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
sprintf(name, "%s Playback Volume", pfx);
err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
if (err < 0)
return err;
sprintf(name, "%s Playback Switch", pfx);
err = add_control(spec, ALC_CTL_BIND_MUTE, name,
HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT));
if (err < 0)
return err;
- } else if (alc880_is_multi_pin(pin)) {
/* set manual connection */
/* we have only a switch on HP-out PIN */
sprintf(name, "%s Playback Switch", pfx);
err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
if (err < 0)
return err;
- }
- return 0;
- mix = alc662_dac_to_mix(codec, pin, nid);
- if (!mix)
return 0;
- err = alc662_add_vol_ctl(spec, pfx, nid, 3);
- if (err < 0)
return err;
- err = alc662_add_sw_ctl(spec, pfx, mix, 3);
- if (err < 0)
return err;
- return nid;
}
/* create playback/capture controls for input pins */ @@ -17274,30 +17333,35 @@ static int alc662_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin,
static void alc662_auto_set_output_and_unmute(struct hda_codec *codec, hda_nid_t nid, int pin_type,
int dac_idx)
hda_nid_t dac)
{
- int i, num;
- hda_nid_t srcs[4];
- alc_set_pin_output(codec, nid, pin_type); /* need the manual connection? */
- if (alc880_is_multi_pin(nid)) {
struct alc_spec *spec = codec->spec;
int idx = alc880_multi_pin_idx(nid);
snd_hda_codec_write(codec, alc880_idx_to_selector(idx), 0,
AC_VERB_SET_CONNECT_SEL,
alc880_dac_to_idx(spec->multiout.dac_nids[dac_idx]));
- num = snd_hda_get_connections(codec, nid, srcs, ARRAY_SIZE(srcs));
- if (num <= 1)
return;
- for (i = 0; i < num; i++) {
if (alc662_mix_to_dac(srcs[i]) != dac)
continue;
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, i);
}return;
}
static void alc662_auto_init_multi_out(struct hda_codec *codec) { struct alc_spec *spec = codec->spec;
int pin_type = get_pin_type(spec->autocfg.line_out_type); int i;
for (i = 0; i <= HDA_SIDE; i++) { hda_nid_t nid = spec->autocfg.line_out_pins[i];
if (nid) alc662_auto_set_output_and_unmute(codec, nid, pin_type,int pin_type = get_pin_type(spec->autocfg.line_out_type);
i);
}spec->multiout.dac_nids[i]);
}
@@ -17307,12 +17371,13 @@ static void alc662_auto_init_hp_out(struct hda_codec *codec) hda_nid_t pin;
pin = spec->autocfg.hp_pins[0];
- if (pin) /* connect to front */
/* use dac 0 */
alc662_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
- if (pin)
alc662_auto_set_output_and_unmute(codec, pin, PIN_HP,
pin = spec->autocfg.speaker_pins[0]; if (pin)spec->multiout.hp_nid);
alc662_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
alc662_auto_set_output_and_unmute(codec, pin, PIN_OUT,
spec->multiout.extra_out_nid[0]);
}
#define ALC662_PIN_CD_NID ALC880_PIN_CD_NID @@ -17350,21 +17415,25 @@ static int alc662_parse_auto_config(struct hda_codec *codec) if (!spec->autocfg.line_outs) return 0; /* can't find valid BIOS pin config */
- err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);
- err = alc662_auto_fill_dac_nids(codec, &spec->autocfg); if (err < 0) return err;
- err = alc662_auto_create_multi_out_ctls(spec, &spec->autocfg);
- err = alc662_auto_create_multi_out_ctls(codec, &spec->autocfg); if (err < 0) return err;
- err = alc662_auto_create_extra_out(spec,
- err = alc662_auto_create_extra_out(codec, spec->autocfg.speaker_pins[0], "Speaker"); if (err < 0) return err;
- err = alc662_auto_create_extra_out(spec, spec->autocfg.hp_pins[0],
- if (err)
spec->multiout.extra_out_nid[0] = err;
- err = alc662_auto_create_extra_out(codec, spec->autocfg.hp_pins[0], "Headphone"); if (err < 0) return err;
- if (err)
err = alc662_auto_create_input_ctls(codec, &spec->autocfg); if (err < 0) return err;spec->multiout.hp_nid = err;