mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-27 12:48:22 +00:00
hda: fixes
This commit is contained in:
+54
-11
@@ -16,6 +16,10 @@
|
||||
|
||||
#define HDA_BDL_FLAGS_IOC 1
|
||||
|
||||
#define INTEL_HDA_TCSEL 0x44
|
||||
#define INTEL_HDA_DEVC 0x78
|
||||
#define INTEL_HDA_DEVC_NOSNOOP (1 << 11)
|
||||
|
||||
typedef struct {
|
||||
uint64_t address;
|
||||
uint32_t length;
|
||||
@@ -59,6 +63,9 @@ typedef struct {
|
||||
#define SIZE_16 1
|
||||
#define SIZE_2 0
|
||||
|
||||
#define CORBRP_RST (1 << 15)
|
||||
#define CORBCTL_DMA_ENABLE (1 << 1)
|
||||
|
||||
typedef struct {
|
||||
uint16_t gcap;
|
||||
uint8_t vmin;
|
||||
@@ -198,6 +205,11 @@ typedef struct {
|
||||
hda_stream_t **streams;
|
||||
} hda_t;
|
||||
|
||||
static uint32_t hda_stream_mask(hda_t *hda) {
|
||||
size_t count = hda->input_stream_count + hda->output_stream_count + hda->bi_stream_count;
|
||||
return count >= 30 ? 0x3fffffff : ((1u << count) - 1);
|
||||
}
|
||||
|
||||
static bool hda_sd_set_reset(volatile hda_sd_t *sd, bool set) {
|
||||
if (set)
|
||||
sd->ctl[0] |= HDA_SD_CTL_BYTE0_RESET;
|
||||
@@ -500,7 +512,7 @@ static void hda_stream_fill_data(hda_stream_t *stream) {
|
||||
}
|
||||
|
||||
static void stream_irq(hda_t *hda) {
|
||||
uint32_t status = hda->regs->intsts & 0x3f;
|
||||
uint32_t status = hda->regs->intsts & hda_stream_mask(hda);
|
||||
|
||||
for (int i = 0; i < 30; ++i) {
|
||||
if ((status & (1 << i)) == 0)
|
||||
@@ -548,7 +560,7 @@ static void hda_isr(isr_t *isr, context_t *) {
|
||||
if (hda->regs->rirbsts)
|
||||
rirb_irq(hda);
|
||||
|
||||
if (hda->regs->intsts & 0x3f)
|
||||
if (hda->regs->intsts & hda_stream_mask(hda))
|
||||
stream_irq(hda);
|
||||
}
|
||||
|
||||
@@ -776,6 +788,27 @@ static void get_sizes(uint8_t reg, uint8_t *size_reg, size_t *size_count) {
|
||||
}
|
||||
}
|
||||
|
||||
static bool corb_reset_read_pointer(volatile hda_regs_t *regs, size_t timeoutms) {
|
||||
regs->corbrp = CORBRP_RST;
|
||||
|
||||
int loops = 0;
|
||||
while ((regs->corbrp & CORBRP_RST) == 0) {
|
||||
if (loops++ >= timeoutms * 10)
|
||||
return false;
|
||||
sched_sleep_us(100);
|
||||
}
|
||||
|
||||
regs->corbrp = 0;
|
||||
loops = 0;
|
||||
while (regs->corbrp & CORBRP_RST) {
|
||||
if (loops++ >= timeoutms * 10)
|
||||
return false;
|
||||
sched_sleep_us(100);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void init_function_group(hda_t *hda, int codec, hda_fg_t *function_group) {
|
||||
function_group->type = hda_get_parameter(hda, codec, function_group->nid, HDA_PARAM_FUNCTION_GROUP_TYPE) & 0xff;
|
||||
if (function_group->type != HDA_FUNCTION_GROUP_TYPE_AFG)
|
||||
@@ -875,6 +908,9 @@ static void initcontroller(pcienum_t *e) {
|
||||
pci_setcommand(e, PCI_COMMAND_IRQDISABLE, 1);
|
||||
pci_setcommand(e, PCI_COMMAND_BUSMASTER, 1);
|
||||
|
||||
PCI_WRITE8(e, INTEL_HDA_TCSEL, PCI_READ8(e, INTEL_HDA_TCSEL) & ~0x7);
|
||||
PCI_WRITE16(e, INTEL_HDA_DEVC, PCI_READ16(e, INTEL_HDA_DEVC) & ~INTEL_HDA_DEVC_NOSNOOP);
|
||||
|
||||
// enable interrupts
|
||||
if (e->msix.exists) {
|
||||
pci_initmsix(e);
|
||||
@@ -923,9 +959,12 @@ static void initcontroller(pcienum_t *e) {
|
||||
regs->corblbase = (uint64_t)corb_phys & 0xffffffff;
|
||||
regs->corbhbase = ((uint64_t)corb_phys >> 32) & 0xffffffff;
|
||||
regs->corbsize = (regs->corbsize & 0xfc) | corbsize;
|
||||
regs->corbrp = 0x8000 | (regs->corbrp & 0x7fff);
|
||||
regs->corbwp = regs->corbwp & 0xff00;
|
||||
regs->corbctl = (regs->corbctl & 0xfc) | 2;
|
||||
if (!corb_reset_read_pointer(regs, 1)) {
|
||||
printf("hda: resetting CORB read pointer timed out\n");
|
||||
return;
|
||||
}
|
||||
regs->corbwp = 0;
|
||||
regs->corbctl = (regs->corbctl & ~CORBCTL_DMA_ENABLE) | CORBCTL_DMA_ENABLE;
|
||||
|
||||
uint8_t rirbsize;
|
||||
size_t rirb_entries;
|
||||
@@ -990,12 +1029,16 @@ static void initcontroller(pcienum_t *e) {
|
||||
}
|
||||
|
||||
void hda_init() {
|
||||
int i = 0;
|
||||
for (;;) {
|
||||
pcienum_t *e = pci_getenum(-1, -1, -1, 0x8086, 0x2668, -1, i++);
|
||||
if (e == NULL)
|
||||
break;
|
||||
initcontroller(e);
|
||||
static const int device_ids[] = {0x2668, 0x8c20};
|
||||
|
||||
for (size_t device = 0; device < sizeof(device_ids) / sizeof(device_ids[0]); ++device) {
|
||||
int i = 0;
|
||||
for (;;) {
|
||||
pcienum_t *e = pci_getenum(-1, -1, -1, 0x8086, device_ids[device], -1, i++);
|
||||
if (e == NULL)
|
||||
break;
|
||||
initcontroller(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user