Commit 111d3af5f5fbf0e28570f1c01e83444d73c68a25
Committed by
Jaroslav Kysela
1 parent
353b9e6670
Exists in
master
and in
20 other branches
[ALSA] hda-intel - Automatic correction to single_cmd mode
Modules: HDA Codec driver,HDA Intel driver Switch to single_cmd mode automatically as a fallback when CORB/RIRB communication doesn't work well. It may make the driver working on some devices with broken BIOS/ACPI support. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Showing 2 changed files with 49 additions and 17 deletions Side-by-side Diff
sound/pci/hda/hda_codec.c
... | ... | @@ -531,6 +531,12 @@ |
531 | 531 | bus->caddr_tbl[codec_addr] = codec; |
532 | 532 | |
533 | 533 | codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT, AC_PAR_VENDOR_ID); |
534 | + if (codec->vendor_id == -1) | |
535 | + /* read again, hopefully the access method was corrected | |
536 | + * in the last read... | |
537 | + */ | |
538 | + codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT, | |
539 | + AC_PAR_VENDOR_ID); | |
534 | 540 | codec->subsystem_id = snd_hda_param_read(codec, AC_NODE_ROOT, AC_PAR_SUBSYSTEM_ID); |
535 | 541 | codec->revision_id = snd_hda_param_read(codec, AC_NODE_ROOT, AC_PAR_REV_ID); |
536 | 542 |
sound/pci/hda/hda_intel.c
... | ... | @@ -446,8 +446,8 @@ |
446 | 446 | } |
447 | 447 | |
448 | 448 | /* send a command */ |
449 | -static int azx_send_cmd(struct hda_codec *codec, hda_nid_t nid, int direct, | |
450 | - unsigned int verb, unsigned int para) | |
449 | +static int azx_corb_send_cmd(struct hda_codec *codec, hda_nid_t nid, int direct, | |
450 | + unsigned int verb, unsigned int para) | |
451 | 451 | { |
452 | 452 | struct azx *chip = codec->bus->private_data; |
453 | 453 | unsigned int wp; |
454 | 454 | |
455 | 455 | |
... | ... | @@ -503,18 +503,21 @@ |
503 | 503 | } |
504 | 504 | |
505 | 505 | /* receive a response */ |
506 | -static unsigned int azx_get_response(struct hda_codec *codec) | |
506 | +static unsigned int azx_rirb_get_response(struct hda_codec *codec) | |
507 | 507 | { |
508 | 508 | struct azx *chip = codec->bus->private_data; |
509 | 509 | int timeout = 50; |
510 | 510 | |
511 | 511 | while (chip->rirb.cmds) { |
512 | 512 | if (! --timeout) { |
513 | - if (printk_ratelimit()) | |
514 | - snd_printk(KERN_ERR | |
515 | - "azx_get_response timeout\n"); | |
513 | + snd_printk(KERN_ERR | |
514 | + "hda_intel: azx_get_response timeout, " | |
515 | + "switching to single_cmd mode...\n"); | |
516 | 516 | chip->rirb.rp = azx_readb(chip, RIRBWP); |
517 | 517 | chip->rirb.cmds = 0; |
518 | + /* switch to single_cmd mode */ | |
519 | + chip->single_cmd = 1; | |
520 | + azx_free_cmd_io(chip); | |
518 | 521 | return -1; |
519 | 522 | } |
520 | 523 | msleep(1); |
... | ... | @@ -578,6 +581,36 @@ |
578 | 581 | return (unsigned int)-1; |
579 | 582 | } |
580 | 583 | |
584 | +/* | |
585 | + * The below are the main callbacks from hda_codec. | |
586 | + * | |
587 | + * They are just the skeleton to call sub-callbacks according to the | |
588 | + * current setting of chip->single_cmd. | |
589 | + */ | |
590 | + | |
591 | +/* send a command */ | |
592 | +static int azx_send_cmd(struct hda_codec *codec, hda_nid_t nid, | |
593 | + int direct, unsigned int verb, | |
594 | + unsigned int para) | |
595 | +{ | |
596 | + struct azx *chip = codec->bus->private_data; | |
597 | + if (chip->single_cmd) | |
598 | + return azx_single_send_cmd(codec, nid, direct, verb, para); | |
599 | + else | |
600 | + return azx_corb_send_cmd(codec, nid, direct, verb, para); | |
601 | +} | |
602 | + | |
603 | +/* get a response */ | |
604 | +static unsigned int azx_get_response(struct hda_codec *codec) | |
605 | +{ | |
606 | + struct azx *chip = codec->bus->private_data; | |
607 | + if (chip->single_cmd) | |
608 | + return azx_single_get_response(codec); | |
609 | + else | |
610 | + return azx_rirb_get_response(codec); | |
611 | +} | |
612 | + | |
613 | + | |
581 | 614 | /* reset codec link */ |
582 | 615 | static int azx_reset(struct azx *chip) |
583 | 616 | { |
... | ... | @@ -900,13 +933,8 @@ |
900 | 933 | bus_temp.private_data = chip; |
901 | 934 | bus_temp.modelname = model; |
902 | 935 | bus_temp.pci = chip->pci; |
903 | - if (chip->single_cmd) { | |
904 | - bus_temp.ops.command = azx_single_send_cmd; | |
905 | - bus_temp.ops.get_response = azx_single_get_response; | |
906 | - } else { | |
907 | - bus_temp.ops.command = azx_send_cmd; | |
908 | - bus_temp.ops.get_response = azx_get_response; | |
909 | - } | |
936 | + bus_temp.ops.command = azx_send_cmd; | |
937 | + bus_temp.ops.get_response = azx_get_response; | |
910 | 938 | |
911 | 939 | if ((err = snd_hda_bus_new(chip->card, &bus_temp, &chip->bus)) < 0) |
912 | 940 | return err; |
... | ... | @@ -1308,8 +1336,7 @@ |
1308 | 1336 | for (i = 0; i < chip->pcm_devs; i++) |
1309 | 1337 | snd_pcm_suspend_all(chip->pcm[i]); |
1310 | 1338 | snd_hda_suspend(chip->bus, state); |
1311 | - if (! chip->single_cmd) | |
1312 | - azx_free_cmd_io(chip); | |
1339 | + azx_free_cmd_io(chip); | |
1313 | 1340 | pci_disable_device(pci); |
1314 | 1341 | pci_save_state(pci); |
1315 | 1342 | return 0; |
... | ... | @@ -1347,8 +1374,7 @@ |
1347 | 1374 | azx_int_clear(chip); |
1348 | 1375 | |
1349 | 1376 | /* disable CORB/RIRB */ |
1350 | - if (! chip->single_cmd) | |
1351 | - azx_free_cmd_io(chip); | |
1377 | + azx_free_cmd_io(chip); | |
1352 | 1378 | |
1353 | 1379 | /* disable position buffer */ |
1354 | 1380 | azx_writel(chip, DPLBASE, 0); |