Commit 299f293b authored by Takashi Iwai's avatar Takashi Iwai

Merge branch 'topic/hda-realtek-amp' into topic/hda

parents 1103f9b2 4a79ba34
...@@ -253,6 +253,15 @@ enum { ...@@ -253,6 +253,15 @@ enum {
/* for GPIO Poll */ /* for GPIO Poll */
#define GPIO_MASK 0x03 #define GPIO_MASK 0x03
/* extra amp-initialization sequence types */
enum {
ALC_INIT_NONE,
ALC_INIT_DEFAULT,
ALC_INIT_GPIO1,
ALC_INIT_GPIO2,
ALC_INIT_GPIO3,
};
struct alc_spec { struct alc_spec {
/* codec parameterization */ /* codec parameterization */
struct snd_kcontrol_new *mixers[5]; /* mixer arrays */ struct snd_kcontrol_new *mixers[5]; /* mixer arrays */
...@@ -322,6 +331,7 @@ struct alc_spec { ...@@ -322,6 +331,7 @@ struct alc_spec {
/* other flags */ /* other flags */
unsigned int no_analog :1; /* digital I/O only */ unsigned int no_analog :1; /* digital I/O only */
int init_amp;
/* for virtual master */ /* for virtual master */
hda_nid_t vmaster_nid; hda_nid_t vmaster_nid;
...@@ -994,74 +1004,21 @@ static void alc888_coef_init(struct hda_codec *codec) ...@@ -994,74 +1004,21 @@ static void alc888_coef_init(struct hda_codec *codec)
AC_VERB_SET_PROC_COEF, 0x3030); AC_VERB_SET_PROC_COEF, 0x3030);
} }
/* 32-bit subsystem ID for BIOS loading in HD Audio codec. static void alc_auto_init_amp(struct hda_codec *codec, int type)
* 31 ~ 16 : Manufacture ID
* 15 ~ 8 : SKU ID
* 7 ~ 0 : Assembly ID
* port-A --> pin 39/41, port-E --> pin 14/15, port-D --> pin 35/36
*/
static void alc_subsystem_id(struct hda_codec *codec,
unsigned int porta, unsigned int porte,
unsigned int portd)
{ {
unsigned int ass, tmp, i; unsigned int tmp;
unsigned nid;
struct alc_spec *spec = codec->spec;
ass = codec->subsystem_id & 0xffff;
if ((ass != codec->bus->pci->subsystem_device) && (ass & 1))
goto do_sku;
/*
* 31~30 : port conetcivity
* 29~21 : reserve
* 20 : PCBEEP input
* 19~16 : Check sum (15:1)
* 15~1 : Custom
* 0 : override
*/
nid = 0x1d;
if (codec->vendor_id == 0x10ec0260)
nid = 0x17;
ass = snd_hda_codec_get_pincfg(codec, nid);
snd_printd("realtek: No valid SSID, "
"checking pincfg 0x%08x for NID 0x%x\n",
ass, nid);
if (!(ass & 1) && !(ass & 0x100000))
return;
if ((ass >> 30) != 1) /* no physical connection */
return;
/* check sum */ switch (type) {
tmp = 0; case ALC_INIT_GPIO1:
for (i = 1; i < 16; i++) {
if ((ass >> i) & 1)
tmp++;
}
if (((ass >> 16) & 0xf) != tmp)
return;
do_sku:
snd_printd("realtek: Enabling init ASM_ID=0x%04x CODEC_ID=%08x\n",
ass & 0xffff, codec->vendor_id);
/*
* 0 : override
* 1 : Swap Jack
* 2 : 0 --> Desktop, 1 --> Laptop
* 3~5 : External Amplifier control
* 7~6 : Reserved
*/
tmp = (ass & 0x38) >> 3; /* external Amp control */
switch (tmp) {
case 1:
snd_hda_sequence_write(codec, alc_gpio1_init_verbs); snd_hda_sequence_write(codec, alc_gpio1_init_verbs);
break; break;
case 3: case ALC_INIT_GPIO2:
snd_hda_sequence_write(codec, alc_gpio2_init_verbs); snd_hda_sequence_write(codec, alc_gpio2_init_verbs);
break; break;
case 7: case ALC_INIT_GPIO3:
snd_hda_sequence_write(codec, alc_gpio3_init_verbs); snd_hda_sequence_write(codec, alc_gpio3_init_verbs);
break; break;
case 5: /* set EAPD output high */ case ALC_INIT_DEFAULT:
switch (codec->vendor_id) { switch (codec->vendor_id) {
case 0x10ec0260: case 0x10ec0260:
snd_hda_codec_write(codec, 0x0f, 0, snd_hda_codec_write(codec, 0x0f, 0,
...@@ -1115,7 +1072,7 @@ static void alc_subsystem_id(struct hda_codec *codec, ...@@ -1115,7 +1072,7 @@ static void alc_subsystem_id(struct hda_codec *codec,
tmp | 0x2010); tmp | 0x2010);
break; break;
case 0x10ec0888: case 0x10ec0888:
/*alc888_coef_init(codec);*/ /* called in alc_init() */ alc888_coef_init(codec);
break; break;
case 0x10ec0267: case 0x10ec0267:
case 0x10ec0268: case 0x10ec0268:
...@@ -1130,7 +1087,104 @@ static void alc_subsystem_id(struct hda_codec *codec, ...@@ -1130,7 +1087,104 @@ static void alc_subsystem_id(struct hda_codec *codec,
tmp | 0x3000); tmp | 0x3000);
break; break;
} }
default: break;
}
}
static void alc_init_auto_hp(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
if (!spec->autocfg.hp_pins[0])
return;
if (!spec->autocfg.speaker_pins[0]) {
if (spec->autocfg.line_out_pins[0])
spec->autocfg.speaker_pins[0] =
spec->autocfg.line_out_pins[0];
else
return;
}
snd_hda_codec_write_cache(codec, spec->autocfg.hp_pins[0], 0,
AC_VERB_SET_UNSOLICITED_ENABLE,
AC_USRSP_EN | ALC880_HP_EVENT);
spec->unsol_event = alc_sku_unsol_event;
}
/* check subsystem ID and set up device-specific initialization;
* return 1 if initialized, 0 if invalid SSID
*/
/* 32-bit subsystem ID for BIOS loading in HD Audio codec.
* 31 ~ 16 : Manufacture ID
* 15 ~ 8 : SKU ID
* 7 ~ 0 : Assembly ID
* port-A --> pin 39/41, port-E --> pin 14/15, port-D --> pin 35/36
*/
static int alc_subsystem_id(struct hda_codec *codec,
hda_nid_t porta, hda_nid_t porte,
hda_nid_t portd)
{
unsigned int ass, tmp, i;
unsigned nid;
struct alc_spec *spec = codec->spec;
ass = codec->subsystem_id & 0xffff;
if ((ass != codec->bus->pci->subsystem_device) && (ass & 1))
goto do_sku;
/* invalid SSID, check the special NID pin defcfg instead */
/*
* 31~30 : port conetcivity
* 29~21 : reserve
* 20 : PCBEEP input
* 19~16 : Check sum (15:1)
* 15~1 : Custom
* 0 : override
*/
nid = 0x1d;
if (codec->vendor_id == 0x10ec0260)
nid = 0x17;
ass = snd_hda_codec_get_pincfg(codec, nid);
snd_printd("realtek: No valid SSID, "
"checking pincfg 0x%08x for NID 0x%x\n",
nid, ass);
if (!(ass & 1) && !(ass & 0x100000))
return 0;
if ((ass >> 30) != 1) /* no physical connection */
return 0;
/* check sum */
tmp = 0;
for (i = 1; i < 16; i++) {
if ((ass >> i) & 1)
tmp++;
}
if (((ass >> 16) & 0xf) != tmp)
return 0;
do_sku:
snd_printd("realtek: Enabling init ASM_ID=0x%04x CODEC_ID=%08x\n",
ass & 0xffff, codec->vendor_id);
/*
* 0 : override
* 1 : Swap Jack
* 2 : 0 --> Desktop, 1 --> Laptop
* 3~5 : External Amplifier control
* 7~6 : Reserved
*/
tmp = (ass & 0x38) >> 3; /* external Amp control */
switch (tmp) {
case 1:
spec->init_amp = ALC_INIT_GPIO1;
break;
case 3:
spec->init_amp = ALC_INIT_GPIO2;
break;
case 7:
spec->init_amp = ALC_INIT_GPIO3;
break;
case 5:
spec->init_amp = ALC_INIT_DEFAULT;
break; break;
} }
...@@ -1138,7 +1192,7 @@ static void alc_subsystem_id(struct hda_codec *codec, ...@@ -1138,7 +1192,7 @@ static void alc_subsystem_id(struct hda_codec *codec,
* when the external headphone out jack is plugged" * when the external headphone out jack is plugged"
*/ */
if (!(ass & 0x8000)) if (!(ass & 0x8000))
return; return 1;
/* /*
* 10~8 : Jack location * 10~8 : Jack location
* 12~11: Headphone out -> 00: PortA, 01: PortE, 02: PortD, 03: Resvered * 12~11: Headphone out -> 00: PortA, 01: PortE, 02: PortD, 03: Resvered
...@@ -1146,14 +1200,6 @@ static void alc_subsystem_id(struct hda_codec *codec, ...@@ -1146,14 +1200,6 @@ static void alc_subsystem_id(struct hda_codec *codec,
* 15 : 1 --> enable the function "Mute internal speaker * 15 : 1 --> enable the function "Mute internal speaker
* when the external headphone out jack is plugged" * when the external headphone out jack is plugged"
*/ */
if (!spec->autocfg.speaker_pins[0]) {
if (spec->autocfg.line_out_pins[0])
spec->autocfg.speaker_pins[0] =
spec->autocfg.line_out_pins[0];
else
return;
}
if (!spec->autocfg.hp_pins[0]) { if (!spec->autocfg.hp_pins[0]) {
tmp = (ass >> 11) & 0x3; /* HP to chassis */ tmp = (ass >> 11) & 0x3; /* HP to chassis */
if (tmp == 0) if (tmp == 0)
...@@ -1163,23 +1209,23 @@ static void alc_subsystem_id(struct hda_codec *codec, ...@@ -1163,23 +1209,23 @@ static void alc_subsystem_id(struct hda_codec *codec,
else if (tmp == 2) else if (tmp == 2)
spec->autocfg.hp_pins[0] = portd; spec->autocfg.hp_pins[0] = portd;
else else
return; return 1;
} }
if (spec->autocfg.hp_pins[0])
snd_hda_codec_write(codec, spec->autocfg.hp_pins[0], 0,
AC_VERB_SET_UNSOLICITED_ENABLE,
AC_USRSP_EN | ALC880_HP_EVENT);
#if 0 /* it's broken in some acses -- temporarily disabled */ alc_init_auto_hp(codec);
if (spec->autocfg.input_pins[AUTO_PIN_MIC] && return 1;
spec->autocfg.input_pins[AUTO_PIN_FRONT_MIC]) }
snd_hda_codec_write(codec,
spec->autocfg.input_pins[AUTO_PIN_MIC], 0,
AC_VERB_SET_UNSOLICITED_ENABLE,
AC_USRSP_EN | ALC880_MIC_EVENT);
#endif /* disabled */
spec->unsol_event = alc_sku_unsol_event; static void alc_ssid_check(struct hda_codec *codec,
hda_nid_t porta, hda_nid_t porte, hda_nid_t portd)
{
if (!alc_subsystem_id(codec, porta, porte, portd)) {
struct alc_spec *spec = codec->spec;
snd_printd("realtek: "
"Enable default setup for auto mode as fallback\n");
spec->init_amp = ALC_INIT_DEFAULT;
alc_init_auto_hp(codec);
}
} }
/* /*
...@@ -2923,8 +2969,7 @@ static int alc_init(struct hda_codec *codec) ...@@ -2923,8 +2969,7 @@ static int alc_init(struct hda_codec *codec)
unsigned int i; unsigned int i;
alc_fix_pll(codec); alc_fix_pll(codec);
if (codec->vendor_id == 0x10ec0888) alc_auto_init_amp(codec, spec->init_amp);
alc888_coef_init(codec);
for (i = 0; i < spec->num_init_verbs; i++) for (i = 0; i < spec->num_init_verbs; i++)
snd_hda_sequence_write(codec, spec->init_verbs[i]); snd_hda_sequence_write(codec, spec->init_verbs[i]);
...@@ -4198,7 +4243,6 @@ static void alc880_auto_init_multi_out(struct hda_codec *codec) ...@@ -4198,7 +4243,6 @@ static void alc880_auto_init_multi_out(struct hda_codec *codec)
struct alc_spec *spec = codec->spec; struct alc_spec *spec = codec->spec;
int i; int i;
alc_subsystem_id(codec, 0x15, 0x1b, 0x14);
for (i = 0; i < spec->autocfg.line_outs; i++) { for (i = 0; i < spec->autocfg.line_outs; i++) {
hda_nid_t nid = spec->autocfg.line_out_pins[i]; hda_nid_t nid = spec->autocfg.line_out_pins[i];
int pin_type = get_pin_type(spec->autocfg.line_out_type); int pin_type = get_pin_type(spec->autocfg.line_out_type);
...@@ -4303,6 +4347,8 @@ static int alc880_parse_auto_config(struct hda_codec *codec) ...@@ -4303,6 +4347,8 @@ static int alc880_parse_auto_config(struct hda_codec *codec)
spec->num_mux_defs = 1; spec->num_mux_defs = 1;
spec->input_mux = &spec->private_imux[0]; spec->input_mux = &spec->private_imux[0];
alc_ssid_check(codec, 0x15, 0x1b, 0x14);
return 1; return 1;
} }
...@@ -5678,7 +5724,6 @@ static void alc260_auto_init_multi_out(struct hda_codec *codec) ...@@ -5678,7 +5724,6 @@ static void alc260_auto_init_multi_out(struct hda_codec *codec)
struct alc_spec *spec = codec->spec; struct alc_spec *spec = codec->spec;
hda_nid_t nid; hda_nid_t nid;
alc_subsystem_id(codec, 0x10, 0x15, 0x0f);
nid = spec->autocfg.line_out_pins[0]; nid = spec->autocfg.line_out_pins[0];
if (nid) { if (nid) {
int pin_type = get_pin_type(spec->autocfg.line_out_type); int pin_type = get_pin_type(spec->autocfg.line_out_type);
...@@ -5788,6 +5833,8 @@ static int alc260_parse_auto_config(struct hda_codec *codec) ...@@ -5788,6 +5833,8 @@ static int alc260_parse_auto_config(struct hda_codec *codec)
spec->num_mux_defs = 1; spec->num_mux_defs = 1;
spec->input_mux = &spec->private_imux[0]; spec->input_mux = &spec->private_imux[0];
alc_ssid_check(codec, 0x10, 0x15, 0x0f);
return 1; return 1;
} }
...@@ -7013,7 +7060,6 @@ static void alc882_auto_init_multi_out(struct hda_codec *codec) ...@@ -7013,7 +7060,6 @@ static void alc882_auto_init_multi_out(struct hda_codec *codec)
struct alc_spec *spec = codec->spec; struct alc_spec *spec = codec->spec;
int i; int i;
alc_subsystem_id(codec, 0x15, 0x1b, 0x14);
for (i = 0; i <= HDA_SIDE; i++) { for (i = 0; i <= HDA_SIDE; i++) {
hda_nid_t nid = spec->autocfg.line_out_pins[i]; hda_nid_t nid = spec->autocfg.line_out_pins[i];
int pin_type = get_pin_type(spec->autocfg.line_out_type); int pin_type = get_pin_type(spec->autocfg.line_out_type);
...@@ -9154,7 +9200,6 @@ static void alc883_auto_init_multi_out(struct hda_codec *codec) ...@@ -9154,7 +9200,6 @@ static void alc883_auto_init_multi_out(struct hda_codec *codec)
struct alc_spec *spec = codec->spec; struct alc_spec *spec = codec->spec;
int i; int i;
alc_subsystem_id(codec, 0x15, 0x1b, 0x14);
for (i = 0; i <= HDA_SIDE; i++) { for (i = 0; i <= HDA_SIDE; i++) {
hda_nid_t nid = spec->autocfg.line_out_pins[i]; hda_nid_t nid = spec->autocfg.line_out_pins[i];
int pin_type = get_pin_type(spec->autocfg.line_out_type); int pin_type = get_pin_type(spec->autocfg.line_out_type);
...@@ -9317,6 +9362,7 @@ static int patch_alc883(struct hda_codec *codec) ...@@ -9317,6 +9362,7 @@ static int patch_alc883(struct hda_codec *codec)
if (!spec->capsrc_nids) if (!spec->capsrc_nids)
spec->capsrc_nids = alc883_capsrc_nids; spec->capsrc_nids = alc883_capsrc_nids;
spec->capture_style = CAPT_MIX; /* matrix-style capture */ spec->capture_style = CAPT_MIX; /* matrix-style capture */
spec->init_amp = ALC_INIT_DEFAULT; /* always initialize */
break; break;
case 0x10ec0889: case 0x10ec0889:
spec->stream_name_analog = "ALC889 Analog"; spec->stream_name_analog = "ALC889 Analog";
...@@ -10842,6 +10888,8 @@ static int alc262_parse_auto_config(struct hda_codec *codec) ...@@ -10842,6 +10888,8 @@ static int alc262_parse_auto_config(struct hda_codec *codec)
if (err < 0) if (err < 0)
return err; return err;
alc_ssid_check(codec, 0x15, 0x14, 0x1b);
return 1; return 1;
} }
...@@ -13925,7 +13973,6 @@ static void alc861_auto_init_multi_out(struct hda_codec *codec) ...@@ -13925,7 +13973,6 @@ static void alc861_auto_init_multi_out(struct hda_codec *codec)
struct alc_spec *spec = codec->spec; struct alc_spec *spec = codec->spec;
int i; int i;
alc_subsystem_id(codec, 0x0e, 0x0f, 0x0b);
for (i = 0; i < spec->autocfg.line_outs; i++) { for (i = 0; i < spec->autocfg.line_outs; i++) {
hda_nid_t nid = spec->autocfg.line_out_pins[i]; hda_nid_t nid = spec->autocfg.line_out_pins[i];
int pin_type = get_pin_type(spec->autocfg.line_out_type); int pin_type = get_pin_type(spec->autocfg.line_out_type);
...@@ -14008,6 +14055,8 @@ static int alc861_parse_auto_config(struct hda_codec *codec) ...@@ -14008,6 +14055,8 @@ static int alc861_parse_auto_config(struct hda_codec *codec)
spec->num_adc_nids = ARRAY_SIZE(alc861_adc_nids); spec->num_adc_nids = ARRAY_SIZE(alc861_adc_nids);
set_capture_mixer(spec); set_capture_mixer(spec);
alc_ssid_check(codec, 0x0e, 0x0f, 0x0b);
return 1; return 1;
} }
...@@ -14889,7 +14938,6 @@ static void alc861vd_auto_init_multi_out(struct hda_codec *codec) ...@@ -14889,7 +14938,6 @@ static void alc861vd_auto_init_multi_out(struct hda_codec *codec)
struct alc_spec *spec = codec->spec; struct alc_spec *spec = codec->spec;
int i; int i;
alc_subsystem_id(codec, 0x15, 0x1b, 0x14);
for (i = 0; i <= HDA_SIDE; i++) { for (i = 0; i <= HDA_SIDE; i++) {
hda_nid_t nid = spec->autocfg.line_out_pins[i]; hda_nid_t nid = spec->autocfg.line_out_pins[i];
int pin_type = get_pin_type(spec->autocfg.line_out_type); int pin_type = get_pin_type(spec->autocfg.line_out_type);
...@@ -15107,6 +15155,8 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec) ...@@ -15107,6 +15155,8 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec)
if (err < 0) if (err < 0)
return err; return err;
alc_ssid_check(codec, 0x15, 0x1b, 0x14);
return 1; return 1;
} }
...@@ -16931,7 +16981,6 @@ static void alc662_auto_init_multi_out(struct hda_codec *codec) ...@@ -16931,7 +16981,6 @@ static void alc662_auto_init_multi_out(struct hda_codec *codec)
struct alc_spec *spec = codec->spec; struct alc_spec *spec = codec->spec;
int i; int i;
alc_subsystem_id(codec, 0x15, 0x1b, 0x14);
for (i = 0; i <= HDA_SIDE; i++) { for (i = 0; i <= HDA_SIDE; i++) {
hda_nid_t nid = spec->autocfg.line_out_pins[i]; hda_nid_t nid = spec->autocfg.line_out_pins[i];
int pin_type = get_pin_type(spec->autocfg.line_out_type); int pin_type = get_pin_type(spec->autocfg.line_out_type);
...@@ -17028,6 +17077,8 @@ static int alc662_parse_auto_config(struct hda_codec *codec) ...@@ -17028,6 +17077,8 @@ static int alc662_parse_auto_config(struct hda_codec *codec)
if (err < 0) if (err < 0)
return err; return err;
alc_ssid_check(codec, 0x15, 0x1b, 0x14);
return 1; return 1;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment