/* ALC268 models */
enum {
ALC268_3ST,
+ ALC268_TOSHIBA,
+ ALC268_ACER,
ALC268_AUTO,
ALC268_MODEL_LAST /* last tag */
};
ALC861VD_6ST_DIG,
ALC861VD_LENOVO,
ALC861VD_DALLAS,
+ ALC861VD_HP,
ALC861VD_AUTO,
ALC861VD_MODEL_LAST,
};
ALC883_TARGA_DIG,
ALC883_TARGA_2ch_DIG,
ALC883_ACER,
+ ALC883_ACER_ASPIRE,
ALC883_MEDION,
ALC883_MEDION_MD2,
ALC883_LAPTOP_EAPD,
/* for pin sensing */
unsigned int sense_updated: 1;
unsigned int jack_present: 1;
+
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ struct hda_loopback_check loopback;
+#endif
};
/*
const struct hda_input_mux *input_mux;
void (*unsol_event)(struct hda_codec *, unsigned int);
void (*init_hook)(struct hda_codec *);
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ struct hda_amp_list *loopbacks;
+#endif
};
change = pinctl != alc_pin_mode_values[val];
if (change) {
/* Set pin mode to that requested */
- snd_hda_codec_write(codec,nid,0,AC_VERB_SET_PIN_WIDGET_CONTROL,
- alc_pin_mode_values[val]);
+ snd_hda_codec_write_cache(codec, nid, 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL,
+ alc_pin_mode_values[val]);
/* Also enable the retasking pin's input/output as required
* for the requested pin mode. Enum values of 2 or less are
* this turns out to be necessary in the future.
*/
if (val <= 2) {
- snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_AMP_GAIN_MUTE,
- AMP_OUT_MUTE);
- snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_AMP_GAIN_MUTE,
- AMP_IN_UNMUTE(0));
+ snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, HDA_AMP_MUTE);
+ snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,
+ HDA_AMP_MUTE, 0);
} else {
- snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_AMP_GAIN_MUTE,
- AMP_IN_MUTE(0));
- snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_AMP_GAIN_MUTE,
- AMP_OUT_UNMUTE);
+ snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,
+ HDA_AMP_MUTE, HDA_AMP_MUTE);
+ snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, 0);
}
}
return change;
* needed for any "production" models.
*/
#ifdef CONFIG_SND_DEBUG
-static int alc_gpio_data_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define alc_gpio_data_info snd_ctl_boolean_mono_info
static int alc_gpio_data_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
gpio_data &= ~mask;
else
gpio_data |= mask;
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_GPIO_DATA, gpio_data);
+ snd_hda_codec_write_cache(codec, nid, 0,
+ AC_VERB_SET_GPIO_DATA, gpio_data);
return change;
}
* necessary.
*/
#ifdef CONFIG_SND_DEBUG
-static int alc_spdif_ctrl_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
+#define alc_spdif_ctrl_info snd_ctl_boolean_mono_info
static int alc_spdif_ctrl_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
ctrl_data &= ~mask;
else
ctrl_data |= mask;
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
- ctrl_data);
+ snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
+ ctrl_data);
return change;
}
spec->unsol_event = preset->unsol_event;
spec->init_hook = preset->init_hook;
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ spec->loopback.amplist = preset->loopbacks;
+#endif
}
/* Enable GPIO mask and set output */
* panel mic (mic 2)
*/
/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
/*
* Set up output mixers (0x0c - 0x0f)
present = snd_hda_codec_read(codec, 0x14, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- bits = present ? 0x80 : 0;
- snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
- 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
- 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x16, 0, HDA_OUTPUT, 0,
- 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x16, 1, HDA_OUTPUT, 0,
- 0x80, bits);
+ bits = present ? HDA_AMP_MUTE : 0;
+ snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, bits);
+ snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, bits);
}
/* auto-toggle front mic */
present = snd_hda_codec_read(codec, 0x18, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- bits = present ? 0x80 : 0;
- snd_hda_codec_amp_update(codec, 0x0b, 0, HDA_INPUT, 1,
- 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x0b, 1, HDA_INPUT, 1,
- 0x80, bits);
+ bits = present ? HDA_AMP_MUTE : 0;
+ snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1, HDA_AMP_MUTE, bits);
}
static void alc880_uniwill_automute(struct hda_codec *codec)
present = snd_hda_codec_read(codec, 0x14, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- bits = present ? 0x80 : 0;
- snd_hda_codec_amp_update(codec, 0x15, 0, HDA_INPUT, 0,
- 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x15, 1, HDA_INPUT, 0,
- 0x80, bits);
+ bits = present ? HDA_AMP_MUTE : 0;
+ snd_hda_codec_amp_stereo(codec, 0x15, HDA_INPUT, 0, HDA_AMP_MUTE, bits);
}
static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec)
unsigned int present;
present = snd_hda_codec_read(codec, 0x21, 0,
- AC_VERB_GET_VOLUME_KNOB_CONTROL, 0) & 0x7f;
-
- snd_hda_codec_amp_update(codec, 0x0c, 0, HDA_OUTPUT, 0,
- 0x7f, present);
- snd_hda_codec_amp_update(codec, 0x0c, 1, HDA_OUTPUT, 0,
- 0x7f, present);
-
- snd_hda_codec_amp_update(codec, 0x0d, 0, HDA_OUTPUT, 0,
- 0x7f, present);
- snd_hda_codec_amp_update(codec, 0x0d, 1, HDA_OUTPUT, 0,
- 0x7f, present);
-
+ AC_VERB_GET_VOLUME_KNOB_CONTROL, 0);
+ present &= HDA_AMP_VOLMASK;
+ snd_hda_codec_amp_stereo(codec, 0x0c, HDA_OUTPUT, 0,
+ HDA_AMP_VOLMASK, present);
+ snd_hda_codec_amp_stereo(codec, 0x0d, HDA_OUTPUT, 0,
+ HDA_AMP_VOLMASK, present);
}
+
static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec,
unsigned int res)
{
{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
/* mute all amp mixer inputs */
{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(6)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(7)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
/* line-in to input */
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
present = snd_hda_codec_read(codec, 0x1b, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- bits = present ? 0x80 : 0;
- snd_hda_codec_amp_update(codec, 0x17, 0, HDA_OUTPUT, 0,
- 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x17, 1, HDA_OUTPUT, 0,
- 0x80, bits);
+ bits = present ? HDA_AMP_MUTE : 0;
+ snd_hda_codec_amp_stereo(codec, 0x17, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, bits);
}
static void alc880_lg_unsol_event(struct hda_codec *codec, unsigned int res)
{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(7)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
/* speaker-out */
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
present = snd_hda_codec_read(codec, 0x1b, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- bits = present ? 0x80 : 0;
- snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
- 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
- 0x80, bits);
+ bits = present ? HDA_AMP_MUTE : 0;
+ snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, bits);
}
static void alc880_lg_lw_unsol_event(struct hda_codec *codec, unsigned int res)
alc880_lg_lw_automute(codec);
}
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static struct hda_amp_list alc880_loopbacks[] = {
+ { 0x0b, HDA_INPUT, 0 },
+ { 0x0b, HDA_INPUT, 1 },
+ { 0x0b, HDA_INPUT, 2 },
+ { 0x0b, HDA_INPUT, 3 },
+ { 0x0b, HDA_INPUT, 4 },
+ { } /* end */
+};
+
+static struct hda_amp_list alc880_lg_loopbacks[] = {
+ { 0x0b, HDA_INPUT, 1 },
+ { 0x0b, HDA_INPUT, 6 },
+ { 0x0b, HDA_INPUT, 7 },
+ { } /* end */
+};
+#endif
+
/*
* Common callbacks
*/
spec->unsol_event(codec, res);
}
-#ifdef CONFIG_PM
-/*
- * resume
- */
-static int alc_resume(struct hda_codec *codec)
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static int alc_check_power_status(struct hda_codec *codec, hda_nid_t nid)
{
struct alc_spec *spec = codec->spec;
- int i;
-
- alc_init(codec);
- for (i = 0; i < spec->num_mixers; i++)
- snd_hda_resume_ctls(codec, spec->mixers[i]);
- if (spec->multiout.dig_out_nid)
- snd_hda_resume_spdif_out(codec);
- if (spec->dig_in_nid)
- snd_hda_resume_spdif_in(codec);
-
- return 0;
+ return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
}
#endif
.init = alc_init,
.free = alc_free,
.unsol_event = alc_unsol_event,
-#ifdef CONFIG_PM
- .resume = alc_resume,
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ .check_power_status = alc_check_power_status,
#endif
};
AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
new_ctl = ctls[ucontrol->value.enumerated.item[0]];
if (old_ctl != new_ctl) {
- snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, new_ctl);
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
- (ucontrol->value.enumerated.item[0] >= 3 ?
- 0xb080 : 0xb000));
+ int val;
+ snd_hda_codec_write_cache(codec, nid, 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL,
+ new_ctl);
+ val = ucontrol->value.enumerated.item[0] >= 3 ?
+ HDA_AMP_MUTE : 0;
+ snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, val);
return 1;
}
return 0;
sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0) & 3;
if (ucontrol->value.enumerated.item[0] != sel) {
sel = ucontrol->value.enumerated.item[0] & 3;
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, sel);
+ snd_hda_codec_write_cache(codec, nid, 0,
+ AC_VERB_SET_CONNECT_SEL, sel);
return 1;
}
return 0;
.input_mux = &alc880_lg_capture_source,
.unsol_event = alc880_lg_unsol_event,
.init_hook = alc880_lg_automute,
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ .loopbacks = alc880_lg_loopbacks,
+#endif
},
[ALC880_LG_LW] = {
.mixers = { alc880_lg_lw_mixer },
codec->patch_ops = alc_patch_ops;
if (board_config == ALC880_AUTO)
spec->init_hook = alc880_auto_init;
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ if (!spec->loopback.amplist)
+ spec->loopback.amplist = alc880_loopbacks;
+#endif
return 0;
}
/* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 &
* Line In 2 = 0x03
*/
- /* mute CD */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
- /* mute Line In */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
- /* mute Mic */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ /* mute analog inputs */
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
/* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
/* mute Front out path */
{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
/* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 &
* Line In 2 = 0x03
*/
- /* unmute CD */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
- /* unmute Line In */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
- /* unmute Mic */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ /* mute analog inputs */
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
/* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
/* Unmute Front out path */
{0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
/* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 &
* Line In 2 = 0x03
*/
- /* unmute CD */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
- /* unmute Line In */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
- /* unmute Mic */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ /* mute analog inputs */
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
/* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
/* Unmute Front out path */
{0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
present = snd_hda_codec_read(codec, 0x0f, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
if (present) {
- snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 1);
- snd_hda_codec_write(codec, 0x0f, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP);
+ snd_hda_codec_write_cache(codec, 0x01, 0,
+ AC_VERB_SET_GPIO_DATA, 1);
+ snd_hda_codec_write_cache(codec, 0x0f, 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL,
+ PIN_HP);
} else {
- snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 0);
- snd_hda_codec_write(codec, 0x0f, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
+ snd_hda_codec_write_cache(codec, 0x01, 0,
+ AC_VERB_SET_GPIO_DATA, 0);
+ snd_hda_codec_write_cache(codec, 0x0f, 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL,
+ PIN_OUT);
}
}
* front panel mic (mic 2)
*/
/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
+ /* mute analog inputs */
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
/*
* Set up output mixers (0x08 - 0x0a)
alc260_auto_init_analog_input(codec);
}
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static struct hda_amp_list alc260_loopbacks[] = {
+ { 0x07, HDA_INPUT, 0 },
+ { 0x07, HDA_INPUT, 1 },
+ { 0x07, HDA_INPUT, 2 },
+ { 0x07, HDA_INPUT, 3 },
+ { 0x07, HDA_INPUT, 4 },
+ { } /* end */
+};
+#endif
+
/*
* ALC260 configurations
*/
codec->patch_ops = alc_patch_ops;
if (board_config == ALC260_AUTO)
spec->init_hook = alc260_auto_init;
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ if (!spec->loopback.amplist)
+ spec->loopback.amplist = alc260_loopbacks;
+#endif
return 0;
}
idx = ucontrol->value.enumerated.item[0];
if (idx >= imux->num_items)
idx = imux->num_items - 1;
- if (*cur_val == idx && !codec->in_resume)
+ if (*cur_val == idx)
return 0;
for (i = 0; i < imux->num_items; i++) {
- unsigned int v = (i == idx) ? 0x7000 : 0x7080;
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
- v | (imux->items[i].index << 8));
+ unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;
+ snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,
+ imux->items[i].index,
+ HDA_AMP_MUTE, v);
}
*cur_val = idx;
return 1;
present = snd_hda_codec_read(codec, 0x14, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- snd_hda_codec_amp_update(codec, 0x18, 0, HDA_OUTPUT, 0,
- 0x80, present ? 0x80 : 0);
- snd_hda_codec_amp_update(codec, 0x18, 1, HDA_OUTPUT, 0,
- 0x80, present ? 0x80 : 0);
- snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_OUTPUT, 0,
- 0x80, present ? 0x80 : 0);
- snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_OUTPUT, 0,
- 0x80, present ? 0x80 : 0);
+ snd_hda_codec_amp_stereo(codec, 0x18, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
+ snd_hda_codec_amp_stereo(codec, 0x1a, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
}
/* Processes unsolicited events. */
present = snd_hda_codec_read(codec, 0x14, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- snd_hda_codec_amp_update(codec, 0x1b, 0, HDA_OUTPUT, 0,
- 0x80, present ? 0x80 : 0);
- snd_hda_codec_amp_update(codec, 0x1b, 1, HDA_OUTPUT, 0,
- 0x80, present ? 0x80 : 0);
- snd_hda_codec_write(codec, 1, 0, AC_VERB_SET_GPIO_DATA, present ? 1 : 3);
+ snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
+ snd_hda_codec_write_cache(codec, 1, 0, AC_VERB_SET_GPIO_DATA,
+ present ? 1 : 3);
}
static void alc882_targa_unsol_event(struct hda_codec *codec, unsigned int res)
AC_VERB_SET_GPIO_DATA, gpiostate);
}
+/* set up GPIO at initialization */
+static void alc885_macpro_init_hook(struct hda_codec *codec)
+{
+ alc882_gpio_mute(codec, 0, 0);
+ alc882_gpio_mute(codec, 1, 0);
+}
+
+/* set up GPIO and update auto-muting at initialization */
+static void alc885_imac24_init_hook(struct hda_codec *codec)
+{
+ alc885_macpro_init_hook(codec);
+ alc885_imac24_automute(codec);
+}
+
/*
* generic initialization of ADC, input mixers and output mixers
*/
{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
+ /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
* mixer widget
* Note: PASD motherboards uses the Line In 2 as the input for
* front panel mic (mic 2)
*/
/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
/*
* Set up output mixers (0x0c - 0x0f)
{ } /* end */
};
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+#define alc882_loopbacks alc880_loopbacks
+#endif
+
/* pcm configuration: identiacal with ALC880 */
#define alc882_pcm_analog_playback alc880_pcm_analog_playback
#define alc882_pcm_analog_capture alc880_pcm_analog_capture
.num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
.channel_mode = alc882_ch_modes,
.input_mux = &alc882_capture_source,
+ .init_hook = alc885_macpro_init_hook,
},
[ALC885_IMAC24] = {
.mixers = { alc885_imac24_mixer },
.channel_mode = alc882_ch_modes,
.input_mux = &alc882_capture_source,
.unsol_event = alc885_imac24_unsol_event,
- .init_hook = alc885_imac24_automute,
+ .init_hook = alc885_imac24_init_hook,
},
[ALC882_TARGA] = {
.mixers = { alc882_targa_mixer, alc882_chmode_mixer,
if (board_config != ALC882_AUTO)
setup_preset(spec, &alc882_presets[board_config]);
- if (board_config == ALC885_MACPRO || board_config == ALC885_IMAC24) {
- alc882_gpio_mute(codec, 0, 0);
- alc882_gpio_mute(codec, 1, 0);
- }
-
spec->stream_name_analog = "ALC882 Analog";
spec->stream_analog_playback = &alc882_pcm_analog_playback;
spec->stream_analog_capture = &alc882_pcm_analog_capture;
codec->patch_ops = alc_patch_ops;
if (board_config == ALC882_AUTO)
spec->init_hook = alc882_auto_init;
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ if (!spec->loopback.amplist)
+ spec->loopback.amplist = alc882_loopbacks;
+#endif
return 0;
}
idx = ucontrol->value.enumerated.item[0];
if (idx >= imux->num_items)
idx = imux->num_items - 1;
- if (*cur_val == idx && !codec->in_resume)
+ if (*cur_val == idx)
return 0;
for (i = 0; i < imux->num_items; i++) {
- unsigned int v = (i == idx) ? 0x7000 : 0x7080;
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
- v | (imux->items[i].index << 8));
+ unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;
+ snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,
+ imux->items[i].index,
+ HDA_AMP_MUTE, v);
}
*cur_val = idx;
return 1;
{ } /* end */
};
+static struct snd_kcontrol_new alc883_acer_aspire_mixer[] = {
+ HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+ HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+ HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+ HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+ HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
+ HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ /* .name = "Capture Source", */
+ .name = "Input Source",
+ .count = 2,
+ .info = alc883_mux_enum_info,
+ .get = alc883_mux_enum_get,
+ .put = alc883_mux_enum_put,
+ },
+ { } /* end */
+};
+
static struct snd_kcontrol_new alc883_chmode_mixer[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
+ /* mute analog input loopbacks */
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
/* Front Pin: output 0 (0x0c) */
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
present = snd_hda_codec_read(codec, 0x1b, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
- 0x80, present ? 0x80 : 0);
- snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
- 0x80, present ? 0x80 : 0);
- snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
- 0x80, present ? 0x80 : 0);
- snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
- 0x80, present ? 0x80 : 0);
-
+ snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
+ snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
}
/* toggle RCA according to the front-jack state */
present = snd_hda_codec_read(codec, 0x14, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
- 0x80, present ? 0x80 : 0);
- snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
- 0x80, present ? 0x80 : 0);
-
+ snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
}
+
static void alc883_lenovo_ms7195_unsol_event(struct hda_codec *codec,
unsigned int res)
{
present = snd_hda_codec_read(codec, 0x14, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
- 0x80, present ? 0x80 : 0);
- snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
- 0x80, present ? 0x80 : 0);
+ snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
}
static void alc883_medion_md2_unsol_event(struct hda_codec *codec,
present = snd_hda_codec_read(codec, 0x14, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- bits = present ? 0x80 : 0;
- snd_hda_codec_amp_update(codec, 0x1b, 0, HDA_OUTPUT, 0,
- 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x1b, 1, HDA_OUTPUT, 0,
- 0x80, bits);
- snd_hda_codec_write(codec, 1, 0, AC_VERB_SET_GPIO_DATA,
- present ? 1 : 3);
+ bits = present ? HDA_AMP_MUTE : 0;
+ snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, bits);
+ snd_hda_codec_write_cache(codec, 1, 0, AC_VERB_SET_GPIO_DATA,
+ present ? 1 : 3);
}
static void alc883_tagra_unsol_event(struct hda_codec *codec, unsigned int res)
present = snd_hda_codec_read(codec, 0x14, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- bits = present ? 0x80 : 0;
- snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
- 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
- 0x80, bits);
+ bits = present ? HDA_AMP_MUTE : 0;
+ snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, bits);
}
static void alc883_lenovo_101e_all_automute(struct hda_codec *codec)
present = snd_hda_codec_read(codec, 0x1b, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- bits = present ? 0x80 : 0;
- snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
- 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
- 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
- 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
- 0x80, bits);
+ bits = present ? HDA_AMP_MUTE : 0;
+ snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, bits);
+ snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, bits);
}
static void alc883_lenovo_101e_unsol_event(struct hda_codec *codec,
alc883_lenovo_101e_ispeaker_automute(codec);
}
+/* toggle speaker-output according to the hp-jack state */
+static void alc883_acer_aspire_automute(struct hda_codec *codec)
+{
+ unsigned int present;
+
+ present = snd_hda_codec_read(codec, 0x14, 0,
+ AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+ snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
+ snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
+}
+
+static void alc883_acer_aspire_unsol_event(struct hda_codec *codec,
+ unsigned int res)
+{
+ if ((res >> 26) == ALC880_HP_EVENT)
+ alc883_acer_aspire_automute(codec);
+}
+
+static struct hda_verb alc883_acer_eapd_verbs[] = {
+ /* HP Pin: output 0 (0x0c) */
+ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
+ /* Front Pin: output 0 (0x0c) */
+ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+ {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x16, AC_VERB_SET_CONNECT_SEL, 0x00},
+ /* eanable EAPD on medion laptop */
+ {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
+ {0x20, AC_VERB_SET_PROC_COEF, 0x3050},
+ /* enable unsolicited event */
+ {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
+ { }
+};
+
/*
* generic initialization of ADC, input mixers and output mixers
*/
{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
+ /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
* mixer widget
* Note: PASD motherboards uses the Line In 2 as the input for
* front panel mic (mic 2)
*/
/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
/*
* Set up output mixers (0x0c - 0x0f)
{ } /* end */
};
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+#define alc883_loopbacks alc880_loopbacks
+#endif
+
/* pcm configuration: identiacal with ALC880 */
#define alc883_pcm_analog_playback alc880_pcm_analog_playback
#define alc883_pcm_analog_capture alc880_pcm_analog_capture
[ALC883_TARGA_DIG] = "targa-dig",
[ALC883_TARGA_2ch_DIG] = "targa-2ch-dig",
[ALC883_ACER] = "acer",
+ [ALC883_ACER_ASPIRE] = "acer-aspire",
[ALC883_MEDION] = "medion",
[ALC883_MEDION_MD2] = "medion-md2",
[ALC883_LAPTOP_EAPD] = "laptop-eapd",
SND_PCI_QUIRK(0x1462, 0x3fcc, "MSI", ALC883_TARGA_DIG),
SND_PCI_QUIRK(0x1462, 0x3fc1, "MSI", ALC883_TARGA_DIG),
SND_PCI_QUIRK(0x1462, 0x3fc3, "MSI", ALC883_TARGA_DIG),
+ SND_PCI_QUIRK(0x1462, 0x3fdf, "MSI", ALC883_TARGA_DIG),
SND_PCI_QUIRK(0x1462, 0x4314, "MSI", ALC883_TARGA_DIG),
SND_PCI_QUIRK(0x1462, 0x4319, "MSI", ALC883_TARGA_DIG),
SND_PCI_QUIRK(0x1462, 0x4324, "MSI", ALC883_TARGA_DIG),
SND_PCI_QUIRK(0x1462, 0xa422, "MSI", ALC883_TARGA_2ch_DIG),
+ SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_ACER_ASPIRE),
+ SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_ACER_ASPIRE),
SND_PCI_QUIRK(0x1025, 0, "Acer laptop", ALC883_ACER),
SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch),
SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION),
.init_hook = alc883_tagra_automute,
},
[ALC883_ACER] = {
- .mixers = { alc883_base_mixer,
- alc883_chmode_mixer },
+ .mixers = { alc883_base_mixer },
/* On TravelMate laptops, GPIO 0 enables the internal speaker
* and the headphone jack. Turn this on and rely on the
* standard mute methods whenever the user wants to turn
.channel_mode = alc883_3ST_2ch_modes,
.input_mux = &alc883_capture_source,
},
+ [ALC883_ACER_ASPIRE] = {
+ .mixers = { alc883_acer_aspire_mixer },
+ .init_verbs = { alc883_init_verbs, alc883_acer_eapd_verbs },
+ .num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ .dac_nids = alc883_dac_nids,
+ .dig_out_nid = ALC883_DIGOUT_NID,
+ .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+ .adc_nids = alc883_adc_nids,
+ .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+ .channel_mode = alc883_3ST_2ch_modes,
+ .input_mux = &alc883_capture_source,
+ .unsol_event = alc883_acer_aspire_unsol_event,
+ .init_hook = alc883_acer_aspire_automute,
+ },
[ALC883_MEDION] = {
.mixers = { alc883_fivestack_mixer,
alc883_chmode_mixer },
.init_hook = alc883_medion_md2_automute,
},
[ALC883_LAPTOP_EAPD] = {
- .mixers = { alc883_base_mixer,
- alc883_chmode_mixer },
+ .mixers = { alc883_base_mixer },
.init_verbs = { alc883_init_verbs, alc882_eapd_verbs },
.num_dacs = ARRAY_SIZE(alc883_dac_nids),
.dac_nids = alc883_dac_nids,
codec->patch_ops = alc_patch_ops;
if (board_config == ALC883_AUTO)
spec->init_hook = alc883_auto_init;
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ if (!spec->loopback.amplist)
+ spec->loopback.amplist = alc883_loopbacks;
+#endif
return 0;
}
{ } /* end */
};
+static struct hda_bind_ctls alc262_sony_bind_sw = {
+ .ops = &snd_hda_bind_sw,
+ .values = {
+ HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT),
+ HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
+ 0,
+ },
+};
+
static struct snd_kcontrol_new alc262_sony_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+ HDA_BIND_SW("Front Playback Switch", &alc262_sony_bind_sw),
HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
+ /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
* mixer widget
* Note: PASD motherboards uses the Line In 2 as the input for
* front panel mic (mic 2)
*/
/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
/*
* Set up output mixers (0x0c - 0x0e)
};
/* mute/unmute internal speaker according to the hp jack and mute state */
-static void alc262_hippo_automute(struct hda_codec *codec, int force)
+static void alc262_hippo_automute(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
unsigned int mute;
+ unsigned int present;
- if (force || !spec->sense_updated) {
- unsigned int present;
- /* need to execute and sync at first */
- snd_hda_codec_read(codec, 0x15, 0, AC_VERB_SET_PIN_SENSE, 0);
- present = snd_hda_codec_read(codec, 0x15, 0,
- AC_VERB_GET_PIN_SENSE, 0);
- spec->jack_present = (present & 0x80000000) != 0;
- spec->sense_updated = 1;
- }
+ /* need to execute and sync at first */
+ snd_hda_codec_read(codec, 0x15, 0, AC_VERB_SET_PIN_SENSE, 0);
+ present = snd_hda_codec_read(codec, 0x15, 0,
+ AC_VERB_GET_PIN_SENSE, 0);
+ spec->jack_present = (present & 0x80000000) != 0;
if (spec->jack_present) {
/* mute internal speaker */
- snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
- 0x80, 0x80);
- snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
- 0x80, 0x80);
+ snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, HDA_AMP_MUTE);
} else {
/* unmute internal speaker if necessary */
mute = snd_hda_codec_amp_read(codec, 0x15, 0, HDA_OUTPUT, 0);
- snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
- 0x80, mute & 0x80);
- mute = snd_hda_codec_amp_read(codec, 0x15, 1, HDA_OUTPUT, 0);
- snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
- 0x80, mute & 0x80);
+ snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, mute);
}
}
{
if ((res >> 26) != ALC880_HP_EVENT)
return;
- alc262_hippo_automute(codec, 1);
+ alc262_hippo_automute(codec);
}
-static void alc262_hippo1_automute(struct hda_codec *codec, int force)
+static void alc262_hippo1_automute(struct hda_codec *codec)
{
- struct alc_spec *spec = codec->spec;
unsigned int mute;
+ unsigned int present;
- if (force || !spec->sense_updated) {
- unsigned int present;
- /* need to execute and sync at first */
- snd_hda_codec_read(codec, 0x1b, 0, AC_VERB_SET_PIN_SENSE, 0);
- present = snd_hda_codec_read(codec, 0x1b, 0,
- AC_VERB_GET_PIN_SENSE, 0);
- spec->jack_present = (present & 0x80000000) != 0;
- spec->sense_updated = 1;
- }
- if (spec->jack_present) {
+ snd_hda_codec_read(codec, 0x1b, 0, AC_VERB_SET_PIN_SENSE, 0);
+ present = snd_hda_codec_read(codec, 0x1b, 0,
+ AC_VERB_GET_PIN_SENSE, 0);
+ present = (present & 0x80000000) != 0;
+ if (present) {
/* mute internal speaker */
- snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
- 0x80, 0x80);
- snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
- 0x80, 0x80);
+ snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, HDA_AMP_MUTE);
} else {
/* unmute internal speaker if necessary */
mute = snd_hda_codec_amp_read(codec, 0x1b, 0, HDA_OUTPUT, 0);
- snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
- 0x80, mute & 0x80);
- mute = snd_hda_codec_amp_read(codec, 0x1b, 1, HDA_OUTPUT, 0);
- snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
- 0x80, mute & 0x80);
+ snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, mute);
}
}
{
if ((res >> 26) != ALC880_HP_EVENT)
return;
- alc262_hippo1_automute(codec, 1);
+ alc262_hippo1_automute(codec);
}
/*
}
if (spec->jack_present) {
/* mute internal speaker */
- snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
- 0x80, 0x80);
- snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
- 0x80, 0x80);
+ snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, HDA_AMP_MUTE);
} else {
/* unmute internal speaker if necessary */
mute = snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0);
- snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
- 0x80, mute & 0x80);
- mute = snd_hda_codec_amp_read(codec, 0x14, 1, HDA_OUTPUT, 0);
- snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
- 0x80, mute & 0x80);
+ snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, mute);
}
}
}
/* bind volumes of both NID 0x0c and 0x0d */
-static int alc262_fujitsu_master_vol_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- long *valp = ucontrol->value.integer.value;
- int change;
-
- change = snd_hda_codec_amp_update(codec, 0x0c, 0, HDA_OUTPUT, 0,
- 0x7f, valp[0] & 0x7f);
- change |= snd_hda_codec_amp_update(codec, 0x0c, 1, HDA_OUTPUT, 0,
- 0x7f, valp[1] & 0x7f);
- snd_hda_codec_amp_update(codec, 0x0d, 0, HDA_OUTPUT, 0,
- 0x7f, valp[0] & 0x7f);
- snd_hda_codec_amp_update(codec, 0x0d, 1, HDA_OUTPUT, 0,
- 0x7f, valp[1] & 0x7f);
- return change;
-}
+static struct hda_bind_ctls alc262_fujitsu_bind_master_vol = {
+ .ops = &snd_hda_bind_vol,
+ .values = {
+ HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT),
+ HDA_COMPOSE_AMP_VAL(0x0d, 3, 0, HDA_OUTPUT),
+ 0
+ },
+};
/* bind hp and internal speaker mute (with plug check) */
static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol,
int change;
change = snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
- 0x80, valp[0] ? 0 : 0x80);
+ HDA_AMP_MUTE,
+ valp[0] ? 0 : HDA_AMP_MUTE);
change |= snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
- 0x80, valp[1] ? 0 : 0x80);
- if (change || codec->in_resume)
- alc262_fujitsu_automute(codec, codec->in_resume);
+ HDA_AMP_MUTE,
+ valp[1] ? 0 : HDA_AMP_MUTE);
+ if (change)
+ alc262_fujitsu_automute(codec, 0);
return change;
}
static struct snd_kcontrol_new alc262_fujitsu_mixer[] = {
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Master Playback Volume",
- .info = snd_hda_mixer_amp_volume_info,
- .get = snd_hda_mixer_amp_volume_get,
- .put = alc262_fujitsu_master_vol_put,
- .tlv = { .c = snd_hda_mixer_amp_tlv },
- .private_value = HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT),
- },
+ HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_bind_master_vol),
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Master Playback Switch",
{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
+ /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
* mixer widget
* Note: PASD motherboards uses the Line In 2 as the input for
* front panel mic (mic 2)
*/
/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
/*
* Set up output mixers (0x0c - 0x0f)
{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
+ /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
* mixer widget
* Note: PASD motherboards uses the Line In 2 as the input for
* front panel mic (mic 2)
*/
/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(6)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
/*
* Set up output mixers (0x0c - 0x0e)
{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
+ /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
* mixer widget
* Note: PASD motherboards uses the Line In 2 as the input for front
* panel mic (mic 2)
*/
/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(6)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(7)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
/*
* Set up output mixers (0x0c - 0x0e)
*/
{ }
};
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+#define alc262_loopbacks alc880_loopbacks
+#endif
+
/* pcm configuration: identiacal with ALC880 */
#define alc262_pcm_analog_playback alc880_pcm_analog_playback
#define alc262_pcm_analog_capture alc880_pcm_analog_capture
SND_PCI_QUIRK(0x17ff, 0x058f, "Benq Hippo", ALC262_HIPPO_1),
SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8),
SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_BENQ_T31),
+ SND_PCI_QUIRK(0x104d, 0x820f, "Sony ASSAMD", ALC262_SONY_ASSAMD),
SND_PCI_QUIRK(0x104d, 0x9015, "Sony 0x9015", ALC262_SONY_ASSAMD),
SND_PCI_QUIRK(0x104d, 0x900e, "Sony ASSAMD", ALC262_SONY_ASSAMD),
SND_PCI_QUIRK(0x104d, 0x1f00, "Sony ASSAMD", ALC262_SONY_ASSAMD),
.channel_mode = alc262_modes,
.input_mux = &alc262_capture_source,
.unsol_event = alc262_hippo_unsol_event,
+ .init_hook = alc262_hippo_automute,
},
[ALC262_HIPPO_1] = {
.mixers = { alc262_hippo1_mixer },
.channel_mode = alc262_modes,
.input_mux = &alc262_capture_source,
.unsol_event = alc262_hippo1_unsol_event,
+ .init_hook = alc262_hippo1_automute,
},
[ALC262_FUJITSU] = {
.mixers = { alc262_fujitsu_mixer },
.channel_mode = alc262_modes,
.input_mux = &alc262_capture_source,
.unsol_event = alc262_hippo_unsol_event,
+ .init_hook = alc262_hippo_automute,
},
[ALC262_BENQ_T31] = {
.mixers = { alc262_benq_t31_mixer },
.channel_mode = alc262_modes,
.input_mux = &alc262_capture_source,
.unsol_event = alc262_hippo_unsol_event,
+ .init_hook = alc262_hippo_automute,
},
};
codec->patch_ops = alc_patch_ops;
if (board_config == ALC262_AUTO)
spec->init_hook = alc262_auto_init;
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ if (!spec->loopback.amplist)
+ spec->loopback.amplist = alc262_loopbacks;
+#endif
return 0;
}
{ }
};
+static struct hda_verb alc268_eapd_verbs[] = {
+ {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
+ {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
+ { }
+};
+
+/* Toshiba specific */
+#define alc268_toshiba_automute alc262_hippo_automute
+
+static struct hda_verb alc268_toshiba_verbs[] = {
+ {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
+ { } /* end */
+};
+
+/* Acer specific */
+#define alc268_acer_bind_master_vol alc262_fujitsu_bind_master_vol
+#define alc268_acer_master_sw_put alc262_fujitsu_master_sw_put
+#define alc268_acer_automute alc262_fujitsu_automute
+
+static struct snd_kcontrol_new alc268_acer_mixer[] = {
+ /* output mixer control */
+ HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Master Playback Switch",
+ .info = snd_hda_mixer_amp_switch_info,
+ .get = snd_hda_mixer_amp_switch_get,
+ .put = alc268_acer_master_sw_put,
+ .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
+ },
+ { }
+};
+
+static struct hda_verb alc268_acer_verbs[] = {
+ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+
+ {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
+ { }
+};
+
+/* unsolicited event for HP jack sensing */
+static void alc268_toshiba_unsol_event(struct hda_codec *codec,
+ unsigned int res)
+{
+ if ((res >> 28) != ALC880_HP_EVENT)
+ return;
+ alc268_toshiba_automute(codec);
+}
+
+static void alc268_acer_unsol_event(struct hda_codec *codec,
+ unsigned int res)
+{
+ if ((res >> 28) != ALC880_HP_EVENT)
+ return;
+ alc268_acer_automute(codec, 1);
+}
+
/*
* generic initialization of ADC, input mixers and output mixers
*/
idx = ucontrol->value.enumerated.item[0];
if (idx >= imux->num_items)
idx = imux->num_items - 1;
- if (*cur_val == idx && !codec->in_resume)
+ if (*cur_val == idx)
return 0;
for (i = 0; i < imux->num_items; i++) {
- unsigned int v = (i == idx) ? 0x7000 : 0x7080;
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
- v | (imux->items[i].index << 8));
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL,
- idx );
+ unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;
+ snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,
+ imux->items[i].index,
+ HDA_AMP_MUTE, v);
+ snd_hda_codec_write_cache(codec, nid, 0,
+ AC_VERB_SET_CONNECT_SEL,
+ idx );
}
*cur_val = idx;
return 1;
*/
static const char *alc268_models[ALC268_MODEL_LAST] = {
[ALC268_3ST] = "3stack",
+ [ALC268_TOSHIBA] = "toshiba",
+ [ALC268_ACER] = "acer",
[ALC268_AUTO] = "auto",
};
static struct snd_pci_quirk alc268_cfg_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC268_3ST),
+ SND_PCI_QUIRK(0x1179, 0xff10, "TOSHIBA A205", ALC268_TOSHIBA),
+ SND_PCI_QUIRK(0x103c, 0x30cc, "TOSHIBA", ALC268_TOSHIBA),
+ SND_PCI_QUIRK(0x1025, 0x0126, "Acer", ALC268_ACER),
{}
};
.channel_mode = alc268_modes,
.input_mux = &alc268_capture_source,
},
+ [ALC268_TOSHIBA] = {
+ .mixers = { alc268_base_mixer, alc268_capture_alt_mixer },
+ .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
+ alc268_toshiba_verbs },
+ .num_dacs = ARRAY_SIZE(alc268_dac_nids),
+ .dac_nids = alc268_dac_nids,
+ .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
+ .adc_nids = alc268_adc_nids_alt,
+ .hp_nid = 0x03,
+ .num_channel_mode = ARRAY_SIZE(alc268_modes),
+ .channel_mode = alc268_modes,
+ .input_mux = &alc268_capture_source,
+ .input_mux = &alc268_capture_source,
+ .unsol_event = alc268_toshiba_unsol_event,
+ .init_hook = alc268_toshiba_automute,
+ },
+ [ALC268_ACER] = {
+ .mixers = { alc268_acer_mixer, alc268_capture_alt_mixer },
+ .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
+ alc268_acer_verbs },
+ .num_dacs = ARRAY_SIZE(alc268_dac_nids),
+ .dac_nids = alc268_dac_nids,
+ .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
+ .adc_nids = alc268_adc_nids_alt,
+ .hp_nid = 0x02,
+ .num_channel_mode = ARRAY_SIZE(alc268_modes),
+ .channel_mode = alc268_modes,
+ .input_mux = &alc268_capture_source,
+ .unsol_event = alc268_acer_unsol_event,
+ },
};
static int patch_alc268(struct hda_codec *codec)
present = snd_hda_codec_read(codec, 0x0f, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- snd_hda_codec_amp_update(codec, 0x16, 0, HDA_INPUT, 0,
- 0x80, present ? 0x80 : 0);
- snd_hda_codec_amp_update(codec, 0x16, 1, HDA_INPUT, 0,
- 0x80, present ? 0x80 : 0);
- snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_INPUT, 3,
- 0x80, present ? 0 : 0x80);
- snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_INPUT, 3,
- 0x80, present ? 0 : 0x80);
+ snd_hda_codec_amp_stereo(codec, 0x16, HDA_INPUT, 0,
+ HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
+ snd_hda_codec_amp_stereo(codec, 0x1a, HDA_INPUT, 3,
+ HDA_AMP_MUTE, present ? 0 : HDA_AMP_MUTE);
}
static void alc861_toshiba_unsol_event(struct hda_codec *codec,
alc861_auto_init_analog_input(codec);
}
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static struct hda_amp_list alc861_loopbacks[] = {
+ { 0x15, HDA_INPUT, 0 },
+ { 0x15, HDA_INPUT, 1 },
+ { 0x15, HDA_INPUT, 2 },
+ { 0x15, HDA_INPUT, 3 },
+ { } /* end */
+};
+#endif
+
/*
* configuration and preset
codec->patch_ops = alc_patch_ops;
if (board_config == ALC861_AUTO)
spec->init_hook = alc861_auto_init;
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ if (!spec->loopback.amplist)
+ spec->loopback.amplist = alc861_loopbacks;
+#endif
return 0;
}
},
};
+static struct hda_input_mux alc861vd_hp_capture_source = {
+ .num_items = 2,
+ .items = {
+ { "Front Mic", 0x0 },
+ { "ATAPI Mic", 0x1 },
+ },
+};
+
#define alc861vd_mux_enum_info alc_mux_enum_info
#define alc861vd_mux_enum_get alc_mux_enum_get
idx = ucontrol->value.enumerated.item[0];
if (idx >= imux->num_items)
idx = imux->num_items - 1;
- if (*cur_val == idx && !codec->in_resume)
+ if (*cur_val == idx)
return 0;
for (i = 0; i < imux->num_items; i++) {
- unsigned int v = (i == idx) ? 0x7000 : 0x7080;
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
- v | (imux->items[i].index << 8));
+ unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;
+ snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,
+ imux->items[i].index,
+ HDA_AMP_MUTE, v);
}
*cur_val = idx;
return 1;
HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x05, HDA_INPUT),
HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x05, HDA_INPUT),
- HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- /* .name = "Capture Source", */
- .name = "Input Source",
- .count = 1,
- .info = alc882_mux_enum_info,
- .get = alc882_mux_enum_get,
- .put = alc882_mux_enum_put,
- },
+ { } /* end */
+};
+
+/* Pin assignment: Speaker=0x14, Line-out = 0x15,
+ * Front Mic=0x18, ATAPI Mic = 0x19,
+ */
+static struct snd_kcontrol_new alc861vd_hp_mixer[] = {
+ HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+ HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+ HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
+ HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
+ HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+ HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+
{ } /* end */
};
* the analog-loopback mixer widget
*/
/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
/* Capture mixer: unmute Mic, F-Mic, Line, CD inputs */
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
present = snd_hda_codec_read(codec, 0x1b, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- bits = present ? 0x80 : 0;
- snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
- 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
- 0x80, bits);
+ bits = present ? HDA_AMP_MUTE : 0;
+ snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, bits);
}
static void alc861vd_lenovo_mic_automute(struct hda_codec *codec)
present = snd_hda_codec_read(codec, 0x18, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- bits = present ? 0x80 : 0;
- snd_hda_codec_amp_update(codec, 0x0b, 0, HDA_INPUT, 1,
- 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x0b, 1, HDA_INPUT, 1,
- 0x80, bits);
+ bits = present ? HDA_AMP_MUTE : 0;
+ snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1,
+ HDA_AMP_MUTE, bits);
}
static void alc861vd_lenovo_automute(struct hda_codec *codec)
present = snd_hda_codec_read(codec, 0x15, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
- 0x80, present ? 0x80 : 0);
- snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
- 0x80, present ? 0x80 : 0);
+ snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
}
static void alc861vd_dallas_unsol_event(struct hda_codec *codec, unsigned int res)
alc861vd_dallas_automute(codec);
}
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+#define alc861vd_loopbacks alc880_loopbacks
+#endif
+
/* pcm configuration: identiacal with ALC880 */
#define alc861vd_pcm_analog_playback alc880_pcm_analog_playback
#define alc861vd_pcm_analog_capture alc880_pcm_analog_capture
*/
static const char *alc861vd_models[ALC861VD_MODEL_LAST] = {
[ALC660VD_3ST] = "3stack-660",
- [ALC660VD_3ST_DIG]= "3stack-660-digout",
+ [ALC660VD_3ST_DIG] = "3stack-660-digout",
[ALC861VD_3ST] = "3stack",
[ALC861VD_3ST_DIG] = "3stack-digout",
[ALC861VD_6ST_DIG] = "6stack-digout",
[ALC861VD_LENOVO] = "lenovo",
[ALC861VD_DALLAS] = "dallas",
+ [ALC861VD_HP] = "hp",
[ALC861VD_AUTO] = "auto",
};
SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo 3000 C200", ALC861VD_LENOVO),
SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo", ALC861VD_LENOVO),
SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba A135", ALC861VD_LENOVO),
+ SND_PCI_QUIRK(0x1565, 0x820d, "Biostar NF61S SE", ALC861VD_6ST_DIG),
+ SND_PCI_QUIRK(0x1849, 0x0862, "ASRock K8NF6G-VSTA", ALC861VD_6ST_DIG),
+ SND_PCI_QUIRK(0x103c, 0x30bf, "HP TX1000", ALC861VD_HP),
{}
};
.input_mux = &alc861vd_dallas_capture_source,
.unsol_event = alc861vd_dallas_unsol_event,
.init_hook = alc861vd_dallas_automute,
- },
+ },
+ [ALC861VD_HP] = {
+ .mixers = { alc861vd_hp_mixer },
+ .init_verbs = { alc861vd_dallas_verbs, alc861vd_eapd_verbs },
+ .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
+ .dac_nids = alc861vd_dac_nids,
+ .num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids),
+ .dig_out_nid = ALC861VD_DIGOUT_NID,
+ .adc_nids = alc861vd_adc_nids,
+ .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
+ .channel_mode = alc861vd_3stack_2ch_modes,
+ .input_mux = &alc861vd_hp_capture_source,
+ .unsol_event = alc861vd_dallas_unsol_event,
+ .init_hook = alc861vd_dallas_automute,
+ },
};
/*
if (board_config == ALC861VD_AUTO)
spec->init_hook = alc861vd_auto_init;
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ if (!spec->loopback.amplist)
+ spec->loopback.amplist = alc861vd_loopbacks;
+#endif
return 0;
}
struct alc_spec *spec = codec->spec;
const struct hda_input_mux *imux = spec->input_mux;
unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
- static hda_nid_t capture_mixers[3] = { 0x24, 0x23, 0x22 };
+ static hda_nid_t capture_mixers[2] = { 0x23, 0x22 };
hda_nid_t nid = capture_mixers[adc_idx];
unsigned int *cur_val = &spec->cur_mux[adc_idx];
unsigned int i, idx;
idx = ucontrol->value.enumerated.item[0];
if (idx >= imux->num_items)
idx = imux->num_items - 1;
- if (*cur_val == idx && !codec->in_resume)
+ if (*cur_val == idx)
return 0;
for (i = 0; i < imux->num_items; i++) {
- unsigned int v = (i == idx) ? 0x7000 : 0x7080;
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
- v | (imux->items[i].index << 8));
+ unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;
+ snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,
+ imux->items[i].index,
+ HDA_AMP_MUTE, v);
}
*cur_val = idx;
return 1;
{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
/* Front mixer: unmute input/output amp left and right (volume = 0) */
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
* panel mic (mic 2)
*/
/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
/*
* Set up output mixers (0x0c - 0x0f)
/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
/* Input mixer */
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
- /*{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},*/
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
-
+ {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{ }
};
present = snd_hda_codec_read(codec, 0x14, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- bits = present ? 0x80 : 0;
- snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
- 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
- 0x80, bits);
+ bits = present ? HDA_AMP_MUTE : 0;
+ snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, bits);
}
static void alc662_lenovo_101e_all_automute(struct hda_codec *codec)
present = snd_hda_codec_read(codec, 0x1b, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- bits = present ? 0x80 : 0;
- snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
- 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
- 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
- 0x80, bits);
- snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
- 0x80, bits);
+ bits = present ? HDA_AMP_MUTE : 0;
+ snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, bits);
+ snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, bits);
}
static void alc662_lenovo_101e_unsol_event(struct hda_codec *codec,
alc662_lenovo_101e_ispeaker_automute(codec);
}
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+#define alc662_loopbacks alc880_loopbacks
+#endif
+
/* pcm configuration: identiacal with ALC880 */
#define alc662_pcm_analog_playback alc880_pcm_analog_playback
codec->patch_ops = alc_patch_ops;
if (board_config == ALC662_AUTO)
spec->init_hook = alc662_auto_init;
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ if (!spec->loopback.amplist)
+ spec->loopback.amplist = alc662_loopbacks;
+#endif
return 0;
}