From 51b735b342238e43cac59bb01f1654f57d6681fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Sun, 1 Sep 2013 21:09:47 +0200 Subject: [PATCH] hdaudio: enable MSI support * disabled for nVidia and Creative Technology devices. --- .../kernel/drivers/audio/hda/driver.cpp | 11 ++++- src/add-ons/kernel/drivers/audio/hda/driver.h | 2 + .../drivers/audio/hda/hda_controller.cpp | 46 +++++++------------ 3 files changed, 28 insertions(+), 31 deletions(-) diff --git a/src/add-ons/kernel/drivers/audio/hda/driver.cpp b/src/add-ons/kernel/drivers/audio/hda/driver.cpp index e0d05f8e52..504a704281 100644 --- a/src/add-ons/kernel/drivers/audio/hda/driver.cpp +++ b/src/add-ons/kernel/drivers/audio/hda/driver.cpp @@ -15,6 +15,7 @@ int32 api_version = B_CUR_DRIVER_API_VERSION; hda_controller gCards[MAX_CARDS]; uint32 gNumCards; pci_module_info* gPci; +pci_x86_module_info* gPCIx86Module; extern "C" status_t @@ -82,6 +83,10 @@ init_driver(void) return ENODEV; } + if (get_module(B_PCI_X86_MODULE_NAME, (module_info**)&gPCIx86Module) + != B_OK) + gPCIx86Module = NULL; + return B_OK; } @@ -99,8 +104,12 @@ uninit_driver(void) free((void*)gCards[i].devfs_path); gCards[i].devfs_path = NULL; } - + put_module(B_PCI_MODULE_NAME); + if (gPCIx86Module != NULL) { + put_module(B_PCI_X86_MODULE_NAME); + gPCIx86Module = NULL; + } } diff --git a/src/add-ons/kernel/drivers/audio/hda/driver.h b/src/add-ons/kernel/drivers/audio/hda/driver.h index 615290379a..fc848b2cb1 100644 --- a/src/add-ons/kernel/drivers/audio/hda/driver.h +++ b/src/add-ons/kernel/drivers/audio/hda/driver.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -334,6 +335,7 @@ struct hda_multi { /* driver.c */ extern device_hooks gDriverHooks; extern pci_module_info* gPci; +extern pci_x86_module_info* gPCIx86Module; extern hda_controller gCards[MAX_CARDS]; extern uint32 gNumCards; diff --git a/src/add-ons/kernel/drivers/audio/hda/hda_controller.cpp b/src/add-ons/kernel/drivers/audio/hda/hda_controller.cpp index cdebc554dc..5d90e3b894 100644 --- a/src/add-ons/kernel/drivers/audio/hda/hda_controller.cpp +++ b/src/add-ons/kernel/drivers/audio/hda/hda_controller.cpp @@ -12,8 +12,6 @@ #include -#include - #include "driver.h" #include "hda_codec_defs.h" @@ -36,10 +34,12 @@ #define PCI_VENDOR_AMD 0x1002 +#define PCI_VENDOR_CREATIVE 0x1102 #define PCI_VENDOR_INTEL 0x8086 #define PCI_VENDOR_NVIDIA 0x10de #define PCI_ALL_DEVICES 0xffffffff #define HDA_QUIRK_SNOOP 0x0001 +#define HDA_QUIRK_NO_MSI 0x0002 static const struct { @@ -58,7 +58,9 @@ static const struct { // Enable snooping for ATI and Nvidia, right now for all their hda-devices, // but only based on guessing. { PCI_VENDOR_AMD, PCI_ALL_DEVICES, HDA_QUIRK_SNOOP }, - { PCI_VENDOR_NVIDIA, PCI_ALL_DEVICES, HDA_QUIRK_SNOOP }, + { PCI_VENDOR_NVIDIA, PCI_ALL_DEVICES, HDA_QUIRK_SNOOP | HDA_QUIRK_NO_MSI }, + { PCI_VENDOR_CREATIVE, 0x0010, HDA_QUIRK_NO_MSI }, + { PCI_VENDOR_CREATIVE, 0x0012, HDA_QUIRK_NO_MSI } }; @@ -83,9 +85,6 @@ static const struct { }; -static pci_x86_module_info* sPCIx86Module; - - static uint32 get_controller_quirks(pci_info& info) { @@ -853,7 +852,7 @@ hda_hw_init(hda_controller* controller) uint16 stateStatus; uint16 cmd; status_t status; - uint32 quirks; + uint32 quirks = get_controller_quirks(controller->pci_info); // Map MMIO registers controller->regs_area = map_physical_memory("hda_hw_regs", @@ -884,27 +883,21 @@ hda_hw_init(hda_controller* controller) controller->pci_info.device, controller->pci_info.function, PCI_command, 2, cmd); - if (get_module(B_PCI_X86_MODULE_NAME, (module_info**)&sPCIx86Module) - != B_OK) - sPCIx86Module = NULL; - // Absolute minimum hw is online; we can now install interrupt handler controller->irq = controller->pci_info.u.h0.interrupt_line; controller->msi = false; - // TODO: temporarily disabled, as at least on my hardware audio becomes - // flaky after this. -/* - if (sPCIx86Module != NULL && sPCIx86Module->get_msi_count( - controller->pci_info.bus, controller->pci_info.device, - controller->pci_info.function) >= 1) { + if (gPCIx86Module != NULL && (quirks & HDA_QUIRK_NO_MSI) == 0 + && gPCIx86Module->get_msi_count( + controller->pci_info.bus, controller->pci_info.device, + controller->pci_info.function) >= 1) { // Try MSI first uint8 vector; - if (sPCIx86Module->configure_msi(controller->pci_info.bus, + if (gPCIx86Module->configure_msi(controller->pci_info.bus, controller->pci_info.device, controller->pci_info.function, 1, &vector) == B_OK - && sPCIx86Module->enable_msi(controller->pci_info.bus, + && gPCIx86Module->enable_msi(controller->pci_info.bus, controller->pci_info.device, controller->pci_info.function) == B_OK) { dprintf("hda: using MSI vector %u\n", vector); @@ -912,7 +905,6 @@ hda_hw_init(hda_controller* controller) controller->msi = true; } } -*/ status = install_io_interrupt_handler(controller->irq, (interrupt_handler)hda_interrupt_handler, controller, 0); @@ -922,7 +914,6 @@ hda_hw_init(hda_controller* controller) // TCSEL is reset to TC0 (clear 0-2 bits) update_pci_register(controller, PCI_HDA_TCSEL, PCI_HDA_TCSEL_MASK, 0, 1); - quirks = get_controller_quirks(controller->pci_info); if ((quirks & HDA_QUIRK_SNOOP) != 0) { switch (controller->pci_info.vendor_id) { case PCI_VENDOR_NVIDIA: @@ -1025,7 +1016,7 @@ corb_rirb_failed: reset_failed: if (controller->msi) { - sPCIx86Module->disable_msi(controller->pci_info.bus, + gPCIx86Module->disable_msi(controller->pci_info.bus, controller->pci_info.device, controller->pci_info.function); } @@ -1037,11 +1028,6 @@ no_irq: controller->regs_area = B_ERROR; controller->regs = NULL; - if (sPCIx86Module != NULL) { - put_module(B_PCI_X86_MODULE_NAME); - sPCIx86Module = NULL; - } - error: dprintf("hda: ERROR: %s(%ld)\n", strerror(status), status); @@ -1083,16 +1069,16 @@ hda_hw_uninit(hda_controller* controller) if (controller->msi) { // Disable MSI - sPCIx86Module->disable_msi(controller->pci_info.bus, + gPCIx86Module->disable_msi(controller->pci_info.bus, controller->pci_info.device, controller->pci_info.function); } remove_io_interrupt_handler(controller->irq, (interrupt_handler)hda_interrupt_handler, controller); - if (sPCIx86Module != NULL) { + if (gPCIx86Module != NULL) { put_module(B_PCI_X86_MODULE_NAME); - sPCIx86Module = NULL; + gPCIx86Module = NULL; } // Delete corb/rirb area