mirror of
https://github.com/acidanthera/OpenCorePkg.git
synced 2025-12-08 19:25:01 +00:00
AudioDxe: Fallback to LPIB register when DMA positions buffer is unusable
This commit is contained in:
parent
97ff599250
commit
b0087a6b9a
@ -63,10 +63,51 @@ HdaControllerStreamOutputPollTimerHandler (
|
||||
return;
|
||||
}
|
||||
|
||||
if (HdaStream->UseLpib) {
|
||||
//
|
||||
// Get stream position through LPIB register.
|
||||
//
|
||||
Status = PciIo->Mem.Read (PciIo, EfiPciIoWidthFifoUint32, PCI_HDA_BAR, HDA_REG_SDNLPIB (HdaStream->Index), 1, &HdaStreamDmaPos);
|
||||
if (EFI_ERROR (Status)) {
|
||||
HdaControllerStreamAbort (HdaStream);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// Get stream position through DMA positions buffer.
|
||||
//
|
||||
HdaStreamDmaPos = HdaStream->HdaDev->DmaPositions[HdaStream->Index].Position;
|
||||
|
||||
//
|
||||
// If zero, give the stream a few cycles to catch up before falling back to LPIB.
|
||||
// Fallback occurs after the set amount of cycles the DMA position is zero.
|
||||
//
|
||||
if (HdaStreamDmaPos == 0 && !HdaStream->DmaCheckComplete) {
|
||||
if (HdaStream->DmaCheckCount >= HDA_STREAM_DMA_CHECK_THRESH) {
|
||||
HdaStream->UseLpib = TRUE;
|
||||
}
|
||||
|
||||
//
|
||||
// Get stream position through LPIB register in the meantime.
|
||||
//
|
||||
DEBUG ((DEBUG_VERBOSE, "AudioDxe: Falling back to LPIB after %u more tries!\n", HDA_STREAM_DMA_CHECK_THRESH - HdaStream->DmaCheckCount));
|
||||
Status = PciIo->Mem.Read (PciIo, EfiPciIoWidthFifoUint32, PCI_HDA_BAR, HDA_REG_SDNLPIB (HdaStream->Index), 1, &HdaStreamDmaPos);
|
||||
if (EFI_ERROR (Status)) {
|
||||
HdaControllerStreamAbort (HdaStream);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Get stream DMA position.
|
||||
// Increment cycle counter. Once complete, store status to avoid false fallbacks later on.
|
||||
//
|
||||
HdaStreamDmaPos = HdaStream->HdaDev->DmaPositions[HdaStream->Index].Position;
|
||||
if (HdaStream->DmaCheckCount < HDA_STREAM_DMA_CHECK_THRESH) {
|
||||
HdaStream->DmaCheckCount++;
|
||||
} else {
|
||||
HdaStream->DmaCheckComplete = TRUE;
|
||||
}
|
||||
|
||||
if (HdaStreamDmaPos >= HdaStream->DmaPositionLast) {
|
||||
DmaChanged = HdaStreamDmaPos - HdaStream->DmaPositionLast;
|
||||
} else {
|
||||
|
||||
@ -111,6 +111,8 @@ typedef struct {
|
||||
#define HDA_STREAM_POLL_TIME (EFI_TIMER_PERIOD_MILLISECONDS(1))
|
||||
#define HDA_STREAM_BUFFER_PADDING 0x200 // 512 byte pad.
|
||||
|
||||
#define HDA_STREAM_DMA_CHECK_THRESH 5
|
||||
|
||||
//
|
||||
// DMA position structure.
|
||||
//
|
||||
@ -148,6 +150,19 @@ typedef struct {
|
||||
//
|
||||
BOOLEAN IsBidirectional;
|
||||
//
|
||||
// Use LPIB register instead of DMA position buffer.
|
||||
//
|
||||
BOOLEAN UseLpib;
|
||||
//
|
||||
// Count of times DMA position buffer usability is checked.
|
||||
//
|
||||
UINT32 DmaCheckCount;
|
||||
//
|
||||
// Indicates whether DMA position buffer usability is complete.
|
||||
// Ensures we don't accidentally fallback to LPIB if the stream position happens to be zero later on.
|
||||
//
|
||||
BOOLEAN DmaCheckComplete;
|
||||
//
|
||||
// Buffer Descriptor List.
|
||||
//
|
||||
HDA_BDL_ENTRY *BufferList;
|
||||
|
||||
@ -584,6 +584,9 @@ HdaControllerResetStream (
|
||||
HdaStream->DmaPositionTotal = 0;
|
||||
HdaStream->DmaPositionLast = 0;
|
||||
HdaStream->DmaPositionChangedMax = 0;
|
||||
HdaStream->UseLpib = TRUE; // TODO: Allow being forced by NVRAM variable?
|
||||
HdaStream->DmaCheckCount = 0;
|
||||
HdaStream->DmaCheckComplete = FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user