ALC888_ACER_ASPIRE_7730G,
ALC883_MEDION,
ALC883_MEDION_MD2,
+ ALC883_MEDION_WIM2160,
ALC883_LAPTOP_EAPD,
ALC883_LENOVO_101E_2ch,
ALC883_LENOVO_NB0763,
#define MUX_IDX_UNDEF ((unsigned char)-1)
+struct alc_customize_define {
+ unsigned int sku_cfg;
+ unsigned char port_connectivity;
+ unsigned char check_sum;
+ unsigned char customization;
+ unsigned char external_amp;
+ unsigned int enable_pcbeep:1;
+ unsigned int platform_type:1;
+ unsigned int swap:1;
+ unsigned int override:1;
+};
+
struct alc_spec {
/* codec parameterization */
struct snd_kcontrol_new *mixers[5]; /* mixer arrays */
/* dynamic controls, init_verbs and input_mux */
struct auto_pin_cfg autocfg;
+ struct alc_customize_define cdefine;
struct snd_array kctls;
struct hda_input_mux private_imux[3];
hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
spec->unsol_event = alc_sku_unsol_event;
}
+static int alc_auto_parse_customize_define(struct hda_codec *codec)
+{
+ unsigned int ass, tmp, i;
+ unsigned nid = 0;
+ struct alc_spec *spec = codec->spec;
+
+ ass = codec->subsystem_id & 0xffff;
+ if (ass != codec->bus->pci->subsystem_device && (ass & 1))
+ goto do_sku;
+
+ nid = 0x1d;
+ if (codec->vendor_id == 0x10ec0260)
+ nid = 0x17;
+ ass = snd_hda_codec_get_pincfg(codec, nid);
+
+ if (!(ass & 1)) {
+ printk(KERN_INFO "hda_codec: %s: SKU not ready 0x%08x\n",
+ codec->chip_name, ass);
+ return -1;
+ }
+
+ /* check sum */
+ tmp = 0;
+ for (i = 1; i < 16; i++) {
+ if ((ass >> i) & 1)
+ tmp++;
+ }
+ if (((ass >> 16) & 0xf) != tmp)
+ return -1;
+
+ spec->cdefine.port_connectivity = ass >> 30;
+ spec->cdefine.enable_pcbeep = (ass & 0x100000) >> 20;
+ spec->cdefine.check_sum = (ass >> 16) & 0xf;
+ spec->cdefine.customization = ass >> 8;
+do_sku:
+ spec->cdefine.sku_cfg = ass;
+ spec->cdefine.external_amp = (ass & 0x38) >> 3;
+ spec->cdefine.platform_type = (ass & 0x4) >> 2;
+ spec->cdefine.swap = (ass & 0x2) >> 1;
+ spec->cdefine.override = ass & 0x1;
+
+ snd_printd("SKU: Nid=0x%x sku_cfg=0x%08x\n",
+ nid, spec->cdefine.sku_cfg);
+ snd_printd("SKU: port_connectivity=0x%x\n",
+ spec->cdefine.port_connectivity);
+ snd_printd("SKU: enable_pcbeep=0x%x\n", spec->cdefine.enable_pcbeep);
+ snd_printd("SKU: check_sum=0x%08x\n", spec->cdefine.check_sum);
+ snd_printd("SKU: customization=0x%08x\n", spec->cdefine.customization);
+ snd_printd("SKU: external_amp=0x%x\n", spec->cdefine.external_amp);
+ snd_printd("SKU: platform_type=0x%x\n", spec->cdefine.platform_type);
+ snd_printd("SKU: swap=0x%x\n", spec->cdefine.swap);
+ snd_printd("SKU: override=0x%x\n", spec->cdefine.override);
+
+ return 0;
+}
+
/* check subsystem ID and set up device-specific initialization;
* return 1 if initialized, 0 if invalid SSID
*/
*/
static struct hda_verb alc888_acer_aspire_6530g_verbs[] = {
+/* Route to built-in subwoofer as well as speakers */
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
/* Bias voltage on for external mic port */
{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN | PIN_VREF80},
/* Front Mic: set to PIN_IN (empty by default) */
/* Enable speaker output */
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
/* Enable headphone output */
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | PIN_HP},
{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+ {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
{ }
};
return err;
}
- alc_free_kctls(codec); /* no longer needed */
-
/* assign Capture Source enums to NID */
kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
if (!kctl)
}
}
}
+
+ alc_free_kctls(codec); /* no longer needed */
+
return 0;
}
if (spec->init_hook)
spec->init_hook(codec);
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ if (codec->patch_ops.check_power_status)
+ codec->patch_ops.check_power_status(codec, 0x01);
+#endif
return 0;
}
codec->patch_ops.init(codec);
snd_hda_codec_resume_amp(codec);
snd_hda_codec_resume_cache(codec);
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ if (codec->patch_ops.check_power_status)
+ codec->patch_ops.check_power_status(codec, 0x01);
+#endif
return 0;
}
#endif
.reboot_notify = alc_shutup,
};
+/* replace the codec chip_name with the given string */
+static int alc_codec_rename(struct hda_codec *codec, const char *name)
+{
+ kfree(codec->chip_name);
+ codec->chip_name = kstrdup(name, GFP_KERNEL);
+ if (!codec->chip_name) {
+ alc_free(codec);
+ return -ENOMEM;
+ }
+ return 0;
+}
/*
* Test configuration for debugging
}
}
+static void alc880_auto_init_input_src(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ int c;
+
+ for (c = 0; c < spec->num_adc_nids; c++) {
+ unsigned int mux_idx;
+ const struct hda_input_mux *imux;
+ mux_idx = c >= spec->num_mux_defs ? 0 : c;
+ imux = &spec->input_mux[mux_idx];
+ if (!imux->num_items && mux_idx > 0)
+ imux = &spec->input_mux[0];
+ if (imux)
+ snd_hda_codec_write(codec, spec->adc_nids[c], 0,
+ AC_VERB_SET_CONNECT_SEL,
+ imux->items[0].index);
+ }
+}
+
/* parse the BIOS configuration and set up the alc_spec */
/* return 1 if successful, 0 if the proper config is not found,
* or a negative error code
alc880_auto_init_multi_out(codec);
alc880_auto_init_extra_out(codec);
alc880_auto_init_analog_input(codec);
+ alc880_auto_init_input_src(codec);
if (spec->unsol_event)
alc_inithook(codec);
}
}
}
+/* fill adc_nids (and capsrc_nids) containing all active input pins */
+static void fillup_priv_adc_nids(struct hda_codec *codec, hda_nid_t *nids,
+ int num_nids)
+{
+ struct alc_spec *spec = codec->spec;
+ int n;
+ hda_nid_t fallback_adc = 0, fallback_cap = 0;
+
+ for (n = 0; n < num_nids; n++) {
+ hda_nid_t adc, cap;
+ hda_nid_t conn[HDA_MAX_NUM_INPUTS];
+ int nconns, i, j;
+
+ adc = nids[n];
+ if (get_wcaps_type(get_wcaps(codec, adc)) != AC_WID_AUD_IN)
+ continue;
+ cap = adc;
+ nconns = snd_hda_get_connections(codec, cap, conn,
+ ARRAY_SIZE(conn));
+ if (nconns == 1) {
+ cap = conn[0];
+ nconns = snd_hda_get_connections(codec, cap, conn,
+ ARRAY_SIZE(conn));
+ }
+ if (nconns <= 0)
+ continue;
+ if (!fallback_adc) {
+ fallback_adc = adc;
+ fallback_cap = cap;
+ }
+ for (i = 0; i < AUTO_PIN_LAST; i++) {
+ hda_nid_t nid = spec->autocfg.input_pins[i];
+ if (!nid)
+ continue;
+ for (j = 0; j < nconns; j++) {
+ if (conn[j] == nid)
+ break;
+ }
+ if (j >= nconns)
+ break;
+ }
+ if (i >= AUTO_PIN_LAST) {
+ int num_adcs = spec->num_adc_nids;
+ spec->private_adc_nids[num_adcs] = adc;
+ spec->private_capsrc_nids[num_adcs] = cap;
+ spec->num_adc_nids++;
+ spec->adc_nids = spec->private_adc_nids;
+ if (adc != cap)
+ spec->capsrc_nids = spec->private_capsrc_nids;
+ }
+ }
+ if (!spec->num_adc_nids) {
+ printk(KERN_WARNING "hda_codec: %s: no valid ADC found;"
+ " using fallback 0x%x\n",
+ codec->chip_name, fallback_adc);
+ spec->private_adc_nids[0] = fallback_adc;
+ spec->adc_nids = spec->private_adc_nids;
+ if (fallback_adc != fallback_cap) {
+ spec->private_capsrc_nids[0] = fallback_cap;
+ spec->capsrc_nids = spec->private_adc_nids;
+ }
+ }
+}
+
#ifdef CONFIG_SND_HDA_INPUT_BEEP
#define set_beep_amp(spec, nid, idx, dir) \
((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir))
}
}
+#define alc260_auto_init_input_src alc880_auto_init_input_src
+
/*
* generic initialization of ADC, input mixers and output mixers
*/
struct alc_spec *spec = codec->spec;
alc260_auto_init_multi_out(codec);
alc260_auto_init_analog_input(codec);
+ alc260_auto_init_input_src(codec);
if (spec->unsol_event)
alc_inithook(codec);
}
{ } /* end */
};
+static struct snd_kcontrol_new alc883_medion_wim2160_mixer[] = {
+ HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+ HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+ HDA_CODEC_MUTE("Speaker Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Line Playback Volume", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Line Playback Switch", 0x08, 0x0, HDA_INPUT),
+ { } /* end */
+};
+
+static struct hda_verb alc883_medion_wim2160_verbs[] = {
+ /* Unmute front mixer */
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+
+ /* Set speaker pin to front mixer */
+ {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+
+ /* Init headphone pin */
+ {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
+ {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
+
+ { } /* end */
+};
+
+/* toggle speaker-output according to the hp-jack state */
+static void alc883_medion_wim2160_setup(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+
+ spec->autocfg.hp_pins[0] = 0x1a;
+ spec->autocfg.speaker_pins[0] = 0x15;
+}
+
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),
static struct snd_kcontrol_new alc888_acer_aspire_6530_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_VOLUME("LFE Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("LFE Playback Switch", 0x0f, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
[ALC888_ACER_ASPIRE_7730G] = "acer-aspire-7730g",
[ALC883_MEDION] = "medion",
[ALC883_MEDION_MD2] = "medion-md2",
+ [ALC883_MEDION_WIM2160] = "medion-wim2160",
[ALC883_LAPTOP_EAPD] = "laptop-eapd",
[ALC883_LENOVO_101E_2ch] = "lenovo-101e",
[ALC883_LENOVO_NB0763] = "lenovo-nb0763",
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, 0x4570, "MSI Wind Top AE2220", ALC883_TARGA_DIG),
SND_PCI_QUIRK(0x1462, 0x6510, "MSI GX620", ALC883_TARGA_8ch_DIG),
SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC883_6ST_DIG),
SND_PCI_QUIRK(0x1462, 0x7187, "MSI", ALC883_6ST_DIG),
SND_PCI_QUIRK(0x1462, 0x7280, "MSI", ALC883_6ST_DIG),
SND_PCI_QUIRK(0x1462, 0x7327, "MSI", ALC883_6ST_DIG),
SND_PCI_QUIRK(0x1462, 0x7350, "MSI", ALC883_6ST_DIG),
+ SND_PCI_QUIRK(0x1462, 0x7437, "MSI NetOn AP1900", ALC883_TARGA_DIG),
SND_PCI_QUIRK(0x1462, 0xa422, "MSI", ALC883_TARGA_2ch_DIG),
SND_PCI_QUIRK(0x1462, 0xaa08, "MSI", ALC883_TARGA_2ch_DIG),
SND_PCI_QUIRK(0x8086, 0x0022, "DX58SO", ALC889_INTEL),
SND_PCI_QUIRK(0x8086, 0x0021, "Intel IbexPeak", ALC889A_INTEL),
SND_PCI_QUIRK(0x8086, 0x3b56, "Intel IbexPeak", ALC889A_INTEL),
- SND_PCI_QUIRK(0x8086, 0xd601, "D102GGC", ALC883_3ST_6ch),
+ SND_PCI_QUIRK(0x8086, 0xd601, "D102GGC", ALC882_6ST_DIG),
{}
};
.setup = alc883_medion_md2_setup,
.init_hook = alc_automute_amp,
},
+ [ALC883_MEDION_WIM2160] = {
+ .mixers = { alc883_medion_wim2160_mixer },
+ .init_verbs = { alc883_init_verbs, alc883_medion_wim2160_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 = alc_automute_amp_unsol_event,
+ .setup = alc883_medion_wim2160_setup,
+ .init_hook = alc_automute_amp,
+ },
[ALC883_LAPTOP_EAPD] = {
.mixers = { alc883_base_mixer },
.init_verbs = { alc883_init_verbs, alc882_eapd_verbs },
static void alc882_auto_set_output_and_unmute(struct hda_codec *codec,
hda_nid_t nid, int pin_type,
- int dac_idx)
+ hda_nid_t dac)
{
- /* set as output */
- struct alc_spec *spec = codec->spec;
int idx;
+ /* set as output */
alc_set_pin_output(codec, nid, pin_type);
- if (spec->multiout.dac_nids[dac_idx] == 0x25)
+
+ if (dac == 0x25)
idx = 4;
+ else if (dac >= 0x02 && dac <= 0x05)
+ idx = dac - 2;
else
- idx = spec->multiout.dac_nids[dac_idx] - 2;
+ return;
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);
-
}
static void alc882_auto_init_multi_out(struct hda_codec *codec)
int pin_type = get_pin_type(spec->autocfg.line_out_type);
if (nid)
alc882_auto_set_output_and_unmute(codec, nid, pin_type,
- i);
+ spec->multiout.dac_nids[i]);
}
}
static void alc882_auto_init_hp_out(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- hda_nid_t pin;
+ hda_nid_t pin, dac;
pin = spec->autocfg.hp_pins[0];
- if (pin) /* connect to front */
- /* use dac 0 */
- alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
+ if (pin) {
+ dac = spec->multiout.hp_nid;
+ if (!dac)
+ dac = spec->multiout.dac_nids[0]; /* to front */
+ alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, dac);
+ }
pin = spec->autocfg.speaker_pins[0];
- if (pin)
- alc882_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
+ if (pin) {
+ dac = spec->multiout.extra_out_nid[0];
+ if (!dac)
+ dac = spec->multiout.dac_nids[0]; /* to front */
+ alc882_auto_set_output_and_unmute(codec, pin, PIN_OUT, dac);
+ }
}
static void alc882_auto_init_analog_input(struct hda_codec *codec)
err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg);
if (err < 0)
return err;
+ err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pins[0],
+ "Headphone");
+ if (err < 0)
+ return err;
err = alc880_auto_create_extra_out(spec,
spec->autocfg.speaker_pins[0],
"Speaker");
if (err < 0)
return err;
- err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pins[0],
- "Headphone");
- if (err < 0)
- return err;
err = alc882_auto_create_input_ctls(codec, &spec->autocfg);
if (err < 0)
return err;
codec->spec = spec;
+ alc_auto_parse_customize_define(codec);
+
switch (codec->vendor_id) {
case 0x10ec0882:
case 0x10ec0885:
}
set_capture_mixer(codec);
- set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
+
+ if (spec->cdefine.enable_pcbeep)
+ set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
spec->vmaster_nid = 0x0c;
snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, tmp | 0x80);
}
#endif
+ alc_auto_parse_customize_define(codec);
alc_fix_pll_init(codec, 0x20, 0x0a, 10);
}
if (!spec->cap_mixer && !spec->no_analog)
set_capture_mixer(codec);
- if (!spec->no_analog)
+ if (!spec->no_analog && spec->cdefine.enable_pcbeep)
set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
spec->vmaster_nid = 0x0c;
unsigned char bits;
present = snd_hda_jack_detect(codec, 0x15);
- bits = present ? AMP_IN_MUTE(0) : 0;
+ bits = present ? HDA_AMP_MUTE : 0;
snd_hda_codec_amp_stereo(codec, 0x0f, HDA_INPUT, 0,
- AMP_IN_MUTE(0), bits);
+ HDA_AMP_MUTE, bits);
snd_hda_codec_amp_stereo(codec, 0x0f, HDA_INPUT, 1,
- AMP_IN_MUTE(0), bits);
+ HDA_AMP_MUTE, bits);
}
static void alc268_acer_lc_unsol_event(struct hda_codec *codec,
dac = 0x02;
break;
case 0x15:
+ case 0x21: /* ALC269vb has this pin, too */
dac = 0x03;
break;
default:
0x22,
};
-/* NOTE: ADC2 (0x07) is connected from a recording *MIXER* (0x24),
- * not a mux!
- */
+static hda_nid_t alc269_adc_candidates[] = {
+ 0x08, 0x09, 0x07,
+};
#define alc269_modes alc260_modes
#define alc269_capture_source alc880_lg_lw_capture_source
unsigned char bits;
present = snd_hda_jack_detect(codec, 0x15);
- bits = present ? AMP_IN_MUTE(0) : 0;
+ bits = present ? HDA_AMP_MUTE : 0;
snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
- AMP_IN_MUTE(0), bits);
+ HDA_AMP_MUTE, bits);
snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
- AMP_IN_MUTE(0), bits);
+ HDA_AMP_MUTE, bits);
snd_hda_codec_write(codec, 0x20, 0,
AC_VERB_SET_COEF_INDEX, 0x0c);
/* Check port replicator headphone socket */
present |= snd_hda_jack_detect(codec, 0x1a);
- bits = present ? AMP_IN_MUTE(0) : 0;
+ bits = present ? HDA_AMP_MUTE : 0;
snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
- AMP_IN_MUTE(0), bits);
+ HDA_AMP_MUTE, bits);
snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
- AMP_IN_MUTE(0), bits);
+ HDA_AMP_MUTE, bits);
snd_hda_codec_write(codec, 0x20, 0,
AC_VERB_SET_COEF_INDEX, 0x0c);
unsigned char bits;
present = snd_hda_jack_detect(codec, nid);
- bits = present ? AMP_IN_MUTE(0) : 0;
+ bits = present ? HDA_AMP_MUTE : 0;
snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
- AMP_IN_MUTE(0), bits);
+ HDA_AMP_MUTE, bits);
snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
- AMP_IN_MUTE(0), bits);
+ HDA_AMP_MUTE, bits);
}
/* unsolicited event for HP jack sensing */
}
}
-static void alc269_laptop_dmic_setup(struct hda_codec *codec)
+static void alc269_laptop_amic_setup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
spec->autocfg.hp_pins[0] = 0x15;
spec->autocfg.speaker_pins[0] = 0x14;
spec->ext_mic.pin = 0x18;
spec->ext_mic.mux_idx = 0;
- spec->int_mic.pin = 0x12;
- spec->int_mic.mux_idx = 5;
+ spec->int_mic.pin = 0x19;
+ spec->int_mic.mux_idx = 1;
spec->auto_mic = 1;
}
-static void alc269vb_laptop_dmic_setup(struct hda_codec *codec)
+static void alc269_laptop_dmic_setup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
spec->autocfg.hp_pins[0] = 0x15;
spec->ext_mic.pin = 0x18;
spec->ext_mic.mux_idx = 0;
spec->int_mic.pin = 0x12;
- spec->int_mic.mux_idx = 6;
+ spec->int_mic.mux_idx = 5;
spec->auto_mic = 1;
}
-static void alc269_laptop_amic_setup(struct hda_codec *codec)
+static void alc269vb_laptop_amic_setup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- spec->autocfg.hp_pins[0] = 0x15;
+ spec->autocfg.hp_pins[0] = 0x21;
spec->autocfg.speaker_pins[0] = 0x14;
spec->ext_mic.pin = 0x18;
spec->ext_mic.mux_idx = 0;
spec->auto_mic = 1;
}
+static void alc269vb_laptop_dmic_setup(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ spec->autocfg.hp_pins[0] = 0x21;
+ spec->autocfg.speaker_pins[0] = 0x14;
+ spec->ext_mic.pin = 0x18;
+ spec->ext_mic.mux_idx = 0;
+ spec->int_mic.pin = 0x12;
+ spec->int_mic.mux_idx = 6;
+ spec->auto_mic = 1;
+}
+
static void alc269_laptop_inithook(struct hda_codec *codec)
{
alc269_speaker_automute(codec);
/* NID is set in alc_build_pcms */
};
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static int alc269_mic2_for_mute_led(struct hda_codec *codec)
+{
+ switch (codec->subsystem_id) {
+ case 0x103c1586:
+ return 1;
+ }
+ return 0;
+}
+
+static int alc269_mic2_mute_check_ps(struct hda_codec *codec, hda_nid_t nid)
+{
+ /* update mute-LED according to the speaker mute state */
+ if (nid == 0x01 || nid == 0x14) {
+ int pinval;
+ if (snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0) &
+ HDA_AMP_MUTE)
+ pinval = 0x24;
+ else
+ pinval = 0x20;
+ /* mic2 vref pin is used for mute LED control */
+ snd_hda_codec_update_cache(codec, 0x19, 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL,
+ pinval);
+ }
+ return alc_check_power_status(codec, nid);
+}
+#endif /* CONFIG_SND_HDA_POWER_SAVE */
+
/*
* BIOS auto configuration
*/
struct alc_spec *spec = codec->spec;
int err;
static hda_nid_t alc269_ignore[] = { 0x1d, 0 };
- hda_nid_t real_capsrc_nids;
err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
alc269_ignore);
if ((alc_read_coef_idx(codec, 0) & 0x00f0) == 0x0010) {
add_verb(spec, alc269vb_init_verbs);
- real_capsrc_nids = alc269vb_capsrc_nids[0];
alc_ssid_check(codec, 0, 0x1b, 0x14, 0x21);
} else {
add_verb(spec, alc269_init_verbs);
- real_capsrc_nids = alc269_capsrc_nids[0];
alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
}
spec->num_mux_defs = 1;
spec->input_mux = &spec->private_imux[0];
+ fillup_priv_adc_nids(codec, alc269_adc_candidates,
+ sizeof(alc269_adc_candidates));
+
/* set default input source */
- snd_hda_codec_write_cache(codec, real_capsrc_nids,
+ snd_hda_codec_write_cache(codec, spec->capsrc_nids[0],
0, AC_VERB_SET_CONNECT_SEL,
spec->input_mux->items[0].index);
.num_channel_mode = ARRAY_SIZE(alc269_modes),
.channel_mode = alc269_modes,
.unsol_event = alc269_laptop_unsol_event,
- .setup = alc269_laptop_amic_setup,
+ .setup = alc269vb_laptop_amic_setup,
.init_hook = alc269_laptop_inithook,
},
[ALC269VB_DMIC] = {
codec->spec = spec;
- alc_fix_pll_init(codec, 0x20, 0x04, 15);
+ alc_auto_parse_customize_define(codec);
if ((alc_read_coef_idx(codec, 0) & 0x00f0) == 0x0010){
- kfree(codec->chip_name);
- codec->chip_name = kstrdup("ALC259", GFP_KERNEL);
- if (!codec->chip_name) {
- alc_free(codec);
- return -ENOMEM;
- }
+ if (codec->bus->pci->subsystem_vendor == 0x1025 &&
+ spec->cdefine.platform_type == 1)
+ alc_codec_rename(codec, "ALC271X");
+ else
+ alc_codec_rename(codec, "ALC259");
is_alc269vb = 1;
- }
+ } else
+ alc_fix_pll_init(codec, 0x20, 0x04, 15);
board_config = snd_hda_check_board_config(codec, ALC269_MODEL_LAST,
alc269_models,
spec->stream_digital_playback = &alc269_pcm_digital_playback;
spec->stream_digital_capture = &alc269_pcm_digital_capture;
- if (!is_alc269vb) {
- spec->adc_nids = alc269_adc_nids;
- spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids);
- spec->capsrc_nids = alc269_capsrc_nids;
- } else {
- spec->adc_nids = alc269vb_adc_nids;
- spec->num_adc_nids = ARRAY_SIZE(alc269vb_adc_nids);
- spec->capsrc_nids = alc269vb_capsrc_nids;
+ if (!spec->adc_nids) { /* wasn't filled automatically? use default */
+ if (!is_alc269vb) {
+ spec->adc_nids = alc269_adc_nids;
+ spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids);
+ spec->capsrc_nids = alc269_capsrc_nids;
+ } else {
+ spec->adc_nids = alc269vb_adc_nids;
+ spec->num_adc_nids = ARRAY_SIZE(alc269vb_adc_nids);
+ spec->capsrc_nids = alc269vb_capsrc_nids;
+ }
}
if (!spec->cap_mixer)
set_capture_mixer(codec);
- set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
+ if (spec->cdefine.enable_pcbeep)
+ set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
spec->vmaster_nid = 0x02;
#ifdef CONFIG_SND_HDA_POWER_SAVE
if (!spec->loopback.amplist)
spec->loopback.amplist = alc269_loopbacks;
+ if (alc269_mic2_for_mute_led(codec))
+ codec->patch_ops.check_power_status = alc269_mic2_mute_check_ps;
#endif
return 0;
present = snd_hda_jack_detect(codec, 0x21);
bits = present ? HDA_AMP_MUTE : 0;
snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
- AMP_IN_MUTE(0), bits);
+ HDA_AMP_MUTE, bits);
snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
- AMP_IN_MUTE(0), bits);
+ HDA_AMP_MUTE, bits);
}
static void alc663_21jd_two_speaker_automute(struct hda_codec *codec)
present = snd_hda_jack_detect(codec, 0x21);
bits = present ? HDA_AMP_MUTE : 0;
snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
- AMP_IN_MUTE(0), bits);
+ HDA_AMP_MUTE, bits);
snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
- AMP_IN_MUTE(0), bits);
+ HDA_AMP_MUTE, bits);
snd_hda_codec_amp_stereo(codec, 0x0e, HDA_INPUT, 0,
- AMP_IN_MUTE(0), bits);
+ HDA_AMP_MUTE, bits);
snd_hda_codec_amp_stereo(codec, 0x0e, HDA_INPUT, 1,
- AMP_IN_MUTE(0), bits);
+ HDA_AMP_MUTE, bits);
}
static void alc663_15jd_two_speaker_automute(struct hda_codec *codec)
present = snd_hda_jack_detect(codec, 0x15);
bits = present ? HDA_AMP_MUTE : 0;
snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
- AMP_IN_MUTE(0), bits);
+ HDA_AMP_MUTE, bits);
snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
- AMP_IN_MUTE(0), bits);
+ HDA_AMP_MUTE, bits);
snd_hda_codec_amp_stereo(codec, 0x0e, HDA_INPUT, 0,
- AMP_IN_MUTE(0), bits);
+ HDA_AMP_MUTE, bits);
snd_hda_codec_amp_stereo(codec, 0x0e, HDA_INPUT, 1,
- AMP_IN_MUTE(0), bits);
+ HDA_AMP_MUTE, bits);
}
static void alc662_f5z_speaker_automute(struct hda_codec *codec)
if (present1 || present2) {
snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
- AMP_IN_MUTE(0), AMP_IN_MUTE(0));
+ HDA_AMP_MUTE, HDA_AMP_MUTE);
snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
- AMP_IN_MUTE(0), AMP_IN_MUTE(0));
+ HDA_AMP_MUTE, HDA_AMP_MUTE);
} else {
snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
- AMP_IN_MUTE(0), 0);
+ HDA_AMP_MUTE, 0);
snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
- AMP_IN_MUTE(0), 0);
+ HDA_AMP_MUTE, 0);
}
}
codec->spec = spec;
+ alc_auto_parse_customize_define(codec);
+
alc_fix_pll_init(codec, 0x20, 0x04, 15);
- if (alc_read_coef_idx(codec, 0)==0x8020){
- kfree(codec->chip_name);
- codec->chip_name = kstrdup("ALC661", GFP_KERNEL);
- if (!codec->chip_name) {
- alc_free(codec);
- return -ENOMEM;
- }
- }
+ if (alc_read_coef_idx(codec, 0) == 0x8020)
+ alc_codec_rename(codec, "ALC661");
+ else if ((alc_read_coef_idx(codec, 0) & (1 << 14)) &&
+ codec->bus->pci->subsystem_vendor == 0x1025 &&
+ spec->cdefine.platform_type == 1)
+ alc_codec_rename(codec, "ALC272X");
board_config = snd_hda_check_board_config(codec, ALC662_MODEL_LAST,
alc662_models,
if (!spec->cap_mixer)
set_capture_mixer(codec);
- switch (codec->vendor_id) {
- case 0x10ec0662:
- set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
- break;
- case 0x10ec0272:
- case 0x10ec0663:
- case 0x10ec0665:
- set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
- break;
- case 0x10ec0273:
- set_beep_amp(spec, 0x0b, 0x03, HDA_INPUT);
- break;
+ if (spec->cdefine.enable_pcbeep) {
+ switch (codec->vendor_id) {
+ case 0x10ec0662:
+ set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
+ break;
+ case 0x10ec0272:
+ case 0x10ec0663:
+ case 0x10ec0665:
+ set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
+ break;
+ case 0x10ec0273:
+ set_beep_amp(spec, 0x0b, 0x03, HDA_INPUT);
+ break;
+ }
}
spec->vmaster_nid = 0x02;