diff options
Diffstat (limited to 'sound/pci')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 47 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.h | 3 | ||||
-rw-r--r-- | sound/pci/hda/hda_intel.c | 15 | ||||
-rw-r--r-- | sound/pci/hda/hda_jack.c | 59 | ||||
-rw-r--r-- | sound/pci/hda/hda_jack.h | 1 | ||||
-rw-r--r-- | sound/pci/hda/hda_proc.c | 17 | ||||
-rw-r--r-- | sound/pci/hda/patch_hdmi.c | 294 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 191 |
8 files changed, 445 insertions, 182 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 51cb2a2e4fce..14bc1c8f5326 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -3509,22 +3509,52 @@ void snd_hda_codec_set_power_to_all(struct hda_codec *codec, hda_nid_t fg, | |||
3509 | EXPORT_SYMBOL_HDA(snd_hda_codec_set_power_to_all); | 3509 | EXPORT_SYMBOL_HDA(snd_hda_codec_set_power_to_all); |
3510 | 3510 | ||
3511 | /* | 3511 | /* |
3512 | * supported power states check | ||
3513 | */ | ||
3514 | static bool snd_hda_codec_get_supported_ps(struct hda_codec *codec, hda_nid_t fg, | ||
3515 | unsigned int power_state) | ||
3516 | { | ||
3517 | int sup = snd_hda_param_read(codec, fg, AC_PAR_POWER_STATE); | ||
3518 | |||
3519 | if (sup < 0) | ||
3520 | return false; | ||
3521 | if (sup & power_state) | ||
3522 | return true; | ||
3523 | else | ||
3524 | return false; | ||
3525 | } | ||
3526 | |||
3527 | /* | ||
3512 | * set power state of the codec | 3528 | * set power state of the codec |
3513 | */ | 3529 | */ |
3514 | static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, | 3530 | static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, |
3515 | unsigned int power_state) | 3531 | unsigned int power_state) |
3516 | { | 3532 | { |
3533 | int count; | ||
3534 | unsigned int state; | ||
3535 | |||
3517 | if (codec->patch_ops.set_power_state) { | 3536 | if (codec->patch_ops.set_power_state) { |
3518 | codec->patch_ops.set_power_state(codec, fg, power_state); | 3537 | codec->patch_ops.set_power_state(codec, fg, power_state); |
3519 | return; | 3538 | return; |
3520 | } | 3539 | } |
3521 | 3540 | ||
3522 | /* this delay seems necessary to avoid click noise at power-down */ | 3541 | /* this delay seems necessary to avoid click noise at power-down */ |
3523 | if (power_state == AC_PWRST_D3) | 3542 | if (power_state == AC_PWRST_D3) { |
3524 | msleep(100); | 3543 | /* transition time less than 10ms for power down */ |
3525 | snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE, | 3544 | bool epss = snd_hda_codec_get_supported_ps(codec, fg, AC_PWRST_EPSS); |
3526 | power_state); | 3545 | msleep(epss ? 10 : 100); |
3527 | snd_hda_codec_set_power_to_all(codec, fg, power_state, true); | 3546 | } |
3547 | |||
3548 | /* repeat power states setting at most 10 times*/ | ||
3549 | for (count = 0; count < 10; count++) { | ||
3550 | snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE, | ||
3551 | power_state); | ||
3552 | snd_hda_codec_set_power_to_all(codec, fg, power_state, true); | ||
3553 | state = snd_hda_codec_read(codec, fg, 0, | ||
3554 | AC_VERB_GET_POWER_STATE, 0); | ||
3555 | if (!(state & AC_PWRST_ERROR)) | ||
3556 | break; | ||
3557 | } | ||
3528 | } | 3558 | } |
3529 | 3559 | ||
3530 | #ifdef CONFIG_SND_HDA_HWDEP | 3560 | #ifdef CONFIG_SND_HDA_HWDEP |
@@ -4418,6 +4448,13 @@ static void __snd_hda_power_up(struct hda_codec *codec, bool wait_power_down) | |||
4418 | cancel_delayed_work_sync(&codec->power_work); | 4448 | cancel_delayed_work_sync(&codec->power_work); |
4419 | 4449 | ||
4420 | spin_lock(&codec->power_lock); | 4450 | spin_lock(&codec->power_lock); |
4451 | /* If the power down delayed work was cancelled above before starting, | ||
4452 | * then there is no need to go through power up here. | ||
4453 | */ | ||
4454 | if (codec->power_on) { | ||
4455 | spin_unlock(&codec->power_lock); | ||
4456 | return; | ||
4457 | } | ||
4421 | trace_hda_power_up(codec); | 4458 | trace_hda_power_up(codec); |
4422 | snd_hda_update_power_acct(codec); | 4459 | snd_hda_update_power_acct(codec); |
4423 | codec->power_on = 1; | 4460 | codec->power_on = 1; |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 2fdaadbb4326..a4ac1de7aa19 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -323,6 +323,9 @@ enum { | |||
323 | #define AC_PWRST_D1 0x01 | 323 | #define AC_PWRST_D1 0x01 |
324 | #define AC_PWRST_D2 0x02 | 324 | #define AC_PWRST_D2 0x02 |
325 | #define AC_PWRST_D3 0x03 | 325 | #define AC_PWRST_D3 0x03 |
326 | #define AC_PWRST_ERROR (1<<8) | ||
327 | #define AC_PWRST_CLK_STOP_OK (1<<9) | ||
328 | #define AC_PWRST_SETTING_RESET (1<<10) | ||
326 | 329 | ||
327 | /* Processing capabilies */ | 330 | /* Processing capabilies */ |
328 | #define AC_PCAP_BENIGN (1<<0) | 331 | #define AC_PCAP_BENIGN (1<<0) |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 7757536b9d5f..86758dded981 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -535,6 +535,7 @@ enum { | |||
535 | #define AZX_DCAPS_BUFSIZE (1 << 21) /* no buffer size alignment */ | 535 | #define AZX_DCAPS_BUFSIZE (1 << 21) /* no buffer size alignment */ |
536 | #define AZX_DCAPS_ALIGN_BUFSIZE (1 << 22) /* buffer size alignment */ | 536 | #define AZX_DCAPS_ALIGN_BUFSIZE (1 << 22) /* buffer size alignment */ |
537 | #define AZX_DCAPS_4K_BDLE_BOUNDARY (1 << 23) /* BDLE in 4k boundary */ | 537 | #define AZX_DCAPS_4K_BDLE_BOUNDARY (1 << 23) /* BDLE in 4k boundary */ |
538 | #define AZX_DCAPS_POSFIX_COMBO (1 << 24) /* Use COMBO as default */ | ||
538 | 539 | ||
539 | /* quirks for ATI SB / AMD Hudson */ | 540 | /* quirks for ATI SB / AMD Hudson */ |
540 | #define AZX_DCAPS_PRESET_ATI_SB \ | 541 | #define AZX_DCAPS_PRESET_ATI_SB \ |
@@ -2731,6 +2732,10 @@ static int __devinit check_position_fix(struct azx *chip, int fix) | |||
2731 | snd_printd(SFX "Using LPIB position fix\n"); | 2732 | snd_printd(SFX "Using LPIB position fix\n"); |
2732 | return POS_FIX_LPIB; | 2733 | return POS_FIX_LPIB; |
2733 | } | 2734 | } |
2735 | if (chip->driver_caps & AZX_DCAPS_POSFIX_COMBO) { | ||
2736 | snd_printd(SFX "Using COMBO position fix\n"); | ||
2737 | return POS_FIX_COMBO; | ||
2738 | } | ||
2734 | return POS_FIX_AUTO; | 2739 | return POS_FIX_AUTO; |
2735 | } | 2740 | } |
2736 | 2741 | ||
@@ -3243,7 +3248,7 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { | |||
3243 | /* CPT */ | 3248 | /* CPT */ |
3244 | { PCI_DEVICE(0x8086, 0x1c20), | 3249 | { PCI_DEVICE(0x8086, 0x1c20), |
3245 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | | 3250 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | |
3246 | AZX_DCAPS_BUFSIZE }, | 3251 | AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO }, |
3247 | /* PBG */ | 3252 | /* PBG */ |
3248 | { PCI_DEVICE(0x8086, 0x1d20), | 3253 | { PCI_DEVICE(0x8086, 0x1d20), |
3249 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | | 3254 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | |
@@ -3251,11 +3256,11 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { | |||
3251 | /* Panther Point */ | 3256 | /* Panther Point */ |
3252 | { PCI_DEVICE(0x8086, 0x1e20), | 3257 | { PCI_DEVICE(0x8086, 0x1e20), |
3253 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | | 3258 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | |
3254 | AZX_DCAPS_BUFSIZE}, | 3259 | AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO }, |
3255 | /* Lynx Point */ | 3260 | /* Lynx Point */ |
3256 | { PCI_DEVICE(0x8086, 0x8c20), | 3261 | { PCI_DEVICE(0x8086, 0x8c20), |
3257 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | | 3262 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | |
3258 | AZX_DCAPS_BUFSIZE}, | 3263 | AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO }, |
3259 | /* SCH */ | 3264 | /* SCH */ |
3260 | { PCI_DEVICE(0x8086, 0x811b), | 3265 | { PCI_DEVICE(0x8086, 0x811b), |
3261 | .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | | 3266 | .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | |
@@ -3341,6 +3346,10 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { | |||
3341 | /* VIA VT8251/VT8237A */ | 3346 | /* VIA VT8251/VT8237A */ |
3342 | { PCI_DEVICE(0x1106, 0x3288), | 3347 | { PCI_DEVICE(0x1106, 0x3288), |
3343 | .driver_data = AZX_DRIVER_VIA | AZX_DCAPS_POSFIX_VIA }, | 3348 | .driver_data = AZX_DRIVER_VIA | AZX_DCAPS_POSFIX_VIA }, |
3349 | /* VIA GFX VT7122/VX900 */ | ||
3350 | { PCI_DEVICE(0x1106, 0x9170), .driver_data = AZX_DRIVER_GENERIC }, | ||
3351 | /* VIA GFX VT6122/VX11 */ | ||
3352 | { PCI_DEVICE(0x1106, 0x9140), .driver_data = AZX_DRIVER_GENERIC }, | ||
3344 | /* SIS966 */ | 3353 | /* SIS966 */ |
3345 | { PCI_DEVICE(0x1039, 0x7502), .driver_data = AZX_DRIVER_SIS }, | 3354 | { PCI_DEVICE(0x1039, 0x7502), .driver_data = AZX_DRIVER_SIS }, |
3346 | /* ULI M5461 */ | 3355 | /* ULI M5461 */ |
diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c index 2dd1c113a4c1..60c976f06280 100644 --- a/sound/pci/hda/hda_jack.c +++ b/sound/pci/hda/hda_jack.c | |||
@@ -127,10 +127,15 @@ void snd_hda_jack_tbl_clear(struct hda_codec *codec) | |||
127 | static void jack_detect_update(struct hda_codec *codec, | 127 | static void jack_detect_update(struct hda_codec *codec, |
128 | struct hda_jack_tbl *jack) | 128 | struct hda_jack_tbl *jack) |
129 | { | 129 | { |
130 | if (jack->jack_dirty || !jack->jack_detect) { | 130 | if (!jack->jack_dirty) |
131 | return; | ||
132 | |||
133 | if (jack->phantom_jack) | ||
134 | jack->pin_sense = AC_PINSENSE_PRESENCE; | ||
135 | else | ||
131 | jack->pin_sense = read_pin_sense(codec, jack->nid); | 136 | jack->pin_sense = read_pin_sense(codec, jack->nid); |
132 | jack->jack_dirty = 0; | 137 | |
133 | } | 138 | jack->jack_dirty = 0; |
134 | } | 139 | } |
135 | 140 | ||
136 | /** | 141 | /** |
@@ -264,8 +269,8 @@ static void hda_free_jack_priv(struct snd_jack *jack) | |||
264 | * This assigns a jack-detection kctl to the given pin. The kcontrol | 269 | * This assigns a jack-detection kctl to the given pin. The kcontrol |
265 | * will have the given name and index. | 270 | * will have the given name and index. |
266 | */ | 271 | */ |
267 | int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, | 272 | static int __snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, |
268 | const char *name, int idx) | 273 | const char *name, int idx, bool phantom_jack) |
269 | { | 274 | { |
270 | struct hda_jack_tbl *jack; | 275 | struct hda_jack_tbl *jack; |
271 | struct snd_kcontrol *kctl; | 276 | struct snd_kcontrol *kctl; |
@@ -283,19 +288,30 @@ int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, | |||
283 | if (err < 0) | 288 | if (err < 0) |
284 | return err; | 289 | return err; |
285 | jack->kctl = kctl; | 290 | jack->kctl = kctl; |
291 | jack->phantom_jack = !!phantom_jack; | ||
292 | |||
286 | state = snd_hda_jack_detect(codec, nid); | 293 | state = snd_hda_jack_detect(codec, nid); |
287 | snd_kctl_jack_report(codec->bus->card, kctl, state); | 294 | snd_kctl_jack_report(codec->bus->card, kctl, state); |
288 | #ifdef CONFIG_SND_HDA_INPUT_JACK | 295 | #ifdef CONFIG_SND_HDA_INPUT_JACK |
289 | jack->type = get_input_jack_type(codec, nid); | 296 | if (!phantom_jack) { |
290 | err = snd_jack_new(codec->bus->card, name, jack->type, &jack->jack); | 297 | jack->type = get_input_jack_type(codec, nid); |
291 | if (err < 0) | 298 | err = snd_jack_new(codec->bus->card, name, jack->type, |
292 | return err; | 299 | &jack->jack); |
293 | jack->jack->private_data = jack; | 300 | if (err < 0) |
294 | jack->jack->private_free = hda_free_jack_priv; | 301 | return err; |
295 | snd_jack_report(jack->jack, state ? jack->type : 0); | 302 | jack->jack->private_data = jack; |
303 | jack->jack->private_free = hda_free_jack_priv; | ||
304 | snd_jack_report(jack->jack, state ? jack->type : 0); | ||
305 | } | ||
296 | #endif | 306 | #endif |
297 | return 0; | 307 | return 0; |
298 | } | 308 | } |
309 | |||
310 | int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, | ||
311 | const char *name, int idx) | ||
312 | { | ||
313 | return __snd_hda_jack_add_kctl(codec, nid, name, idx, false); | ||
314 | } | ||
299 | EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctl); | 315 | EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctl); |
300 | 316 | ||
301 | static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, | 317 | static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, |
@@ -305,25 +321,32 @@ static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, | |||
305 | unsigned int def_conf, conn; | 321 | unsigned int def_conf, conn; |
306 | char name[44]; | 322 | char name[44]; |
307 | int idx, err; | 323 | int idx, err; |
324 | bool phantom_jack; | ||
308 | 325 | ||
309 | if (!nid) | 326 | if (!nid) |
310 | return 0; | 327 | return 0; |
311 | if (!is_jack_detectable(codec, nid)) | ||
312 | return 0; | ||
313 | def_conf = snd_hda_codec_get_pincfg(codec, nid); | 328 | def_conf = snd_hda_codec_get_pincfg(codec, nid); |
314 | conn = get_defcfg_connect(def_conf); | 329 | conn = get_defcfg_connect(def_conf); |
315 | if (conn != AC_JACK_PORT_COMPLEX) | 330 | if (conn == AC_JACK_PORT_NONE) |
316 | return 0; | 331 | return 0; |
332 | phantom_jack = (conn != AC_JACK_PORT_COMPLEX) || | ||
333 | !is_jack_detectable(codec, nid); | ||
317 | 334 | ||
318 | snd_hda_get_pin_label(codec, nid, cfg, name, sizeof(name), &idx); | 335 | snd_hda_get_pin_label(codec, nid, cfg, name, sizeof(name), &idx); |
336 | if (phantom_jack) | ||
337 | /* Example final name: "Internal Mic Phantom Jack" */ | ||
338 | strncat(name, " Phantom", sizeof(name) - strlen(name) - 1); | ||
319 | if (!strcmp(name, lastname) && idx == *lastidx) | 339 | if (!strcmp(name, lastname) && idx == *lastidx) |
320 | idx++; | 340 | idx++; |
321 | strncpy(lastname, name, 44); | 341 | strncpy(lastname, name, sizeof(name)); |
322 | *lastidx = idx; | 342 | *lastidx = idx; |
323 | err = snd_hda_jack_add_kctl(codec, nid, name, idx); | 343 | err = __snd_hda_jack_add_kctl(codec, nid, name, idx, phantom_jack); |
324 | if (err < 0) | 344 | if (err < 0) |
325 | return err; | 345 | return err; |
326 | return snd_hda_jack_detect_enable(codec, nid, 0); | 346 | |
347 | if (!phantom_jack) | ||
348 | return snd_hda_jack_detect_enable(codec, nid, 0); | ||
349 | return 0; | ||
327 | } | 350 | } |
328 | 351 | ||
329 | /** | 352 | /** |
diff --git a/sound/pci/hda/hda_jack.h b/sound/pci/hda/hda_jack.h index 8ae52465ec5d..a9803da633c0 100644 --- a/sound/pci/hda/hda_jack.h +++ b/sound/pci/hda/hda_jack.h | |||
@@ -23,6 +23,7 @@ struct hda_jack_tbl { | |||
23 | unsigned int pin_sense; /* cached pin-sense value */ | 23 | unsigned int pin_sense; /* cached pin-sense value */ |
24 | unsigned int jack_detect:1; /* capable of jack-detection? */ | 24 | unsigned int jack_detect:1; /* capable of jack-detection? */ |
25 | unsigned int jack_dirty:1; /* needs to update? */ | 25 | unsigned int jack_dirty:1; /* needs to update? */ |
26 | unsigned int phantom_jack:1; /* a fixed, always present port? */ | ||
26 | struct snd_kcontrol *kctl; /* assigned kctl for jack-detection */ | 27 | struct snd_kcontrol *kctl; /* assigned kctl for jack-detection */ |
27 | #ifdef CONFIG_SND_HDA_INPUT_JACK | 28 | #ifdef CONFIG_SND_HDA_INPUT_JACK |
28 | int type; | 29 | int type; |
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index e59e2f059b6e..7e46258fc700 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c | |||
@@ -426,10 +426,10 @@ static void print_digital_conv(struct snd_info_buffer *buffer, | |||
426 | 426 | ||
427 | static const char *get_pwr_state(u32 state) | 427 | static const char *get_pwr_state(u32 state) |
428 | { | 428 | { |
429 | static const char * const buf[4] = { | 429 | static const char * const buf[] = { |
430 | "D0", "D1", "D2", "D3" | 430 | "D0", "D1", "D2", "D3", "D3cold" |
431 | }; | 431 | }; |
432 | if (state < 4) | 432 | if (state < ARRAY_SIZE(buf)) |
433 | return buf[state]; | 433 | return buf[state]; |
434 | return "UNKNOWN"; | 434 | return "UNKNOWN"; |
435 | } | 435 | } |
@@ -451,14 +451,21 @@ static void print_power_state(struct snd_info_buffer *buffer, | |||
451 | int sup = snd_hda_param_read(codec, nid, AC_PAR_POWER_STATE); | 451 | int sup = snd_hda_param_read(codec, nid, AC_PAR_POWER_STATE); |
452 | int pwr = snd_hda_codec_read(codec, nid, 0, | 452 | int pwr = snd_hda_codec_read(codec, nid, 0, |
453 | AC_VERB_GET_POWER_STATE, 0); | 453 | AC_VERB_GET_POWER_STATE, 0); |
454 | if (sup) | 454 | if (sup != -1) |
455 | snd_iprintf(buffer, " Power states: %s\n", | 455 | snd_iprintf(buffer, " Power states: %s\n", |
456 | bits_names(sup, names, ARRAY_SIZE(names))); | 456 | bits_names(sup, names, ARRAY_SIZE(names))); |
457 | 457 | ||
458 | snd_iprintf(buffer, " Power: setting=%s, actual=%s\n", | 458 | snd_iprintf(buffer, " Power: setting=%s, actual=%s", |
459 | get_pwr_state(pwr & AC_PWRST_SETTING), | 459 | get_pwr_state(pwr & AC_PWRST_SETTING), |
460 | get_pwr_state((pwr & AC_PWRST_ACTUAL) >> | 460 | get_pwr_state((pwr & AC_PWRST_ACTUAL) >> |
461 | AC_PWRST_ACTUAL_SHIFT)); | 461 | AC_PWRST_ACTUAL_SHIFT)); |
462 | if (pwr & AC_PWRST_ERROR) | ||
463 | snd_iprintf(buffer, ", Error"); | ||
464 | if (pwr & AC_PWRST_CLK_STOP_OK) | ||
465 | snd_iprintf(buffer, ", Clock-stop-OK"); | ||
466 | if (pwr & AC_PWRST_SETTING_RESET) | ||
467 | snd_iprintf(buffer, ", Setting-reset"); | ||
468 | snd_iprintf(buffer, "\n"); | ||
462 | } | 469 | } |
463 | 470 | ||
464 | static void print_unsol_cap(struct snd_info_buffer *buffer, | 471 | static void print_unsol_cap(struct snd_info_buffer *buffer, |
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index ad319d4dc32f..d6a8260a6f74 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c | |||
@@ -85,7 +85,7 @@ struct hdmi_spec { | |||
85 | * Non-generic ATI/NVIDIA specific | 85 | * Non-generic ATI/NVIDIA specific |
86 | */ | 86 | */ |
87 | struct hda_multi_out multiout; | 87 | struct hda_multi_out multiout; |
88 | const struct hda_pcm_stream *pcm_playback; | 88 | struct hda_pcm_stream pcm_playback; |
89 | }; | 89 | }; |
90 | 90 | ||
91 | 91 | ||
@@ -787,7 +787,7 @@ static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res) | |||
787 | int cp_ready = !!(res & AC_UNSOL_RES_CP_READY); | 787 | int cp_ready = !!(res & AC_UNSOL_RES_CP_READY); |
788 | 788 | ||
789 | printk(KERN_INFO | 789 | printk(KERN_INFO |
790 | "HDMI CP event: CODEC=%d PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n", | 790 | "HDMI CP event: CODEC=%d TAG=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n", |
791 | codec->addr, | 791 | codec->addr, |
792 | tag, | 792 | tag, |
793 | subtag, | 793 | subtag, |
@@ -1277,23 +1277,34 @@ static int generic_hdmi_build_controls(struct hda_codec *codec) | |||
1277 | return 0; | 1277 | return 0; |
1278 | } | 1278 | } |
1279 | 1279 | ||
1280 | static int generic_hdmi_init(struct hda_codec *codec) | 1280 | static int generic_hdmi_init_per_pins(struct hda_codec *codec) |
1281 | { | 1281 | { |
1282 | struct hdmi_spec *spec = codec->spec; | 1282 | struct hdmi_spec *spec = codec->spec; |
1283 | int pin_idx; | 1283 | int pin_idx; |
1284 | 1284 | ||
1285 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { | 1285 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { |
1286 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; | 1286 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; |
1287 | hda_nid_t pin_nid = per_pin->pin_nid; | ||
1288 | struct hdmi_eld *eld = &per_pin->sink_eld; | 1287 | struct hdmi_eld *eld = &per_pin->sink_eld; |
1289 | 1288 | ||
1290 | hdmi_init_pin(codec, pin_nid); | ||
1291 | snd_hda_jack_detect_enable(codec, pin_nid, pin_nid); | ||
1292 | |||
1293 | per_pin->codec = codec; | 1289 | per_pin->codec = codec; |
1294 | INIT_DELAYED_WORK(&per_pin->work, hdmi_repoll_eld); | 1290 | INIT_DELAYED_WORK(&per_pin->work, hdmi_repoll_eld); |
1295 | snd_hda_eld_proc_new(codec, eld, pin_idx); | 1291 | snd_hda_eld_proc_new(codec, eld, pin_idx); |
1296 | } | 1292 | } |
1293 | return 0; | ||
1294 | } | ||
1295 | |||
1296 | static int generic_hdmi_init(struct hda_codec *codec) | ||
1297 | { | ||
1298 | struct hdmi_spec *spec = codec->spec; | ||
1299 | int pin_idx; | ||
1300 | |||
1301 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { | ||
1302 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; | ||
1303 | hda_nid_t pin_nid = per_pin->pin_nid; | ||
1304 | |||
1305 | hdmi_init_pin(codec, pin_nid); | ||
1306 | snd_hda_jack_detect_enable(codec, pin_nid, pin_nid); | ||
1307 | } | ||
1297 | snd_hda_jack_report_sync(codec); | 1308 | snd_hda_jack_report_sync(codec); |
1298 | return 0; | 1309 | return 0; |
1299 | } | 1310 | } |
@@ -1338,6 +1349,7 @@ static int patch_generic_hdmi(struct hda_codec *codec) | |||
1338 | return -EINVAL; | 1349 | return -EINVAL; |
1339 | } | 1350 | } |
1340 | codec->patch_ops = generic_hdmi_patch_ops; | 1351 | codec->patch_ops = generic_hdmi_patch_ops; |
1352 | generic_hdmi_init_per_pins(codec); | ||
1341 | 1353 | ||
1342 | init_channel_allocations(); | 1354 | init_channel_allocations(); |
1343 | 1355 | ||
@@ -1352,45 +1364,65 @@ static int simple_playback_build_pcms(struct hda_codec *codec) | |||
1352 | { | 1364 | { |
1353 | struct hdmi_spec *spec = codec->spec; | 1365 | struct hdmi_spec *spec = codec->spec; |
1354 | struct hda_pcm *info = spec->pcm_rec; | 1366 | struct hda_pcm *info = spec->pcm_rec; |
1355 | int i; | 1367 | unsigned int chans; |
1368 | struct hda_pcm_stream *pstr; | ||
1356 | 1369 | ||
1357 | codec->num_pcms = spec->num_cvts; | 1370 | codec->num_pcms = 1; |
1358 | codec->pcm_info = info; | 1371 | codec->pcm_info = info; |
1359 | 1372 | ||
1360 | for (i = 0; i < codec->num_pcms; i++, info++) { | 1373 | chans = get_wcaps(codec, spec->cvts[0].cvt_nid); |
1361 | unsigned int chans; | 1374 | chans = get_wcaps_channels(chans); |
1362 | struct hda_pcm_stream *pstr; | ||
1363 | |||
1364 | chans = get_wcaps(codec, spec->cvts[i].cvt_nid); | ||
1365 | chans = get_wcaps_channels(chans); | ||
1366 | 1375 | ||
1367 | info->name = get_hdmi_pcm_name(i); | 1376 | info->name = get_hdmi_pcm_name(0); |
1368 | info->pcm_type = HDA_PCM_TYPE_HDMI; | 1377 | info->pcm_type = HDA_PCM_TYPE_HDMI; |
1369 | pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK]; | 1378 | pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK]; |
1370 | snd_BUG_ON(!spec->pcm_playback); | 1379 | *pstr = spec->pcm_playback; |
1371 | *pstr = *spec->pcm_playback; | 1380 | pstr->nid = spec->cvts[0].cvt_nid; |
1372 | pstr->nid = spec->cvts[i].cvt_nid; | 1381 | if (pstr->channels_max <= 2 && chans && chans <= 16) |
1373 | if (pstr->channels_max <= 2 && chans && chans <= 16) | 1382 | pstr->channels_max = chans; |
1374 | pstr->channels_max = chans; | ||
1375 | } | ||
1376 | 1383 | ||
1377 | return 0; | 1384 | return 0; |
1378 | } | 1385 | } |
1379 | 1386 | ||
1387 | /* unsolicited event for jack sensing */ | ||
1388 | static void simple_hdmi_unsol_event(struct hda_codec *codec, | ||
1389 | unsigned int res) | ||
1390 | { | ||
1391 | snd_hda_jack_set_dirty_all(codec); | ||
1392 | snd_hda_jack_report_sync(codec); | ||
1393 | } | ||
1394 | |||
1395 | /* generic_hdmi_build_jack can be used for simple_hdmi, too, | ||
1396 | * as long as spec->pins[] is set correctly | ||
1397 | */ | ||
1398 | #define simple_hdmi_build_jack generic_hdmi_build_jack | ||
1399 | |||
1380 | static int simple_playback_build_controls(struct hda_codec *codec) | 1400 | static int simple_playback_build_controls(struct hda_codec *codec) |
1381 | { | 1401 | { |
1382 | struct hdmi_spec *spec = codec->spec; | 1402 | struct hdmi_spec *spec = codec->spec; |
1383 | int err; | 1403 | int err; |
1384 | int i; | ||
1385 | 1404 | ||
1386 | for (i = 0; i < codec->num_pcms; i++) { | 1405 | err = snd_hda_create_spdif_out_ctls(codec, |
1387 | err = snd_hda_create_spdif_out_ctls(codec, | 1406 | spec->cvts[0].cvt_nid, |
1388 | spec->cvts[i].cvt_nid, | 1407 | spec->cvts[0].cvt_nid); |
1389 | spec->cvts[i].cvt_nid); | 1408 | if (err < 0) |
1390 | if (err < 0) | 1409 | return err; |
1391 | return err; | 1410 | return simple_hdmi_build_jack(codec, 0); |
1392 | } | 1411 | } |
1393 | 1412 | ||
1413 | static int simple_playback_init(struct hda_codec *codec) | ||
1414 | { | ||
1415 | struct hdmi_spec *spec = codec->spec; | ||
1416 | hda_nid_t pin = spec->pins[0].pin_nid; | ||
1417 | |||
1418 | snd_hda_codec_write(codec, pin, 0, | ||
1419 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); | ||
1420 | /* some codecs require to unmute the pin */ | ||
1421 | if (get_wcaps(codec, pin) & AC_WCAP_OUT_AMP) | ||
1422 | snd_hda_codec_write(codec, pin, 0, AC_VERB_SET_AMP_GAIN_MUTE, | ||
1423 | AMP_OUT_UNMUTE); | ||
1424 | snd_hda_jack_detect_enable(codec, pin, pin); | ||
1425 | snd_hda_jack_report_sync(codec); | ||
1394 | return 0; | 1426 | return 0; |
1395 | } | 1427 | } |
1396 | 1428 | ||
@@ -1418,7 +1450,15 @@ static const hda_nid_t nvhdmi_con_nids_7x[4] = { | |||
1418 | 0x6, 0x8, 0xa, 0xc, | 1450 | 0x6, 0x8, 0xa, 0xc, |
1419 | }; | 1451 | }; |
1420 | 1452 | ||
1421 | static const struct hda_verb nvhdmi_basic_init_7x[] = { | 1453 | static const struct hda_verb nvhdmi_basic_init_7x_2ch[] = { |
1454 | /* set audio protect on */ | ||
1455 | { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1}, | ||
1456 | /* enable digital output on pin widget */ | ||
1457 | { 0x5, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | ||
1458 | {} /* terminator */ | ||
1459 | }; | ||
1460 | |||
1461 | static const struct hda_verb nvhdmi_basic_init_7x_8ch[] = { | ||
1422 | /* set audio protect on */ | 1462 | /* set audio protect on */ |
1423 | { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1}, | 1463 | { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1}, |
1424 | /* enable digital output on pin widget */ | 1464 | /* enable digital output on pin widget */ |
@@ -1446,9 +1486,15 @@ static const struct hda_verb nvhdmi_basic_init_7x[] = { | |||
1446 | (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE) | 1486 | (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE) |
1447 | #endif | 1487 | #endif |
1448 | 1488 | ||
1449 | static int nvhdmi_7x_init(struct hda_codec *codec) | 1489 | static int nvhdmi_7x_init_2ch(struct hda_codec *codec) |
1450 | { | 1490 | { |
1451 | snd_hda_sequence_write(codec, nvhdmi_basic_init_7x); | 1491 | snd_hda_sequence_write(codec, nvhdmi_basic_init_7x_2ch); |
1492 | return 0; | ||
1493 | } | ||
1494 | |||
1495 | static int nvhdmi_7x_init_8ch(struct hda_codec *codec) | ||
1496 | { | ||
1497 | snd_hda_sequence_write(codec, nvhdmi_basic_init_7x_8ch); | ||
1452 | return 0; | 1498 | return 0; |
1453 | } | 1499 | } |
1454 | 1500 | ||
@@ -1524,6 +1570,50 @@ static int simple_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | |||
1524 | stream_tag, format, substream); | 1570 | stream_tag, format, substream); |
1525 | } | 1571 | } |
1526 | 1572 | ||
1573 | static const struct hda_pcm_stream simple_pcm_playback = { | ||
1574 | .substreams = 1, | ||
1575 | .channels_min = 2, | ||
1576 | .channels_max = 2, | ||
1577 | .ops = { | ||
1578 | .open = simple_playback_pcm_open, | ||
1579 | .close = simple_playback_pcm_close, | ||
1580 | .prepare = simple_playback_pcm_prepare | ||
1581 | }, | ||
1582 | }; | ||
1583 | |||
1584 | static const struct hda_codec_ops simple_hdmi_patch_ops = { | ||
1585 | .build_controls = simple_playback_build_controls, | ||
1586 | .build_pcms = simple_playback_build_pcms, | ||
1587 | .init = simple_playback_init, | ||
1588 | .free = simple_playback_free, | ||
1589 | .unsol_event = simple_hdmi_unsol_event, | ||
1590 | }; | ||
1591 | |||
1592 | static int patch_simple_hdmi(struct hda_codec *codec, | ||
1593 | hda_nid_t cvt_nid, hda_nid_t pin_nid) | ||
1594 | { | ||
1595 | struct hdmi_spec *spec; | ||
1596 | |||
1597 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
1598 | if (!spec) | ||
1599 | return -ENOMEM; | ||
1600 | |||
1601 | codec->spec = spec; | ||
1602 | |||
1603 | spec->multiout.num_dacs = 0; /* no analog */ | ||
1604 | spec->multiout.max_channels = 2; | ||
1605 | spec->multiout.dig_out_nid = cvt_nid; | ||
1606 | spec->num_cvts = 1; | ||
1607 | spec->num_pins = 1; | ||
1608 | spec->cvts[0].cvt_nid = cvt_nid; | ||
1609 | spec->pins[0].pin_nid = pin_nid; | ||
1610 | spec->pcm_playback = simple_pcm_playback; | ||
1611 | |||
1612 | codec->patch_ops = simple_hdmi_patch_ops; | ||
1613 | |||
1614 | return 0; | ||
1615 | } | ||
1616 | |||
1527 | static void nvhdmi_8ch_7x_set_info_frame_parameters(struct hda_codec *codec, | 1617 | static void nvhdmi_8ch_7x_set_info_frame_parameters(struct hda_codec *codec, |
1528 | int channels) | 1618 | int channels) |
1529 | { | 1619 | { |
@@ -1696,54 +1786,20 @@ static const struct hda_pcm_stream nvhdmi_pcm_playback_8ch_7x = { | |||
1696 | }, | 1786 | }, |
1697 | }; | 1787 | }; |
1698 | 1788 | ||
1699 | static const struct hda_pcm_stream nvhdmi_pcm_playback_2ch = { | ||
1700 | .substreams = 1, | ||
1701 | .channels_min = 2, | ||
1702 | .channels_max = 2, | ||
1703 | .nid = nvhdmi_master_con_nid_7x, | ||
1704 | .rates = SUPPORTED_RATES, | ||
1705 | .maxbps = SUPPORTED_MAXBPS, | ||
1706 | .formats = SUPPORTED_FORMATS, | ||
1707 | .ops = { | ||
1708 | .open = simple_playback_pcm_open, | ||
1709 | .close = simple_playback_pcm_close, | ||
1710 | .prepare = simple_playback_pcm_prepare | ||
1711 | }, | ||
1712 | }; | ||
1713 | |||
1714 | static const struct hda_codec_ops nvhdmi_patch_ops_8ch_7x = { | ||
1715 | .build_controls = simple_playback_build_controls, | ||
1716 | .build_pcms = simple_playback_build_pcms, | ||
1717 | .init = nvhdmi_7x_init, | ||
1718 | .free = simple_playback_free, | ||
1719 | }; | ||
1720 | |||
1721 | static const struct hda_codec_ops nvhdmi_patch_ops_2ch = { | ||
1722 | .build_controls = simple_playback_build_controls, | ||
1723 | .build_pcms = simple_playback_build_pcms, | ||
1724 | .init = nvhdmi_7x_init, | ||
1725 | .free = simple_playback_free, | ||
1726 | }; | ||
1727 | |||
1728 | static int patch_nvhdmi_2ch(struct hda_codec *codec) | 1789 | static int patch_nvhdmi_2ch(struct hda_codec *codec) |
1729 | { | 1790 | { |
1730 | struct hdmi_spec *spec; | 1791 | struct hdmi_spec *spec; |
1792 | int err = patch_simple_hdmi(codec, nvhdmi_master_con_nid_7x, | ||
1793 | nvhdmi_master_pin_nid_7x); | ||
1794 | if (err < 0) | ||
1795 | return err; | ||
1731 | 1796 | ||
1732 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 1797 | codec->patch_ops.init = nvhdmi_7x_init_2ch; |
1733 | if (spec == NULL) | 1798 | /* override the PCM rates, etc, as the codec doesn't give full list */ |
1734 | return -ENOMEM; | 1799 | spec = codec->spec; |
1735 | 1800 | spec->pcm_playback.rates = SUPPORTED_RATES; | |
1736 | codec->spec = spec; | 1801 | spec->pcm_playback.maxbps = SUPPORTED_MAXBPS; |
1737 | 1802 | spec->pcm_playback.formats = SUPPORTED_FORMATS; | |
1738 | spec->multiout.num_dacs = 0; /* no analog */ | ||
1739 | spec->multiout.max_channels = 2; | ||
1740 | spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x; | ||
1741 | spec->num_cvts = 1; | ||
1742 | spec->cvts[0].cvt_nid = nvhdmi_master_con_nid_7x; | ||
1743 | spec->pcm_playback = &nvhdmi_pcm_playback_2ch; | ||
1744 | |||
1745 | codec->patch_ops = nvhdmi_patch_ops_2ch; | ||
1746 | |||
1747 | return 0; | 1803 | return 0; |
1748 | } | 1804 | } |
1749 | 1805 | ||
@@ -1751,13 +1807,12 @@ static int patch_nvhdmi_8ch_7x(struct hda_codec *codec) | |||
1751 | { | 1807 | { |
1752 | struct hdmi_spec *spec; | 1808 | struct hdmi_spec *spec; |
1753 | int err = patch_nvhdmi_2ch(codec); | 1809 | int err = patch_nvhdmi_2ch(codec); |
1754 | |||
1755 | if (err < 0) | 1810 | if (err < 0) |
1756 | return err; | 1811 | return err; |
1757 | spec = codec->spec; | 1812 | spec = codec->spec; |
1758 | spec->multiout.max_channels = 8; | 1813 | spec->multiout.max_channels = 8; |
1759 | spec->pcm_playback = &nvhdmi_pcm_playback_8ch_7x; | 1814 | spec->pcm_playback = nvhdmi_pcm_playback_8ch_7x; |
1760 | codec->patch_ops = nvhdmi_patch_ops_8ch_7x; | 1815 | codec->patch_ops.init = nvhdmi_7x_init_8ch; |
1761 | 1816 | ||
1762 | /* Initialize the audio infoframe channel mask and checksum to something | 1817 | /* Initialize the audio infoframe channel mask and checksum to something |
1763 | * valid */ | 1818 | * valid */ |
@@ -1801,69 +1856,26 @@ static int atihdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | |||
1801 | return 0; | 1856 | return 0; |
1802 | } | 1857 | } |
1803 | 1858 | ||
1804 | static const struct hda_pcm_stream atihdmi_pcm_digital_playback = { | 1859 | static int patch_atihdmi(struct hda_codec *codec) |
1805 | .substreams = 1, | ||
1806 | .channels_min = 2, | ||
1807 | .channels_max = 2, | ||
1808 | .nid = ATIHDMI_CVT_NID, | ||
1809 | .ops = { | ||
1810 | .open = simple_playback_pcm_open, | ||
1811 | .close = simple_playback_pcm_close, | ||
1812 | .prepare = atihdmi_playback_pcm_prepare | ||
1813 | }, | ||
1814 | }; | ||
1815 | |||
1816 | static const struct hda_verb atihdmi_basic_init[] = { | ||
1817 | /* enable digital output on pin widget */ | ||
1818 | { 0x03, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
1819 | {} /* terminator */ | ||
1820 | }; | ||
1821 | |||
1822 | static int atihdmi_init(struct hda_codec *codec) | ||
1823 | { | 1860 | { |
1824 | struct hdmi_spec *spec = codec->spec; | 1861 | struct hdmi_spec *spec; |
1825 | 1862 | int err = patch_simple_hdmi(codec, ATIHDMI_CVT_NID, ATIHDMI_PIN_NID); | |
1826 | snd_hda_sequence_write(codec, atihdmi_basic_init); | 1863 | if (err < 0) |
1827 | /* SI codec requires to unmute the pin */ | 1864 | return err; |
1828 | if (get_wcaps(codec, spec->pins[0].pin_nid) & AC_WCAP_OUT_AMP) | 1865 | spec = codec->spec; |
1829 | snd_hda_codec_write(codec, spec->pins[0].pin_nid, 0, | 1866 | spec->pcm_playback.ops.prepare = atihdmi_playback_pcm_prepare; |
1830 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
1831 | AMP_OUT_UNMUTE); | ||
1832 | return 0; | 1867 | return 0; |
1833 | } | 1868 | } |
1834 | 1869 | ||
1835 | static const struct hda_codec_ops atihdmi_patch_ops = { | 1870 | /* VIA HDMI Implementation */ |
1836 | .build_controls = simple_playback_build_controls, | 1871 | #define VIAHDMI_CVT_NID 0x02 /* audio converter1 */ |
1837 | .build_pcms = simple_playback_build_pcms, | 1872 | #define VIAHDMI_PIN_NID 0x03 /* HDMI output pin1 */ |
1838 | .init = atihdmi_init, | ||
1839 | .free = simple_playback_free, | ||
1840 | }; | ||
1841 | |||
1842 | 1873 | ||
1843 | static int patch_atihdmi(struct hda_codec *codec) | 1874 | static int patch_via_hdmi(struct hda_codec *codec) |
1844 | { | 1875 | { |
1845 | struct hdmi_spec *spec; | 1876 | return patch_simple_hdmi(codec, VIAHDMI_CVT_NID, VIAHDMI_PIN_NID); |
1846 | |||
1847 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
1848 | if (spec == NULL) | ||
1849 | return -ENOMEM; | ||
1850 | |||
1851 | codec->spec = spec; | ||
1852 | |||
1853 | spec->multiout.num_dacs = 0; /* no analog */ | ||
1854 | spec->multiout.max_channels = 2; | ||
1855 | spec->multiout.dig_out_nid = ATIHDMI_CVT_NID; | ||
1856 | spec->num_cvts = 1; | ||
1857 | spec->cvts[0].cvt_nid = ATIHDMI_CVT_NID; | ||
1858 | spec->pins[0].pin_nid = ATIHDMI_PIN_NID; | ||
1859 | spec->pcm_playback = &atihdmi_pcm_digital_playback; | ||
1860 | |||
1861 | codec->patch_ops = atihdmi_patch_ops; | ||
1862 | |||
1863 | return 0; | ||
1864 | } | 1877 | } |
1865 | 1878 | ||
1866 | |||
1867 | /* | 1879 | /* |
1868 | * patch entries | 1880 | * patch entries |
1869 | */ | 1881 | */ |
@@ -1904,6 +1916,10 @@ static const struct hda_codec_preset snd_hda_preset_hdmi[] = { | |||
1904 | { .id = 0x10de0044, .name = "GPU 44 HDMI/DP", .patch = patch_generic_hdmi }, | 1916 | { .id = 0x10de0044, .name = "GPU 44 HDMI/DP", .patch = patch_generic_hdmi }, |
1905 | { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch }, | 1917 | { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch }, |
1906 | { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, | 1918 | { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, |
1919 | { .id = 0x11069f80, .name = "VX900 HDMI/DP", .patch = patch_via_hdmi }, | ||
1920 | { .id = 0x11069f81, .name = "VX900 HDMI/DP", .patch = patch_via_hdmi }, | ||
1921 | { .id = 0x11069f84, .name = "VX11 HDMI/DP", .patch = patch_generic_hdmi }, | ||
1922 | { .id = 0x11069f85, .name = "VX11 HDMI/DP", .patch = patch_generic_hdmi }, | ||
1907 | { .id = 0x80860054, .name = "IbexPeak HDMI", .patch = patch_generic_hdmi }, | 1923 | { .id = 0x80860054, .name = "IbexPeak HDMI", .patch = patch_generic_hdmi }, |
1908 | { .id = 0x80862801, .name = "Bearlake HDMI", .patch = patch_generic_hdmi }, | 1924 | { .id = 0x80862801, .name = "Bearlake HDMI", .patch = patch_generic_hdmi }, |
1909 | { .id = 0x80862802, .name = "Cantiga HDMI", .patch = patch_generic_hdmi }, | 1925 | { .id = 0x80862802, .name = "Cantiga HDMI", .patch = patch_generic_hdmi }, |
@@ -1950,6 +1966,10 @@ MODULE_ALIAS("snd-hda-codec-id:10de0043"); | |||
1950 | MODULE_ALIAS("snd-hda-codec-id:10de0044"); | 1966 | MODULE_ALIAS("snd-hda-codec-id:10de0044"); |
1951 | MODULE_ALIAS("snd-hda-codec-id:10de0067"); | 1967 | MODULE_ALIAS("snd-hda-codec-id:10de0067"); |
1952 | MODULE_ALIAS("snd-hda-codec-id:10de8001"); | 1968 | MODULE_ALIAS("snd-hda-codec-id:10de8001"); |
1969 | MODULE_ALIAS("snd-hda-codec-id:11069f80"); | ||
1970 | MODULE_ALIAS("snd-hda-codec-id:11069f81"); | ||
1971 | MODULE_ALIAS("snd-hda-codec-id:11069f84"); | ||
1972 | MODULE_ALIAS("snd-hda-codec-id:11069f85"); | ||
1953 | MODULE_ALIAS("snd-hda-codec-id:17e80047"); | 1973 | MODULE_ALIAS("snd-hda-codec-id:17e80047"); |
1954 | MODULE_ALIAS("snd-hda-codec-id:80860054"); | 1974 | MODULE_ALIAS("snd-hda-codec-id:80860054"); |
1955 | MODULE_ALIAS("snd-hda-codec-id:80862801"); | 1975 | MODULE_ALIAS("snd-hda-codec-id:80862801"); |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 5ccf10a4d593..5c81ee95d7f0 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -170,6 +170,7 @@ struct alc_spec { | |||
170 | hda_nid_t imux_pins[HDA_MAX_NUM_INPUTS]; | 170 | hda_nid_t imux_pins[HDA_MAX_NUM_INPUTS]; |
171 | unsigned int dyn_adc_idx[HDA_MAX_NUM_INPUTS]; | 171 | unsigned int dyn_adc_idx[HDA_MAX_NUM_INPUTS]; |
172 | int int_mic_idx, ext_mic_idx, dock_mic_idx; /* for auto-mic */ | 172 | int int_mic_idx, ext_mic_idx, dock_mic_idx; /* for auto-mic */ |
173 | hda_nid_t inv_dmic_pin; | ||
173 | 174 | ||
174 | /* hooks */ | 175 | /* hooks */ |
175 | void (*init_hook)(struct hda_codec *codec); | 176 | void (*init_hook)(struct hda_codec *codec); |
@@ -201,6 +202,8 @@ struct alc_spec { | |||
201 | unsigned int vol_in_capsrc:1; /* use capsrc volume (ADC has no vol) */ | 202 | unsigned int vol_in_capsrc:1; /* use capsrc volume (ADC has no vol) */ |
202 | unsigned int parse_flags; /* passed to snd_hda_parse_pin_defcfg() */ | 203 | unsigned int parse_flags; /* passed to snd_hda_parse_pin_defcfg() */ |
203 | unsigned int shared_mic_hp:1; /* HP/Mic-in sharing */ | 204 | unsigned int shared_mic_hp:1; /* HP/Mic-in sharing */ |
205 | unsigned int inv_dmic_fixup:1; /* has inverted digital-mic workaround */ | ||
206 | unsigned int inv_dmic_muted:1; /* R-ch of inv d-mic is muted? */ | ||
204 | 207 | ||
205 | /* auto-mute control */ | 208 | /* auto-mute control */ |
206 | int automute_mode; | 209 | int automute_mode; |
@@ -298,6 +301,7 @@ static inline hda_nid_t get_capsrc(struct alc_spec *spec, int idx) | |||
298 | } | 301 | } |
299 | 302 | ||
300 | static void call_update_outputs(struct hda_codec *codec); | 303 | static void call_update_outputs(struct hda_codec *codec); |
304 | static void alc_inv_dmic_sync(struct hda_codec *codec, bool force); | ||
301 | 305 | ||
302 | /* select the given imux item; either unmute exclusively or select the route */ | 306 | /* select the given imux item; either unmute exclusively or select the route */ |
303 | static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx, | 307 | static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx, |
@@ -368,6 +372,7 @@ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx, | |||
368 | AC_VERB_SET_CONNECT_SEL, | 372 | AC_VERB_SET_CONNECT_SEL, |
369 | imux->items[idx].index); | 373 | imux->items[idx].index); |
370 | } | 374 | } |
375 | alc_inv_dmic_sync(codec, true); | ||
371 | return 1; | 376 | return 1; |
372 | } | 377 | } |
373 | 378 | ||
@@ -1556,14 +1561,14 @@ typedef int (*getput_call_t)(struct snd_kcontrol *kcontrol, | |||
1556 | 1561 | ||
1557 | static int alc_cap_getput_caller(struct snd_kcontrol *kcontrol, | 1562 | static int alc_cap_getput_caller(struct snd_kcontrol *kcontrol, |
1558 | struct snd_ctl_elem_value *ucontrol, | 1563 | struct snd_ctl_elem_value *ucontrol, |
1559 | getput_call_t func, bool check_adc_switch) | 1564 | getput_call_t func, bool is_put) |
1560 | { | 1565 | { |
1561 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 1566 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
1562 | struct alc_spec *spec = codec->spec; | 1567 | struct alc_spec *spec = codec->spec; |
1563 | int i, err = 0; | 1568 | int i, err = 0; |
1564 | 1569 | ||
1565 | mutex_lock(&codec->control_mutex); | 1570 | mutex_lock(&codec->control_mutex); |
1566 | if (check_adc_switch && spec->dyn_adc_switch) { | 1571 | if (is_put && spec->dyn_adc_switch) { |
1567 | for (i = 0; i < spec->num_adc_nids; i++) { | 1572 | for (i = 0; i < spec->num_adc_nids; i++) { |
1568 | kcontrol->private_value = | 1573 | kcontrol->private_value = |
1569 | HDA_COMPOSE_AMP_VAL(spec->adc_nids[i], | 1574 | HDA_COMPOSE_AMP_VAL(spec->adc_nids[i], |
@@ -1584,6 +1589,8 @@ static int alc_cap_getput_caller(struct snd_kcontrol *kcontrol, | |||
1584 | 3, 0, HDA_INPUT); | 1589 | 3, 0, HDA_INPUT); |
1585 | err = func(kcontrol, ucontrol); | 1590 | err = func(kcontrol, ucontrol); |
1586 | } | 1591 | } |
1592 | if (err >= 0 && is_put) | ||
1593 | alc_inv_dmic_sync(codec, false); | ||
1587 | error: | 1594 | error: |
1588 | mutex_unlock(&codec->control_mutex); | 1595 | mutex_unlock(&codec->control_mutex); |
1589 | return err; | 1596 | return err; |
@@ -1676,6 +1683,116 @@ DEFINE_CAPMIX_NOSRC(2); | |||
1676 | DEFINE_CAPMIX_NOSRC(3); | 1683 | DEFINE_CAPMIX_NOSRC(3); |
1677 | 1684 | ||
1678 | /* | 1685 | /* |
1686 | * Inverted digital-mic handling | ||
1687 | * | ||
1688 | * First off, it's a bit tricky. The "Inverted Internal Mic Capture Switch" | ||
1689 | * gives the additional mute only to the right channel of the digital mic | ||
1690 | * capture stream. This is a workaround for avoiding the almost silence | ||
1691 | * by summing the stereo stream from some (known to be ForteMedia) | ||
1692 | * digital mic unit. | ||
1693 | * | ||
1694 | * The logic is to call alc_inv_dmic_sync() after each action (possibly) | ||
1695 | * modifying ADC amp. When the mute flag is set, it mutes the R-channel | ||
1696 | * without caching so that the cache can still keep the original value. | ||
1697 | * The cached value is then restored when the flag is set off or any other | ||
1698 | * than d-mic is used as the current input source. | ||
1699 | */ | ||
1700 | static void alc_inv_dmic_sync(struct hda_codec *codec, bool force) | ||
1701 | { | ||
1702 | struct alc_spec *spec = codec->spec; | ||
1703 | int i; | ||
1704 | |||
1705 | if (!spec->inv_dmic_fixup) | ||
1706 | return; | ||
1707 | if (!spec->inv_dmic_muted && !force) | ||
1708 | return; | ||
1709 | for (i = 0; i < spec->num_adc_nids; i++) { | ||
1710 | int src = spec->dyn_adc_switch ? 0 : i; | ||
1711 | bool dmic_fixup = false; | ||
1712 | hda_nid_t nid; | ||
1713 | int parm, dir, v; | ||
1714 | |||
1715 | if (spec->inv_dmic_muted && | ||
1716 | spec->imux_pins[spec->cur_mux[src]] == spec->inv_dmic_pin) | ||
1717 | dmic_fixup = true; | ||
1718 | if (!dmic_fixup && !force) | ||
1719 | continue; | ||
1720 | if (spec->vol_in_capsrc) { | ||
1721 | nid = spec->capsrc_nids[i]; | ||
1722 | parm = AC_AMP_SET_RIGHT | AC_AMP_SET_OUTPUT; | ||
1723 | dir = HDA_OUTPUT; | ||
1724 | } else { | ||
1725 | nid = spec->adc_nids[i]; | ||
1726 | parm = AC_AMP_SET_RIGHT | AC_AMP_SET_INPUT; | ||
1727 | dir = HDA_INPUT; | ||
1728 | } | ||
1729 | /* we care only right channel */ | ||
1730 | v = snd_hda_codec_amp_read(codec, nid, 1, dir, 0); | ||
1731 | if (v & 0x80) /* if already muted, we don't need to touch */ | ||
1732 | continue; | ||
1733 | if (dmic_fixup) /* add mute for d-mic */ | ||
1734 | v |= 0x80; | ||
1735 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, | ||
1736 | parm | v); | ||
1737 | } | ||
1738 | } | ||
1739 | |||
1740 | static int alc_inv_dmic_sw_get(struct snd_kcontrol *kcontrol, | ||
1741 | struct snd_ctl_elem_value *ucontrol) | ||
1742 | { | ||
1743 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1744 | struct alc_spec *spec = codec->spec; | ||
1745 | |||
1746 | ucontrol->value.integer.value[0] = !spec->inv_dmic_muted; | ||
1747 | return 0; | ||
1748 | } | ||
1749 | |||
1750 | static int alc_inv_dmic_sw_put(struct snd_kcontrol *kcontrol, | ||
1751 | struct snd_ctl_elem_value *ucontrol) | ||
1752 | { | ||
1753 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1754 | struct alc_spec *spec = codec->spec; | ||
1755 | unsigned int val = !ucontrol->value.integer.value[0]; | ||
1756 | |||
1757 | if (val == spec->inv_dmic_muted) | ||
1758 | return 0; | ||
1759 | spec->inv_dmic_muted = val; | ||
1760 | alc_inv_dmic_sync(codec, true); | ||
1761 | return 0; | ||
1762 | } | ||
1763 | |||
1764 | static const struct snd_kcontrol_new alc_inv_dmic_sw = { | ||
1765 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1766 | .info = snd_ctl_boolean_mono_info, | ||
1767 | .get = alc_inv_dmic_sw_get, | ||
1768 | .put = alc_inv_dmic_sw_put, | ||
1769 | }; | ||
1770 | |||
1771 | static int alc_add_inv_dmic_mixer(struct hda_codec *codec, hda_nid_t nid) | ||
1772 | { | ||
1773 | struct alc_spec *spec = codec->spec; | ||
1774 | struct snd_kcontrol_new *knew = alc_kcontrol_new(spec); | ||
1775 | if (!knew) | ||
1776 | return -ENOMEM; | ||
1777 | *knew = alc_inv_dmic_sw; | ||
1778 | knew->name = kstrdup("Inverted Internal Mic Capture Switch", GFP_KERNEL); | ||
1779 | if (!knew->name) | ||
1780 | return -ENOMEM; | ||
1781 | spec->inv_dmic_fixup = 1; | ||
1782 | spec->inv_dmic_muted = 0; | ||
1783 | spec->inv_dmic_pin = nid; | ||
1784 | return 0; | ||
1785 | } | ||
1786 | |||
1787 | /* typically the digital mic is put at node 0x12 */ | ||
1788 | static void alc_fixup_inv_dmic_0x12(struct hda_codec *codec, | ||
1789 | const struct alc_fixup *fix, int action) | ||
1790 | { | ||
1791 | if (action == ALC_FIXUP_ACT_PROBE) | ||
1792 | alc_add_inv_dmic_mixer(codec, 0x12); | ||
1793 | } | ||
1794 | |||
1795 | /* | ||
1679 | * virtual master controls | 1796 | * virtual master controls |
1680 | */ | 1797 | */ |
1681 | 1798 | ||
@@ -2317,6 +2434,7 @@ static int alc_resume(struct hda_codec *codec) | |||
2317 | codec->patch_ops.init(codec); | 2434 | codec->patch_ops.init(codec); |
2318 | snd_hda_codec_resume_amp(codec); | 2435 | snd_hda_codec_resume_amp(codec); |
2319 | snd_hda_codec_resume_cache(codec); | 2436 | snd_hda_codec_resume_cache(codec); |
2437 | alc_inv_dmic_sync(codec, true); | ||
2320 | hda_call_check_power_status(codec, 0x01); | 2438 | hda_call_check_power_status(codec, 0x01); |
2321 | return 0; | 2439 | return 0; |
2322 | } | 2440 | } |
@@ -4909,6 +5027,7 @@ enum { | |||
4909 | ALC889_FIXUP_DAC_ROUTE, | 5027 | ALC889_FIXUP_DAC_ROUTE, |
4910 | ALC889_FIXUP_MBP_VREF, | 5028 | ALC889_FIXUP_MBP_VREF, |
4911 | ALC889_FIXUP_IMAC91_VREF, | 5029 | ALC889_FIXUP_IMAC91_VREF, |
5030 | ALC882_FIXUP_INV_DMIC, | ||
4912 | }; | 5031 | }; |
4913 | 5032 | ||
4914 | static void alc889_fixup_coef(struct hda_codec *codec, | 5033 | static void alc889_fixup_coef(struct hda_codec *codec, |
@@ -5212,6 +5331,10 @@ static const struct alc_fixup alc882_fixups[] = { | |||
5212 | .chained = true, | 5331 | .chained = true, |
5213 | .chain_id = ALC882_FIXUP_GPIO1, | 5332 | .chain_id = ALC882_FIXUP_GPIO1, |
5214 | }, | 5333 | }, |
5334 | [ALC882_FIXUP_INV_DMIC] = { | ||
5335 | .type = ALC_FIXUP_FUNC, | ||
5336 | .v.func = alc_fixup_inv_dmic_0x12, | ||
5337 | }, | ||
5215 | }; | 5338 | }; |
5216 | 5339 | ||
5217 | static const struct snd_pci_quirk alc882_fixup_tbl[] = { | 5340 | static const struct snd_pci_quirk alc882_fixup_tbl[] = { |
@@ -5286,6 +5409,7 @@ static const struct alc_model_fixup alc882_fixup_models[] = { | |||
5286 | {.id = ALC882_FIXUP_ACER_ASPIRE_4930G, .name = "acer-aspire-4930g"}, | 5409 | {.id = ALC882_FIXUP_ACER_ASPIRE_4930G, .name = "acer-aspire-4930g"}, |
5287 | {.id = ALC882_FIXUP_ACER_ASPIRE_8930G, .name = "acer-aspire-8930g"}, | 5410 | {.id = ALC882_FIXUP_ACER_ASPIRE_8930G, .name = "acer-aspire-8930g"}, |
5288 | {.id = ALC883_FIXUP_ACER_EAPD, .name = "acer-aspire"}, | 5411 | {.id = ALC883_FIXUP_ACER_EAPD, .name = "acer-aspire"}, |
5412 | {.id = ALC882_FIXUP_INV_DMIC, .name = "inv-dmic"}, | ||
5289 | {} | 5413 | {} |
5290 | }; | 5414 | }; |
5291 | 5415 | ||
@@ -5373,6 +5497,7 @@ enum { | |||
5373 | ALC262_FIXUP_LENOVO_3000, | 5497 | ALC262_FIXUP_LENOVO_3000, |
5374 | ALC262_FIXUP_BENQ, | 5498 | ALC262_FIXUP_BENQ, |
5375 | ALC262_FIXUP_BENQ_T31, | 5499 | ALC262_FIXUP_BENQ_T31, |
5500 | ALC262_FIXUP_INV_DMIC, | ||
5376 | }; | 5501 | }; |
5377 | 5502 | ||
5378 | static const struct alc_fixup alc262_fixups[] = { | 5503 | static const struct alc_fixup alc262_fixups[] = { |
@@ -5424,6 +5549,10 @@ static const struct alc_fixup alc262_fixups[] = { | |||
5424 | {} | 5549 | {} |
5425 | } | 5550 | } |
5426 | }, | 5551 | }, |
5552 | [ALC262_FIXUP_INV_DMIC] = { | ||
5553 | .type = ALC_FIXUP_FUNC, | ||
5554 | .v.func = alc_fixup_inv_dmic_0x12, | ||
5555 | }, | ||
5427 | }; | 5556 | }; |
5428 | 5557 | ||
5429 | static const struct snd_pci_quirk alc262_fixup_tbl[] = { | 5558 | static const struct snd_pci_quirk alc262_fixup_tbl[] = { |
@@ -5438,6 +5567,10 @@ static const struct snd_pci_quirk alc262_fixup_tbl[] = { | |||
5438 | {} | 5567 | {} |
5439 | }; | 5568 | }; |
5440 | 5569 | ||
5570 | static const struct alc_model_fixup alc262_fixup_models[] = { | ||
5571 | {.id = ALC262_FIXUP_INV_DMIC, .name = "inv-dmic"}, | ||
5572 | {} | ||
5573 | }; | ||
5441 | 5574 | ||
5442 | /* | 5575 | /* |
5443 | */ | 5576 | */ |
@@ -5466,7 +5599,8 @@ static int patch_alc262(struct hda_codec *codec) | |||
5466 | #endif | 5599 | #endif |
5467 | alc_fix_pll_init(codec, 0x20, 0x0a, 10); | 5600 | alc_fix_pll_init(codec, 0x20, 0x0a, 10); |
5468 | 5601 | ||
5469 | alc_pick_fixup(codec, NULL, alc262_fixup_tbl, alc262_fixups); | 5602 | alc_pick_fixup(codec, alc262_fixup_models, alc262_fixup_tbl, |
5603 | alc262_fixups); | ||
5470 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); | 5604 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); |
5471 | 5605 | ||
5472 | alc_auto_parse_customize_define(codec); | 5606 | alc_auto_parse_customize_define(codec); |
@@ -5522,6 +5656,22 @@ static const struct hda_verb alc268_beep_init_verbs[] = { | |||
5522 | { } | 5656 | { } |
5523 | }; | 5657 | }; |
5524 | 5658 | ||
5659 | enum { | ||
5660 | ALC268_FIXUP_INV_DMIC, | ||
5661 | }; | ||
5662 | |||
5663 | static const struct alc_fixup alc268_fixups[] = { | ||
5664 | [ALC268_FIXUP_INV_DMIC] = { | ||
5665 | .type = ALC_FIXUP_FUNC, | ||
5666 | .v.func = alc_fixup_inv_dmic_0x12, | ||
5667 | }, | ||
5668 | }; | ||
5669 | |||
5670 | static const struct alc_model_fixup alc268_fixup_models[] = { | ||
5671 | {.id = ALC268_FIXUP_INV_DMIC, .name = "inv-dmic"}, | ||
5672 | {} | ||
5673 | }; | ||
5674 | |||
5525 | /* | 5675 | /* |
5526 | * BIOS auto configuration | 5676 | * BIOS auto configuration |
5527 | */ | 5677 | */ |
@@ -5553,6 +5703,9 @@ static int patch_alc268(struct hda_codec *codec) | |||
5553 | 5703 | ||
5554 | spec = codec->spec; | 5704 | spec = codec->spec; |
5555 | 5705 | ||
5706 | alc_pick_fixup(codec, alc268_fixup_models, NULL, alc268_fixups); | ||
5707 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); | ||
5708 | |||
5556 | /* automatic parse from the BIOS config */ | 5709 | /* automatic parse from the BIOS config */ |
5557 | err = alc268_parse_auto_config(codec); | 5710 | err = alc268_parse_auto_config(codec); |
5558 | if (err < 0) | 5711 | if (err < 0) |
@@ -5582,6 +5735,8 @@ static int patch_alc268(struct hda_codec *codec) | |||
5582 | codec->patch_ops = alc_patch_ops; | 5735 | codec->patch_ops = alc_patch_ops; |
5583 | spec->shutup = alc_eapd_shutup; | 5736 | spec->shutup = alc_eapd_shutup; |
5584 | 5737 | ||
5738 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); | ||
5739 | |||
5585 | return 0; | 5740 | return 0; |
5586 | 5741 | ||
5587 | error: | 5742 | error: |
@@ -5810,6 +5965,7 @@ static void alc269_fixup_mic2_mute(struct hda_codec *codec, | |||
5810 | } | 5965 | } |
5811 | } | 5966 | } |
5812 | 5967 | ||
5968 | |||
5813 | enum { | 5969 | enum { |
5814 | ALC269_FIXUP_SONY_VAIO, | 5970 | ALC269_FIXUP_SONY_VAIO, |
5815 | ALC275_FIXUP_SONY_VAIO_GPIO2, | 5971 | ALC275_FIXUP_SONY_VAIO_GPIO2, |
@@ -5828,6 +5984,7 @@ enum { | |||
5828 | ALC269VB_FIXUP_AMIC, | 5984 | ALC269VB_FIXUP_AMIC, |
5829 | ALC269VB_FIXUP_DMIC, | 5985 | ALC269VB_FIXUP_DMIC, |
5830 | ALC269_FIXUP_MIC2_MUTE_LED, | 5986 | ALC269_FIXUP_MIC2_MUTE_LED, |
5987 | ALC269_FIXUP_INV_DMIC, | ||
5831 | }; | 5988 | }; |
5832 | 5989 | ||
5833 | static const struct alc_fixup alc269_fixups[] = { | 5990 | static const struct alc_fixup alc269_fixups[] = { |
@@ -5952,12 +6109,19 @@ static const struct alc_fixup alc269_fixups[] = { | |||
5952 | .type = ALC_FIXUP_FUNC, | 6109 | .type = ALC_FIXUP_FUNC, |
5953 | .v.func = alc269_fixup_mic2_mute, | 6110 | .v.func = alc269_fixup_mic2_mute, |
5954 | }, | 6111 | }, |
6112 | [ALC269_FIXUP_INV_DMIC] = { | ||
6113 | .type = ALC_FIXUP_FUNC, | ||
6114 | .v.func = alc_fixup_inv_dmic_0x12, | ||
6115 | }, | ||
5955 | }; | 6116 | }; |
5956 | 6117 | ||
5957 | static const struct snd_pci_quirk alc269_fixup_tbl[] = { | 6118 | static const struct snd_pci_quirk alc269_fixup_tbl[] = { |
6119 | SND_PCI_QUIRK(0x1025, 0x029b, "Acer 1810TZ", ALC269_FIXUP_INV_DMIC), | ||
6120 | SND_PCI_QUIRK(0x1025, 0x0349, "Acer AOD260", ALC269_FIXUP_INV_DMIC), | ||
5958 | SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_MIC2_MUTE_LED), | 6121 | SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_MIC2_MUTE_LED), |
5959 | SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_DMIC), | 6122 | SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_DMIC), |
5960 | SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW), | 6123 | SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW), |
6124 | SND_PCI_QUIRK(0x1043, 0x1b13, "Asus U41SV", ALC269_FIXUP_INV_DMIC), | ||
5961 | SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC), | 6125 | SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC), |
5962 | SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC), | 6126 | SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC), |
5963 | SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC), | 6127 | SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC), |
@@ -6033,6 +6197,9 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
6033 | static const struct alc_model_fixup alc269_fixup_models[] = { | 6197 | static const struct alc_model_fixup alc269_fixup_models[] = { |
6034 | {.id = ALC269_FIXUP_AMIC, .name = "laptop-amic"}, | 6198 | {.id = ALC269_FIXUP_AMIC, .name = "laptop-amic"}, |
6035 | {.id = ALC269_FIXUP_DMIC, .name = "laptop-dmic"}, | 6199 | {.id = ALC269_FIXUP_DMIC, .name = "laptop-dmic"}, |
6200 | {.id = ALC269_FIXUP_STEREO_DMIC, .name = "alc269-dmic"}, | ||
6201 | {.id = ALC271_FIXUP_DMIC, .name = "alc271-dmic"}, | ||
6202 | {.id = ALC269_FIXUP_INV_DMIC, .name = "inv-dmic"}, | ||
6036 | {} | 6203 | {} |
6037 | }; | 6204 | }; |
6038 | 6205 | ||
@@ -6329,12 +6496,6 @@ static const struct snd_pci_quirk alc861vd_fixup_tbl[] = { | |||
6329 | {} | 6496 | {} |
6330 | }; | 6497 | }; |
6331 | 6498 | ||
6332 | static const struct hda_verb alc660vd_eapd_verbs[] = { | ||
6333 | {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2}, | ||
6334 | {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2}, | ||
6335 | { } | ||
6336 | }; | ||
6337 | |||
6338 | /* | 6499 | /* |
6339 | */ | 6500 | */ |
6340 | static int patch_alc861vd(struct hda_codec *codec) | 6501 | static int patch_alc861vd(struct hda_codec *codec) |
@@ -6356,11 +6517,6 @@ static int patch_alc861vd(struct hda_codec *codec) | |||
6356 | if (err < 0) | 6517 | if (err < 0) |
6357 | goto error; | 6518 | goto error; |
6358 | 6519 | ||
6359 | if (codec->vendor_id == 0x10ec0660) { | ||
6360 | /* always turn on EAPD */ | ||
6361 | snd_hda_gen_add_verbs(&spec->gen, alc660vd_eapd_verbs); | ||
6362 | } | ||
6363 | |||
6364 | if (!spec->no_analog) { | 6520 | if (!spec->no_analog) { |
6365 | err = snd_hda_attach_beep_device(codec, 0x23); | 6521 | err = snd_hda_attach_beep_device(codec, 0x23); |
6366 | if (err < 0) | 6522 | if (err < 0) |
@@ -6443,6 +6599,7 @@ enum { | |||
6443 | ALC662_FIXUP_ASUS_MODE8, | 6599 | ALC662_FIXUP_ASUS_MODE8, |
6444 | ALC662_FIXUP_NO_JACK_DETECT, | 6600 | ALC662_FIXUP_NO_JACK_DETECT, |
6445 | ALC662_FIXUP_ZOTAC_Z68, | 6601 | ALC662_FIXUP_ZOTAC_Z68, |
6602 | ALC662_FIXUP_INV_DMIC, | ||
6446 | }; | 6603 | }; |
6447 | 6604 | ||
6448 | static const struct alc_fixup alc662_fixups[] = { | 6605 | static const struct alc_fixup alc662_fixups[] = { |
@@ -6599,12 +6756,17 @@ static const struct alc_fixup alc662_fixups[] = { | |||
6599 | { } | 6756 | { } |
6600 | } | 6757 | } |
6601 | }, | 6758 | }, |
6759 | [ALC662_FIXUP_INV_DMIC] = { | ||
6760 | .type = ALC_FIXUP_FUNC, | ||
6761 | .v.func = alc_fixup_inv_dmic_0x12, | ||
6762 | }, | ||
6602 | }; | 6763 | }; |
6603 | 6764 | ||
6604 | static const struct snd_pci_quirk alc662_fixup_tbl[] = { | 6765 | static const struct snd_pci_quirk alc662_fixup_tbl[] = { |
6605 | SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_FIXUP_ASUS_MODE2), | 6766 | SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_FIXUP_ASUS_MODE2), |
6606 | SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE), | 6767 | SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE), |
6607 | SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE), | 6768 | SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE), |
6769 | SND_PCI_QUIRK(0x1025, 0x0349, "eMachines eM250", ALC662_FIXUP_INV_DMIC), | ||
6608 | SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE), | 6770 | SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE), |
6609 | SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800), | 6771 | SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800), |
6610 | SND_PCI_QUIRK(0x1043, 0x8469, "ASUS mobo", ALC662_FIXUP_NO_JACK_DETECT), | 6772 | SND_PCI_QUIRK(0x1043, 0x8469, "ASUS mobo", ALC662_FIXUP_NO_JACK_DETECT), |
@@ -6685,6 +6847,7 @@ static const struct alc_model_fixup alc662_fixup_models[] = { | |||
6685 | {.id = ALC662_FIXUP_ASUS_MODE6, .name = "asus-mode6"}, | 6847 | {.id = ALC662_FIXUP_ASUS_MODE6, .name = "asus-mode6"}, |
6686 | {.id = ALC662_FIXUP_ASUS_MODE7, .name = "asus-mode7"}, | 6848 | {.id = ALC662_FIXUP_ASUS_MODE7, .name = "asus-mode7"}, |
6687 | {.id = ALC662_FIXUP_ASUS_MODE8, .name = "asus-mode8"}, | 6849 | {.id = ALC662_FIXUP_ASUS_MODE8, .name = "asus-mode8"}, |
6850 | {.id = ALC662_FIXUP_INV_DMIC, .name = "inv-dmic"}, | ||
6688 | {} | 6851 | {} |
6689 | }; | 6852 | }; |
6690 | 6853 | ||