提交 b0087a6b 编写于 作者: G Goldfish64

AudioDxe: Fallback to LPIB register when DMA positions buffer is unusable

上级 97ff5992
......@@ -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;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册