hdaudio: enable MSI support
* disabled for nVidia and Creative Technology devices.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <KernelExport.h>
|
||||
#include <Drivers.h>
|
||||
#include <PCI.h>
|
||||
#include <PCI_x86.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -12,8 +12,6 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <PCI_x86.h>
|
||||
|
||||
#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
|
||||
|
||||
Reference in New Issue
Block a user