aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2006-10-23 07:40:59 -0400
committerJaroslav Kysela <perex@suse.cz>2006-10-23 08:10:34 -0400
commit68e7fffc0f3e95063ba5bd94ee6f9b8927247297 (patch)
tree4b29ce42e3884db52e56e4e4cd7ca162954cb328 /sound/pci
parenta5c81b648476f5b0594daeefb38bb98409da5340 (diff)
[ALSA] hda-intel - Add check of MSI availabity
Check the availability of MSI and turn off MSI automatically when it's not available on the hardware. MSI seems broken on some hardwares but the kernel doesn't know exactly, thus we have to turn the MSI feature off on the sound driver manually. Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@suse.cz>
Diffstat (limited to 'sound/pci')
-rw-r--r--sound/pci/hda/hda_intel.c56
1 files changed, 39 insertions, 17 deletions
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index c1771929466b..0e292dc4fd87 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -337,6 +337,7 @@ struct azx {
337 unsigned int initialized :1; 337 unsigned int initialized :1;
338 unsigned int single_cmd :1; 338 unsigned int single_cmd :1;
339 unsigned int polling_mode :1; 339 unsigned int polling_mode :1;
340 unsigned int msi :1;
340}; 341};
341 342
342/* driver types */ 343/* driver types */
@@ -397,6 +398,7 @@ static char *driver_short_names[] __devinitdata = {
397 */ 398 */
398#define upper_32bit(addr) (sizeof(addr) > 4 ? (u32)((addr) >> 32) : (u32)0) 399#define upper_32bit(addr) (sizeof(addr) > 4 ? (u32)((addr) >> 32) : (u32)0)
399 400
401static int azx_acquire_irq(struct azx *chip, int do_disconnect);
400 402
401/* 403/*
402 * Interface for HD codec 404 * Interface for HD codec
@@ -536,6 +538,18 @@ static unsigned int azx_rirb_get_response(struct hda_codec *codec)
536 schedule_timeout_interruptible(1); 538 schedule_timeout_interruptible(1);
537 } while (time_after_eq(timeout, jiffies)); 539 } while (time_after_eq(timeout, jiffies));
538 540
541 if (chip->msi) {
542 snd_printk(KERN_WARNING "hda_intel: No response from codec, "
543 "disabling MSI...\n");
544 free_irq(chip->irq, chip);
545 chip->irq = -1;
546 pci_disable_msi(chip->pci);
547 chip->msi = 0;
548 if (azx_acquire_irq(chip, 1) < 0)
549 return -1;
550 goto again;
551 }
552
539 if (!chip->polling_mode) { 553 if (!chip->polling_mode) {
540 snd_printk(KERN_WARNING "hda_intel: azx_get_response timeout, " 554 snd_printk(KERN_WARNING "hda_intel: azx_get_response timeout, "
541 "switching to polling mode...\n"); 555 "switching to polling mode...\n");
@@ -1364,6 +1378,20 @@ static int __devinit azx_init_stream(struct azx *chip)
1364 return 0; 1378 return 0;
1365} 1379}
1366 1380
1381static int azx_acquire_irq(struct azx *chip, int do_disconnect)
1382{
1383 if (request_irq(chip->pci->irq, azx_interrupt, IRQF_DISABLED|IRQF_SHARED,
1384 "HDA Intel", chip)) {
1385 printk(KERN_ERR "hda-intel: unable to grab IRQ %d, "
1386 "disabling device\n", chip->pci->irq);
1387 if (do_disconnect)
1388 snd_card_disconnect(chip->card);
1389 return -1;
1390 }
1391 chip->irq = chip->pci->irq;
1392 return 0;
1393}
1394
1367 1395
1368#ifdef CONFIG_PM 1396#ifdef CONFIG_PM
1369/* 1397/*
@@ -1385,7 +1413,7 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state)
1385 free_irq(chip->irq, chip); 1413 free_irq(chip->irq, chip);
1386 chip->irq = -1; 1414 chip->irq = -1;
1387 } 1415 }
1388 if (!disable_msi) 1416 if (chip->msi)
1389 pci_disable_msi(chip->pci); 1417 pci_disable_msi(chip->pci);
1390 pci_disable_device(pci); 1418 pci_disable_device(pci);
1391 pci_save_state(pci); 1419 pci_save_state(pci);
@@ -1407,16 +1435,11 @@ static int azx_resume(struct pci_dev *pci)
1407 return -EIO; 1435 return -EIO;
1408 } 1436 }
1409 pci_set_master(pci); 1437 pci_set_master(pci);
1410 if (!disable_msi) 1438 if (chip->msi)
1411 pci_enable_msi(pci); 1439 if (pci_enable_msi(pci) < 0)
1412 if (request_irq(pci->irq, azx_interrupt, IRQF_DISABLED|IRQF_SHARED, 1440 chip->msi = 0;
1413 "HDA Intel", chip)) { 1441 if (azx_acquire_irq(chip, 1) < 0)
1414 printk(KERN_ERR "hda-intel: unable to grab IRQ %d, "
1415 "disabling device\n", pci->irq);
1416 snd_card_disconnect(card);
1417 return -EIO; 1442 return -EIO;
1418 }
1419 chip->irq = pci->irq;
1420 azx_init_chip(chip); 1443 azx_init_chip(chip);
1421 snd_hda_resume(chip->bus); 1444 snd_hda_resume(chip->bus);
1422 snd_power_change_state(card, SNDRV_CTL_POWER_D0); 1445 snd_power_change_state(card, SNDRV_CTL_POWER_D0);
@@ -1452,7 +1475,7 @@ static int azx_free(struct azx *chip)
1452 synchronize_irq(chip->irq); 1475 synchronize_irq(chip->irq);
1453 free_irq(chip->irq, (void*)chip); 1476 free_irq(chip->irq, (void*)chip);
1454 } 1477 }
1455 if (!disable_msi) 1478 if (chip->msi)
1456 pci_disable_msi(chip->pci); 1479 pci_disable_msi(chip->pci);
1457 if (chip->remap_addr) 1480 if (chip->remap_addr)
1458 iounmap(chip->remap_addr); 1481 iounmap(chip->remap_addr);
@@ -1508,6 +1531,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
1508 chip->pci = pci; 1531 chip->pci = pci;
1509 chip->irq = -1; 1532 chip->irq = -1;
1510 chip->driver_type = driver_type; 1533 chip->driver_type = driver_type;
1534 chip->msi = !disable_msi;
1511 1535
1512 chip->position_fix = position_fix; 1536 chip->position_fix = position_fix;
1513 chip->single_cmd = single_cmd; 1537 chip->single_cmd = single_cmd;
@@ -1537,16 +1561,14 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
1537 goto errout; 1561 goto errout;
1538 } 1562 }
1539 1563
1540 if (!disable_msi) 1564 if (chip->msi)
1541 pci_enable_msi(pci); 1565 if (pci_enable_msi(pci) < 0)
1566 chip->msi = 0;
1542 1567
1543 if (request_irq(pci->irq, azx_interrupt, IRQF_DISABLED|IRQF_SHARED, 1568 if (azx_acquire_irq(chip, 0) < 0) {
1544 "HDA Intel", (void*)chip)) {
1545 snd_printk(KERN_ERR SFX "unable to grab IRQ %d\n", pci->irq);
1546 err = -EBUSY; 1569 err = -EBUSY;
1547 goto errout; 1570 goto errout;
1548 } 1571 }
1549 chip->irq = pci->irq;
1550 1572
1551 pci_set_master(pci); 1573 pci_set_master(pci);
1552 synchronize_irq(chip->irq); 1574 synchronize_irq(chip->irq);