diff options
Diffstat (limited to 'sound/pci/hda')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 76 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.h | 2 | ||||
-rw-r--r-- | sound/pci/hda/hda_generic.c | 199 | ||||
-rw-r--r-- | sound/pci/hda/hda_intel.c | 132 | ||||
-rw-r--r-- | sound/pci/hda/hda_local.h | 8 | ||||
-rw-r--r-- | sound/pci/hda/hda_proc.c | 12 | ||||
-rw-r--r-- | sound/pci/hda/patch_analog.c | 21 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 330 | ||||
-rw-r--r-- | sound/pci/hda/patch_si3054.c | 1 | ||||
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 904 |
10 files changed, 1323 insertions, 362 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 23201f3eeb12..9c3d7ac08068 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <sound/core.h> | 29 | #include <sound/core.h> |
30 | #include "hda_codec.h" | 30 | #include "hda_codec.h" |
31 | #include <sound/asoundef.h> | 31 | #include <sound/asoundef.h> |
32 | #include <sound/tlv.h> | ||
32 | #include <sound/initval.h> | 33 | #include <sound/initval.h> |
33 | #include "hda_local.h" | 34 | #include "hda_local.h" |
34 | 35 | ||
@@ -50,8 +51,10 @@ struct hda_vendor_id { | |||
50 | /* codec vendor labels */ | 51 | /* codec vendor labels */ |
51 | static struct hda_vendor_id hda_vendor_ids[] = { | 52 | static struct hda_vendor_id hda_vendor_ids[] = { |
52 | { 0x10ec, "Realtek" }, | 53 | { 0x10ec, "Realtek" }, |
54 | { 0x1057, "Motorola" }, | ||
53 | { 0x11d4, "Analog Devices" }, | 55 | { 0x11d4, "Analog Devices" }, |
54 | { 0x13f6, "C-Media" }, | 56 | { 0x13f6, "C-Media" }, |
57 | { 0x14f1, "Conexant" }, | ||
55 | { 0x434d, "C-Media" }, | 58 | { 0x434d, "C-Media" }, |
56 | { 0x8384, "SigmaTel" }, | 59 | { 0x8384, "SigmaTel" }, |
57 | {} /* terminator */ | 60 | {} /* terminator */ |
@@ -841,6 +844,31 @@ int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
841 | return change; | 844 | return change; |
842 | } | 845 | } |
843 | 846 | ||
847 | int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, | ||
848 | unsigned int size, unsigned int __user *_tlv) | ||
849 | { | ||
850 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
851 | hda_nid_t nid = get_amp_nid(kcontrol); | ||
852 | int dir = get_amp_direction(kcontrol); | ||
853 | u32 caps, val1, val2; | ||
854 | |||
855 | if (size < 4 * sizeof(unsigned int)) | ||
856 | return -ENOMEM; | ||
857 | caps = query_amp_caps(codec, nid, dir); | ||
858 | val2 = (((caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT) + 1) * 25; | ||
859 | val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT); | ||
860 | val1 = ((int)val1) * ((int)val2); | ||
861 | if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv)) | ||
862 | return -EFAULT; | ||
863 | if (put_user(2 * sizeof(unsigned int), _tlv + 1)) | ||
864 | return -EFAULT; | ||
865 | if (put_user(val1, _tlv + 2)) | ||
866 | return -EFAULT; | ||
867 | if (put_user(val2, _tlv + 3)) | ||
868 | return -EFAULT; | ||
869 | return 0; | ||
870 | } | ||
871 | |||
844 | /* switch */ | 872 | /* switch */ |
845 | int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 873 | int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) |
846 | { | 874 | { |
@@ -1477,10 +1505,10 @@ int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, | |||
1477 | formats |= SNDRV_PCM_FMTBIT_S32_LE; | 1505 | formats |= SNDRV_PCM_FMTBIT_S32_LE; |
1478 | if (val & AC_SUPPCM_BITS_32) | 1506 | if (val & AC_SUPPCM_BITS_32) |
1479 | bps = 32; | 1507 | bps = 32; |
1480 | else if (val & AC_SUPPCM_BITS_20) | ||
1481 | bps = 20; | ||
1482 | else if (val & AC_SUPPCM_BITS_24) | 1508 | else if (val & AC_SUPPCM_BITS_24) |
1483 | bps = 24; | 1509 | bps = 24; |
1510 | else if (val & AC_SUPPCM_BITS_20) | ||
1511 | bps = 20; | ||
1484 | } | 1512 | } |
1485 | } | 1513 | } |
1486 | else if (streams == AC_SUPFMT_FLOAT32) { /* should be exclusive */ | 1514 | else if (streams == AC_SUPFMT_FLOAT32) { /* should be exclusive */ |
@@ -1916,7 +1944,7 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_o | |||
1916 | 1944 | ||
1917 | /* front */ | 1945 | /* front */ |
1918 | snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag, 0, format); | 1946 | snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag, 0, format); |
1919 | if (mout->hp_nid) | 1947 | if (mout->hp_nid && mout->hp_nid != nids[HDA_FRONT]) |
1920 | /* headphone out will just decode front left/right (stereo) */ | 1948 | /* headphone out will just decode front left/right (stereo) */ |
1921 | snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag, 0, format); | 1949 | snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag, 0, format); |
1922 | /* extra outputs copied from front */ | 1950 | /* extra outputs copied from front */ |
@@ -1984,7 +2012,7 @@ static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list) | |||
1984 | * in the order of front, rear, CLFE, side, ... | 2012 | * in the order of front, rear, CLFE, side, ... |
1985 | * | 2013 | * |
1986 | * If more extra outputs (speaker and headphone) are found, the pins are | 2014 | * If more extra outputs (speaker and headphone) are found, the pins are |
1987 | * assisnged to hp_pin and speaker_pins[], respectively. If no line-out jack | 2015 | * assisnged to hp_pins[] and speaker_pins[], respectively. If no line-out jack |
1988 | * is detected, one of speaker of HP pins is assigned as the primary | 2016 | * is detected, one of speaker of HP pins is assigned as the primary |
1989 | * output, i.e. to line_out_pins[0]. So, line_outs is always positive | 2017 | * output, i.e. to line_out_pins[0]. So, line_outs is always positive |
1990 | * if any analog output exists. | 2018 | * if any analog output exists. |
@@ -2046,14 +2074,26 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c | |||
2046 | cfg->speaker_outs++; | 2074 | cfg->speaker_outs++; |
2047 | break; | 2075 | break; |
2048 | case AC_JACK_HP_OUT: | 2076 | case AC_JACK_HP_OUT: |
2049 | cfg->hp_pin = nid; | 2077 | if (cfg->hp_outs >= ARRAY_SIZE(cfg->hp_pins)) |
2078 | continue; | ||
2079 | cfg->hp_pins[cfg->hp_outs] = nid; | ||
2080 | cfg->hp_outs++; | ||
2050 | break; | 2081 | break; |
2051 | case AC_JACK_MIC_IN: | 2082 | case AC_JACK_MIC_IN: { |
2052 | if (loc == AC_JACK_LOC_FRONT) | 2083 | int preferred, alt; |
2053 | cfg->input_pins[AUTO_PIN_FRONT_MIC] = nid; | 2084 | if (loc == AC_JACK_LOC_FRONT) { |
2054 | else | 2085 | preferred = AUTO_PIN_FRONT_MIC; |
2055 | cfg->input_pins[AUTO_PIN_MIC] = nid; | 2086 | alt = AUTO_PIN_MIC; |
2087 | } else { | ||
2088 | preferred = AUTO_PIN_MIC; | ||
2089 | alt = AUTO_PIN_FRONT_MIC; | ||
2090 | } | ||
2091 | if (!cfg->input_pins[preferred]) | ||
2092 | cfg->input_pins[preferred] = nid; | ||
2093 | else if (!cfg->input_pins[alt]) | ||
2094 | cfg->input_pins[alt] = nid; | ||
2056 | break; | 2095 | break; |
2096 | } | ||
2057 | case AC_JACK_LINE_IN: | 2097 | case AC_JACK_LINE_IN: |
2058 | if (loc == AC_JACK_LOC_FRONT) | 2098 | if (loc == AC_JACK_LOC_FRONT) |
2059 | cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid; | 2099 | cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid; |
@@ -2119,8 +2159,10 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c | |||
2119 | cfg->speaker_outs, cfg->speaker_pins[0], | 2159 | cfg->speaker_outs, cfg->speaker_pins[0], |
2120 | cfg->speaker_pins[1], cfg->speaker_pins[2], | 2160 | cfg->speaker_pins[1], cfg->speaker_pins[2], |
2121 | cfg->speaker_pins[3], cfg->speaker_pins[4]); | 2161 | cfg->speaker_pins[3], cfg->speaker_pins[4]); |
2122 | snd_printd(" hp=0x%x, dig_out=0x%x, din_in=0x%x\n", | 2162 | snd_printd(" hp_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n", |
2123 | cfg->hp_pin, cfg->dig_out_pin, cfg->dig_in_pin); | 2163 | cfg->hp_outs, cfg->hp_pins[0], |
2164 | cfg->hp_pins[1], cfg->hp_pins[2], | ||
2165 | cfg->hp_pins[3], cfg->hp_pins[4]); | ||
2124 | snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x," | 2166 | snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x," |
2125 | " cd=0x%x, aux=0x%x\n", | 2167 | " cd=0x%x, aux=0x%x\n", |
2126 | cfg->input_pins[AUTO_PIN_MIC], | 2168 | cfg->input_pins[AUTO_PIN_MIC], |
@@ -2141,10 +2183,12 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c | |||
2141 | sizeof(cfg->speaker_pins)); | 2183 | sizeof(cfg->speaker_pins)); |
2142 | cfg->speaker_outs = 0; | 2184 | cfg->speaker_outs = 0; |
2143 | memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins)); | 2185 | memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins)); |
2144 | } else if (cfg->hp_pin) { | 2186 | } else if (cfg->hp_outs) { |
2145 | cfg->line_outs = 1; | 2187 | cfg->line_outs = cfg->hp_outs; |
2146 | cfg->line_out_pins[0] = cfg->hp_pin; | 2188 | memcpy(cfg->line_out_pins, cfg->hp_pins, |
2147 | cfg->hp_pin = 0; | 2189 | sizeof(cfg->hp_pins)); |
2190 | cfg->hp_outs = 0; | ||
2191 | memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins)); | ||
2148 | } | 2192 | } |
2149 | } | 2193 | } |
2150 | 2194 | ||
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 40520e9d5a4b..c12bc4e8840f 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -479,7 +479,7 @@ struct hda_codec_ops { | |||
479 | struct hda_amp_info { | 479 | struct hda_amp_info { |
480 | u32 key; /* hash key */ | 480 | u32 key; /* hash key */ |
481 | u32 amp_caps; /* amp capabilities */ | 481 | u32 amp_caps; /* amp capabilities */ |
482 | u16 vol[2]; /* current volume & mute*/ | 482 | u16 vol[2]; /* current volume & mute */ |
483 | u16 status; /* update flag */ | 483 | u16 status; /* update flag */ |
484 | u16 next; /* next link */ | 484 | u16 next; /* next link */ |
485 | }; | 485 | }; |
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 85ad164ada59..97e9af130b71 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c | |||
@@ -46,11 +46,18 @@ struct hda_gnode { | |||
46 | }; | 46 | }; |
47 | 47 | ||
48 | /* patch-specific record */ | 48 | /* patch-specific record */ |
49 | |||
50 | #define MAX_PCM_VOLS 2 | ||
51 | struct pcm_vol { | ||
52 | struct hda_gnode *node; /* Node for PCM volume */ | ||
53 | unsigned int index; /* connection of PCM volume */ | ||
54 | }; | ||
55 | |||
49 | struct hda_gspec { | 56 | struct hda_gspec { |
50 | struct hda_gnode *dac_node[2]; /* DAC node */ | 57 | struct hda_gnode *dac_node[2]; /* DAC node */ |
51 | struct hda_gnode *out_pin_node[2]; /* Output pin (Line-Out) node */ | 58 | struct hda_gnode *out_pin_node[2]; /* Output pin (Line-Out) node */ |
52 | struct hda_gnode *pcm_vol_node[2]; /* Node for PCM volume */ | 59 | struct pcm_vol pcm_vol[MAX_PCM_VOLS]; /* PCM volumes */ |
53 | unsigned int pcm_vol_index[2]; /* connection of PCM volume */ | 60 | unsigned int pcm_vol_nodes; /* number of PCM volumes */ |
54 | 61 | ||
55 | struct hda_gnode *adc_node; /* ADC node */ | 62 | struct hda_gnode *adc_node; /* ADC node */ |
56 | struct hda_gnode *cap_vol_node; /* Node for capture volume */ | 63 | struct hda_gnode *cap_vol_node; /* Node for capture volume */ |
@@ -285,9 +292,11 @@ static int parse_output_path(struct hda_codec *codec, struct hda_gspec *spec, | |||
285 | return node == spec->dac_node[dac_idx]; | 292 | return node == spec->dac_node[dac_idx]; |
286 | } | 293 | } |
287 | spec->dac_node[dac_idx] = node; | 294 | spec->dac_node[dac_idx] = node; |
288 | if (node->wid_caps & AC_WCAP_OUT_AMP) { | 295 | if ((node->wid_caps & AC_WCAP_OUT_AMP) && |
289 | spec->pcm_vol_node[dac_idx] = node; | 296 | spec->pcm_vol_nodes < MAX_PCM_VOLS) { |
290 | spec->pcm_vol_index[dac_idx] = 0; | 297 | spec->pcm_vol[spec->pcm_vol_nodes].node = node; |
298 | spec->pcm_vol[spec->pcm_vol_nodes].index = 0; | ||
299 | spec->pcm_vol_nodes++; | ||
291 | } | 300 | } |
292 | return 1; /* found */ | 301 | return 1; /* found */ |
293 | } | 302 | } |
@@ -307,13 +316,16 @@ static int parse_output_path(struct hda_codec *codec, struct hda_gspec *spec, | |||
307 | select_input_connection(codec, node, i); | 316 | select_input_connection(codec, node, i); |
308 | unmute_input(codec, node, i); | 317 | unmute_input(codec, node, i); |
309 | unmute_output(codec, node); | 318 | unmute_output(codec, node); |
310 | if (! spec->pcm_vol_node[dac_idx]) { | 319 | if (spec->dac_node[dac_idx] && |
311 | if (node->wid_caps & AC_WCAP_IN_AMP) { | 320 | spec->pcm_vol_nodes < MAX_PCM_VOLS && |
312 | spec->pcm_vol_node[dac_idx] = node; | 321 | !(spec->dac_node[dac_idx]->wid_caps & |
313 | spec->pcm_vol_index[dac_idx] = i; | 322 | AC_WCAP_OUT_AMP)) { |
314 | } else if (node->wid_caps & AC_WCAP_OUT_AMP) { | 323 | if ((node->wid_caps & AC_WCAP_IN_AMP) || |
315 | spec->pcm_vol_node[dac_idx] = node; | 324 | (node->wid_caps & AC_WCAP_OUT_AMP)) { |
316 | spec->pcm_vol_index[dac_idx] = 0; | 325 | int n = spec->pcm_vol_nodes; |
326 | spec->pcm_vol[n].node = node; | ||
327 | spec->pcm_vol[n].index = i; | ||
328 | spec->pcm_vol_nodes++; | ||
317 | } | 329 | } |
318 | } | 330 | } |
319 | return 1; | 331 | return 1; |
@@ -370,7 +382,9 @@ static struct hda_gnode *parse_output_jack(struct hda_codec *codec, | |||
370 | /* set PIN-Out enable */ | 382 | /* set PIN-Out enable */ |
371 | snd_hda_codec_write(codec, node->nid, 0, | 383 | snd_hda_codec_write(codec, node->nid, 0, |
372 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 384 | AC_VERB_SET_PIN_WIDGET_CONTROL, |
373 | AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN); | 385 | AC_PINCTL_OUT_EN | |
386 | ((node->pin_caps & AC_PINCAP_HP_DRV) ? | ||
387 | AC_PINCTL_HP_EN : 0)); | ||
374 | return node; | 388 | return node; |
375 | } | 389 | } |
376 | } | 390 | } |
@@ -461,14 +475,19 @@ static const char *get_input_type(struct hda_gnode *node, unsigned int *pinctl) | |||
461 | return "Front Line"; | 475 | return "Front Line"; |
462 | return "Line"; | 476 | return "Line"; |
463 | case AC_JACK_CD: | 477 | case AC_JACK_CD: |
478 | #if 0 | ||
464 | if (pinctl) | 479 | if (pinctl) |
465 | *pinctl |= AC_PINCTL_VREF_GRD; | 480 | *pinctl |= AC_PINCTL_VREF_GRD; |
481 | #endif | ||
466 | return "CD"; | 482 | return "CD"; |
467 | case AC_JACK_AUX: | 483 | case AC_JACK_AUX: |
468 | if ((location & 0x0f) == AC_JACK_LOC_FRONT) | 484 | if ((location & 0x0f) == AC_JACK_LOC_FRONT) |
469 | return "Front Aux"; | 485 | return "Front Aux"; |
470 | return "Aux"; | 486 | return "Aux"; |
471 | case AC_JACK_MIC_IN: | 487 | case AC_JACK_MIC_IN: |
488 | if (node->pin_caps & | ||
489 | (AC_PINCAP_VREF_80 << AC_PINCAP_VREF_SHIFT)) | ||
490 | *pinctl |= AC_PINCTL_VREF_80; | ||
472 | if ((location & 0x0f) == AC_JACK_LOC_FRONT) | 491 | if ((location & 0x0f) == AC_JACK_LOC_FRONT) |
473 | return "Front Mic"; | 492 | return "Front Mic"; |
474 | return "Mic"; | 493 | return "Mic"; |
@@ -556,6 +575,29 @@ static int parse_adc_sub_nodes(struct hda_codec *codec, struct hda_gspec *spec, | |||
556 | return 1; /* found */ | 575 | return 1; /* found */ |
557 | } | 576 | } |
558 | 577 | ||
578 | /* add a capture source element */ | ||
579 | static void add_cap_src(struct hda_gspec *spec, int idx) | ||
580 | { | ||
581 | struct hda_input_mux_item *csrc; | ||
582 | char *buf; | ||
583 | int num, ocap; | ||
584 | |||
585 | num = spec->input_mux.num_items; | ||
586 | csrc = &spec->input_mux.items[num]; | ||
587 | buf = spec->cap_labels[num]; | ||
588 | for (ocap = 0; ocap < num; ocap++) { | ||
589 | if (! strcmp(buf, spec->cap_labels[ocap])) { | ||
590 | /* same label already exists, | ||
591 | * put the index number to be unique | ||
592 | */ | ||
593 | sprintf(buf, "%s %d", spec->cap_labels[ocap], num); | ||
594 | break; | ||
595 | } | ||
596 | } | ||
597 | csrc->index = idx; | ||
598 | spec->input_mux.num_items++; | ||
599 | } | ||
600 | |||
559 | /* | 601 | /* |
560 | * parse input | 602 | * parse input |
561 | */ | 603 | */ |
@@ -576,28 +618,26 @@ static int parse_input_path(struct hda_codec *codec, struct hda_gnode *adc_node) | |||
576 | * if it reaches to a proper input PIN, add the path as the | 618 | * if it reaches to a proper input PIN, add the path as the |
577 | * input path. | 619 | * input path. |
578 | */ | 620 | */ |
621 | /* first, check the direct connections to PIN widgets */ | ||
579 | for (i = 0; i < adc_node->nconns; i++) { | 622 | for (i = 0; i < adc_node->nconns; i++) { |
580 | node = hda_get_node(spec, adc_node->conn_list[i]); | 623 | node = hda_get_node(spec, adc_node->conn_list[i]); |
581 | if (! node) | 624 | if (node && node->type == AC_WID_PIN) { |
582 | continue; | 625 | err = parse_adc_sub_nodes(codec, spec, node); |
583 | err = parse_adc_sub_nodes(codec, spec, node); | 626 | if (err < 0) |
584 | if (err < 0) | 627 | return err; |
585 | return err; | 628 | else if (err > 0) |
586 | else if (err > 0) { | 629 | add_cap_src(spec, i); |
587 | struct hda_input_mux_item *csrc = &spec->input_mux.items[spec->input_mux.num_items]; | 630 | } |
588 | char *buf = spec->cap_labels[spec->input_mux.num_items]; | 631 | } |
589 | int ocap; | 632 | /* ... then check the rests, more complicated connections */ |
590 | for (ocap = 0; ocap < spec->input_mux.num_items; ocap++) { | 633 | for (i = 0; i < adc_node->nconns; i++) { |
591 | if (! strcmp(buf, spec->cap_labels[ocap])) { | 634 | node = hda_get_node(spec, adc_node->conn_list[i]); |
592 | /* same label already exists, | 635 | if (node && node->type != AC_WID_PIN) { |
593 | * put the index number to be unique | 636 | err = parse_adc_sub_nodes(codec, spec, node); |
594 | */ | 637 | if (err < 0) |
595 | sprintf(buf, "%s %d", spec->cap_labels[ocap], | 638 | return err; |
596 | spec->input_mux.num_items); | 639 | else if (err > 0) |
597 | } | 640 | add_cap_src(spec, i); |
598 | } | ||
599 | csrc->index = i; | ||
600 | spec->input_mux.num_items++; | ||
601 | } | 641 | } |
602 | } | 642 | } |
603 | 643 | ||
@@ -647,9 +687,6 @@ static int parse_input(struct hda_codec *codec) | |||
647 | /* | 687 | /* |
648 | * create mixer controls if possible | 688 | * create mixer controls if possible |
649 | */ | 689 | */ |
650 | #define DIR_OUT 0x1 | ||
651 | #define DIR_IN 0x2 | ||
652 | |||
653 | static int create_mixer(struct hda_codec *codec, struct hda_gnode *node, | 690 | static int create_mixer(struct hda_codec *codec, struct hda_gnode *node, |
654 | unsigned int index, const char *type, const char *dir_sfx) | 691 | unsigned int index, const char *type, const char *dir_sfx) |
655 | { | 692 | { |
@@ -722,49 +759,97 @@ static int check_existing_control(struct hda_codec *codec, const char *type, con | |||
722 | /* | 759 | /* |
723 | * build output mixer controls | 760 | * build output mixer controls |
724 | */ | 761 | */ |
725 | static int build_output_controls(struct hda_codec *codec) | 762 | static int create_output_mixers(struct hda_codec *codec, const char **names) |
726 | { | 763 | { |
727 | struct hda_gspec *spec = codec->spec; | 764 | struct hda_gspec *spec = codec->spec; |
728 | static const char *types[2] = { "Master", "Headphone" }; | ||
729 | int i, err; | 765 | int i, err; |
730 | 766 | ||
731 | for (i = 0; i < 2 && spec->pcm_vol_node[i]; i++) { | 767 | for (i = 0; i < spec->pcm_vol_nodes; i++) { |
732 | err = create_mixer(codec, spec->pcm_vol_node[i], | 768 | err = create_mixer(codec, spec->pcm_vol[i].node, |
733 | spec->pcm_vol_index[i], | 769 | spec->pcm_vol[i].index, |
734 | types[i], "Playback"); | 770 | names[i], "Playback"); |
735 | if (err < 0) | 771 | if (err < 0) |
736 | return err; | 772 | return err; |
737 | } | 773 | } |
738 | return 0; | 774 | return 0; |
739 | } | 775 | } |
740 | 776 | ||
777 | static int build_output_controls(struct hda_codec *codec) | ||
778 | { | ||
779 | struct hda_gspec *spec = codec->spec; | ||
780 | static const char *types_speaker[] = { "Speaker", "Headphone" }; | ||
781 | static const char *types_line[] = { "Front", "Headphone" }; | ||
782 | |||
783 | switch (spec->pcm_vol_nodes) { | ||
784 | case 1: | ||
785 | return create_mixer(codec, spec->pcm_vol[0].node, | ||
786 | spec->pcm_vol[0].index, | ||
787 | "Master", "Playback"); | ||
788 | case 2: | ||
789 | if (defcfg_type(spec->out_pin_node[0]) == AC_JACK_SPEAKER) | ||
790 | return create_output_mixers(codec, types_speaker); | ||
791 | else | ||
792 | return create_output_mixers(codec, types_line); | ||
793 | } | ||
794 | return 0; | ||
795 | } | ||
796 | |||
741 | /* create capture volume/switch */ | 797 | /* create capture volume/switch */ |
742 | static int build_input_controls(struct hda_codec *codec) | 798 | static int build_input_controls(struct hda_codec *codec) |
743 | { | 799 | { |
744 | struct hda_gspec *spec = codec->spec; | 800 | struct hda_gspec *spec = codec->spec; |
745 | struct hda_gnode *adc_node = spec->adc_node; | 801 | struct hda_gnode *adc_node = spec->adc_node; |
746 | int err; | 802 | int i, err; |
747 | 803 | static struct snd_kcontrol_new cap_sel = { | |
748 | if (! adc_node) | 804 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
805 | .name = "Capture Source", | ||
806 | .info = capture_source_info, | ||
807 | .get = capture_source_get, | ||
808 | .put = capture_source_put, | ||
809 | }; | ||
810 | |||
811 | if (! adc_node || ! spec->input_mux.num_items) | ||
749 | return 0; /* not found */ | 812 | return 0; /* not found */ |
750 | 813 | ||
814 | spec->cur_cap_src = 0; | ||
815 | select_input_connection(codec, adc_node, | ||
816 | spec->input_mux.items[0].index); | ||
817 | |||
751 | /* create capture volume and switch controls if the ADC has an amp */ | 818 | /* create capture volume and switch controls if the ADC has an amp */ |
752 | err = create_mixer(codec, adc_node, 0, NULL, "Capture"); | 819 | /* do we have only a single item? */ |
820 | if (spec->input_mux.num_items == 1) { | ||
821 | err = create_mixer(codec, adc_node, | ||
822 | spec->input_mux.items[0].index, | ||
823 | NULL, "Capture"); | ||
824 | if (err < 0) | ||
825 | return err; | ||
826 | return 0; | ||
827 | } | ||
753 | 828 | ||
754 | /* create input MUX if multiple sources are available */ | 829 | /* create input MUX if multiple sources are available */ |
755 | if (spec->input_mux.num_items > 1) { | 830 | if ((err = snd_ctl_add(codec->bus->card, |
756 | static struct snd_kcontrol_new cap_sel = { | 831 | snd_ctl_new1(&cap_sel, codec))) < 0) |
757 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 832 | return err; |
758 | .name = "Capture Source", | 833 | |
759 | .info = capture_source_info, | 834 | /* no volume control? */ |
760 | .get = capture_source_get, | 835 | if (! (adc_node->wid_caps & AC_WCAP_IN_AMP) || |
761 | .put = capture_source_put, | 836 | ! (adc_node->amp_in_caps & AC_AMPCAP_NUM_STEPS)) |
762 | }; | 837 | return 0; |
763 | if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&cap_sel, codec))) < 0) | 838 | |
839 | for (i = 0; i < spec->input_mux.num_items; i++) { | ||
840 | struct snd_kcontrol_new knew; | ||
841 | char name[32]; | ||
842 | sprintf(name, "%s Capture Volume", | ||
843 | spec->input_mux.items[i].label); | ||
844 | knew = (struct snd_kcontrol_new) | ||
845 | HDA_CODEC_VOLUME(name, adc_node->nid, | ||
846 | spec->input_mux.items[i].index, | ||
847 | HDA_INPUT); | ||
848 | if ((err = snd_ctl_add(codec->bus->card, | ||
849 | snd_ctl_new1(&knew, codec))) < 0) | ||
764 | return err; | 850 | return err; |
765 | spec->cur_cap_src = 0; | ||
766 | select_input_connection(codec, adc_node, spec->input_mux.items[0].index); | ||
767 | } | 851 | } |
852 | |||
768 | return 0; | 853 | return 0; |
769 | } | 854 | } |
770 | 855 | ||
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 79d63c99f092..e9d4cb4d07e1 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -55,6 +55,7 @@ static char *model; | |||
55 | static int position_fix; | 55 | static int position_fix; |
56 | static int probe_mask = -1; | 56 | static int probe_mask = -1; |
57 | static int single_cmd; | 57 | static int single_cmd; |
58 | static int disable_msi; | ||
58 | 59 | ||
59 | module_param(index, int, 0444); | 60 | module_param(index, int, 0444); |
60 | MODULE_PARM_DESC(index, "Index value for Intel HD audio interface."); | 61 | MODULE_PARM_DESC(index, "Index value for Intel HD audio interface."); |
@@ -68,6 +69,8 @@ module_param(probe_mask, int, 0444); | |||
68 | MODULE_PARM_DESC(probe_mask, "Bitmask to probe codecs (default = -1)."); | 69 | MODULE_PARM_DESC(probe_mask, "Bitmask to probe codecs (default = -1)."); |
69 | module_param(single_cmd, bool, 0444); | 70 | module_param(single_cmd, bool, 0444); |
70 | MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs (for debugging only)."); | 71 | MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs (for debugging only)."); |
72 | module_param(disable_msi, int, 0); | ||
73 | MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)"); | ||
71 | 74 | ||
72 | 75 | ||
73 | /* just for backward compatibility */ | 76 | /* just for backward compatibility */ |
@@ -252,7 +255,7 @@ enum { | |||
252 | struct azx_dev { | 255 | struct azx_dev { |
253 | u32 *bdl; /* virtual address of the BDL */ | 256 | u32 *bdl; /* virtual address of the BDL */ |
254 | dma_addr_t bdl_addr; /* physical address of the BDL */ | 257 | dma_addr_t bdl_addr; /* physical address of the BDL */ |
255 | volatile u32 *posbuf; /* position buffer pointer */ | 258 | u32 *posbuf; /* position buffer pointer */ |
256 | 259 | ||
257 | unsigned int bufsize; /* size of the play buffer in bytes */ | 260 | unsigned int bufsize; /* size of the play buffer in bytes */ |
258 | unsigned int fragsize; /* size of each period in bytes */ | 261 | unsigned int fragsize; /* size of each period in bytes */ |
@@ -271,8 +274,8 @@ struct azx_dev { | |||
271 | /* for sanity check of position buffer */ | 274 | /* for sanity check of position buffer */ |
272 | unsigned int period_intr; | 275 | unsigned int period_intr; |
273 | 276 | ||
274 | unsigned int opened: 1; | 277 | unsigned int opened :1; |
275 | unsigned int running: 1; | 278 | unsigned int running :1; |
276 | }; | 279 | }; |
277 | 280 | ||
278 | /* CORB/RIRB */ | 281 | /* CORB/RIRB */ |
@@ -330,8 +333,9 @@ struct azx { | |||
330 | 333 | ||
331 | /* flags */ | 334 | /* flags */ |
332 | int position_fix; | 335 | int position_fix; |
333 | unsigned int initialized: 1; | 336 | unsigned int initialized :1; |
334 | unsigned int single_cmd: 1; | 337 | unsigned int single_cmd :1; |
338 | unsigned int polling_mode :1; | ||
335 | }; | 339 | }; |
336 | 340 | ||
337 | /* driver types */ | 341 | /* driver types */ |
@@ -516,23 +520,36 @@ static void azx_update_rirb(struct azx *chip) | |||
516 | static unsigned int azx_rirb_get_response(struct hda_codec *codec) | 520 | static unsigned int azx_rirb_get_response(struct hda_codec *codec) |
517 | { | 521 | { |
518 | struct azx *chip = codec->bus->private_data; | 522 | struct azx *chip = codec->bus->private_data; |
519 | int timeout = 50; | 523 | unsigned long timeout; |
520 | 524 | ||
521 | while (chip->rirb.cmds) { | 525 | again: |
522 | if (! --timeout) { | 526 | timeout = jiffies + msecs_to_jiffies(1000); |
523 | snd_printk(KERN_ERR | 527 | do { |
524 | "hda_intel: azx_get_response timeout, " | 528 | if (chip->polling_mode) { |
525 | "switching to single_cmd mode...\n"); | 529 | spin_lock_irq(&chip->reg_lock); |
526 | chip->rirb.rp = azx_readb(chip, RIRBWP); | 530 | azx_update_rirb(chip); |
527 | chip->rirb.cmds = 0; | 531 | spin_unlock_irq(&chip->reg_lock); |
528 | /* switch to single_cmd mode */ | ||
529 | chip->single_cmd = 1; | ||
530 | azx_free_cmd_io(chip); | ||
531 | return -1; | ||
532 | } | 532 | } |
533 | msleep(1); | 533 | if (! chip->rirb.cmds) |
534 | return chip->rirb.res; /* the last value */ | ||
535 | schedule_timeout_interruptible(1); | ||
536 | } while (time_after_eq(timeout, jiffies)); | ||
537 | |||
538 | if (!chip->polling_mode) { | ||
539 | snd_printk(KERN_WARNING "hda_intel: azx_get_response timeout, " | ||
540 | "switching to polling mode...\n"); | ||
541 | chip->polling_mode = 1; | ||
542 | goto again; | ||
534 | } | 543 | } |
535 | return chip->rirb.res; /* the last value */ | 544 | |
545 | snd_printk(KERN_ERR "hda_intel: azx_get_response timeout, " | ||
546 | "switching to single_cmd mode...\n"); | ||
547 | chip->rirb.rp = azx_readb(chip, RIRBWP); | ||
548 | chip->rirb.cmds = 0; | ||
549 | /* switch to single_cmd mode */ | ||
550 | chip->single_cmd = 1; | ||
551 | azx_free_cmd_io(chip); | ||
552 | return -1; | ||
536 | } | 553 | } |
537 | 554 | ||
538 | /* | 555 | /* |
@@ -642,14 +659,14 @@ static int azx_reset(struct azx *chip) | |||
642 | azx_writeb(chip, GCTL, azx_readb(chip, GCTL) | ICH6_GCTL_RESET); | 659 | azx_writeb(chip, GCTL, azx_readb(chip, GCTL) | ICH6_GCTL_RESET); |
643 | 660 | ||
644 | count = 50; | 661 | count = 50; |
645 | while (! azx_readb(chip, GCTL) && --count) | 662 | while (!azx_readb(chip, GCTL) && --count) |
646 | msleep(1); | 663 | msleep(1); |
647 | 664 | ||
648 | /* Brent Chartrand said to wait >= 540us for codecs to intialize */ | 665 | /* Brent Chartrand said to wait >= 540us for codecs to initialize */ |
649 | msleep(1); | 666 | msleep(1); |
650 | 667 | ||
651 | /* check to see if controller is ready */ | 668 | /* check to see if controller is ready */ |
652 | if (! azx_readb(chip, GCTL)) { | 669 | if (!azx_readb(chip, GCTL)) { |
653 | snd_printd("azx_reset: controller not ready!\n"); | 670 | snd_printd("azx_reset: controller not ready!\n"); |
654 | return -EBUSY; | 671 | return -EBUSY; |
655 | } | 672 | } |
@@ -658,7 +675,7 @@ static int azx_reset(struct azx *chip) | |||
658 | azx_writel(chip, GCTL, azx_readl(chip, GCTL) | ICH6_GCTL_UREN); | 675 | azx_writel(chip, GCTL, azx_readl(chip, GCTL) | ICH6_GCTL_UREN); |
659 | 676 | ||
660 | /* detect codecs */ | 677 | /* detect codecs */ |
661 | if (! chip->codec_mask) { | 678 | if (!chip->codec_mask) { |
662 | chip->codec_mask = azx_readw(chip, STATESTS); | 679 | chip->codec_mask = azx_readw(chip, STATESTS); |
663 | snd_printdd("codec_mask = 0x%x\n", chip->codec_mask); | 680 | snd_printdd("codec_mask = 0x%x\n", chip->codec_mask); |
664 | } | 681 | } |
@@ -766,7 +783,7 @@ static void azx_init_chip(struct azx *chip) | |||
766 | azx_int_enable(chip); | 783 | azx_int_enable(chip); |
767 | 784 | ||
768 | /* initialize the codec command I/O */ | 785 | /* initialize the codec command I/O */ |
769 | if (! chip->single_cmd) | 786 | if (!chip->single_cmd) |
770 | azx_init_cmd_io(chip); | 787 | azx_init_cmd_io(chip); |
771 | 788 | ||
772 | /* program the position buffer */ | 789 | /* program the position buffer */ |
@@ -794,7 +811,7 @@ static void azx_init_chip(struct azx *chip) | |||
794 | /* | 811 | /* |
795 | * interrupt handler | 812 | * interrupt handler |
796 | */ | 813 | */ |
797 | static irqreturn_t azx_interrupt(int irq, void* dev_id, struct pt_regs *regs) | 814 | static irqreturn_t azx_interrupt(int irq, void *dev_id, struct pt_regs *regs) |
798 | { | 815 | { |
799 | struct azx *chip = dev_id; | 816 | struct azx *chip = dev_id; |
800 | struct azx_dev *azx_dev; | 817 | struct azx_dev *azx_dev; |
@@ -999,8 +1016,9 @@ static struct snd_pcm_hardware azx_pcm_hw = { | |||
999 | .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | | 1016 | .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | |
1000 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 1017 | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
1001 | SNDRV_PCM_INFO_MMAP_VALID | | 1018 | SNDRV_PCM_INFO_MMAP_VALID | |
1002 | SNDRV_PCM_INFO_PAUSE /*|*/ | 1019 | /* No full-resume yet implemented */ |
1003 | /*SNDRV_PCM_INFO_RESUME*/), | 1020 | /* SNDRV_PCM_INFO_RESUME |*/ |
1021 | SNDRV_PCM_INFO_PAUSE), | ||
1004 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 1022 | .formats = SNDRV_PCM_FMTBIT_S16_LE, |
1005 | .rates = SNDRV_PCM_RATE_48000, | 1023 | .rates = SNDRV_PCM_RATE_48000, |
1006 | .rate_min = 48000, | 1024 | .rate_min = 48000, |
@@ -1178,7 +1196,7 @@ static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream) | |||
1178 | if (chip->position_fix == POS_FIX_POSBUF || | 1196 | if (chip->position_fix == POS_FIX_POSBUF || |
1179 | chip->position_fix == POS_FIX_AUTO) { | 1197 | chip->position_fix == POS_FIX_AUTO) { |
1180 | /* use the position buffer */ | 1198 | /* use the position buffer */ |
1181 | pos = *azx_dev->posbuf; | 1199 | pos = le32_to_cpu(*azx_dev->posbuf); |
1182 | if (chip->position_fix == POS_FIX_AUTO && | 1200 | if (chip->position_fix == POS_FIX_AUTO && |
1183 | azx_dev->period_intr == 1 && ! pos) { | 1201 | azx_dev->period_intr == 1 && ! pos) { |
1184 | printk(KERN_WARNING | 1202 | printk(KERN_WARNING |
@@ -1222,7 +1240,12 @@ static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec, | |||
1222 | struct snd_pcm *pcm; | 1240 | struct snd_pcm *pcm; |
1223 | struct azx_pcm *apcm; | 1241 | struct azx_pcm *apcm; |
1224 | 1242 | ||
1225 | snd_assert(cpcm->stream[0].substreams || cpcm->stream[1].substreams, return -EINVAL); | 1243 | /* if no substreams are defined for both playback and capture, |
1244 | * it's just a placeholder. ignore it. | ||
1245 | */ | ||
1246 | if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams) | ||
1247 | return 0; | ||
1248 | |||
1226 | snd_assert(cpcm->name, return -EINVAL); | 1249 | snd_assert(cpcm->name, return -EINVAL); |
1227 | 1250 | ||
1228 | err = snd_pcm_new(chip->card, cpcm->name, pcm_dev, | 1251 | err = snd_pcm_new(chip->card, cpcm->name, pcm_dev, |
@@ -1248,7 +1271,8 @@ static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec, | |||
1248 | snd_dma_pci_data(chip->pci), | 1271 | snd_dma_pci_data(chip->pci), |
1249 | 1024 * 64, 1024 * 128); | 1272 | 1024 * 64, 1024 * 128); |
1250 | chip->pcm[pcm_dev] = pcm; | 1273 | chip->pcm[pcm_dev] = pcm; |
1251 | chip->pcm_devs = pcm_dev + 1; | 1274 | if (chip->pcm_devs < pcm_dev + 1) |
1275 | chip->pcm_devs = pcm_dev + 1; | ||
1252 | 1276 | ||
1253 | return 0; | 1277 | return 0; |
1254 | } | 1278 | } |
@@ -1326,7 +1350,7 @@ static int __devinit azx_init_stream(struct azx *chip) | |||
1326 | struct azx_dev *azx_dev = &chip->azx_dev[i]; | 1350 | struct azx_dev *azx_dev = &chip->azx_dev[i]; |
1327 | azx_dev->bdl = (u32 *)(chip->bdl.area + off); | 1351 | azx_dev->bdl = (u32 *)(chip->bdl.area + off); |
1328 | azx_dev->bdl_addr = chip->bdl.addr + off; | 1352 | azx_dev->bdl_addr = chip->bdl.addr + off; |
1329 | azx_dev->posbuf = (volatile u32 *)(chip->posbuf.area + i * 8); | 1353 | azx_dev->posbuf = (u32 __iomem *)(chip->posbuf.area + i * 8); |
1330 | /* offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */ | 1354 | /* offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */ |
1331 | azx_dev->sd_addr = chip->remap_addr + (0x20 * i + 0x80); | 1355 | azx_dev->sd_addr = chip->remap_addr + (0x20 * i + 0x80); |
1332 | /* int mask: SDI0=0x01, SDI1=0x02, ... SDO3=0x80 */ | 1356 | /* int mask: SDI0=0x01, SDI1=0x02, ... SDO3=0x80 */ |
@@ -1355,6 +1379,10 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state) | |||
1355 | snd_pcm_suspend_all(chip->pcm[i]); | 1379 | snd_pcm_suspend_all(chip->pcm[i]); |
1356 | snd_hda_suspend(chip->bus, state); | 1380 | snd_hda_suspend(chip->bus, state); |
1357 | azx_free_cmd_io(chip); | 1381 | azx_free_cmd_io(chip); |
1382 | if (chip->irq >= 0) | ||
1383 | free_irq(chip->irq, chip); | ||
1384 | if (!disable_msi) | ||
1385 | pci_disable_msi(chip->pci); | ||
1358 | pci_disable_device(pci); | 1386 | pci_disable_device(pci); |
1359 | pci_save_state(pci); | 1387 | pci_save_state(pci); |
1360 | return 0; | 1388 | return 0; |
@@ -1367,6 +1395,12 @@ static int azx_resume(struct pci_dev *pci) | |||
1367 | 1395 | ||
1368 | pci_restore_state(pci); | 1396 | pci_restore_state(pci); |
1369 | pci_enable_device(pci); | 1397 | pci_enable_device(pci); |
1398 | if (!disable_msi) | ||
1399 | pci_enable_msi(pci); | ||
1400 | /* FIXME: need proper error handling */ | ||
1401 | request_irq(pci->irq, azx_interrupt, IRQF_DISABLED|IRQF_SHARED, | ||
1402 | "HDA Intel", chip); | ||
1403 | chip->irq = pci->irq; | ||
1370 | pci_set_master(pci); | 1404 | pci_set_master(pci); |
1371 | azx_init_chip(chip); | 1405 | azx_init_chip(chip); |
1372 | snd_hda_resume(chip->bus); | 1406 | snd_hda_resume(chip->bus); |
@@ -1398,12 +1432,14 @@ static int azx_free(struct azx *chip) | |||
1398 | azx_writel(chip, DPLBASE, 0); | 1432 | azx_writel(chip, DPLBASE, 0); |
1399 | azx_writel(chip, DPUBASE, 0); | 1433 | azx_writel(chip, DPUBASE, 0); |
1400 | 1434 | ||
1401 | /* wait a little for interrupts to finish */ | 1435 | synchronize_irq(chip->irq); |
1402 | msleep(1); | ||
1403 | } | 1436 | } |
1404 | 1437 | ||
1405 | if (chip->irq >= 0) | 1438 | if (chip->irq >= 0) { |
1406 | free_irq(chip->irq, (void*)chip); | 1439 | free_irq(chip->irq, (void*)chip); |
1440 | if (!disable_msi) | ||
1441 | pci_disable_msi(chip->pci); | ||
1442 | } | ||
1407 | if (chip->remap_addr) | 1443 | if (chip->remap_addr) |
1408 | iounmap(chip->remap_addr); | 1444 | iounmap(chip->remap_addr); |
1409 | 1445 | ||
@@ -1434,19 +1470,19 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, | |||
1434 | struct azx **rchip) | 1470 | struct azx **rchip) |
1435 | { | 1471 | { |
1436 | struct azx *chip; | 1472 | struct azx *chip; |
1437 | int err = 0; | 1473 | int err; |
1438 | static struct snd_device_ops ops = { | 1474 | static struct snd_device_ops ops = { |
1439 | .dev_free = azx_dev_free, | 1475 | .dev_free = azx_dev_free, |
1440 | }; | 1476 | }; |
1441 | 1477 | ||
1442 | *rchip = NULL; | 1478 | *rchip = NULL; |
1443 | 1479 | ||
1444 | if ((err = pci_enable_device(pci)) < 0) | 1480 | err = pci_enable_device(pci); |
1481 | if (err < 0) | ||
1445 | return err; | 1482 | return err; |
1446 | 1483 | ||
1447 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | 1484 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); |
1448 | 1485 | if (!chip) { | |
1449 | if (NULL == chip) { | ||
1450 | snd_printk(KERN_ERR SFX "cannot allocate chip\n"); | 1486 | snd_printk(KERN_ERR SFX "cannot allocate chip\n"); |
1451 | pci_disable_device(pci); | 1487 | pci_disable_device(pci); |
1452 | return -ENOMEM; | 1488 | return -ENOMEM; |
@@ -1472,13 +1508,14 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, | |||
1472 | } | 1508 | } |
1473 | #endif | 1509 | #endif |
1474 | 1510 | ||
1475 | if ((err = pci_request_regions(pci, "ICH HD audio")) < 0) { | 1511 | err = pci_request_regions(pci, "ICH HD audio"); |
1512 | if (err < 0) { | ||
1476 | kfree(chip); | 1513 | kfree(chip); |
1477 | pci_disable_device(pci); | 1514 | pci_disable_device(pci); |
1478 | return err; | 1515 | return err; |
1479 | } | 1516 | } |
1480 | 1517 | ||
1481 | chip->addr = pci_resource_start(pci,0); | 1518 | chip->addr = pci_resource_start(pci, 0); |
1482 | chip->remap_addr = ioremap_nocache(chip->addr, pci_resource_len(pci,0)); | 1519 | chip->remap_addr = ioremap_nocache(chip->addr, pci_resource_len(pci,0)); |
1483 | if (chip->remap_addr == NULL) { | 1520 | if (chip->remap_addr == NULL) { |
1484 | snd_printk(KERN_ERR SFX "ioremap error\n"); | 1521 | snd_printk(KERN_ERR SFX "ioremap error\n"); |
@@ -1486,6 +1523,9 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, | |||
1486 | goto errout; | 1523 | goto errout; |
1487 | } | 1524 | } |
1488 | 1525 | ||
1526 | if (!disable_msi) | ||
1527 | pci_enable_msi(pci); | ||
1528 | |||
1489 | if (request_irq(pci->irq, azx_interrupt, IRQF_DISABLED|IRQF_SHARED, | 1529 | if (request_irq(pci->irq, azx_interrupt, IRQF_DISABLED|IRQF_SHARED, |
1490 | "HDA Intel", (void*)chip)) { | 1530 | "HDA Intel", (void*)chip)) { |
1491 | snd_printk(KERN_ERR SFX "unable to grab IRQ %d\n", pci->irq); | 1531 | snd_printk(KERN_ERR SFX "unable to grab IRQ %d\n", pci->irq); |
@@ -1519,7 +1559,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, | |||
1519 | } | 1559 | } |
1520 | chip->num_streams = chip->playback_streams + chip->capture_streams; | 1560 | chip->num_streams = chip->playback_streams + chip->capture_streams; |
1521 | chip->azx_dev = kcalloc(chip->num_streams, sizeof(*chip->azx_dev), GFP_KERNEL); | 1561 | chip->azx_dev = kcalloc(chip->num_streams, sizeof(*chip->azx_dev), GFP_KERNEL); |
1522 | if (! chip->azx_dev) { | 1562 | if (!chip->azx_dev) { |
1523 | snd_printk(KERN_ERR "cannot malloc azx_dev\n"); | 1563 | snd_printk(KERN_ERR "cannot malloc azx_dev\n"); |
1524 | goto errout; | 1564 | goto errout; |
1525 | } | 1565 | } |
@@ -1550,7 +1590,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, | |||
1550 | chip->initialized = 1; | 1590 | chip->initialized = 1; |
1551 | 1591 | ||
1552 | /* codec detection */ | 1592 | /* codec detection */ |
1553 | if (! chip->codec_mask) { | 1593 | if (!chip->codec_mask) { |
1554 | snd_printk(KERN_ERR SFX "no codecs found!\n"); | 1594 | snd_printk(KERN_ERR SFX "no codecs found!\n"); |
1555 | err = -ENODEV; | 1595 | err = -ENODEV; |
1556 | goto errout; | 1596 | goto errout; |
@@ -1577,16 +1617,16 @@ static int __devinit azx_probe(struct pci_dev *pci, const struct pci_device_id * | |||
1577 | { | 1617 | { |
1578 | struct snd_card *card; | 1618 | struct snd_card *card; |
1579 | struct azx *chip; | 1619 | struct azx *chip; |
1580 | int err = 0; | 1620 | int err; |
1581 | 1621 | ||
1582 | card = snd_card_new(index, id, THIS_MODULE, 0); | 1622 | card = snd_card_new(index, id, THIS_MODULE, 0); |
1583 | if (NULL == card) { | 1623 | if (!card) { |
1584 | snd_printk(KERN_ERR SFX "Error creating card!\n"); | 1624 | snd_printk(KERN_ERR SFX "Error creating card!\n"); |
1585 | return -ENOMEM; | 1625 | return -ENOMEM; |
1586 | } | 1626 | } |
1587 | 1627 | ||
1588 | if ((err = azx_create(card, pci, pci_id->driver_data, | 1628 | err = azx_create(card, pci, pci_id->driver_data, &chip); |
1589 | &chip)) < 0) { | 1629 | if (err < 0) { |
1590 | snd_card_free(card); | 1630 | snd_card_free(card); |
1591 | return err; | 1631 | return err; |
1592 | } | 1632 | } |
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 14e8aa2806ed..f9416c36396e 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
@@ -30,9 +30,13 @@ | |||
30 | /* mono volume with index (index=0,1,...) (channel=1,2) */ | 30 | /* mono volume with index (index=0,1,...) (channel=1,2) */ |
31 | #define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ | 31 | #define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ |
32 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ | 32 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ |
33 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ | ||
34 | SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ | ||
35 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, \ | ||
33 | .info = snd_hda_mixer_amp_volume_info, \ | 36 | .info = snd_hda_mixer_amp_volume_info, \ |
34 | .get = snd_hda_mixer_amp_volume_get, \ | 37 | .get = snd_hda_mixer_amp_volume_get, \ |
35 | .put = snd_hda_mixer_amp_volume_put, \ | 38 | .put = snd_hda_mixer_amp_volume_put, \ |
39 | .tlv = { .c = snd_hda_mixer_amp_tlv }, \ | ||
36 | .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, direction) } | 40 | .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, direction) } |
37 | /* stereo volume with index */ | 41 | /* stereo volume with index */ |
38 | #define HDA_CODEC_VOLUME_IDX(xname, xcidx, nid, xindex, direction) \ | 42 | #define HDA_CODEC_VOLUME_IDX(xname, xcidx, nid, xindex, direction) \ |
@@ -63,6 +67,7 @@ | |||
63 | int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); | 67 | int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); |
64 | int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); | 68 | int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); |
65 | int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); | 69 | int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); |
70 | int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, unsigned int size, unsigned int __user *tlv); | ||
66 | int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); | 71 | int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); |
67 | int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); | 72 | int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); |
68 | int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); | 73 | int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); |
@@ -224,7 +229,8 @@ struct auto_pin_cfg { | |||
224 | hda_nid_t line_out_pins[5]; /* sorted in the order of Front/Surr/CLFE/Side */ | 229 | hda_nid_t line_out_pins[5]; /* sorted in the order of Front/Surr/CLFE/Side */ |
225 | int speaker_outs; | 230 | int speaker_outs; |
226 | hda_nid_t speaker_pins[5]; | 231 | hda_nid_t speaker_pins[5]; |
227 | hda_nid_t hp_pin; | 232 | int hp_outs; |
233 | hda_nid_t hp_pins[5]; | ||
228 | hda_nid_t input_pins[AUTO_PIN_LAST]; | 234 | hda_nid_t input_pins[AUTO_PIN_LAST]; |
229 | hda_nid_t dig_out_pin; | 235 | hda_nid_t dig_out_pin; |
230 | hda_nid_t dig_in_pin; | 236 | hda_nid_t dig_in_pin; |
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index c2f0fe85bf35..d737f17695a3 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c | |||
@@ -52,10 +52,9 @@ static void print_amp_caps(struct snd_info_buffer *buffer, | |||
52 | struct hda_codec *codec, hda_nid_t nid, int dir) | 52 | struct hda_codec *codec, hda_nid_t nid, int dir) |
53 | { | 53 | { |
54 | unsigned int caps; | 54 | unsigned int caps; |
55 | if (dir == HDA_OUTPUT) | 55 | caps = snd_hda_param_read(codec, nid, |
56 | caps = snd_hda_param_read(codec, nid, AC_PAR_AMP_OUT_CAP); | 56 | dir == HDA_OUTPUT ? |
57 | else | 57 | AC_PAR_AMP_OUT_CAP : AC_PAR_AMP_IN_CAP); |
58 | caps = snd_hda_param_read(codec, nid, AC_PAR_AMP_IN_CAP); | ||
59 | if (caps == -1 || caps == 0) { | 58 | if (caps == -1 || caps == 0) { |
60 | snd_iprintf(buffer, "N/A\n"); | 59 | snd_iprintf(buffer, "N/A\n"); |
61 | return; | 60 | return; |
@@ -74,10 +73,7 @@ static void print_amp_vals(struct snd_info_buffer *buffer, | |||
74 | unsigned int val; | 73 | unsigned int val; |
75 | int i; | 74 | int i; |
76 | 75 | ||
77 | if (dir == HDA_OUTPUT) | 76 | dir = dir == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT; |
78 | dir = AC_AMP_GET_OUTPUT; | ||
79 | else | ||
80 | dir = AC_AMP_GET_INPUT; | ||
81 | for (i = 0; i < indices; i++) { | 77 | for (i = 0; i < indices; i++) { |
82 | snd_iprintf(buffer, " ["); | 78 | snd_iprintf(buffer, " ["); |
83 | if (stereo) { | 79 | if (stereo) { |
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 6823f2bc10b3..511df07fa2a3 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
@@ -488,9 +488,13 @@ static struct snd_kcontrol_new ad1986a_mixers[] = { | |||
488 | { | 488 | { |
489 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 489 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
490 | .name = "PCM Playback Volume", | 490 | .name = "PCM Playback Volume", |
491 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
492 | SNDRV_CTL_ELEM_ACCESS_TLV_READ | | ||
493 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, | ||
491 | .info = ad1986a_pcm_amp_vol_info, | 494 | .info = ad1986a_pcm_amp_vol_info, |
492 | .get = ad1986a_pcm_amp_vol_get, | 495 | .get = ad1986a_pcm_amp_vol_get, |
493 | .put = ad1986a_pcm_amp_vol_put, | 496 | .put = ad1986a_pcm_amp_vol_put, |
497 | .tlv = { .c = snd_hda_mixer_amp_tlv }, | ||
494 | .private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT) | 498 | .private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT) |
495 | }, | 499 | }, |
496 | { | 500 | { |
@@ -637,6 +641,7 @@ static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = { | |||
637 | .info = snd_hda_mixer_amp_volume_info, | 641 | .info = snd_hda_mixer_amp_volume_info, |
638 | .get = snd_hda_mixer_amp_volume_get, | 642 | .get = snd_hda_mixer_amp_volume_get, |
639 | .put = ad1986a_laptop_master_vol_put, | 643 | .put = ad1986a_laptop_master_vol_put, |
644 | .tlv = { .c = snd_hda_mixer_amp_tlv }, | ||
640 | .private_value = HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT), | 645 | .private_value = HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT), |
641 | }, | 646 | }, |
642 | { | 647 | { |
@@ -791,6 +796,8 @@ static struct hda_board_config ad1986a_cfg_tbl[] = { | |||
791 | .config = AD1986A_3STACK }, /* ASUS A8N-VM CSM */ | 796 | .config = AD1986A_3STACK }, /* ASUS A8N-VM CSM */ |
792 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x81b3, | 797 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x81b3, |
793 | .config = AD1986A_3STACK }, /* ASUS P5RD2-VM / P5GPL-X SE */ | 798 | .config = AD1986A_3STACK }, /* ASUS P5RD2-VM / P5GPL-X SE */ |
799 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x81cb, | ||
800 | .config = AD1986A_3STACK }, /* ASUS M2NPV-VM */ | ||
794 | { .modelname = "laptop", .config = AD1986A_LAPTOP }, | 801 | { .modelname = "laptop", .config = AD1986A_LAPTOP }, |
795 | { .pci_subvendor = 0x144d, .pci_subdevice = 0xc01e, | 802 | { .pci_subvendor = 0x144d, .pci_subdevice = 0xc01e, |
796 | .config = AD1986A_LAPTOP }, /* FSC V2060 */ | 803 | .config = AD1986A_LAPTOP }, /* FSC V2060 */ |
@@ -803,6 +810,8 @@ static struct hda_board_config ad1986a_cfg_tbl[] = { | |||
803 | .config = AD1986A_LAPTOP_EAPD }, /* Samsung X60 Chane */ | 810 | .config = AD1986A_LAPTOP_EAPD }, /* Samsung X60 Chane */ |
804 | { .pci_subvendor = 0x144d, .pci_subdevice = 0xc024, | 811 | { .pci_subvendor = 0x144d, .pci_subdevice = 0xc024, |
805 | .config = AD1986A_LAPTOP_EAPD }, /* Samsung R65-T2300 Charis */ | 812 | .config = AD1986A_LAPTOP_EAPD }, /* Samsung R65-T2300 Charis */ |
813 | { .pci_subvendor = 0x144d, .pci_subdevice = 0xc026, | ||
814 | .config = AD1986A_LAPTOP_EAPD }, /* Samsung X10-T2300 Culesa */ | ||
806 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1153, | 815 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1153, |
807 | .config = AD1986A_LAPTOP_EAPD }, /* ASUS M9 */ | 816 | .config = AD1986A_LAPTOP_EAPD }, /* ASUS M9 */ |
808 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1213, | 817 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1213, |
@@ -1626,10 +1635,12 @@ static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol, | |||
1626 | { | 1635 | { |
1627 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 1636 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
1628 | struct ad198x_spec *spec = codec->spec; | 1637 | struct ad198x_spec *spec = codec->spec; |
1629 | if (spec->need_dac_fix) | 1638 | int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode, |
1639 | spec->num_channel_mode, | ||
1640 | &spec->multiout.max_channels); | ||
1641 | if (! err && spec->need_dac_fix) | ||
1630 | spec->multiout.num_dacs = spec->multiout.max_channels / 2; | 1642 | spec->multiout.num_dacs = spec->multiout.max_channels / 2; |
1631 | return snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode, | 1643 | return err; |
1632 | spec->num_channel_mode, &spec->multiout.max_channels); | ||
1633 | } | 1644 | } |
1634 | 1645 | ||
1635 | /* 6-stack mode */ | 1646 | /* 6-stack mode */ |
@@ -2460,7 +2471,7 @@ static void ad1988_auto_init_extra_out(struct hda_codec *codec) | |||
2460 | pin = spec->autocfg.speaker_pins[0]; | 2471 | pin = spec->autocfg.speaker_pins[0]; |
2461 | if (pin) /* connect to front */ | 2472 | if (pin) /* connect to front */ |
2462 | ad1988_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); | 2473 | ad1988_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); |
2463 | pin = spec->autocfg.hp_pin; | 2474 | pin = spec->autocfg.hp_pins[0]; |
2464 | if (pin) /* connect to front */ | 2475 | if (pin) /* connect to front */ |
2465 | ad1988_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); | 2476 | ad1988_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); |
2466 | } | 2477 | } |
@@ -2512,7 +2523,7 @@ static int ad1988_parse_auto_config(struct hda_codec *codec) | |||
2512 | (err = ad1988_auto_create_extra_out(codec, | 2523 | (err = ad1988_auto_create_extra_out(codec, |
2513 | spec->autocfg.speaker_pins[0], | 2524 | spec->autocfg.speaker_pins[0], |
2514 | "Speaker")) < 0 || | 2525 | "Speaker")) < 0 || |
2515 | (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pin, | 2526 | (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pins[0], |
2516 | "Headphone")) < 0 || | 2527 | "Headphone")) < 0 || |
2517 | (err = ad1988_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) | 2528 | (err = ad1988_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) |
2518 | return err; | 2529 | return err; |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 18d105263fea..d08d2e399c8f 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -79,6 +79,7 @@ enum { | |||
79 | ALC262_BASIC, | 79 | ALC262_BASIC, |
80 | ALC262_FUJITSU, | 80 | ALC262_FUJITSU, |
81 | ALC262_HP_BPC, | 81 | ALC262_HP_BPC, |
82 | ALC262_BENQ_ED8, | ||
82 | ALC262_AUTO, | 83 | ALC262_AUTO, |
83 | ALC262_MODEL_LAST /* last tag */ | 84 | ALC262_MODEL_LAST /* last tag */ |
84 | }; | 85 | }; |
@@ -89,6 +90,7 @@ enum { | |||
89 | ALC660_3ST, | 90 | ALC660_3ST, |
90 | ALC861_3ST_DIG, | 91 | ALC861_3ST_DIG, |
91 | ALC861_6ST_DIG, | 92 | ALC861_6ST_DIG, |
93 | ALC861_UNIWILL_M31, | ||
92 | ALC861_AUTO, | 94 | ALC861_AUTO, |
93 | ALC861_MODEL_LAST, | 95 | ALC861_MODEL_LAST, |
94 | }; | 96 | }; |
@@ -97,6 +99,7 @@ enum { | |||
97 | enum { | 99 | enum { |
98 | ALC882_3ST_DIG, | 100 | ALC882_3ST_DIG, |
99 | ALC882_6ST_DIG, | 101 | ALC882_6ST_DIG, |
102 | ALC882_ARIMA, | ||
100 | ALC882_AUTO, | 103 | ALC882_AUTO, |
101 | ALC882_MODEL_LAST, | 104 | ALC882_MODEL_LAST, |
102 | }; | 105 | }; |
@@ -108,6 +111,7 @@ enum { | |||
108 | ALC883_3ST_6ch, | 111 | ALC883_3ST_6ch, |
109 | ALC883_6ST_DIG, | 112 | ALC883_6ST_DIG, |
110 | ALC888_DEMO_BOARD, | 113 | ALC888_DEMO_BOARD, |
114 | ALC883_ACER, | ||
111 | ALC883_AUTO, | 115 | ALC883_AUTO, |
112 | ALC883_MODEL_LAST, | 116 | ALC883_MODEL_LAST, |
113 | }; | 117 | }; |
@@ -153,6 +157,7 @@ struct alc_spec { | |||
153 | /* channel model */ | 157 | /* channel model */ |
154 | const struct hda_channel_mode *channel_mode; | 158 | const struct hda_channel_mode *channel_mode; |
155 | int num_channel_mode; | 159 | int num_channel_mode; |
160 | int need_dac_fix; | ||
156 | 161 | ||
157 | /* PCM information */ | 162 | /* PCM information */ |
158 | struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */ | 163 | struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */ |
@@ -190,6 +195,7 @@ struct alc_config_preset { | |||
190 | hda_nid_t dig_in_nid; | 195 | hda_nid_t dig_in_nid; |
191 | unsigned int num_channel_mode; | 196 | unsigned int num_channel_mode; |
192 | const struct hda_channel_mode *channel_mode; | 197 | const struct hda_channel_mode *channel_mode; |
198 | int need_dac_fix; | ||
193 | unsigned int num_mux_defs; | 199 | unsigned int num_mux_defs; |
194 | const struct hda_input_mux *input_mux; | 200 | const struct hda_input_mux *input_mux; |
195 | void (*unsol_event)(struct hda_codec *, unsigned int); | 201 | void (*unsol_event)(struct hda_codec *, unsigned int); |
@@ -262,9 +268,12 @@ static int alc_ch_mode_put(struct snd_kcontrol *kcontrol, | |||
262 | { | 268 | { |
263 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 269 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
264 | struct alc_spec *spec = codec->spec; | 270 | struct alc_spec *spec = codec->spec; |
265 | return snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode, | 271 | int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode, |
266 | spec->num_channel_mode, | 272 | spec->num_channel_mode, |
267 | &spec->multiout.max_channels); | 273 | &spec->multiout.max_channels); |
274 | if (! err && spec->need_dac_fix) | ||
275 | spec->multiout.num_dacs = spec->multiout.max_channels / 2; | ||
276 | return err; | ||
268 | } | 277 | } |
269 | 278 | ||
270 | /* | 279 | /* |
@@ -544,6 +553,7 @@ static void setup_preset(struct alc_spec *spec, | |||
544 | 553 | ||
545 | spec->channel_mode = preset->channel_mode; | 554 | spec->channel_mode = preset->channel_mode; |
546 | spec->num_channel_mode = preset->num_channel_mode; | 555 | spec->num_channel_mode = preset->num_channel_mode; |
556 | spec->need_dac_fix = preset->need_dac_fix; | ||
547 | 557 | ||
548 | spec->multiout.max_channels = spec->channel_mode[0].channels; | 558 | spec->multiout.max_channels = spec->channel_mode[0].channels; |
549 | 559 | ||
@@ -1348,6 +1358,10 @@ static struct hda_verb alc880_pin_clevo_init_verbs[] = { | |||
1348 | }; | 1358 | }; |
1349 | 1359 | ||
1350 | static struct hda_verb alc880_pin_tcl_S700_init_verbs[] = { | 1360 | static struct hda_verb alc880_pin_tcl_S700_init_verbs[] = { |
1361 | /* change to EAPD mode */ | ||
1362 | {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, | ||
1363 | {0x20, AC_VERB_SET_PROC_COEF, 0x3060}, | ||
1364 | |||
1351 | /* Headphone output */ | 1365 | /* Headphone output */ |
1352 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | 1366 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, |
1353 | /* Front output*/ | 1367 | /* Front output*/ |
@@ -1782,25 +1796,9 @@ static int alc_build_pcms(struct hda_codec *codec) | |||
1782 | } | 1796 | } |
1783 | } | 1797 | } |
1784 | 1798 | ||
1785 | /* If the use of more than one ADC is requested for the current | 1799 | /* SPDIF for stream index #1 */ |
1786 | * model, configure a second analog capture-only PCM. | ||
1787 | */ | ||
1788 | if (spec->num_adc_nids > 1) { | ||
1789 | codec->num_pcms++; | ||
1790 | info++; | ||
1791 | info->name = spec->stream_name_analog; | ||
1792 | /* No playback stream for second PCM */ | ||
1793 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = alc_pcm_null_playback; | ||
1794 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0; | ||
1795 | if (spec->stream_analog_capture) { | ||
1796 | snd_assert(spec->adc_nids, return -EINVAL); | ||
1797 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture); | ||
1798 | info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[1]; | ||
1799 | } | ||
1800 | } | ||
1801 | |||
1802 | if (spec->multiout.dig_out_nid || spec->dig_in_nid) { | 1800 | if (spec->multiout.dig_out_nid || spec->dig_in_nid) { |
1803 | codec->num_pcms++; | 1801 | codec->num_pcms = 2; |
1804 | info++; | 1802 | info++; |
1805 | info->name = spec->stream_name_digital; | 1803 | info->name = spec->stream_name_digital; |
1806 | if (spec->multiout.dig_out_nid && | 1804 | if (spec->multiout.dig_out_nid && |
@@ -1815,6 +1813,24 @@ static int alc_build_pcms(struct hda_codec *codec) | |||
1815 | } | 1813 | } |
1816 | } | 1814 | } |
1817 | 1815 | ||
1816 | /* If the use of more than one ADC is requested for the current | ||
1817 | * model, configure a second analog capture-only PCM. | ||
1818 | */ | ||
1819 | /* Additional Analaog capture for index #2 */ | ||
1820 | if (spec->num_adc_nids > 1 && spec->stream_analog_capture && | ||
1821 | spec->adc_nids) { | ||
1822 | codec->num_pcms = 3; | ||
1823 | info++; | ||
1824 | info->name = spec->stream_name_analog; | ||
1825 | /* No playback stream for second PCM */ | ||
1826 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = alc_pcm_null_playback; | ||
1827 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0; | ||
1828 | if (spec->stream_analog_capture) { | ||
1829 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture); | ||
1830 | info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[1]; | ||
1831 | } | ||
1832 | } | ||
1833 | |||
1818 | return 0; | 1834 | return 0; |
1819 | } | 1835 | } |
1820 | 1836 | ||
@@ -2130,7 +2146,10 @@ static struct hda_board_config alc880_cfg_tbl[] = { | |||
2130 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20f, .config = ALC880_3ST }, | 2146 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20f, .config = ALC880_3ST }, |
2131 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe210, .config = ALC880_3ST }, | 2147 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe210, .config = ALC880_3ST }, |
2132 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe211, .config = ALC880_3ST }, | 2148 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe211, .config = ALC880_3ST }, |
2149 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe212, .config = ALC880_3ST }, | ||
2150 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe213, .config = ALC880_3ST }, | ||
2133 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe214, .config = ALC880_3ST }, | 2151 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe214, .config = ALC880_3ST }, |
2152 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe234, .config = ALC880_3ST }, | ||
2134 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe302, .config = ALC880_3ST }, | 2153 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe302, .config = ALC880_3ST }, |
2135 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe303, .config = ALC880_3ST }, | 2154 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe303, .config = ALC880_3ST }, |
2136 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe304, .config = ALC880_3ST }, | 2155 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe304, .config = ALC880_3ST }, |
@@ -2145,6 +2164,7 @@ static struct hda_board_config alc880_cfg_tbl[] = { | |||
2145 | { .pci_subvendor = 0x107b, .pci_subdevice = 0x4040, .config = ALC880_3ST }, | 2164 | { .pci_subvendor = 0x107b, .pci_subdevice = 0x4040, .config = ALC880_3ST }, |
2146 | { .pci_subvendor = 0x107b, .pci_subdevice = 0x4041, .config = ALC880_3ST }, | 2165 | { .pci_subvendor = 0x107b, .pci_subdevice = 0x4041, .config = ALC880_3ST }, |
2147 | /* TCL S700 */ | 2166 | /* TCL S700 */ |
2167 | { .modelname = "tcl", .config = ALC880_TCL_S700 }, | ||
2148 | { .pci_subvendor = 0x19db, .pci_subdevice = 0x4188, .config = ALC880_TCL_S700 }, | 2168 | { .pci_subvendor = 0x19db, .pci_subdevice = 0x4188, .config = ALC880_TCL_S700 }, |
2149 | 2169 | ||
2150 | /* Back 3 jack, front 2 jack (Internal add Aux-In) */ | 2170 | /* Back 3 jack, front 2 jack (Internal add Aux-In) */ |
@@ -2156,8 +2176,13 @@ static struct hda_board_config alc880_cfg_tbl[] = { | |||
2156 | { .modelname = "3stack-digout", .config = ALC880_3ST_DIG }, | 2176 | { .modelname = "3stack-digout", .config = ALC880_3ST_DIG }, |
2157 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe308, .config = ALC880_3ST_DIG }, | 2177 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe308, .config = ALC880_3ST_DIG }, |
2158 | { .pci_subvendor = 0x1025, .pci_subdevice = 0x0070, .config = ALC880_3ST_DIG }, | 2178 | { .pci_subvendor = 0x1025, .pci_subdevice = 0x0070, .config = ALC880_3ST_DIG }, |
2159 | /* Clevo m520G NB */ | 2179 | |
2160 | { .pci_subvendor = 0x1558, .pci_subdevice = 0x0520, .config = ALC880_CLEVO }, | 2180 | /* Clevo laptops */ |
2181 | { .modelname = "clevo", .config = ALC880_CLEVO }, | ||
2182 | { .pci_subvendor = 0x1558, .pci_subdevice = 0x0520, | ||
2183 | .config = ALC880_CLEVO }, /* Clevo m520G NB */ | ||
2184 | { .pci_subvendor = 0x1558, .pci_subdevice = 0x0660, | ||
2185 | .config = ALC880_CLEVO }, /* Clevo m665n */ | ||
2161 | 2186 | ||
2162 | /* Back 3 jack plus 1 SPDIF out jack, front 2 jack (Internal add Aux-In)*/ | 2187 | /* Back 3 jack plus 1 SPDIF out jack, front 2 jack (Internal add Aux-In)*/ |
2163 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe305, .config = ALC880_3ST_DIG }, | 2188 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe305, .config = ALC880_3ST_DIG }, |
@@ -2222,12 +2247,16 @@ static struct hda_board_config alc880_cfg_tbl[] = { | |||
2222 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1113, .config = ALC880_ASUS_DIG }, | 2247 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1113, .config = ALC880_ASUS_DIG }, |
2223 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1173, .config = ALC880_ASUS_DIG }, | 2248 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1173, .config = ALC880_ASUS_DIG }, |
2224 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1993, .config = ALC880_ASUS }, | 2249 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1993, .config = ALC880_ASUS }, |
2250 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x10c2, .config = ALC880_ASUS_DIG }, /* Asus W6A */ | ||
2225 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x10c3, .config = ALC880_ASUS_DIG }, | 2251 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x10c3, .config = ALC880_ASUS_DIG }, |
2226 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1133, .config = ALC880_ASUS }, | 2252 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1133, .config = ALC880_ASUS }, |
2227 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1123, .config = ALC880_ASUS_DIG }, | 2253 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1123, .config = ALC880_ASUS_DIG }, |
2228 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1143, .config = ALC880_ASUS }, | 2254 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1143, .config = ALC880_ASUS }, |
2255 | { .modelname = "asus-w1v", .config = ALC880_ASUS_W1V }, | ||
2229 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x10b3, .config = ALC880_ASUS_W1V }, | 2256 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x10b3, .config = ALC880_ASUS_W1V }, |
2257 | { .modelname = "asus-dig", .config = ALC880_ASUS_DIG }, | ||
2230 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x8181, .config = ALC880_ASUS_DIG }, /* ASUS P4GPL-X */ | 2258 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x8181, .config = ALC880_ASUS_DIG }, /* ASUS P4GPL-X */ |
2259 | { .modelname = "asus-dig2", .config = ALC880_ASUS_DIG2 }, | ||
2231 | { .pci_subvendor = 0x1558, .pci_subdevice = 0x5401, .config = ALC880_ASUS_DIG2 }, | 2260 | { .pci_subvendor = 0x1558, .pci_subdevice = 0x5401, .config = ALC880_ASUS_DIG2 }, |
2232 | 2261 | ||
2233 | { .modelname = "uniwill", .config = ALC880_UNIWILL_DIG }, | 2262 | { .modelname = "uniwill", .config = ALC880_UNIWILL_DIG }, |
@@ -2243,6 +2272,7 @@ static struct hda_board_config alc880_cfg_tbl[] = { | |||
2243 | 2272 | ||
2244 | { .modelname = "lg-lw", .config = ALC880_LG_LW }, | 2273 | { .modelname = "lg-lw", .config = ALC880_LG_LW }, |
2245 | { .pci_subvendor = 0x1854, .pci_subdevice = 0x0018, .config = ALC880_LG_LW }, | 2274 | { .pci_subvendor = 0x1854, .pci_subdevice = 0x0018, .config = ALC880_LG_LW }, |
2275 | { .pci_subvendor = 0x1854, .pci_subdevice = 0x0077, .config = ALC880_LG_LW }, | ||
2246 | 2276 | ||
2247 | #ifdef CONFIG_SND_DEBUG | 2277 | #ifdef CONFIG_SND_DEBUG |
2248 | { .modelname = "test", .config = ALC880_TEST }, | 2278 | { .modelname = "test", .config = ALC880_TEST }, |
@@ -2263,6 +2293,7 @@ static struct alc_config_preset alc880_presets[] = { | |||
2263 | .dac_nids = alc880_dac_nids, | 2293 | .dac_nids = alc880_dac_nids, |
2264 | .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), | 2294 | .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), |
2265 | .channel_mode = alc880_threestack_modes, | 2295 | .channel_mode = alc880_threestack_modes, |
2296 | .need_dac_fix = 1, | ||
2266 | .input_mux = &alc880_capture_source, | 2297 | .input_mux = &alc880_capture_source, |
2267 | }, | 2298 | }, |
2268 | [ALC880_3ST_DIG] = { | 2299 | [ALC880_3ST_DIG] = { |
@@ -2273,6 +2304,7 @@ static struct alc_config_preset alc880_presets[] = { | |||
2273 | .dig_out_nid = ALC880_DIGOUT_NID, | 2304 | .dig_out_nid = ALC880_DIGOUT_NID, |
2274 | .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), | 2305 | .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), |
2275 | .channel_mode = alc880_threestack_modes, | 2306 | .channel_mode = alc880_threestack_modes, |
2307 | .need_dac_fix = 1, | ||
2276 | .input_mux = &alc880_capture_source, | 2308 | .input_mux = &alc880_capture_source, |
2277 | }, | 2309 | }, |
2278 | [ALC880_TCL_S700] = { | 2310 | [ALC880_TCL_S700] = { |
@@ -2365,6 +2397,7 @@ static struct alc_config_preset alc880_presets[] = { | |||
2365 | .dac_nids = alc880_asus_dac_nids, | 2397 | .dac_nids = alc880_asus_dac_nids, |
2366 | .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), | 2398 | .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), |
2367 | .channel_mode = alc880_asus_modes, | 2399 | .channel_mode = alc880_asus_modes, |
2400 | .need_dac_fix = 1, | ||
2368 | .input_mux = &alc880_capture_source, | 2401 | .input_mux = &alc880_capture_source, |
2369 | }, | 2402 | }, |
2370 | [ALC880_ASUS_DIG] = { | 2403 | [ALC880_ASUS_DIG] = { |
@@ -2376,6 +2409,7 @@ static struct alc_config_preset alc880_presets[] = { | |||
2376 | .dig_out_nid = ALC880_DIGOUT_NID, | 2409 | .dig_out_nid = ALC880_DIGOUT_NID, |
2377 | .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), | 2410 | .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), |
2378 | .channel_mode = alc880_asus_modes, | 2411 | .channel_mode = alc880_asus_modes, |
2412 | .need_dac_fix = 1, | ||
2379 | .input_mux = &alc880_capture_source, | 2413 | .input_mux = &alc880_capture_source, |
2380 | }, | 2414 | }, |
2381 | [ALC880_ASUS_DIG2] = { | 2415 | [ALC880_ASUS_DIG2] = { |
@@ -2387,6 +2421,7 @@ static struct alc_config_preset alc880_presets[] = { | |||
2387 | .dig_out_nid = ALC880_DIGOUT_NID, | 2421 | .dig_out_nid = ALC880_DIGOUT_NID, |
2388 | .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), | 2422 | .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), |
2389 | .channel_mode = alc880_asus_modes, | 2423 | .channel_mode = alc880_asus_modes, |
2424 | .need_dac_fix = 1, | ||
2390 | .input_mux = &alc880_capture_source, | 2425 | .input_mux = &alc880_capture_source, |
2391 | }, | 2426 | }, |
2392 | [ALC880_ASUS_W1V] = { | 2427 | [ALC880_ASUS_W1V] = { |
@@ -2398,6 +2433,7 @@ static struct alc_config_preset alc880_presets[] = { | |||
2398 | .dig_out_nid = ALC880_DIGOUT_NID, | 2433 | .dig_out_nid = ALC880_DIGOUT_NID, |
2399 | .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), | 2434 | .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), |
2400 | .channel_mode = alc880_asus_modes, | 2435 | .channel_mode = alc880_asus_modes, |
2436 | .need_dac_fix = 1, | ||
2401 | .input_mux = &alc880_capture_source, | 2437 | .input_mux = &alc880_capture_source, |
2402 | }, | 2438 | }, |
2403 | [ALC880_UNIWILL_DIG] = { | 2439 | [ALC880_UNIWILL_DIG] = { |
@@ -2408,6 +2444,7 @@ static struct alc_config_preset alc880_presets[] = { | |||
2408 | .dig_out_nid = ALC880_DIGOUT_NID, | 2444 | .dig_out_nid = ALC880_DIGOUT_NID, |
2409 | .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), | 2445 | .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), |
2410 | .channel_mode = alc880_asus_modes, | 2446 | .channel_mode = alc880_asus_modes, |
2447 | .need_dac_fix = 1, | ||
2411 | .input_mux = &alc880_capture_source, | 2448 | .input_mux = &alc880_capture_source, |
2412 | }, | 2449 | }, |
2413 | [ALC880_CLEVO] = { | 2450 | [ALC880_CLEVO] = { |
@@ -2419,6 +2456,7 @@ static struct alc_config_preset alc880_presets[] = { | |||
2419 | .hp_nid = 0x03, | 2456 | .hp_nid = 0x03, |
2420 | .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), | 2457 | .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), |
2421 | .channel_mode = alc880_threestack_modes, | 2458 | .channel_mode = alc880_threestack_modes, |
2459 | .need_dac_fix = 1, | ||
2422 | .input_mux = &alc880_capture_source, | 2460 | .input_mux = &alc880_capture_source, |
2423 | }, | 2461 | }, |
2424 | [ALC880_LG] = { | 2462 | [ALC880_LG] = { |
@@ -2430,6 +2468,7 @@ static struct alc_config_preset alc880_presets[] = { | |||
2430 | .dig_out_nid = ALC880_DIGOUT_NID, | 2468 | .dig_out_nid = ALC880_DIGOUT_NID, |
2431 | .num_channel_mode = ARRAY_SIZE(alc880_lg_ch_modes), | 2469 | .num_channel_mode = ARRAY_SIZE(alc880_lg_ch_modes), |
2432 | .channel_mode = alc880_lg_ch_modes, | 2470 | .channel_mode = alc880_lg_ch_modes, |
2471 | .need_dac_fix = 1, | ||
2433 | .input_mux = &alc880_lg_capture_source, | 2472 | .input_mux = &alc880_lg_capture_source, |
2434 | .unsol_event = alc880_lg_unsol_event, | 2473 | .unsol_event = alc880_lg_unsol_event, |
2435 | .init_hook = alc880_lg_automute, | 2474 | .init_hook = alc880_lg_automute, |
@@ -2714,7 +2753,7 @@ static void alc880_auto_init_extra_out(struct hda_codec *codec) | |||
2714 | pin = spec->autocfg.speaker_pins[0]; | 2753 | pin = spec->autocfg.speaker_pins[0]; |
2715 | if (pin) /* connect to front */ | 2754 | if (pin) /* connect to front */ |
2716 | alc880_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); | 2755 | alc880_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); |
2717 | pin = spec->autocfg.hp_pin; | 2756 | pin = spec->autocfg.hp_pins[0]; |
2718 | if (pin) /* connect to front */ | 2757 | if (pin) /* connect to front */ |
2719 | alc880_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); | 2758 | alc880_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); |
2720 | } | 2759 | } |
@@ -2755,7 +2794,7 @@ static int alc880_parse_auto_config(struct hda_codec *codec) | |||
2755 | (err = alc880_auto_create_extra_out(spec, | 2794 | (err = alc880_auto_create_extra_out(spec, |
2756 | spec->autocfg.speaker_pins[0], | 2795 | spec->autocfg.speaker_pins[0], |
2757 | "Speaker")) < 0 || | 2796 | "Speaker")) < 0 || |
2758 | (err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pin, | 2797 | (err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pins[0], |
2759 | "Headphone")) < 0 || | 2798 | "Headphone")) < 0 || |
2760 | (err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) | 2799 | (err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) |
2761 | return err; | 2800 | return err; |
@@ -3697,7 +3736,7 @@ static int alc260_auto_create_multi_out_ctls(struct alc_spec *spec, | |||
3697 | return err; | 3736 | return err; |
3698 | } | 3737 | } |
3699 | 3738 | ||
3700 | nid = cfg->hp_pin; | 3739 | nid = cfg->hp_pins[0]; |
3701 | if (nid) { | 3740 | if (nid) { |
3702 | err = alc260_add_playback_controls(spec, nid, "Headphone"); | 3741 | err = alc260_add_playback_controls(spec, nid, "Headphone"); |
3703 | if (err < 0) | 3742 | if (err < 0) |
@@ -3767,7 +3806,7 @@ static void alc260_auto_init_multi_out(struct hda_codec *codec) | |||
3767 | if (nid) | 3806 | if (nid) |
3768 | alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0); | 3807 | alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0); |
3769 | 3808 | ||
3770 | nid = spec->autocfg.hp_pin; | 3809 | nid = spec->autocfg.hp_pins[0]; |
3771 | if (nid) | 3810 | if (nid) |
3772 | alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0); | 3811 | alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0); |
3773 | } | 3812 | } |
@@ -3900,7 +3939,8 @@ static struct hda_board_config alc260_cfg_tbl[] = { | |||
3900 | { .pci_subvendor = 0x152d, .pci_subdevice = 0x0729, | 3939 | { .pci_subvendor = 0x152d, .pci_subdevice = 0x0729, |
3901 | .config = ALC260_BASIC }, /* CTL Travel Master U553W */ | 3940 | .config = ALC260_BASIC }, /* CTL Travel Master U553W */ |
3902 | { .modelname = "hp", .config = ALC260_HP }, | 3941 | { .modelname = "hp", .config = ALC260_HP }, |
3903 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x3010, .config = ALC260_HP }, | 3942 | { .modelname = "hp-3013", .config = ALC260_HP_3013 }, |
3943 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x3010, .config = ALC260_HP_3013 }, | ||
3904 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x3011, .config = ALC260_HP }, | 3944 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x3011, .config = ALC260_HP }, |
3905 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x3012, .config = ALC260_HP_3013 }, | 3945 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x3012, .config = ALC260_HP_3013 }, |
3906 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x3013, .config = ALC260_HP_3013 }, | 3946 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x3013, .config = ALC260_HP_3013 }, |
@@ -4266,6 +4306,13 @@ static struct hda_verb alc882_init_verbs[] = { | |||
4266 | { } | 4306 | { } |
4267 | }; | 4307 | }; |
4268 | 4308 | ||
4309 | static struct hda_verb alc882_eapd_verbs[] = { | ||
4310 | /* change to EAPD mode */ | ||
4311 | {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, | ||
4312 | {0x20, AC_VERB_SET_PROC_COEF, 0x3060}, | ||
4313 | { } | ||
4314 | }; | ||
4315 | |||
4269 | /* | 4316 | /* |
4270 | * generic initialization of ADC, input mixers and output mixers | 4317 | * generic initialization of ADC, input mixers and output mixers |
4271 | */ | 4318 | */ |
@@ -4397,6 +4444,9 @@ static struct hda_board_config alc882_cfg_tbl[] = { | |||
4397 | .config = ALC882_6ST_DIG }, /* Foxconn */ | 4444 | .config = ALC882_6ST_DIG }, /* Foxconn */ |
4398 | { .pci_subvendor = 0x1019, .pci_subdevice = 0x6668, | 4445 | { .pci_subvendor = 0x1019, .pci_subdevice = 0x6668, |
4399 | .config = ALC882_6ST_DIG }, /* ECS to Intel*/ | 4446 | .config = ALC882_6ST_DIG }, /* ECS to Intel*/ |
4447 | { .modelname = "arima", .config = ALC882_ARIMA }, | ||
4448 | { .pci_subvendor = 0x161f, .pci_subdevice = 0x2054, | ||
4449 | .config = ALC882_ARIMA }, /* Arima W820Di1 */ | ||
4400 | { .modelname = "auto", .config = ALC882_AUTO }, | 4450 | { .modelname = "auto", .config = ALC882_AUTO }, |
4401 | {} | 4451 | {} |
4402 | }; | 4452 | }; |
@@ -4411,6 +4461,7 @@ static struct alc_config_preset alc882_presets[] = { | |||
4411 | .dig_in_nid = ALC882_DIGIN_NID, | 4461 | .dig_in_nid = ALC882_DIGIN_NID, |
4412 | .num_channel_mode = ARRAY_SIZE(alc882_ch_modes), | 4462 | .num_channel_mode = ARRAY_SIZE(alc882_ch_modes), |
4413 | .channel_mode = alc882_ch_modes, | 4463 | .channel_mode = alc882_ch_modes, |
4464 | .need_dac_fix = 1, | ||
4414 | .input_mux = &alc882_capture_source, | 4465 | .input_mux = &alc882_capture_source, |
4415 | }, | 4466 | }, |
4416 | [ALC882_6ST_DIG] = { | 4467 | [ALC882_6ST_DIG] = { |
@@ -4424,6 +4475,15 @@ static struct alc_config_preset alc882_presets[] = { | |||
4424 | .channel_mode = alc882_sixstack_modes, | 4475 | .channel_mode = alc882_sixstack_modes, |
4425 | .input_mux = &alc882_capture_source, | 4476 | .input_mux = &alc882_capture_source, |
4426 | }, | 4477 | }, |
4478 | [ALC882_ARIMA] = { | ||
4479 | .mixers = { alc882_base_mixer, alc882_chmode_mixer }, | ||
4480 | .init_verbs = { alc882_init_verbs, alc882_eapd_verbs }, | ||
4481 | .num_dacs = ARRAY_SIZE(alc882_dac_nids), | ||
4482 | .dac_nids = alc882_dac_nids, | ||
4483 | .num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes), | ||
4484 | .channel_mode = alc882_sixstack_modes, | ||
4485 | .input_mux = &alc882_capture_source, | ||
4486 | }, | ||
4427 | }; | 4487 | }; |
4428 | 4488 | ||
4429 | 4489 | ||
@@ -4466,7 +4526,7 @@ static void alc882_auto_init_hp_out(struct hda_codec *codec) | |||
4466 | struct alc_spec *spec = codec->spec; | 4526 | struct alc_spec *spec = codec->spec; |
4467 | hda_nid_t pin; | 4527 | hda_nid_t pin; |
4468 | 4528 | ||
4469 | pin = spec->autocfg.hp_pin; | 4529 | pin = spec->autocfg.hp_pins[0]; |
4470 | if (pin) /* connect to front */ | 4530 | if (pin) /* connect to front */ |
4471 | alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); /* use dac 0 */ | 4531 | alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); /* use dac 0 */ |
4472 | } | 4532 | } |
@@ -4999,16 +5059,23 @@ static struct snd_kcontrol_new alc883_capture_mixer[] = { | |||
4999 | */ | 5059 | */ |
5000 | static struct hda_board_config alc883_cfg_tbl[] = { | 5060 | static struct hda_board_config alc883_cfg_tbl[] = { |
5001 | { .modelname = "3stack-dig", .config = ALC883_3ST_2ch_DIG }, | 5061 | { .modelname = "3stack-dig", .config = ALC883_3ST_2ch_DIG }, |
5062 | { .modelname = "3stack-6ch-dig", .config = ALC883_3ST_6ch_DIG }, | ||
5063 | { .pci_subvendor = 0x1019, .pci_subdevice = 0x6668, | ||
5064 | .config = ALC883_3ST_6ch_DIG }, /* ECS to Intel*/ | ||
5065 | { .modelname = "3stack-6ch", .config = ALC883_3ST_6ch }, | ||
5066 | { .pci_subvendor = 0x108e, .pci_subdevice = 0x534d, | ||
5067 | .config = ALC883_3ST_6ch }, | ||
5068 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xd601, | ||
5069 | .config = ALC883_3ST_6ch }, /* D102GGC */ | ||
5002 | { .modelname = "6stack-dig", .config = ALC883_6ST_DIG }, | 5070 | { .modelname = "6stack-dig", .config = ALC883_6ST_DIG }, |
5003 | { .modelname = "6stack-dig-demo", .config = ALC888_DEMO_BOARD }, | ||
5004 | { .pci_subvendor = 0x1462, .pci_subdevice = 0x6668, | 5071 | { .pci_subvendor = 0x1462, .pci_subdevice = 0x6668, |
5005 | .config = ALC883_6ST_DIG }, /* MSI */ | 5072 | .config = ALC883_6ST_DIG }, /* MSI */ |
5006 | { .pci_subvendor = 0x105b, .pci_subdevice = 0x6668, | 5073 | { .pci_subvendor = 0x105b, .pci_subdevice = 0x6668, |
5007 | .config = ALC883_6ST_DIG }, /* Foxconn */ | 5074 | .config = ALC883_6ST_DIG }, /* Foxconn */ |
5008 | { .pci_subvendor = 0x1019, .pci_subdevice = 0x6668, | 5075 | { .modelname = "6stack-dig-demo", .config = ALC888_DEMO_BOARD }, |
5009 | .config = ALC883_3ST_6ch_DIG }, /* ECS to Intel*/ | 5076 | { .modelname = "acer", .config = ALC883_ACER }, |
5010 | { .pci_subvendor = 0x108e, .pci_subdevice = 0x534d, | 5077 | { .pci_subvendor = 0x1025, .pci_subdevice = 0/*0x0102*/, |
5011 | .config = ALC883_3ST_6ch }, | 5078 | .config = ALC883_ACER }, |
5012 | { .modelname = "auto", .config = ALC883_AUTO }, | 5079 | { .modelname = "auto", .config = ALC883_AUTO }, |
5013 | {} | 5080 | {} |
5014 | }; | 5081 | }; |
@@ -5038,6 +5105,7 @@ static struct alc_config_preset alc883_presets[] = { | |||
5038 | .dig_in_nid = ALC883_DIGIN_NID, | 5105 | .dig_in_nid = ALC883_DIGIN_NID, |
5039 | .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes), | 5106 | .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes), |
5040 | .channel_mode = alc883_3ST_6ch_modes, | 5107 | .channel_mode = alc883_3ST_6ch_modes, |
5108 | .need_dac_fix = 1, | ||
5041 | .input_mux = &alc883_capture_source, | 5109 | .input_mux = &alc883_capture_source, |
5042 | }, | 5110 | }, |
5043 | [ALC883_3ST_6ch] = { | 5111 | [ALC883_3ST_6ch] = { |
@@ -5049,6 +5117,7 @@ static struct alc_config_preset alc883_presets[] = { | |||
5049 | .adc_nids = alc883_adc_nids, | 5117 | .adc_nids = alc883_adc_nids, |
5050 | .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes), | 5118 | .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes), |
5051 | .channel_mode = alc883_3ST_6ch_modes, | 5119 | .channel_mode = alc883_3ST_6ch_modes, |
5120 | .need_dac_fix = 1, | ||
5052 | .input_mux = &alc883_capture_source, | 5121 | .input_mux = &alc883_capture_source, |
5053 | }, | 5122 | }, |
5054 | [ALC883_6ST_DIG] = { | 5123 | [ALC883_6ST_DIG] = { |
@@ -5077,6 +5146,23 @@ static struct alc_config_preset alc883_presets[] = { | |||
5077 | .channel_mode = alc883_sixstack_modes, | 5146 | .channel_mode = alc883_sixstack_modes, |
5078 | .input_mux = &alc883_capture_source, | 5147 | .input_mux = &alc883_capture_source, |
5079 | }, | 5148 | }, |
5149 | [ALC883_ACER] = { | ||
5150 | .mixers = { alc883_base_mixer, | ||
5151 | alc883_chmode_mixer }, | ||
5152 | /* On TravelMate laptops, GPIO 0 enables the internal speaker | ||
5153 | * and the headphone jack. Turn this on and rely on the | ||
5154 | * standard mute methods whenever the user wants to turn | ||
5155 | * these outputs off. | ||
5156 | */ | ||
5157 | .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs }, | ||
5158 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), | ||
5159 | .dac_nids = alc883_dac_nids, | ||
5160 | .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), | ||
5161 | .adc_nids = alc883_adc_nids, | ||
5162 | .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), | ||
5163 | .channel_mode = alc883_3ST_2ch_modes, | ||
5164 | .input_mux = &alc883_capture_source, | ||
5165 | }, | ||
5080 | }; | 5166 | }; |
5081 | 5167 | ||
5082 | 5168 | ||
@@ -5121,7 +5207,7 @@ static void alc883_auto_init_hp_out(struct hda_codec *codec) | |||
5121 | struct alc_spec *spec = codec->spec; | 5207 | struct alc_spec *spec = codec->spec; |
5122 | hda_nid_t pin; | 5208 | hda_nid_t pin; |
5123 | 5209 | ||
5124 | pin = spec->autocfg.hp_pin; | 5210 | pin = spec->autocfg.hp_pins[0]; |
5125 | if (pin) /* connect to front */ | 5211 | if (pin) /* connect to front */ |
5126 | /* use dac 0 */ | 5212 | /* use dac 0 */ |
5127 | alc883_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); | 5213 | alc883_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); |
@@ -5217,8 +5303,10 @@ static int patch_alc883(struct hda_codec *codec) | |||
5217 | spec->stream_digital_playback = &alc883_pcm_digital_playback; | 5303 | spec->stream_digital_playback = &alc883_pcm_digital_playback; |
5218 | spec->stream_digital_capture = &alc883_pcm_digital_capture; | 5304 | spec->stream_digital_capture = &alc883_pcm_digital_capture; |
5219 | 5305 | ||
5220 | spec->adc_nids = alc883_adc_nids; | 5306 | if (! spec->adc_nids && spec->input_mux) { |
5221 | spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids); | 5307 | spec->adc_nids = alc883_adc_nids; |
5308 | spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids); | ||
5309 | } | ||
5222 | 5310 | ||
5223 | codec->patch_ops = alc_patch_ops; | 5311 | codec->patch_ops = alc_patch_ops; |
5224 | if (board_config == ALC883_AUTO) | 5312 | if (board_config == ALC883_AUTO) |
@@ -5481,6 +5569,7 @@ static struct snd_kcontrol_new alc262_fujitsu_mixer[] = { | |||
5481 | .info = snd_hda_mixer_amp_volume_info, | 5569 | .info = snd_hda_mixer_amp_volume_info, |
5482 | .get = snd_hda_mixer_amp_volume_get, | 5570 | .get = snd_hda_mixer_amp_volume_get, |
5483 | .put = alc262_fujitsu_master_vol_put, | 5571 | .put = alc262_fujitsu_master_vol_put, |
5572 | .tlv = { .c = snd_hda_mixer_amp_tlv }, | ||
5484 | .private_value = HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT), | 5573 | .private_value = HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT), |
5485 | }, | 5574 | }, |
5486 | { | 5575 | { |
@@ -5499,6 +5588,13 @@ static struct snd_kcontrol_new alc262_fujitsu_mixer[] = { | |||
5499 | { } /* end */ | 5588 | { } /* end */ |
5500 | }; | 5589 | }; |
5501 | 5590 | ||
5591 | /* additional init verbs for Benq laptops */ | ||
5592 | static struct hda_verb alc262_EAPD_verbs[] = { | ||
5593 | {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, | ||
5594 | {0x20, AC_VERB_SET_PROC_COEF, 0x3070}, | ||
5595 | {} | ||
5596 | }; | ||
5597 | |||
5502 | /* add playback controls from the parsed DAC table */ | 5598 | /* add playback controls from the parsed DAC table */ |
5503 | static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg) | 5599 | static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg) |
5504 | { | 5600 | { |
@@ -5534,7 +5630,7 @@ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, const struct | |||
5534 | return err; | 5630 | return err; |
5535 | } | 5631 | } |
5536 | } | 5632 | } |
5537 | nid = cfg->hp_pin; | 5633 | nid = cfg->hp_pins[0]; |
5538 | if (nid) { | 5634 | if (nid) { |
5539 | /* spec->multiout.hp_nid = 2; */ | 5635 | /* spec->multiout.hp_nid = 2; */ |
5540 | if (nid == 0x16) { | 5636 | if (nid == 0x16) { |
@@ -5769,6 +5865,7 @@ static struct hda_board_config alc262_cfg_tbl[] = { | |||
5769 | { .modelname = "fujitsu", .config = ALC262_FUJITSU }, | 5865 | { .modelname = "fujitsu", .config = ALC262_FUJITSU }, |
5770 | { .pci_subvendor = 0x10cf, .pci_subdevice = 0x1397, | 5866 | { .pci_subvendor = 0x10cf, .pci_subdevice = 0x1397, |
5771 | .config = ALC262_FUJITSU }, | 5867 | .config = ALC262_FUJITSU }, |
5868 | { .modelname = "hp-bpc", .config = ALC262_HP_BPC }, | ||
5772 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x208c, | 5869 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x208c, |
5773 | .config = ALC262_HP_BPC }, /* xw4400 */ | 5870 | .config = ALC262_HP_BPC }, /* xw4400 */ |
5774 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x3014, | 5871 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x3014, |
@@ -5777,6 +5874,9 @@ static struct hda_board_config alc262_cfg_tbl[] = { | |||
5777 | .config = ALC262_HP_BPC }, /* xw8400 */ | 5874 | .config = ALC262_HP_BPC }, /* xw8400 */ |
5778 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x12fe, | 5875 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x12fe, |
5779 | .config = ALC262_HP_BPC }, /* xw9400 */ | 5876 | .config = ALC262_HP_BPC }, /* xw9400 */ |
5877 | { .modelname = "benq", .config = ALC262_BENQ_ED8 }, | ||
5878 | { .pci_subvendor = 0x17ff, .pci_subdevice = 0x0560, | ||
5879 | .config = ALC262_BENQ_ED8 }, | ||
5780 | { .modelname = "auto", .config = ALC262_AUTO }, | 5880 | { .modelname = "auto", .config = ALC262_AUTO }, |
5781 | {} | 5881 | {} |
5782 | }; | 5882 | }; |
@@ -5814,6 +5914,16 @@ static struct alc_config_preset alc262_presets[] = { | |||
5814 | .channel_mode = alc262_modes, | 5914 | .channel_mode = alc262_modes, |
5815 | .input_mux = &alc262_HP_capture_source, | 5915 | .input_mux = &alc262_HP_capture_source, |
5816 | }, | 5916 | }, |
5917 | [ALC262_BENQ_ED8] = { | ||
5918 | .mixers = { alc262_base_mixer }, | ||
5919 | .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs }, | ||
5920 | .num_dacs = ARRAY_SIZE(alc262_dac_nids), | ||
5921 | .dac_nids = alc262_dac_nids, | ||
5922 | .hp_nid = 0x03, | ||
5923 | .num_channel_mode = ARRAY_SIZE(alc262_modes), | ||
5924 | .channel_mode = alc262_modes, | ||
5925 | .input_mux = &alc262_capture_source, | ||
5926 | }, | ||
5817 | }; | 5927 | }; |
5818 | 5928 | ||
5819 | static int patch_alc262(struct hda_codec *codec) | 5929 | static int patch_alc262(struct hda_codec *codec) |
@@ -5942,6 +6052,23 @@ static struct hda_channel_mode alc861_threestack_modes[2] = { | |||
5942 | { 2, alc861_threestack_ch2_init }, | 6052 | { 2, alc861_threestack_ch2_init }, |
5943 | { 6, alc861_threestack_ch6_init }, | 6053 | { 6, alc861_threestack_ch6_init }, |
5944 | }; | 6054 | }; |
6055 | /* Set mic1 as input and unmute the mixer */ | ||
6056 | static struct hda_verb alc861_uniwill_m31_ch2_init[] = { | ||
6057 | { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, | ||
6058 | { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/ | ||
6059 | { } /* end */ | ||
6060 | }; | ||
6061 | /* Set mic1 as output and mute mixer */ | ||
6062 | static struct hda_verb alc861_uniwill_m31_ch4_init[] = { | ||
6063 | { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, | ||
6064 | { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/ | ||
6065 | { } /* end */ | ||
6066 | }; | ||
6067 | |||
6068 | static struct hda_channel_mode alc861_uniwill_m31_modes[2] = { | ||
6069 | { 2, alc861_uniwill_m31_ch2_init }, | ||
6070 | { 4, alc861_uniwill_m31_ch4_init }, | ||
6071 | }; | ||
5945 | 6072 | ||
5946 | /* patch-ALC861 */ | 6073 | /* patch-ALC861 */ |
5947 | 6074 | ||
@@ -6020,6 +6147,47 @@ static struct snd_kcontrol_new alc861_3ST_mixer[] = { | |||
6020 | }, | 6147 | }, |
6021 | { } /* end */ | 6148 | { } /* end */ |
6022 | }; | 6149 | }; |
6150 | static struct snd_kcontrol_new alc861_uniwill_m31_mixer[] = { | ||
6151 | /* output mixer control */ | ||
6152 | HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT), | ||
6153 | HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT), | ||
6154 | HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT), | ||
6155 | HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT), | ||
6156 | /*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */ | ||
6157 | |||
6158 | /* Input mixer control */ | ||
6159 | /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT), | ||
6160 | HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */ | ||
6161 | HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT), | ||
6162 | HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT), | ||
6163 | HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT), | ||
6164 | HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT), | ||
6165 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT), | ||
6166 | HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT), | ||
6167 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT), | ||
6168 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT), | ||
6169 | |||
6170 | /* Capture mixer control */ | ||
6171 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | ||
6172 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | ||
6173 | { | ||
6174 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
6175 | .name = "Capture Source", | ||
6176 | .count = 1, | ||
6177 | .info = alc_mux_enum_info, | ||
6178 | .get = alc_mux_enum_get, | ||
6179 | .put = alc_mux_enum_put, | ||
6180 | }, | ||
6181 | { | ||
6182 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
6183 | .name = "Channel Mode", | ||
6184 | .info = alc_ch_mode_info, | ||
6185 | .get = alc_ch_mode_get, | ||
6186 | .put = alc_ch_mode_put, | ||
6187 | .private_value = ARRAY_SIZE(alc861_uniwill_m31_modes), | ||
6188 | }, | ||
6189 | { } /* end */ | ||
6190 | }; | ||
6023 | 6191 | ||
6024 | /* | 6192 | /* |
6025 | * generic initialization of ADC, input mixers and output mixers | 6193 | * generic initialization of ADC, input mixers and output mixers |
@@ -6148,6 +6316,67 @@ static struct hda_verb alc861_threestack_init_verbs[] = { | |||
6148 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 6316 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, |
6149 | { } | 6317 | { } |
6150 | }; | 6318 | }; |
6319 | |||
6320 | static struct hda_verb alc861_uniwill_m31_init_verbs[] = { | ||
6321 | /* | ||
6322 | * Unmute ADC0 and set the default input to mic-in | ||
6323 | */ | ||
6324 | /* port-A for surround (rear panel) */ | ||
6325 | { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, | ||
6326 | /* port-B for mic-in (rear panel) with vref */ | ||
6327 | { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, | ||
6328 | /* port-C for line-in (rear panel) */ | ||
6329 | { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, | ||
6330 | /* port-D for Front */ | ||
6331 | { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, | ||
6332 | { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 }, | ||
6333 | /* port-E for HP out (front panel) */ | ||
6334 | { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, // this has to be set to VREF80 | ||
6335 | /* route front PCM to HP */ | ||
6336 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x01 }, | ||
6337 | /* port-F for mic-in (front panel) with vref */ | ||
6338 | { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, | ||
6339 | /* port-G for CLFE (rear panel) */ | ||
6340 | { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, | ||
6341 | /* port-H for side (rear panel) */ | ||
6342 | { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, | ||
6343 | /* CD-in */ | ||
6344 | { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, | ||
6345 | /* route front mic to ADC1*/ | ||
6346 | {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
6347 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
6348 | /* Unmute DAC0~3 & spdif out*/ | ||
6349 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
6350 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
6351 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
6352 | {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
6353 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
6354 | |||
6355 | /* Unmute Mixer 14 (mic) 1c (Line in)*/ | ||
6356 | {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
6357 | {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
6358 | {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
6359 | {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
6360 | |||
6361 | /* Unmute Stereo Mixer 15 */ | ||
6362 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
6363 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
6364 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | ||
6365 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c }, //Output 0~12 step | ||
6366 | |||
6367 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
6368 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
6369 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
6370 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
6371 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
6372 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
6373 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
6374 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
6375 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, // hp used DAC 3 (Front) | ||
6376 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | ||
6377 | { } | ||
6378 | }; | ||
6379 | |||
6151 | /* | 6380 | /* |
6152 | * generic initialization of ADC, input mixers and output mixers | 6381 | * generic initialization of ADC, input mixers and output mixers |
6153 | */ | 6382 | */ |
@@ -6401,7 +6630,7 @@ static void alc861_auto_init_hp_out(struct hda_codec *codec) | |||
6401 | struct alc_spec *spec = codec->spec; | 6630 | struct alc_spec *spec = codec->spec; |
6402 | hda_nid_t pin; | 6631 | hda_nid_t pin; |
6403 | 6632 | ||
6404 | pin = spec->autocfg.hp_pin; | 6633 | pin = spec->autocfg.hp_pins[0]; |
6405 | if (pin) /* connect to front */ | 6634 | if (pin) /* connect to front */ |
6406 | alc861_auto_set_output_and_unmute(codec, pin, PIN_HP, spec->multiout.dac_nids[0]); | 6635 | alc861_auto_set_output_and_unmute(codec, pin, PIN_HP, spec->multiout.dac_nids[0]); |
6407 | } | 6636 | } |
@@ -6436,7 +6665,7 @@ static int alc861_parse_auto_config(struct hda_codec *codec) | |||
6436 | 6665 | ||
6437 | if ((err = alc861_auto_fill_dac_nids(spec, &spec->autocfg)) < 0 || | 6666 | if ((err = alc861_auto_fill_dac_nids(spec, &spec->autocfg)) < 0 || |
6438 | (err = alc861_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || | 6667 | (err = alc861_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || |
6439 | (err = alc861_auto_create_hp_ctls(spec, spec->autocfg.hp_pin)) < 0 || | 6668 | (err = alc861_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0])) < 0 || |
6440 | (err = alc861_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) | 6669 | (err = alc861_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) |
6441 | return err; | 6670 | return err; |
6442 | 6671 | ||
@@ -6477,10 +6706,14 @@ static struct hda_board_config alc861_cfg_tbl[] = { | |||
6477 | { .modelname = "3stack", .config = ALC861_3ST }, | 6706 | { .modelname = "3stack", .config = ALC861_3ST }, |
6478 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xd600, | 6707 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xd600, |
6479 | .config = ALC861_3ST }, | 6708 | .config = ALC861_3ST }, |
6709 | { .modelname = "3stack-660", .config = ALC660_3ST }, | ||
6480 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x81e7, | 6710 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x81e7, |
6481 | .config = ALC660_3ST }, | 6711 | .config = ALC660_3ST }, |
6482 | { .modelname = "3stack-dig", .config = ALC861_3ST_DIG }, | 6712 | { .modelname = "3stack-dig", .config = ALC861_3ST_DIG }, |
6483 | { .modelname = "6stack-dig", .config = ALC861_6ST_DIG }, | 6713 | { .modelname = "6stack-dig", .config = ALC861_6ST_DIG }, |
6714 | { .modelname = "uniwill-m31", .config = ALC861_UNIWILL_M31}, | ||
6715 | { .pci_subvendor = 0x1584, .pci_subdevice = 0x9072, | ||
6716 | .config = ALC861_UNIWILL_M31 }, | ||
6484 | { .modelname = "auto", .config = ALC861_AUTO }, | 6717 | { .modelname = "auto", .config = ALC861_AUTO }, |
6485 | {} | 6718 | {} |
6486 | }; | 6719 | }; |
@@ -6493,6 +6726,7 @@ static struct alc_config_preset alc861_presets[] = { | |||
6493 | .dac_nids = alc861_dac_nids, | 6726 | .dac_nids = alc861_dac_nids, |
6494 | .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes), | 6727 | .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes), |
6495 | .channel_mode = alc861_threestack_modes, | 6728 | .channel_mode = alc861_threestack_modes, |
6729 | .need_dac_fix = 1, | ||
6496 | .num_adc_nids = ARRAY_SIZE(alc861_adc_nids), | 6730 | .num_adc_nids = ARRAY_SIZE(alc861_adc_nids), |
6497 | .adc_nids = alc861_adc_nids, | 6731 | .adc_nids = alc861_adc_nids, |
6498 | .input_mux = &alc861_capture_source, | 6732 | .input_mux = &alc861_capture_source, |
@@ -6505,6 +6739,7 @@ static struct alc_config_preset alc861_presets[] = { | |||
6505 | .dig_out_nid = ALC861_DIGOUT_NID, | 6739 | .dig_out_nid = ALC861_DIGOUT_NID, |
6506 | .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes), | 6740 | .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes), |
6507 | .channel_mode = alc861_threestack_modes, | 6741 | .channel_mode = alc861_threestack_modes, |
6742 | .need_dac_fix = 1, | ||
6508 | .num_adc_nids = ARRAY_SIZE(alc861_adc_nids), | 6743 | .num_adc_nids = ARRAY_SIZE(alc861_adc_nids), |
6509 | .adc_nids = alc861_adc_nids, | 6744 | .adc_nids = alc861_adc_nids, |
6510 | .input_mux = &alc861_capture_source, | 6745 | .input_mux = &alc861_capture_source, |
@@ -6528,10 +6763,25 @@ static struct alc_config_preset alc861_presets[] = { | |||
6528 | .dac_nids = alc660_dac_nids, | 6763 | .dac_nids = alc660_dac_nids, |
6529 | .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes), | 6764 | .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes), |
6530 | .channel_mode = alc861_threestack_modes, | 6765 | .channel_mode = alc861_threestack_modes, |
6766 | .need_dac_fix = 1, | ||
6767 | .num_adc_nids = ARRAY_SIZE(alc861_adc_nids), | ||
6768 | .adc_nids = alc861_adc_nids, | ||
6769 | .input_mux = &alc861_capture_source, | ||
6770 | }, | ||
6771 | [ALC861_UNIWILL_M31] = { | ||
6772 | .mixers = { alc861_uniwill_m31_mixer }, | ||
6773 | .init_verbs = { alc861_uniwill_m31_init_verbs }, | ||
6774 | .num_dacs = ARRAY_SIZE(alc861_dac_nids), | ||
6775 | .dac_nids = alc861_dac_nids, | ||
6776 | .dig_out_nid = ALC861_DIGOUT_NID, | ||
6777 | .num_channel_mode = ARRAY_SIZE(alc861_uniwill_m31_modes), | ||
6778 | .channel_mode = alc861_uniwill_m31_modes, | ||
6779 | .need_dac_fix = 1, | ||
6531 | .num_adc_nids = ARRAY_SIZE(alc861_adc_nids), | 6780 | .num_adc_nids = ARRAY_SIZE(alc861_adc_nids), |
6532 | .adc_nids = alc861_adc_nids, | 6781 | .adc_nids = alc861_adc_nids, |
6533 | .input_mux = &alc861_capture_source, | 6782 | .input_mux = &alc861_capture_source, |
6534 | }, | 6783 | }, |
6784 | |||
6535 | }; | 6785 | }; |
6536 | 6786 | ||
6537 | 6787 | ||
diff --git a/sound/pci/hda/patch_si3054.c b/sound/pci/hda/patch_si3054.c index 250242cd6c70..76ec3d75fa9e 100644 --- a/sound/pci/hda/patch_si3054.c +++ b/sound/pci/hda/patch_si3054.c | |||
@@ -298,6 +298,7 @@ struct hda_codec_preset snd_hda_preset_si3054[] = { | |||
298 | { .id = 0x163c3055, .name = "Si3054", .patch = patch_si3054 }, | 298 | { .id = 0x163c3055, .name = "Si3054", .patch = patch_si3054 }, |
299 | { .id = 0x163c3155, .name = "Si3054", .patch = patch_si3054 }, | 299 | { .id = 0x163c3155, .name = "Si3054", .patch = patch_si3054 }, |
300 | { .id = 0x11c13026, .name = "Si3054", .patch = patch_si3054 }, | 300 | { .id = 0x11c13026, .name = "Si3054", .patch = patch_si3054 }, |
301 | { .id = 0x10573057, .name = "Si3054", .patch = patch_si3054 }, | ||
301 | {} | 302 | {} |
302 | }; | 303 | }; |
303 | 304 | ||
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index ea99083a1024..731b7b97ee71 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -36,15 +36,15 @@ | |||
36 | 36 | ||
37 | #define NUM_CONTROL_ALLOC 32 | 37 | #define NUM_CONTROL_ALLOC 32 |
38 | #define STAC_HP_EVENT 0x37 | 38 | #define STAC_HP_EVENT 0x37 |
39 | #define STAC_UNSOL_ENABLE (AC_USRSP_EN | STAC_HP_EVENT) | ||
40 | 39 | ||
41 | #define STAC_REF 0 | 40 | #define STAC_REF 0 |
42 | #define STAC_D945GTP3 1 | 41 | #define STAC_D945GTP3 1 |
43 | #define STAC_D945GTP5 2 | 42 | #define STAC_D945GTP5 2 |
44 | #define STAC_MACMINI 3 | 43 | #define STAC_MACMINI 3 |
45 | #define STAC_D965_2112 4 | 44 | #define STAC_922X_MODELS 4 /* number of 922x models */ |
46 | #define STAC_D965_284B 5 | 45 | #define STAC_D965_3ST 4 |
47 | #define STAC_922X_MODELS 6 /* number of 922x models */ | 46 | #define STAC_D965_5ST 5 |
47 | #define STAC_927X_MODELS 6 /* number of 922x models */ | ||
48 | 48 | ||
49 | struct sigmatel_spec { | 49 | struct sigmatel_spec { |
50 | struct snd_kcontrol_new *mixers[4]; | 50 | struct snd_kcontrol_new *mixers[4]; |
@@ -73,6 +73,7 @@ struct sigmatel_spec { | |||
73 | hda_nid_t *pin_nids; | 73 | hda_nid_t *pin_nids; |
74 | unsigned int num_pins; | 74 | unsigned int num_pins; |
75 | unsigned int *pin_configs; | 75 | unsigned int *pin_configs; |
76 | unsigned int *bios_pin_configs; | ||
76 | 77 | ||
77 | /* codec specific stuff */ | 78 | /* codec specific stuff */ |
78 | struct hda_verb *init; | 79 | struct hda_verb *init; |
@@ -110,24 +111,10 @@ static hda_nid_t stac922x_adc_nids[2] = { | |||
110 | 0x06, 0x07, | 111 | 0x06, 0x07, |
111 | }; | 112 | }; |
112 | 113 | ||
113 | static hda_nid_t stac9227_adc_nids[2] = { | ||
114 | 0x07, 0x08, | ||
115 | }; | ||
116 | |||
117 | #if 0 | ||
118 | static hda_nid_t d965_2112_dac_nids[3] = { | ||
119 | 0x02, 0x03, 0x05, | ||
120 | }; | ||
121 | #endif | ||
122 | |||
123 | static hda_nid_t stac922x_mux_nids[2] = { | 114 | static hda_nid_t stac922x_mux_nids[2] = { |
124 | 0x12, 0x13, | 115 | 0x12, 0x13, |
125 | }; | 116 | }; |
126 | 117 | ||
127 | static hda_nid_t stac9227_mux_nids[2] = { | ||
128 | 0x15, 0x16, | ||
129 | }; | ||
130 | |||
131 | static hda_nid_t stac927x_adc_nids[3] = { | 118 | static hda_nid_t stac927x_adc_nids[3] = { |
132 | 0x07, 0x08, 0x09 | 119 | 0x07, 0x08, 0x09 |
133 | }; | 120 | }; |
@@ -136,8 +123,17 @@ static hda_nid_t stac927x_mux_nids[3] = { | |||
136 | 0x15, 0x16, 0x17 | 123 | 0x15, 0x16, 0x17 |
137 | }; | 124 | }; |
138 | 125 | ||
126 | static hda_nid_t stac9205_adc_nids[2] = { | ||
127 | 0x12, 0x13 | ||
128 | }; | ||
129 | |||
130 | static hda_nid_t stac9205_mux_nids[2] = { | ||
131 | 0x19, 0x1a | ||
132 | }; | ||
133 | |||
139 | static hda_nid_t stac9200_pin_nids[8] = { | 134 | static hda_nid_t stac9200_pin_nids[8] = { |
140 | 0x08, 0x09, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, | 135 | 0x08, 0x09, 0x0d, 0x0e, |
136 | 0x0f, 0x10, 0x11, 0x12, | ||
141 | }; | 137 | }; |
142 | 138 | ||
143 | static hda_nid_t stac922x_pin_nids[10] = { | 139 | static hda_nid_t stac922x_pin_nids[10] = { |
@@ -151,6 +147,13 @@ static hda_nid_t stac927x_pin_nids[14] = { | |||
151 | 0x14, 0x21, 0x22, 0x23, | 147 | 0x14, 0x21, 0x22, 0x23, |
152 | }; | 148 | }; |
153 | 149 | ||
150 | static hda_nid_t stac9205_pin_nids[12] = { | ||
151 | 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, | ||
152 | 0x0f, 0x14, 0x16, 0x17, 0x18, | ||
153 | 0x21, 0x22, | ||
154 | |||
155 | }; | ||
156 | |||
154 | static int stac92xx_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 157 | static int stac92xx_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) |
155 | { | 158 | { |
156 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 159 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
@@ -190,25 +193,23 @@ static struct hda_verb stac922x_core_init[] = { | |||
190 | {} | 193 | {} |
191 | }; | 194 | }; |
192 | 195 | ||
193 | static struct hda_verb stac9227_core_init[] = { | 196 | static struct hda_verb d965_core_init[] = { |
194 | /* set master volume and direct control */ | 197 | /* set master volume and direct control */ |
195 | { 0x16, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | 198 | { 0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, |
196 | /* unmute node 0x1b */ | 199 | /* unmute node 0x1b */ |
197 | { 0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 200 | { 0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, |
201 | /* select node 0x03 as DAC */ | ||
202 | { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
198 | {} | 203 | {} |
199 | }; | 204 | }; |
200 | 205 | ||
201 | static struct hda_verb d965_2112_core_init[] = { | 206 | static struct hda_verb stac927x_core_init[] = { |
202 | /* set master volume and direct control */ | 207 | /* set master volume and direct control */ |
203 | { 0x16, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | 208 | { 0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, |
204 | /* unmute node 0x1b */ | ||
205 | { 0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
206 | /* select node 0x03 as DAC */ | ||
207 | { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
208 | {} | 209 | {} |
209 | }; | 210 | }; |
210 | 211 | ||
211 | static struct hda_verb stac927x_core_init[] = { | 212 | static struct hda_verb stac9205_core_init[] = { |
212 | /* set master volume and direct control */ | 213 | /* set master volume and direct control */ |
213 | { 0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | 214 | { 0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, |
214 | {} | 215 | {} |
@@ -277,6 +278,21 @@ static snd_kcontrol_new_t stac927x_mixer[] = { | |||
277 | { } /* end */ | 278 | { } /* end */ |
278 | }; | 279 | }; |
279 | 280 | ||
281 | static snd_kcontrol_new_t stac9205_mixer[] = { | ||
282 | { | ||
283 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
284 | .name = "Input Source", | ||
285 | .count = 1, | ||
286 | .info = stac92xx_mux_enum_info, | ||
287 | .get = stac92xx_mux_enum_get, | ||
288 | .put = stac92xx_mux_enum_put, | ||
289 | }, | ||
290 | HDA_CODEC_VOLUME("InMux Capture Volume", 0x19, 0x0, HDA_OUTPUT), | ||
291 | HDA_CODEC_VOLUME("InVol Capture Volume", 0x1b, 0x0, HDA_INPUT), | ||
292 | HDA_CODEC_MUTE("ADCMux Capture Switch", 0x1d, 0x0, HDA_OUTPUT), | ||
293 | { } /* end */ | ||
294 | }; | ||
295 | |||
280 | static int stac92xx_build_controls(struct hda_codec *codec) | 296 | static int stac92xx_build_controls(struct hda_codec *codec) |
281 | { | 297 | { |
282 | struct sigmatel_spec *spec = codec->spec; | 298 | struct sigmatel_spec *spec = codec->spec; |
@@ -341,38 +357,67 @@ static unsigned int d945gtp5_pin_configs[10] = { | |||
341 | 0x02a19320, 0x40000100, | 357 | 0x02a19320, 0x40000100, |
342 | }; | 358 | }; |
343 | 359 | ||
344 | static unsigned int d965_2112_pin_configs[10] = { | ||
345 | 0x0221401f, 0x40000100, 0x40000100, 0x01014011, | ||
346 | 0x01a19021, 0x01813024, 0x01452130, 0x40000100, | ||
347 | 0x02a19320, 0x40000100, | ||
348 | }; | ||
349 | |||
350 | static unsigned int *stac922x_brd_tbl[STAC_922X_MODELS] = { | 360 | static unsigned int *stac922x_brd_tbl[STAC_922X_MODELS] = { |
351 | [STAC_REF] = ref922x_pin_configs, | 361 | [STAC_REF] = ref922x_pin_configs, |
352 | [STAC_D945GTP3] = d945gtp3_pin_configs, | 362 | [STAC_D945GTP3] = d945gtp3_pin_configs, |
353 | [STAC_D945GTP5] = d945gtp5_pin_configs, | 363 | [STAC_D945GTP5] = d945gtp5_pin_configs, |
354 | [STAC_MACMINI] = d945gtp5_pin_configs, | 364 | [STAC_MACMINI] = d945gtp5_pin_configs, |
355 | [STAC_D965_2112] = d965_2112_pin_configs, | ||
356 | }; | 365 | }; |
357 | 366 | ||
358 | static struct hda_board_config stac922x_cfg_tbl[] = { | 367 | static struct hda_board_config stac922x_cfg_tbl[] = { |
368 | { .modelname = "5stack", .config = STAC_D945GTP5 }, | ||
369 | { .modelname = "3stack", .config = STAC_D945GTP3 }, | ||
359 | { .modelname = "ref", | 370 | { .modelname = "ref", |
360 | .pci_subvendor = PCI_VENDOR_ID_INTEL, | 371 | .pci_subvendor = PCI_VENDOR_ID_INTEL, |
361 | .pci_subdevice = 0x2668, /* DFI LanParty */ | 372 | .pci_subdevice = 0x2668, /* DFI LanParty */ |
362 | .config = STAC_REF }, /* SigmaTel reference board */ | 373 | .config = STAC_REF }, /* SigmaTel reference board */ |
374 | /* Intel 945G based systems */ | ||
363 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | 375 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, |
364 | .pci_subdevice = 0x0101, | 376 | .pci_subdevice = 0x0101, |
365 | .config = STAC_D945GTP3 }, /* Intel D945GTP - 3 Stack */ | 377 | .config = STAC_D945GTP3 }, /* Intel D945GTP - 3 Stack */ |
366 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | 378 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, |
367 | .pci_subdevice = 0x0202, | 379 | .pci_subdevice = 0x0202, |
368 | .config = STAC_D945GTP3 }, /* Intel D945GNT - 3 Stack, 9221 A1 */ | 380 | .config = STAC_D945GTP3 }, /* Intel D945GNT - 3 Stack */ |
369 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | 381 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, |
370 | .pci_subdevice = 0x0b0b, | 382 | .pci_subdevice = 0x0606, |
371 | .config = STAC_D945GTP3 }, /* Intel D945PSN - 3 Stack, 9221 A1 */ | 383 | .config = STAC_D945GTP3 }, /* Intel D945GTP - 3 Stack */ |
384 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
385 | .pci_subdevice = 0x0601, | ||
386 | .config = STAC_D945GTP3 }, /* Intel D945GTP - 3 Stack */ | ||
387 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
388 | .pci_subdevice = 0x0111, | ||
389 | .config = STAC_D945GTP3 }, /* Intel D945GZP - 3 Stack */ | ||
390 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
391 | .pci_subdevice = 0x1115, | ||
392 | .config = STAC_D945GTP3 }, /* Intel D945GPM - 3 Stack */ | ||
393 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
394 | .pci_subdevice = 0x1116, | ||
395 | .config = STAC_D945GTP3 }, /* Intel D945GBO - 3 Stack */ | ||
396 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
397 | .pci_subdevice = 0x1117, | ||
398 | .config = STAC_D945GTP3 }, /* Intel D945GPM - 3 Stack */ | ||
399 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
400 | .pci_subdevice = 0x1118, | ||
401 | .config = STAC_D945GTP3 }, /* Intel D945GPM - 3 Stack */ | ||
402 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
403 | .pci_subdevice = 0x1119, | ||
404 | .config = STAC_D945GTP3 }, /* Intel D945GPM - 3 Stack */ | ||
405 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
406 | .pci_subdevice = 0x8826, | ||
407 | .config = STAC_D945GTP3 }, /* Intel D945GPM - 3 Stack */ | ||
408 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
409 | .pci_subdevice = 0x5049, | ||
410 | .config = STAC_D945GTP3 }, /* Intel D945GCZ - 3 Stack */ | ||
411 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
412 | .pci_subdevice = 0x5055, | ||
413 | .config = STAC_D945GTP3 }, /* Intel D945GCZ - 3 Stack */ | ||
414 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
415 | .pci_subdevice = 0x5048, | ||
416 | .config = STAC_D945GTP3 }, /* Intel D945GPB - 3 Stack */ | ||
417 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
418 | .pci_subdevice = 0x0110, | ||
419 | .config = STAC_D945GTP3 }, /* Intel D945GLR - 3 Stack */ | ||
372 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | 420 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, |
373 | .pci_subdevice = 0x0707, | ||
374 | .config = STAC_D945GTP5 }, /* Intel D945PSV - 5 Stack */ | ||
375 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
376 | .pci_subdevice = 0x0404, | 421 | .pci_subdevice = 0x0404, |
377 | .config = STAC_D945GTP5 }, /* Intel D945GTP - 5 Stack */ | 422 | .config = STAC_D945GTP5 }, /* Intel D945GTP - 5 Stack */ |
378 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | 423 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, |
@@ -384,44 +429,214 @@ static struct hda_board_config stac922x_cfg_tbl[] = { | |||
384 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | 429 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, |
385 | .pci_subdevice = 0x0417, | 430 | .pci_subdevice = 0x0417, |
386 | .config = STAC_D945GTP5 }, /* Intel D975XBK - 5 Stack */ | 431 | .config = STAC_D945GTP5 }, /* Intel D975XBK - 5 Stack */ |
432 | /* Intel 945P based systems */ | ||
433 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
434 | .pci_subdevice = 0x0b0b, | ||
435 | .config = STAC_D945GTP3 }, /* Intel D945PSN - 3 Stack */ | ||
436 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
437 | .pci_subdevice = 0x0112, | ||
438 | .config = STAC_D945GTP3 }, /* Intel D945PLN - 3 Stack */ | ||
439 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
440 | .pci_subdevice = 0x0d0d, | ||
441 | .config = STAC_D945GTP3 }, /* Intel D945PLM - 3 Stack */ | ||
442 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
443 | .pci_subdevice = 0x0909, | ||
444 | .config = STAC_D945GTP3 }, /* Intel D945PAW - 3 Stack */ | ||
445 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
446 | .pci_subdevice = 0x0505, | ||
447 | .config = STAC_D945GTP3 }, /* Intel D945PLM - 3 Stack */ | ||
448 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
449 | .pci_subdevice = 0x0707, | ||
450 | .config = STAC_D945GTP5 }, /* Intel D945PSV - 5 Stack */ | ||
451 | /* other systems */ | ||
387 | { .pci_subvendor = 0x8384, | 452 | { .pci_subvendor = 0x8384, |
388 | .pci_subdevice = 0x7680, | 453 | .pci_subdevice = 0x7680, |
389 | .config = STAC_MACMINI }, /* Apple Mac Mini (early 2006) */ | 454 | .config = STAC_MACMINI }, /* Apple Mac Mini (early 2006) */ |
455 | {} /* terminator */ | ||
456 | }; | ||
457 | |||
458 | static unsigned int ref927x_pin_configs[14] = { | ||
459 | 0x02214020, 0x02a19080, 0x0181304e, 0x01014010, | ||
460 | 0x01a19040, 0x01011012, 0x01016011, 0x0101201f, | ||
461 | 0x183301f0, 0x18a001f0, 0x18a001f0, 0x01442070, | ||
462 | 0x01c42190, 0x40000100, | ||
463 | }; | ||
464 | |||
465 | static unsigned int d965_3st_pin_configs[14] = { | ||
466 | 0x0221401f, 0x02a19120, 0x40000100, 0x01014011, | ||
467 | 0x01a19021, 0x01813024, 0x40000100, 0x40000100, | ||
468 | 0x40000100, 0x40000100, 0x40000100, 0x40000100, | ||
469 | 0x40000100, 0x40000100 | ||
470 | }; | ||
471 | |||
472 | static unsigned int d965_5st_pin_configs[14] = { | ||
473 | 0x02214020, 0x02a19080, 0x0181304e, 0x01014010, | ||
474 | 0x01a19040, 0x01011012, 0x01016011, 0x40000100, | ||
475 | 0x40000100, 0x40000100, 0x40000100, 0x01442070, | ||
476 | 0x40000100, 0x40000100 | ||
477 | }; | ||
478 | |||
479 | static unsigned int *stac927x_brd_tbl[STAC_927X_MODELS] = { | ||
480 | [STAC_REF] = ref927x_pin_configs, | ||
481 | [STAC_D965_3ST] = d965_3st_pin_configs, | ||
482 | [STAC_D965_5ST] = d965_5st_pin_configs, | ||
483 | }; | ||
484 | |||
485 | static struct hda_board_config stac927x_cfg_tbl[] = { | ||
486 | { .modelname = "5stack", .config = STAC_D965_5ST }, | ||
487 | { .modelname = "3stack", .config = STAC_D965_3ST }, | ||
488 | { .modelname = "ref", | ||
489 | .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
490 | .pci_subdevice = 0x2668, /* DFI LanParty */ | ||
491 | .config = STAC_REF }, /* SigmaTel reference board */ | ||
492 | /* Intel 946 based systems */ | ||
493 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
494 | .pci_subdevice = 0x3d01, | ||
495 | .config = STAC_D965_3ST }, /* D946 configuration */ | ||
496 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
497 | .pci_subdevice = 0xa301, | ||
498 | .config = STAC_D965_3ST }, /* Intel D946GZT - 3 stack */ | ||
499 | /* 965 based 3 stack systems */ | ||
500 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
501 | .pci_subdevice = 0x2116, | ||
502 | .config = STAC_D965_3ST }, /* Intel D965 3Stack config */ | ||
503 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
504 | .pci_subdevice = 0x2115, | ||
505 | .config = STAC_D965_3ST }, /* Intel DQ965WC - 3 Stack */ | ||
506 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
507 | .pci_subdevice = 0x2114, | ||
508 | .config = STAC_D965_3ST }, /* Intel D965 3Stack config */ | ||
509 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
510 | .pci_subdevice = 0x2113, | ||
511 | .config = STAC_D965_3ST }, /* Intel D965 3Stack config */ | ||
390 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | 512 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, |
391 | .pci_subdevice = 0x2112, | 513 | .pci_subdevice = 0x2112, |
392 | .config = STAC_D965_2112 }, | 514 | .config = STAC_D965_3ST }, /* Intel DG965MS - 3 Stack */ |
515 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
516 | .pci_subdevice = 0x2111, | ||
517 | .config = STAC_D965_3ST }, /* Intel D965 3Stack config */ | ||
518 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
519 | .pci_subdevice = 0x2110, | ||
520 | .config = STAC_D965_3ST }, /* Intel D965 3Stack config */ | ||
521 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
522 | .pci_subdevice = 0x2009, | ||
523 | .config = STAC_D965_3ST }, /* Intel D965 3Stack config */ | ||
524 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
525 | .pci_subdevice = 0x2008, | ||
526 | .config = STAC_D965_3ST }, /* Intel DQ965GF - 3 Stack */ | ||
527 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
528 | .pci_subdevice = 0x2007, | ||
529 | .config = STAC_D965_3ST }, /* Intel D965 3Stack config */ | ||
530 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
531 | .pci_subdevice = 0x2006, | ||
532 | .config = STAC_D965_3ST }, /* Intel D965 3Stack config */ | ||
533 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
534 | .pci_subdevice = 0x2005, | ||
535 | .config = STAC_D965_3ST }, /* Intel D965 3Stack config */ | ||
536 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
537 | .pci_subdevice = 0x2004, | ||
538 | .config = STAC_D965_3ST }, /* Intel D965 3Stack config */ | ||
539 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
540 | .pci_subdevice = 0x2003, | ||
541 | .config = STAC_D965_3ST }, /* Intel D965 3Stack config */ | ||
542 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
543 | .pci_subdevice = 0x2002, | ||
544 | .config = STAC_D965_3ST }, /* Intel D965 3Stack config */ | ||
545 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
546 | .pci_subdevice = 0x2001, | ||
547 | .config = STAC_D965_3ST }, /* Intel DQ965GF - 3 Stack */ | ||
548 | /* 965 based 5 stack systems */ | ||
549 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
550 | .pci_subdevice = 0x2301, | ||
551 | .config = STAC_D965_5ST }, /* Intel DG965 - 5 Stack */ | ||
552 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
553 | .pci_subdevice = 0x2302, | ||
554 | .config = STAC_D965_5ST }, /* Intel DG965 - 5 Stack */ | ||
555 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
556 | .pci_subdevice = 0x2303, | ||
557 | .config = STAC_D965_5ST }, /* Intel DG965 - 5 Stack */ | ||
393 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | 558 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, |
394 | .pci_subdevice = 0x284b, | 559 | .pci_subdevice = 0x2304, |
395 | .config = STAC_D965_284B }, | 560 | .config = STAC_D965_5ST }, /* Intel DG965 - 5 Stack */ |
561 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
562 | .pci_subdevice = 0x2305, | ||
563 | .config = STAC_D965_5ST }, /* Intel DG965 - 5 Stack */ | ||
564 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
565 | .pci_subdevice = 0x2501, | ||
566 | .config = STAC_D965_5ST }, /* Intel DG965MQ - 5 Stack */ | ||
567 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
568 | .pci_subdevice = 0x2502, | ||
569 | .config = STAC_D965_5ST }, /* Intel DG965 - 5 Stack */ | ||
570 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
571 | .pci_subdevice = 0x2503, | ||
572 | .config = STAC_D965_5ST }, /* Intel DG965 - 5 Stack */ | ||
573 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
574 | .pci_subdevice = 0x2504, | ||
575 | .config = STAC_D965_5ST }, /* Intel DQ965GF - 5 Stack */ | ||
396 | {} /* terminator */ | 576 | {} /* terminator */ |
397 | }; | 577 | }; |
398 | 578 | ||
399 | static unsigned int ref927x_pin_configs[14] = { | 579 | static unsigned int ref9205_pin_configs[12] = { |
400 | 0x01813122, 0x01a19021, 0x01014010, 0x01016011, | 580 | 0x40000100, 0x40000100, 0x01016011, 0x01014010, |
401 | 0x01012012, 0x01011014, 0x40000100, 0x40000100, | 581 | 0x01813122, 0x01a19021, 0x40000100, 0x40000100, |
402 | 0x40000100, 0x40000100, 0x40000100, 0x01441030, | 582 | 0x40000100, 0x40000100, 0x01441030, 0x01c41030 |
403 | 0x01c41030, 0x40000100, | ||
404 | }; | 583 | }; |
405 | 584 | ||
406 | static unsigned int *stac927x_brd_tbl[] = { | 585 | static unsigned int *stac9205_brd_tbl[] = { |
407 | ref927x_pin_configs, | 586 | ref9205_pin_configs, |
408 | }; | 587 | }; |
409 | 588 | ||
410 | static struct hda_board_config stac927x_cfg_tbl[] = { | 589 | static struct hda_board_config stac9205_cfg_tbl[] = { |
411 | { .modelname = "ref", | 590 | { .modelname = "ref", |
412 | .pci_subvendor = PCI_VENDOR_ID_INTEL, | 591 | .pci_subvendor = PCI_VENDOR_ID_INTEL, |
413 | .pci_subdevice = 0x2668, /* DFI LanParty */ | 592 | .pci_subdevice = 0x2668, /* DFI LanParty */ |
414 | .config = STAC_REF }, /* SigmaTel reference board */ | 593 | .config = STAC_REF }, /* SigmaTel reference board */ |
594 | /* Dell laptops have BIOS problem */ | ||
595 | { .pci_subvendor = PCI_VENDOR_ID_DELL, .pci_subdevice = 0x01b5, | ||
596 | .config = STAC_REF }, /* Dell Inspiron 630m */ | ||
597 | { .pci_subvendor = PCI_VENDOR_ID_DELL, .pci_subdevice = 0x01c2, | ||
598 | .config = STAC_REF }, /* Dell Latitude D620 */ | ||
599 | { .pci_subvendor = PCI_VENDOR_ID_DELL, .pci_subdevice = 0x01cb, | ||
600 | .config = STAC_REF }, /* Dell Latitude 120L */ | ||
415 | {} /* terminator */ | 601 | {} /* terminator */ |
416 | }; | 602 | }; |
417 | 603 | ||
604 | static int stac92xx_save_bios_config_regs(struct hda_codec *codec) | ||
605 | { | ||
606 | int i; | ||
607 | struct sigmatel_spec *spec = codec->spec; | ||
608 | |||
609 | if (! spec->bios_pin_configs) { | ||
610 | spec->bios_pin_configs = kcalloc(spec->num_pins, | ||
611 | sizeof(*spec->bios_pin_configs), GFP_KERNEL); | ||
612 | if (! spec->bios_pin_configs) | ||
613 | return -ENOMEM; | ||
614 | } | ||
615 | |||
616 | for (i = 0; i < spec->num_pins; i++) { | ||
617 | hda_nid_t nid = spec->pin_nids[i]; | ||
618 | unsigned int pin_cfg; | ||
619 | |||
620 | pin_cfg = snd_hda_codec_read(codec, nid, 0, | ||
621 | AC_VERB_GET_CONFIG_DEFAULT, 0x00); | ||
622 | snd_printdd(KERN_INFO "hda_codec: pin nid %2.2x bios pin config %8.8x\n", | ||
623 | nid, pin_cfg); | ||
624 | spec->bios_pin_configs[i] = pin_cfg; | ||
625 | } | ||
626 | |||
627 | return 0; | ||
628 | } | ||
629 | |||
418 | static void stac92xx_set_config_regs(struct hda_codec *codec) | 630 | static void stac92xx_set_config_regs(struct hda_codec *codec) |
419 | { | 631 | { |
420 | int i; | 632 | int i; |
421 | struct sigmatel_spec *spec = codec->spec; | 633 | struct sigmatel_spec *spec = codec->spec; |
422 | unsigned int pin_cfg; | 634 | unsigned int pin_cfg; |
423 | 635 | ||
424 | for (i=0; i < spec->num_pins; i++) { | 636 | if (! spec->pin_nids || ! spec->pin_configs) |
637 | return; | ||
638 | |||
639 | for (i = 0; i < spec->num_pins; i++) { | ||
425 | snd_hda_codec_write(codec, spec->pin_nids[i], 0, | 640 | snd_hda_codec_write(codec, spec->pin_nids[i], 0, |
426 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_0, | 641 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_0, |
427 | spec->pin_configs[i] & 0x000000ff); | 642 | spec->pin_configs[i] & 0x000000ff); |
@@ -795,11 +1010,29 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec, | |||
795 | return 0; | 1010 | return 0; |
796 | } | 1011 | } |
797 | 1012 | ||
1013 | /* create volume control/switch for the given prefx type */ | ||
1014 | static int create_controls(struct sigmatel_spec *spec, const char *pfx, hda_nid_t nid, int chs) | ||
1015 | { | ||
1016 | char name[32]; | ||
1017 | int err; | ||
1018 | |||
1019 | sprintf(name, "%s Playback Volume", pfx); | ||
1020 | err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, name, | ||
1021 | HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT)); | ||
1022 | if (err < 0) | ||
1023 | return err; | ||
1024 | sprintf(name, "%s Playback Switch", pfx); | ||
1025 | err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, name, | ||
1026 | HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT)); | ||
1027 | if (err < 0) | ||
1028 | return err; | ||
1029 | return 0; | ||
1030 | } | ||
1031 | |||
798 | /* add playback controls from the parsed DAC table */ | 1032 | /* add playback controls from the parsed DAC table */ |
799 | static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec, | 1033 | static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec, |
800 | const struct auto_pin_cfg *cfg) | 1034 | const struct auto_pin_cfg *cfg) |
801 | { | 1035 | { |
802 | char name[32]; | ||
803 | static const char *chname[4] = { | 1036 | static const char *chname[4] = { |
804 | "Front", "Surround", NULL /*CLFE*/, "Side" | 1037 | "Front", "Surround", NULL /*CLFE*/, "Side" |
805 | }; | 1038 | }; |
@@ -814,26 +1047,15 @@ static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec, | |||
814 | 1047 | ||
815 | if (i == 2) { | 1048 | if (i == 2) { |
816 | /* Center/LFE */ | 1049 | /* Center/LFE */ |
817 | if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, "Center Playback Volume", | 1050 | err = create_controls(spec, "Center", nid, 1); |
818 | HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT))) < 0) | 1051 | if (err < 0) |
819 | return err; | ||
820 | if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, "LFE Playback Volume", | ||
821 | HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0) | ||
822 | return err; | ||
823 | if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, "Center Playback Switch", | ||
824 | HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT))) < 0) | ||
825 | return err; | 1052 | return err; |
826 | if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, "LFE Playback Switch", | 1053 | err = create_controls(spec, "LFE", nid, 2); |
827 | HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0) | 1054 | if (err < 0) |
828 | return err; | 1055 | return err; |
829 | } else { | 1056 | } else { |
830 | sprintf(name, "%s Playback Volume", chname[i]); | 1057 | err = create_controls(spec, chname[i], nid, 3); |
831 | if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, name, | 1058 | if (err < 0) |
832 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) | ||
833 | return err; | ||
834 | sprintf(name, "%s Playback Switch", chname[i]); | ||
835 | if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, name, | ||
836 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) | ||
837 | return err; | 1059 | return err; |
838 | } | 1060 | } |
839 | } | 1061 | } |
@@ -849,39 +1071,85 @@ static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec, | |||
849 | return 0; | 1071 | return 0; |
850 | } | 1072 | } |
851 | 1073 | ||
852 | /* add playback controls for HP output */ | 1074 | static int check_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid) |
853 | static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec, struct auto_pin_cfg *cfg) | ||
854 | { | 1075 | { |
855 | struct sigmatel_spec *spec = codec->spec; | 1076 | int i; |
856 | hda_nid_t pin = cfg->hp_pin; | ||
857 | hda_nid_t nid; | ||
858 | int i, err; | ||
859 | unsigned int wid_caps; | ||
860 | 1077 | ||
861 | if (! pin) | 1078 | for (i = 0; i < spec->multiout.num_dacs; i++) { |
862 | return 0; | 1079 | if (spec->multiout.dac_nids[i] == nid) |
1080 | return 1; | ||
1081 | } | ||
1082 | if (spec->multiout.hp_nid == nid) | ||
1083 | return 1; | ||
1084 | return 0; | ||
1085 | } | ||
863 | 1086 | ||
864 | wid_caps = get_wcaps(codec, pin); | 1087 | static int add_spec_dacs(struct sigmatel_spec *spec, hda_nid_t nid) |
865 | if (wid_caps & AC_WCAP_UNSOL_CAP) | 1088 | { |
866 | spec->hp_detect = 1; | 1089 | if (!spec->multiout.hp_nid) |
1090 | spec->multiout.hp_nid = nid; | ||
1091 | else if (spec->multiout.num_dacs > 4) { | ||
1092 | printk(KERN_WARNING "stac92xx: No space for DAC 0x%x\n", nid); | ||
1093 | return 1; | ||
1094 | } else { | ||
1095 | spec->multiout.dac_nids[spec->multiout.num_dacs] = nid; | ||
1096 | spec->multiout.num_dacs++; | ||
1097 | } | ||
1098 | return 0; | ||
1099 | } | ||
867 | 1100 | ||
868 | nid = snd_hda_codec_read(codec, pin, 0, AC_VERB_GET_CONNECT_LIST, 0) & 0xff; | 1101 | /* add playback controls for Speaker and HP outputs */ |
869 | for (i = 0; i < cfg->line_outs; i++) { | 1102 | static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec, |
870 | if (! spec->multiout.dac_nids[i]) | 1103 | struct auto_pin_cfg *cfg) |
1104 | { | ||
1105 | struct sigmatel_spec *spec = codec->spec; | ||
1106 | hda_nid_t nid; | ||
1107 | int i, old_num_dacs, err; | ||
1108 | |||
1109 | old_num_dacs = spec->multiout.num_dacs; | ||
1110 | for (i = 0; i < cfg->hp_outs; i++) { | ||
1111 | unsigned int wid_caps = get_wcaps(codec, cfg->hp_pins[i]); | ||
1112 | if (wid_caps & AC_WCAP_UNSOL_CAP) | ||
1113 | spec->hp_detect = 1; | ||
1114 | nid = snd_hda_codec_read(codec, cfg->hp_pins[i], 0, | ||
1115 | AC_VERB_GET_CONNECT_LIST, 0) & 0xff; | ||
1116 | if (check_in_dac_nids(spec, nid)) | ||
1117 | nid = 0; | ||
1118 | if (! nid) | ||
871 | continue; | 1119 | continue; |
872 | if (spec->multiout.dac_nids[i] == nid) | 1120 | add_spec_dacs(spec, nid); |
873 | return 0; | 1121 | } |
1122 | for (i = 0; i < cfg->speaker_outs; i++) { | ||
1123 | nid = snd_hda_codec_read(codec, cfg->speaker_pins[0], 0, | ||
1124 | AC_VERB_GET_CONNECT_LIST, 0) & 0xff; | ||
1125 | if (check_in_dac_nids(spec, nid)) | ||
1126 | nid = 0; | ||
1127 | if (check_in_dac_nids(spec, nid)) | ||
1128 | nid = 0; | ||
1129 | if (! nid) | ||
1130 | continue; | ||
1131 | add_spec_dacs(spec, nid); | ||
874 | } | 1132 | } |
875 | 1133 | ||
876 | spec->multiout.hp_nid = nid; | 1134 | for (i = old_num_dacs; i < spec->multiout.num_dacs; i++) { |
877 | 1135 | static const char *pfxs[] = { | |
878 | /* control HP volume/switch on the output mixer amp */ | 1136 | "Speaker", "External Speaker", "Speaker2", |
879 | if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, "Headphone Playback Volume", | 1137 | }; |
880 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) | 1138 | err = create_controls(spec, pfxs[i - old_num_dacs], |
881 | return err; | 1139 | spec->multiout.dac_nids[i], 3); |
882 | if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, "Headphone Playback Switch", | 1140 | if (err < 0) |
883 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) | 1141 | return err; |
884 | return err; | 1142 | } |
1143 | if (spec->multiout.hp_nid) { | ||
1144 | const char *pfx; | ||
1145 | if (old_num_dacs == spec->multiout.num_dacs) | ||
1146 | pfx = "Master"; | ||
1147 | else | ||
1148 | pfx = "Headphone"; | ||
1149 | err = create_controls(spec, pfx, spec->multiout.hp_nid, 3); | ||
1150 | if (err < 0) | ||
1151 | return err; | ||
1152 | } | ||
885 | 1153 | ||
886 | return 0; | 1154 | return 0; |
887 | } | 1155 | } |
@@ -895,23 +1163,28 @@ static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const | |||
895 | int i, j, k; | 1163 | int i, j, k; |
896 | 1164 | ||
897 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 1165 | for (i = 0; i < AUTO_PIN_LAST; i++) { |
898 | int index = -1; | 1166 | int index; |
899 | if (cfg->input_pins[i]) { | 1167 | |
900 | imux->items[imux->num_items].label = auto_pin_cfg_labels[i]; | 1168 | if (!cfg->input_pins[i]) |
901 | 1169 | continue; | |
902 | for (j=0; j<spec->num_muxes; j++) { | 1170 | index = -1; |
903 | int num_cons = snd_hda_get_connections(codec, spec->mux_nids[j], con_lst, HDA_MAX_NUM_INPUTS); | 1171 | for (j = 0; j < spec->num_muxes; j++) { |
904 | for (k=0; k<num_cons; k++) | 1172 | int num_cons; |
905 | if (con_lst[k] == cfg->input_pins[i]) { | 1173 | num_cons = snd_hda_get_connections(codec, |
906 | index = k; | 1174 | spec->mux_nids[j], |
907 | break; | 1175 | con_lst, |
908 | } | 1176 | HDA_MAX_NUM_INPUTS); |
909 | if (index >= 0) | 1177 | for (k = 0; k < num_cons; k++) |
910 | break; | 1178 | if (con_lst[k] == cfg->input_pins[i]) { |
911 | } | 1179 | index = k; |
912 | imux->items[imux->num_items].index = index; | 1180 | goto found; |
913 | imux->num_items++; | 1181 | } |
914 | } | 1182 | } |
1183 | continue; | ||
1184 | found: | ||
1185 | imux->items[imux->num_items].label = auto_pin_cfg_labels[i]; | ||
1186 | imux->items[imux->num_items].index = index; | ||
1187 | imux->num_items++; | ||
915 | } | 1188 | } |
916 | 1189 | ||
917 | if (imux->num_items == 1) { | 1190 | if (imux->num_items == 1) { |
@@ -944,11 +1217,20 @@ static void stac92xx_auto_init_multi_out(struct hda_codec *codec) | |||
944 | static void stac92xx_auto_init_hp_out(struct hda_codec *codec) | 1217 | static void stac92xx_auto_init_hp_out(struct hda_codec *codec) |
945 | { | 1218 | { |
946 | struct sigmatel_spec *spec = codec->spec; | 1219 | struct sigmatel_spec *spec = codec->spec; |
947 | hda_nid_t pin; | 1220 | int i; |
948 | 1221 | ||
949 | pin = spec->autocfg.hp_pin; | 1222 | for (i = 0; i < spec->autocfg.hp_outs; i++) { |
950 | if (pin) /* connect to front */ | 1223 | hda_nid_t pin; |
951 | stac92xx_auto_set_pinctl(codec, pin, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN); | 1224 | pin = spec->autocfg.hp_pins[i]; |
1225 | if (pin) /* connect to front */ | ||
1226 | stac92xx_auto_set_pinctl(codec, pin, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN); | ||
1227 | } | ||
1228 | for (i = 0; i < spec->autocfg.speaker_outs; i++) { | ||
1229 | hda_nid_t pin; | ||
1230 | pin = spec->autocfg.speaker_pins[i]; | ||
1231 | if (pin) /* connect to front */ | ||
1232 | stac92xx_auto_set_pinctl(codec, pin, AC_PINCTL_OUT_EN); | ||
1233 | } | ||
952 | } | 1234 | } |
953 | 1235 | ||
954 | static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out, hda_nid_t dig_in) | 1236 | static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out, hda_nid_t dig_in) |
@@ -994,7 +1276,7 @@ static int stac9200_auto_create_hp_ctls(struct hda_codec *codec, | |||
994 | struct auto_pin_cfg *cfg) | 1276 | struct auto_pin_cfg *cfg) |
995 | { | 1277 | { |
996 | struct sigmatel_spec *spec = codec->spec; | 1278 | struct sigmatel_spec *spec = codec->spec; |
997 | hda_nid_t pin = cfg->hp_pin; | 1279 | hda_nid_t pin = cfg->hp_pins[0]; |
998 | unsigned int wid_caps; | 1280 | unsigned int wid_caps; |
999 | 1281 | ||
1000 | if (! pin) | 1282 | if (! pin) |
@@ -1007,6 +1289,57 @@ static int stac9200_auto_create_hp_ctls(struct hda_codec *codec, | |||
1007 | return 0; | 1289 | return 0; |
1008 | } | 1290 | } |
1009 | 1291 | ||
1292 | /* add playback controls for LFE output */ | ||
1293 | static int stac9200_auto_create_lfe_ctls(struct hda_codec *codec, | ||
1294 | struct auto_pin_cfg *cfg) | ||
1295 | { | ||
1296 | struct sigmatel_spec *spec = codec->spec; | ||
1297 | int err; | ||
1298 | hda_nid_t lfe_pin = 0x0; | ||
1299 | int i; | ||
1300 | |||
1301 | /* | ||
1302 | * search speaker outs and line outs for a mono speaker pin | ||
1303 | * with an amp. If one is found, add LFE controls | ||
1304 | * for it. | ||
1305 | */ | ||
1306 | for (i = 0; i < spec->autocfg.speaker_outs && lfe_pin == 0x0; i++) { | ||
1307 | hda_nid_t pin = spec->autocfg.speaker_pins[i]; | ||
1308 | unsigned long wcaps = get_wcaps(codec, pin); | ||
1309 | wcaps &= (AC_WCAP_STEREO | AC_WCAP_OUT_AMP); | ||
1310 | if (wcaps == AC_WCAP_OUT_AMP) | ||
1311 | /* found a mono speaker with an amp, must be lfe */ | ||
1312 | lfe_pin = pin; | ||
1313 | } | ||
1314 | |||
1315 | /* if speaker_outs is 0, then speakers may be in line_outs */ | ||
1316 | if (lfe_pin == 0 && spec->autocfg.speaker_outs == 0) { | ||
1317 | for (i = 0; i < spec->autocfg.line_outs && lfe_pin == 0x0; i++) { | ||
1318 | hda_nid_t pin = spec->autocfg.line_out_pins[i]; | ||
1319 | unsigned long cfg; | ||
1320 | cfg = snd_hda_codec_read(codec, pin, 0, | ||
1321 | AC_VERB_GET_CONFIG_DEFAULT, | ||
1322 | 0x00); | ||
1323 | if (get_defcfg_device(cfg) == AC_JACK_SPEAKER) { | ||
1324 | unsigned long wcaps = get_wcaps(codec, pin); | ||
1325 | wcaps &= (AC_WCAP_STEREO | AC_WCAP_OUT_AMP); | ||
1326 | if (wcaps == AC_WCAP_OUT_AMP) | ||
1327 | /* found a mono speaker with an amp, | ||
1328 | must be lfe */ | ||
1329 | lfe_pin = pin; | ||
1330 | } | ||
1331 | } | ||
1332 | } | ||
1333 | |||
1334 | if (lfe_pin) { | ||
1335 | err = create_controls(spec, "LFE", lfe_pin, 1); | ||
1336 | if (err < 0) | ||
1337 | return err; | ||
1338 | } | ||
1339 | |||
1340 | return 0; | ||
1341 | } | ||
1342 | |||
1010 | static int stac9200_parse_auto_config(struct hda_codec *codec) | 1343 | static int stac9200_parse_auto_config(struct hda_codec *codec) |
1011 | { | 1344 | { |
1012 | struct sigmatel_spec *spec = codec->spec; | 1345 | struct sigmatel_spec *spec = codec->spec; |
@@ -1021,6 +1354,9 @@ static int stac9200_parse_auto_config(struct hda_codec *codec) | |||
1021 | if ((err = stac9200_auto_create_hp_ctls(codec, &spec->autocfg)) < 0) | 1354 | if ((err = stac9200_auto_create_hp_ctls(codec, &spec->autocfg)) < 0) |
1022 | return err; | 1355 | return err; |
1023 | 1356 | ||
1357 | if ((err = stac9200_auto_create_lfe_ctls(codec, &spec->autocfg)) < 0) | ||
1358 | return err; | ||
1359 | |||
1024 | if (spec->autocfg.dig_out_pin) | 1360 | if (spec->autocfg.dig_out_pin) |
1025 | spec->multiout.dig_out_nid = 0x05; | 1361 | spec->multiout.dig_out_nid = 0x05; |
1026 | if (spec->autocfg.dig_in_pin) | 1362 | if (spec->autocfg.dig_in_pin) |
@@ -1073,6 +1409,15 @@ static void stac922x_gpio_mute(struct hda_codec *codec, int pin, int muted) | |||
1073 | AC_VERB_SET_GPIO_DATA, gpiostate); | 1409 | AC_VERB_SET_GPIO_DATA, gpiostate); |
1074 | } | 1410 | } |
1075 | 1411 | ||
1412 | static void enable_pin_detect(struct hda_codec *codec, hda_nid_t nid, | ||
1413 | unsigned int event) | ||
1414 | { | ||
1415 | if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) | ||
1416 | snd_hda_codec_write(codec, nid, 0, | ||
1417 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
1418 | (AC_USRSP_EN | event)); | ||
1419 | } | ||
1420 | |||
1076 | static int stac92xx_init(struct hda_codec *codec) | 1421 | static int stac92xx_init(struct hda_codec *codec) |
1077 | { | 1422 | { |
1078 | struct sigmatel_spec *spec = codec->spec; | 1423 | struct sigmatel_spec *spec = codec->spec; |
@@ -1084,9 +1429,10 @@ static int stac92xx_init(struct hda_codec *codec) | |||
1084 | /* set up pins */ | 1429 | /* set up pins */ |
1085 | if (spec->hp_detect) { | 1430 | if (spec->hp_detect) { |
1086 | /* Enable unsolicited responses on the HP widget */ | 1431 | /* Enable unsolicited responses on the HP widget */ |
1087 | snd_hda_codec_write(codec, cfg->hp_pin, 0, | 1432 | for (i = 0; i < cfg->hp_outs; i++) |
1088 | AC_VERB_SET_UNSOLICITED_ENABLE, | 1433 | enable_pin_detect(codec, cfg->hp_pins[i], |
1089 | STAC_UNSOL_ENABLE); | 1434 | STAC_HP_EVENT); |
1435 | stac92xx_auto_init_hp_out(codec); | ||
1090 | /* fake event to set up pins */ | 1436 | /* fake event to set up pins */ |
1091 | codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); | 1437 | codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); |
1092 | } else { | 1438 | } else { |
@@ -1131,6 +1477,9 @@ static void stac92xx_free(struct hda_codec *codec) | |||
1131 | kfree(spec->kctl_alloc); | 1477 | kfree(spec->kctl_alloc); |
1132 | } | 1478 | } |
1133 | 1479 | ||
1480 | if (spec->bios_pin_configs) | ||
1481 | kfree(spec->bios_pin_configs); | ||
1482 | |||
1134 | kfree(spec); | 1483 | kfree(spec); |
1135 | } | 1484 | } |
1136 | 1485 | ||
@@ -1139,6 +1488,8 @@ static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid, | |||
1139 | { | 1488 | { |
1140 | unsigned int pin_ctl = snd_hda_codec_read(codec, nid, | 1489 | unsigned int pin_ctl = snd_hda_codec_read(codec, nid, |
1141 | 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00); | 1490 | 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00); |
1491 | if (flag == AC_PINCTL_OUT_EN && (pin_ctl & AC_PINCTL_IN_EN)) | ||
1492 | return; | ||
1142 | snd_hda_codec_write(codec, nid, 0, | 1493 | snd_hda_codec_write(codec, nid, 0, |
1143 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 1494 | AC_VERB_SET_PIN_WIDGET_CONTROL, |
1144 | pin_ctl | flag); | 1495 | pin_ctl | flag); |
@@ -1154,33 +1505,57 @@ static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid, | |||
1154 | pin_ctl & ~flag); | 1505 | pin_ctl & ~flag); |
1155 | } | 1506 | } |
1156 | 1507 | ||
1157 | static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) | 1508 | static int get_pin_presence(struct hda_codec *codec, hda_nid_t nid) |
1509 | { | ||
1510 | if (!nid) | ||
1511 | return 0; | ||
1512 | if (snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_SENSE, 0x00) | ||
1513 | & (1 << 31)) | ||
1514 | return 1; | ||
1515 | return 0; | ||
1516 | } | ||
1517 | |||
1518 | static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res) | ||
1158 | { | 1519 | { |
1159 | struct sigmatel_spec *spec = codec->spec; | 1520 | struct sigmatel_spec *spec = codec->spec; |
1160 | struct auto_pin_cfg *cfg = &spec->autocfg; | 1521 | struct auto_pin_cfg *cfg = &spec->autocfg; |
1161 | int i, presence; | 1522 | int i, presence; |
1162 | 1523 | ||
1163 | if ((res >> 26) != STAC_HP_EVENT) | 1524 | presence = 0; |
1164 | return; | 1525 | for (i = 0; i < cfg->hp_outs; i++) { |
1165 | 1526 | presence = get_pin_presence(codec, cfg->hp_pins[i]); | |
1166 | presence = snd_hda_codec_read(codec, cfg->hp_pin, 0, | 1527 | if (presence) |
1167 | AC_VERB_GET_PIN_SENSE, 0x00) >> 31; | 1528 | break; |
1529 | } | ||
1168 | 1530 | ||
1169 | if (presence) { | 1531 | if (presence) { |
1170 | /* disable lineouts, enable hp */ | 1532 | /* disable lineouts, enable hp */ |
1171 | for (i = 0; i < cfg->line_outs; i++) | 1533 | for (i = 0; i < cfg->line_outs; i++) |
1172 | stac92xx_reset_pinctl(codec, cfg->line_out_pins[i], | 1534 | stac92xx_reset_pinctl(codec, cfg->line_out_pins[i], |
1173 | AC_PINCTL_OUT_EN); | 1535 | AC_PINCTL_OUT_EN); |
1174 | stac92xx_set_pinctl(codec, cfg->hp_pin, AC_PINCTL_OUT_EN); | 1536 | for (i = 0; i < cfg->speaker_outs; i++) |
1537 | stac92xx_reset_pinctl(codec, cfg->speaker_pins[i], | ||
1538 | AC_PINCTL_OUT_EN); | ||
1175 | } else { | 1539 | } else { |
1176 | /* enable lineouts, disable hp */ | 1540 | /* enable lineouts, disable hp */ |
1177 | for (i = 0; i < cfg->line_outs; i++) | 1541 | for (i = 0; i < cfg->line_outs; i++) |
1178 | stac92xx_set_pinctl(codec, cfg->line_out_pins[i], | 1542 | stac92xx_set_pinctl(codec, cfg->line_out_pins[i], |
1179 | AC_PINCTL_OUT_EN); | 1543 | AC_PINCTL_OUT_EN); |
1180 | stac92xx_reset_pinctl(codec, cfg->hp_pin, AC_PINCTL_OUT_EN); | 1544 | for (i = 0; i < cfg->speaker_outs; i++) |
1545 | stac92xx_set_pinctl(codec, cfg->speaker_pins[i], | ||
1546 | AC_PINCTL_OUT_EN); | ||
1181 | } | 1547 | } |
1182 | } | 1548 | } |
1183 | 1549 | ||
1550 | static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) | ||
1551 | { | ||
1552 | switch (res >> 26) { | ||
1553 | case STAC_HP_EVENT: | ||
1554 | stac92xx_hp_detect(codec, res); | ||
1555 | break; | ||
1556 | } | ||
1557 | } | ||
1558 | |||
1184 | #ifdef CONFIG_PM | 1559 | #ifdef CONFIG_PM |
1185 | static int stac92xx_resume(struct hda_codec *codec) | 1560 | static int stac92xx_resume(struct hda_codec *codec) |
1186 | { | 1561 | { |
@@ -1188,6 +1563,7 @@ static int stac92xx_resume(struct hda_codec *codec) | |||
1188 | int i; | 1563 | int i; |
1189 | 1564 | ||
1190 | stac92xx_init(codec); | 1565 | stac92xx_init(codec); |
1566 | stac92xx_set_config_regs(codec); | ||
1191 | for (i = 0; i < spec->num_mixers; i++) | 1567 | for (i = 0; i < spec->num_mixers; i++) |
1192 | snd_hda_resume_ctls(codec, spec->mixers[i]); | 1568 | snd_hda_resume_ctls(codec, spec->mixers[i]); |
1193 | if (spec->multiout.dig_out_nid) | 1569 | if (spec->multiout.dig_out_nid) |
@@ -1220,12 +1596,18 @@ static int patch_stac9200(struct hda_codec *codec) | |||
1220 | return -ENOMEM; | 1596 | return -ENOMEM; |
1221 | 1597 | ||
1222 | codec->spec = spec; | 1598 | codec->spec = spec; |
1599 | spec->num_pins = 8; | ||
1600 | spec->pin_nids = stac9200_pin_nids; | ||
1223 | spec->board_config = snd_hda_check_board_config(codec, stac9200_cfg_tbl); | 1601 | spec->board_config = snd_hda_check_board_config(codec, stac9200_cfg_tbl); |
1224 | if (spec->board_config < 0) | 1602 | if (spec->board_config < 0) { |
1225 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9200, using BIOS defaults\n"); | 1603 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9200, using BIOS defaults\n"); |
1226 | else { | 1604 | err = stac92xx_save_bios_config_regs(codec); |
1227 | spec->num_pins = 8; | 1605 | if (err < 0) { |
1228 | spec->pin_nids = stac9200_pin_nids; | 1606 | stac92xx_free(codec); |
1607 | return err; | ||
1608 | } | ||
1609 | spec->pin_configs = spec->bios_pin_configs; | ||
1610 | } else { | ||
1229 | spec->pin_configs = stac9200_brd_tbl[spec->board_config]; | 1611 | spec->pin_configs = stac9200_brd_tbl[spec->board_config]; |
1230 | stac92xx_set_config_regs(codec); | 1612 | stac92xx_set_config_regs(codec); |
1231 | } | 1613 | } |
@@ -1261,13 +1643,19 @@ static int patch_stac922x(struct hda_codec *codec) | |||
1261 | return -ENOMEM; | 1643 | return -ENOMEM; |
1262 | 1644 | ||
1263 | codec->spec = spec; | 1645 | codec->spec = spec; |
1646 | spec->num_pins = 10; | ||
1647 | spec->pin_nids = stac922x_pin_nids; | ||
1264 | spec->board_config = snd_hda_check_board_config(codec, stac922x_cfg_tbl); | 1648 | spec->board_config = snd_hda_check_board_config(codec, stac922x_cfg_tbl); |
1265 | if (spec->board_config < 0) | 1649 | if (spec->board_config < 0) { |
1266 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC922x, " | 1650 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC922x, " |
1267 | "using BIOS defaults\n"); | 1651 | "using BIOS defaults\n"); |
1268 | else if (stac922x_brd_tbl[spec->board_config] != NULL) { | 1652 | err = stac92xx_save_bios_config_regs(codec); |
1269 | spec->num_pins = 10; | 1653 | if (err < 0) { |
1270 | spec->pin_nids = stac922x_pin_nids; | 1654 | stac92xx_free(codec); |
1655 | return err; | ||
1656 | } | ||
1657 | spec->pin_configs = spec->bios_pin_configs; | ||
1658 | } else if (stac922x_brd_tbl[spec->board_config] != NULL) { | ||
1271 | spec->pin_configs = stac922x_brd_tbl[spec->board_config]; | 1659 | spec->pin_configs = stac922x_brd_tbl[spec->board_config]; |
1272 | stac92xx_set_config_regs(codec); | 1660 | stac92xx_set_config_regs(codec); |
1273 | } | 1661 | } |
@@ -1281,25 +1669,6 @@ static int patch_stac922x(struct hda_codec *codec) | |||
1281 | 1669 | ||
1282 | spec->multiout.dac_nids = spec->dac_nids; | 1670 | spec->multiout.dac_nids = spec->dac_nids; |
1283 | 1671 | ||
1284 | switch (spec->board_config) { | ||
1285 | case STAC_D965_2112: | ||
1286 | spec->adc_nids = stac9227_adc_nids; | ||
1287 | spec->mux_nids = stac9227_mux_nids; | ||
1288 | #if 0 | ||
1289 | spec->multiout.dac_nids = d965_2112_dac_nids; | ||
1290 | spec->multiout.num_dacs = ARRAY_SIZE(d965_2112_dac_nids); | ||
1291 | #endif | ||
1292 | spec->init = d965_2112_core_init; | ||
1293 | spec->mixer = stac9227_mixer; | ||
1294 | break; | ||
1295 | case STAC_D965_284B: | ||
1296 | spec->adc_nids = stac9227_adc_nids; | ||
1297 | spec->mux_nids = stac9227_mux_nids; | ||
1298 | spec->init = stac9227_core_init; | ||
1299 | spec->mixer = stac9227_mixer; | ||
1300 | break; | ||
1301 | } | ||
1302 | |||
1303 | err = stac92xx_parse_auto_config(codec, 0x08, 0x09); | 1672 | err = stac92xx_parse_auto_config(codec, 0x08, 0x09); |
1304 | if (err < 0) { | 1673 | if (err < 0) { |
1305 | stac92xx_free(codec); | 1674 | stac92xx_free(codec); |
@@ -1324,26 +1693,94 @@ static int patch_stac927x(struct hda_codec *codec) | |||
1324 | return -ENOMEM; | 1693 | return -ENOMEM; |
1325 | 1694 | ||
1326 | codec->spec = spec; | 1695 | codec->spec = spec; |
1696 | spec->num_pins = 14; | ||
1697 | spec->pin_nids = stac927x_pin_nids; | ||
1327 | spec->board_config = snd_hda_check_board_config(codec, stac927x_cfg_tbl); | 1698 | spec->board_config = snd_hda_check_board_config(codec, stac927x_cfg_tbl); |
1328 | if (spec->board_config < 0) | 1699 | if (spec->board_config < 0) { |
1329 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC927x, using BIOS defaults\n"); | 1700 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC927x, using BIOS defaults\n"); |
1330 | else { | 1701 | err = stac92xx_save_bios_config_regs(codec); |
1331 | spec->num_pins = 14; | 1702 | if (err < 0) { |
1332 | spec->pin_nids = stac927x_pin_nids; | 1703 | stac92xx_free(codec); |
1704 | return err; | ||
1705 | } | ||
1706 | spec->pin_configs = spec->bios_pin_configs; | ||
1707 | } else if (stac927x_brd_tbl[spec->board_config] != NULL) { | ||
1333 | spec->pin_configs = stac927x_brd_tbl[spec->board_config]; | 1708 | spec->pin_configs = stac927x_brd_tbl[spec->board_config]; |
1334 | stac92xx_set_config_regs(codec); | 1709 | stac92xx_set_config_regs(codec); |
1335 | } | 1710 | } |
1336 | 1711 | ||
1337 | spec->adc_nids = stac927x_adc_nids; | 1712 | switch (spec->board_config) { |
1338 | spec->mux_nids = stac927x_mux_nids; | 1713 | case STAC_D965_3ST: |
1714 | spec->adc_nids = stac927x_adc_nids; | ||
1715 | spec->mux_nids = stac927x_mux_nids; | ||
1716 | spec->num_muxes = 3; | ||
1717 | spec->init = d965_core_init; | ||
1718 | spec->mixer = stac9227_mixer; | ||
1719 | break; | ||
1720 | case STAC_D965_5ST: | ||
1721 | spec->adc_nids = stac927x_adc_nids; | ||
1722 | spec->mux_nids = stac927x_mux_nids; | ||
1723 | spec->num_muxes = 3; | ||
1724 | spec->init = d965_core_init; | ||
1725 | spec->mixer = stac9227_mixer; | ||
1726 | break; | ||
1727 | default: | ||
1728 | spec->adc_nids = stac927x_adc_nids; | ||
1729 | spec->mux_nids = stac927x_mux_nids; | ||
1730 | spec->num_muxes = 3; | ||
1731 | spec->init = stac927x_core_init; | ||
1732 | spec->mixer = stac927x_mixer; | ||
1733 | } | ||
1734 | |||
1735 | spec->multiout.dac_nids = spec->dac_nids; | ||
1736 | |||
1737 | err = stac92xx_parse_auto_config(codec, 0x1e, 0x20); | ||
1738 | if (err < 0) { | ||
1739 | stac92xx_free(codec); | ||
1740 | return err; | ||
1741 | } | ||
1742 | |||
1743 | codec->patch_ops = stac92xx_patch_ops; | ||
1744 | |||
1745 | return 0; | ||
1746 | } | ||
1747 | |||
1748 | static int patch_stac9205(struct hda_codec *codec) | ||
1749 | { | ||
1750 | struct sigmatel_spec *spec; | ||
1751 | int err; | ||
1752 | |||
1753 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
1754 | if (spec == NULL) | ||
1755 | return -ENOMEM; | ||
1756 | |||
1757 | codec->spec = spec; | ||
1758 | spec->num_pins = 14; | ||
1759 | spec->pin_nids = stac9205_pin_nids; | ||
1760 | spec->board_config = snd_hda_check_board_config(codec, stac9205_cfg_tbl); | ||
1761 | if (spec->board_config < 0) { | ||
1762 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9205, using BIOS defaults\n"); | ||
1763 | err = stac92xx_save_bios_config_regs(codec); | ||
1764 | if (err < 0) { | ||
1765 | stac92xx_free(codec); | ||
1766 | return err; | ||
1767 | } | ||
1768 | spec->pin_configs = spec->bios_pin_configs; | ||
1769 | } else { | ||
1770 | spec->pin_configs = stac9205_brd_tbl[spec->board_config]; | ||
1771 | stac92xx_set_config_regs(codec); | ||
1772 | } | ||
1773 | |||
1774 | spec->adc_nids = stac9205_adc_nids; | ||
1775 | spec->mux_nids = stac9205_mux_nids; | ||
1339 | spec->num_muxes = 3; | 1776 | spec->num_muxes = 3; |
1340 | 1777 | ||
1341 | spec->init = stac927x_core_init; | 1778 | spec->init = stac9205_core_init; |
1342 | spec->mixer = stac927x_mixer; | 1779 | spec->mixer = stac9205_mixer; |
1343 | 1780 | ||
1344 | spec->multiout.dac_nids = spec->dac_nids; | 1781 | spec->multiout.dac_nids = spec->dac_nids; |
1345 | 1782 | ||
1346 | err = stac92xx_parse_auto_config(codec, 0x1e, 0x20); | 1783 | err = stac92xx_parse_auto_config(codec, 0x1f, 0x20); |
1347 | if (err < 0) { | 1784 | if (err < 0) { |
1348 | stac92xx_free(codec); | 1785 | stac92xx_free(codec); |
1349 | return err; | 1786 | return err; |
@@ -1355,10 +1792,10 @@ static int patch_stac927x(struct hda_codec *codec) | |||
1355 | } | 1792 | } |
1356 | 1793 | ||
1357 | /* | 1794 | /* |
1358 | * STAC 7661(?) hack | 1795 | * STAC9872 hack |
1359 | */ | 1796 | */ |
1360 | 1797 | ||
1361 | /* static config for Sony VAIO FE550G */ | 1798 | /* static config for Sony VAIO FE550G and Sony VAIO AR */ |
1362 | static hda_nid_t vaio_dacs[] = { 0x2 }; | 1799 | static hda_nid_t vaio_dacs[] = { 0x2 }; |
1363 | #define VAIO_HP_DAC 0x5 | 1800 | #define VAIO_HP_DAC 0x5 |
1364 | static hda_nid_t vaio_adcs[] = { 0x8 /*,0x6*/ }; | 1801 | static hda_nid_t vaio_adcs[] = { 0x8 /*,0x6*/ }; |
@@ -1389,6 +1826,23 @@ static struct hda_verb vaio_init[] = { | |||
1389 | {} | 1826 | {} |
1390 | }; | 1827 | }; |
1391 | 1828 | ||
1829 | static struct hda_verb vaio_ar_init[] = { | ||
1830 | {0x0a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP <- 0x2 */ | ||
1831 | {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Speaker <- 0x5 */ | ||
1832 | {0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? (<- 0x2) */ | ||
1833 | {0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD */ | ||
1834 | /* {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },*/ /* Optical Out */ | ||
1835 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? */ | ||
1836 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x2}, /* mic-sel: 0a,0d,14,02 */ | ||
1837 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* HP */ | ||
1838 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Speaker */ | ||
1839 | /* {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},*/ /* Optical Out */ | ||
1840 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* capture sw/vol -> 0x8 */ | ||
1841 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, /* CD-in -> 0x6 */ | ||
1842 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Mic-in -> 0x9 */ | ||
1843 | {} | ||
1844 | }; | ||
1845 | |||
1392 | /* bind volumes of both NID 0x02 and 0x05 */ | 1846 | /* bind volumes of both NID 0x02 and 0x05 */ |
1393 | static int vaio_master_vol_put(struct snd_kcontrol *kcontrol, | 1847 | static int vaio_master_vol_put(struct snd_kcontrol *kcontrol, |
1394 | struct snd_ctl_elem_value *ucontrol) | 1848 | struct snd_ctl_elem_value *ucontrol) |
@@ -1434,6 +1888,38 @@ static struct snd_kcontrol_new vaio_mixer[] = { | |||
1434 | .info = snd_hda_mixer_amp_volume_info, | 1888 | .info = snd_hda_mixer_amp_volume_info, |
1435 | .get = snd_hda_mixer_amp_volume_get, | 1889 | .get = snd_hda_mixer_amp_volume_get, |
1436 | .put = vaio_master_vol_put, | 1890 | .put = vaio_master_vol_put, |
1891 | .tlv = { .c = snd_hda_mixer_amp_tlv }, | ||
1892 | .private_value = HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT), | ||
1893 | }, | ||
1894 | { | ||
1895 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1896 | .name = "Master Playback Switch", | ||
1897 | .info = snd_hda_mixer_amp_switch_info, | ||
1898 | .get = snd_hda_mixer_amp_switch_get, | ||
1899 | .put = vaio_master_sw_put, | ||
1900 | .private_value = HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT), | ||
1901 | }, | ||
1902 | /* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */ | ||
1903 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT), | ||
1904 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT), | ||
1905 | { | ||
1906 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1907 | .name = "Capture Source", | ||
1908 | .count = 1, | ||
1909 | .info = stac92xx_mux_enum_info, | ||
1910 | .get = stac92xx_mux_enum_get, | ||
1911 | .put = stac92xx_mux_enum_put, | ||
1912 | }, | ||
1913 | {} | ||
1914 | }; | ||
1915 | |||
1916 | static struct snd_kcontrol_new vaio_ar_mixer[] = { | ||
1917 | { | ||
1918 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1919 | .name = "Master Playback Volume", | ||
1920 | .info = snd_hda_mixer_amp_volume_info, | ||
1921 | .get = snd_hda_mixer_amp_volume_get, | ||
1922 | .put = vaio_master_vol_put, | ||
1437 | .private_value = HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT), | 1923 | .private_value = HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT), |
1438 | }, | 1924 | }, |
1439 | { | 1925 | { |
@@ -1447,6 +1933,8 @@ static struct snd_kcontrol_new vaio_mixer[] = { | |||
1447 | /* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */ | 1933 | /* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */ |
1448 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT), | 1934 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT), |
1449 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT), | 1935 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT), |
1936 | /*HDA_CODEC_MUTE("Optical Out Switch", 0x10, 0, HDA_OUTPUT), | ||
1937 | HDA_CODEC_VOLUME("Optical Out Volume", 0x10, 0, HDA_OUTPUT),*/ | ||
1450 | { | 1938 | { |
1451 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1939 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1452 | .name = "Capture Source", | 1940 | .name = "Capture Source", |
@@ -1458,7 +1946,7 @@ static struct snd_kcontrol_new vaio_mixer[] = { | |||
1458 | {} | 1946 | {} |
1459 | }; | 1947 | }; |
1460 | 1948 | ||
1461 | static struct hda_codec_ops stac7661_patch_ops = { | 1949 | static struct hda_codec_ops stac9872_patch_ops = { |
1462 | .build_controls = stac92xx_build_controls, | 1950 | .build_controls = stac92xx_build_controls, |
1463 | .build_pcms = stac92xx_build_pcms, | 1951 | .build_pcms = stac92xx_build_pcms, |
1464 | .init = stac92xx_init, | 1952 | .init = stac92xx_init, |
@@ -1468,23 +1956,34 @@ static struct hda_codec_ops stac7661_patch_ops = { | |||
1468 | #endif | 1956 | #endif |
1469 | }; | 1957 | }; |
1470 | 1958 | ||
1471 | enum { STAC7661_VAIO }; | 1959 | enum { /* FE and SZ series. id=0x83847661 and subsys=0x104D0700 or 104D1000. */ |
1472 | 1960 | CXD9872RD_VAIO, | |
1473 | static struct hda_board_config stac7661_cfg_tbl[] = { | 1961 | /* Unknown. id=0x83847662 and subsys=0x104D1200 or 104D1000. */ |
1474 | { .modelname = "vaio", .config = STAC7661_VAIO }, | 1962 | STAC9872AK_VAIO, |
1963 | /* Unknown. id=0x83847661 and subsys=0x104D1200. */ | ||
1964 | STAC9872K_VAIO, | ||
1965 | /* AR Series. id=0x83847664 and subsys=104D1300 */ | ||
1966 | CXD9872AKD_VAIO | ||
1967 | }; | ||
1968 | |||
1969 | static struct hda_board_config stac9872_cfg_tbl[] = { | ||
1970 | { .modelname = "vaio", .config = CXD9872RD_VAIO }, | ||
1971 | { .modelname = "vaio-ar", .config = CXD9872AKD_VAIO }, | ||
1475 | { .pci_subvendor = 0x104d, .pci_subdevice = 0x81e6, | 1972 | { .pci_subvendor = 0x104d, .pci_subdevice = 0x81e6, |
1476 | .config = STAC7661_VAIO }, | 1973 | .config = CXD9872RD_VAIO }, |
1477 | { .pci_subvendor = 0x104d, .pci_subdevice = 0x81ef, | 1974 | { .pci_subvendor = 0x104d, .pci_subdevice = 0x81ef, |
1478 | .config = STAC7661_VAIO }, | 1975 | .config = CXD9872RD_VAIO }, |
1976 | { .pci_subvendor = 0x104d, .pci_subdevice = 0x81fd, | ||
1977 | .config = CXD9872AKD_VAIO }, | ||
1479 | {} | 1978 | {} |
1480 | }; | 1979 | }; |
1481 | 1980 | ||
1482 | static int patch_stac7661(struct hda_codec *codec) | 1981 | static int patch_stac9872(struct hda_codec *codec) |
1483 | { | 1982 | { |
1484 | struct sigmatel_spec *spec; | 1983 | struct sigmatel_spec *spec; |
1485 | int board_config; | 1984 | int board_config; |
1486 | 1985 | ||
1487 | board_config = snd_hda_check_board_config(codec, stac7661_cfg_tbl); | 1986 | board_config = snd_hda_check_board_config(codec, stac9872_cfg_tbl); |
1488 | if (board_config < 0) | 1987 | if (board_config < 0) |
1489 | /* unknown config, let generic-parser do its job... */ | 1988 | /* unknown config, let generic-parser do its job... */ |
1490 | return snd_hda_parse_generic_codec(codec); | 1989 | return snd_hda_parse_generic_codec(codec); |
@@ -1495,7 +1994,9 @@ static int patch_stac7661(struct hda_codec *codec) | |||
1495 | 1994 | ||
1496 | codec->spec = spec; | 1995 | codec->spec = spec; |
1497 | switch (board_config) { | 1996 | switch (board_config) { |
1498 | case STAC7661_VAIO: | 1997 | case CXD9872RD_VAIO: |
1998 | case STAC9872AK_VAIO: | ||
1999 | case STAC9872K_VAIO: | ||
1499 | spec->mixer = vaio_mixer; | 2000 | spec->mixer = vaio_mixer; |
1500 | spec->init = vaio_init; | 2001 | spec->init = vaio_init; |
1501 | spec->multiout.max_channels = 2; | 2002 | spec->multiout.max_channels = 2; |
@@ -1507,9 +2008,22 @@ static int patch_stac7661(struct hda_codec *codec) | |||
1507 | spec->input_mux = &vaio_mux; | 2008 | spec->input_mux = &vaio_mux; |
1508 | spec->mux_nids = vaio_mux_nids; | 2009 | spec->mux_nids = vaio_mux_nids; |
1509 | break; | 2010 | break; |
2011 | |||
2012 | case CXD9872AKD_VAIO: | ||
2013 | spec->mixer = vaio_ar_mixer; | ||
2014 | spec->init = vaio_ar_init; | ||
2015 | spec->multiout.max_channels = 2; | ||
2016 | spec->multiout.num_dacs = ARRAY_SIZE(vaio_dacs); | ||
2017 | spec->multiout.dac_nids = vaio_dacs; | ||
2018 | spec->multiout.hp_nid = VAIO_HP_DAC; | ||
2019 | spec->num_adcs = ARRAY_SIZE(vaio_adcs); | ||
2020 | spec->adc_nids = vaio_adcs; | ||
2021 | spec->input_mux = &vaio_mux; | ||
2022 | spec->mux_nids = vaio_mux_nids; | ||
2023 | break; | ||
1510 | } | 2024 | } |
1511 | 2025 | ||
1512 | codec->patch_ops = stac7661_patch_ops; | 2026 | codec->patch_ops = stac9872_patch_ops; |
1513 | return 0; | 2027 | return 0; |
1514 | } | 2028 | } |
1515 | 2029 | ||
@@ -1525,12 +2039,12 @@ struct hda_codec_preset snd_hda_preset_sigmatel[] = { | |||
1525 | { .id = 0x83847681, .name = "STAC9220D/9223D A2", .patch = patch_stac922x }, | 2039 | { .id = 0x83847681, .name = "STAC9220D/9223D A2", .patch = patch_stac922x }, |
1526 | { .id = 0x83847682, .name = "STAC9221 A2", .patch = patch_stac922x }, | 2040 | { .id = 0x83847682, .name = "STAC9221 A2", .patch = patch_stac922x }, |
1527 | { .id = 0x83847683, .name = "STAC9221D A2", .patch = patch_stac922x }, | 2041 | { .id = 0x83847683, .name = "STAC9221D A2", .patch = patch_stac922x }, |
1528 | { .id = 0x83847618, .name = "STAC9227", .patch = patch_stac922x }, | 2042 | { .id = 0x83847618, .name = "STAC9227", .patch = patch_stac927x }, |
1529 | { .id = 0x83847619, .name = "STAC9227", .patch = patch_stac922x }, | 2043 | { .id = 0x83847619, .name = "STAC9227", .patch = patch_stac927x }, |
1530 | { .id = 0x83847616, .name = "STAC9228", .patch = patch_stac922x }, | 2044 | { .id = 0x83847616, .name = "STAC9228", .patch = patch_stac927x }, |
1531 | { .id = 0x83847617, .name = "STAC9228", .patch = patch_stac922x }, | 2045 | { .id = 0x83847617, .name = "STAC9228", .patch = patch_stac927x }, |
1532 | { .id = 0x83847614, .name = "STAC9229", .patch = patch_stac922x }, | 2046 | { .id = 0x83847614, .name = "STAC9229", .patch = patch_stac927x }, |
1533 | { .id = 0x83847615, .name = "STAC9229", .patch = patch_stac922x }, | 2047 | { .id = 0x83847615, .name = "STAC9229", .patch = patch_stac927x }, |
1534 | { .id = 0x83847620, .name = "STAC9274", .patch = patch_stac927x }, | 2048 | { .id = 0x83847620, .name = "STAC9274", .patch = patch_stac927x }, |
1535 | { .id = 0x83847621, .name = "STAC9274D", .patch = patch_stac927x }, | 2049 | { .id = 0x83847621, .name = "STAC9274D", .patch = patch_stac927x }, |
1536 | { .id = 0x83847622, .name = "STAC9273X", .patch = patch_stac927x }, | 2050 | { .id = 0x83847622, .name = "STAC9273X", .patch = patch_stac927x }, |
@@ -1541,6 +2055,20 @@ struct hda_codec_preset snd_hda_preset_sigmatel[] = { | |||
1541 | { .id = 0x83847627, .name = "STAC9271D", .patch = patch_stac927x }, | 2055 | { .id = 0x83847627, .name = "STAC9271D", .patch = patch_stac927x }, |
1542 | { .id = 0x83847628, .name = "STAC9274X5NH", .patch = patch_stac927x }, | 2056 | { .id = 0x83847628, .name = "STAC9274X5NH", .patch = patch_stac927x }, |
1543 | { .id = 0x83847629, .name = "STAC9274D5NH", .patch = patch_stac927x }, | 2057 | { .id = 0x83847629, .name = "STAC9274D5NH", .patch = patch_stac927x }, |
1544 | { .id = 0x83847661, .name = "STAC7661", .patch = patch_stac7661 }, | 2058 | /* The following does not take into account .id=0x83847661 when subsys = |
2059 | * 104D0C00 which is STAC9225s. Because of this, some SZ Notebooks are | ||
2060 | * currently not fully supported. | ||
2061 | */ | ||
2062 | { .id = 0x83847661, .name = "CXD9872RD/K", .patch = patch_stac9872 }, | ||
2063 | { .id = 0x83847662, .name = "STAC9872AK", .patch = patch_stac9872 }, | ||
2064 | { .id = 0x83847664, .name = "CXD9872AKD", .patch = patch_stac9872 }, | ||
2065 | { .id = 0x838476a0, .name = "STAC9205", .patch = patch_stac9205 }, | ||
2066 | { .id = 0x838476a1, .name = "STAC9205D", .patch = patch_stac9205 }, | ||
2067 | { .id = 0x838476a2, .name = "STAC9204", .patch = patch_stac9205 }, | ||
2068 | { .id = 0x838476a3, .name = "STAC9204D", .patch = patch_stac9205 }, | ||
2069 | { .id = 0x838476a4, .name = "STAC9255", .patch = patch_stac9205 }, | ||
2070 | { .id = 0x838476a5, .name = "STAC9255D", .patch = patch_stac9205 }, | ||
2071 | { .id = 0x838476a6, .name = "STAC9254", .patch = patch_stac9205 }, | ||
2072 | { .id = 0x838476a7, .name = "STAC9254D", .patch = patch_stac9205 }, | ||
1545 | {} /* terminator */ | 2073 | {} /* terminator */ |
1546 | }; | 2074 | }; |