hda: wait between set and unset of the GLOBAL_CONTROL_RESET bit.

* the spec requires 521us, 1000us is generally used.
* also only uninit streams, corb and rirb when a codec reset is in progress (seen in zircon).
linux instead clears HDAC_STATE_STATUS.
This commit is contained in:
Jérôme Duval 2019-03-09 15:57:35 +01:00
parent 3131c13005
commit 10baa577a9

View File

@ -356,6 +356,10 @@ hda_interrupt_handler(hda_controller* controller)
static status_t
reset_controller(hda_controller* controller)
{
uint32 control = controller->Read32(HDAC_GLOBAL_CONTROL);
if ((control & GLOBAL_CONTROL_RESET) != 0) {
controller->Write32(HDAC_INTR_CONTROL, 0);
// stop streams
for (uint32 i = 0; i < controller->num_input_streams; i++) {
@ -400,9 +404,10 @@ reset_controller(hda_controller* controller)
controller->Write32(HDAC_DMA_POSITION_BASE_LOWER, 0);
controller->Write32(HDAC_DMA_POSITION_BASE_UPPER, 0);
// Set reset bit - it must be asserted for at least 100us
control = controller->Read32(HDAC_GLOBAL_CONTROL);
}
uint32 control = controller->Read32(HDAC_GLOBAL_CONTROL);
// Set reset bit - it must be asserted for at least 100us
controller->Write32(HDAC_GLOBAL_CONTROL, control & ~GLOBAL_CONTROL_RESET);
for (int timeout = 0; timeout < 10; timeout++) {
@ -417,6 +422,9 @@ reset_controller(hda_controller* controller)
return B_BUSY;
}
// Wait for codec PLL to lock at least 100us, section 5.5.1.2
snooze(1000);
// Unset reset bit
control = controller->Read32(HDAC_GLOBAL_CONTROL);