diff options
author | Takashi Iwai <tiwai@suse.de> | 2006-02-16 12:17:58 -0500 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2006-03-22 04:29:53 -0500 |
commit | 111d3af5f5fbf0e28570f1c01e83444d73c68a25 (patch) | |
tree | 4679b8c2336c475016cd19c81263df0347741684 /sound/pci/hda/hda_intel.c | |
parent | 353b9e667042d6faa15a41df022bf38c949a7b2f (diff) |
[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>
Diffstat (limited to 'sound/pci/hda/hda_intel.c')
-rw-r--r-- | sound/pci/hda/hda_intel.c | 60 |
1 files changed, 43 insertions, 17 deletions
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index dbed2644a192..016fbc263e55 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -446,8 +446,8 @@ static void azx_free_cmd_io(struct azx *chip) | |||
446 | } | 446 | } |
447 | 447 | ||
448 | /* send a command */ | 448 | /* send a command */ |
449 | static int azx_send_cmd(struct hda_codec *codec, hda_nid_t nid, int direct, | 449 | static int azx_corb_send_cmd(struct hda_codec *codec, hda_nid_t nid, int direct, |
450 | unsigned int verb, unsigned int para) | 450 | unsigned int verb, unsigned int para) |
451 | { | 451 | { |
452 | struct azx *chip = codec->bus->private_data; | 452 | struct azx *chip = codec->bus->private_data; |
453 | unsigned int wp; | 453 | unsigned int wp; |
@@ -503,18 +503,21 @@ static void azx_update_rirb(struct azx *chip) | |||
503 | } | 503 | } |
504 | 504 | ||
505 | /* receive a response */ | 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 | struct azx *chip = codec->bus->private_data; | 508 | struct azx *chip = codec->bus->private_data; |
509 | int timeout = 50; | 509 | int timeout = 50; |
510 | 510 | ||
511 | while (chip->rirb.cmds) { | 511 | while (chip->rirb.cmds) { |
512 | if (! --timeout) { | 512 | if (! --timeout) { |
513 | if (printk_ratelimit()) | 513 | snd_printk(KERN_ERR |
514 | snd_printk(KERN_ERR | 514 | "hda_intel: azx_get_response timeout, " |
515 | "azx_get_response timeout\n"); | 515 | "switching to single_cmd mode...\n"); |
516 | chip->rirb.rp = azx_readb(chip, RIRBWP); | 516 | chip->rirb.rp = azx_readb(chip, RIRBWP); |
517 | chip->rirb.cmds = 0; | 517 | chip->rirb.cmds = 0; |
518 | /* switch to single_cmd mode */ | ||
519 | chip->single_cmd = 1; | ||
520 | azx_free_cmd_io(chip); | ||
518 | return -1; | 521 | return -1; |
519 | } | 522 | } |
520 | msleep(1); | 523 | msleep(1); |
@@ -578,6 +581,36 @@ static unsigned int azx_single_get_response(struct hda_codec *codec) | |||
578 | return (unsigned int)-1; | 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 | /* reset codec link */ | 614 | /* reset codec link */ |
582 | static int azx_reset(struct azx *chip) | 615 | static int azx_reset(struct azx *chip) |
583 | { | 616 | { |
@@ -900,13 +933,8 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model) | |||
900 | bus_temp.private_data = chip; | 933 | bus_temp.private_data = chip; |
901 | bus_temp.modelname = model; | 934 | bus_temp.modelname = model; |
902 | bus_temp.pci = chip->pci; | 935 | bus_temp.pci = chip->pci; |
903 | if (chip->single_cmd) { | 936 | bus_temp.ops.command = azx_send_cmd; |
904 | bus_temp.ops.command = azx_single_send_cmd; | 937 | bus_temp.ops.get_response = azx_get_response; |
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 | } | ||
910 | 938 | ||
911 | if ((err = snd_hda_bus_new(chip->card, &bus_temp, &chip->bus)) < 0) | 939 | if ((err = snd_hda_bus_new(chip->card, &bus_temp, &chip->bus)) < 0) |
912 | return err; | 940 | return err; |
@@ -1308,8 +1336,7 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state) | |||
1308 | for (i = 0; i < chip->pcm_devs; i++) | 1336 | for (i = 0; i < chip->pcm_devs; i++) |
1309 | snd_pcm_suspend_all(chip->pcm[i]); | 1337 | snd_pcm_suspend_all(chip->pcm[i]); |
1310 | snd_hda_suspend(chip->bus, state); | 1338 | snd_hda_suspend(chip->bus, state); |
1311 | if (! chip->single_cmd) | 1339 | azx_free_cmd_io(chip); |
1312 | azx_free_cmd_io(chip); | ||
1313 | pci_disable_device(pci); | 1340 | pci_disable_device(pci); |
1314 | pci_save_state(pci); | 1341 | pci_save_state(pci); |
1315 | return 0; | 1342 | return 0; |
@@ -1347,8 +1374,7 @@ static int azx_free(struct azx *chip) | |||
1347 | azx_int_clear(chip); | 1374 | azx_int_clear(chip); |
1348 | 1375 | ||
1349 | /* disable CORB/RIRB */ | 1376 | /* disable CORB/RIRB */ |
1350 | if (! chip->single_cmd) | 1377 | azx_free_cmd_io(chip); |
1351 | azx_free_cmd_io(chip); | ||
1352 | 1378 | ||
1353 | /* disable position buffer */ | 1379 | /* disable position buffer */ |
1354 | azx_writel(chip, DPLBASE, 0); | 1380 | azx_writel(chip, DPLBASE, 0); |