571 lines
23 KiB
C
571 lines
23 KiB
C
/*********************************************************************************/
|
|
/* Module Name: hda.c */
|
|
/* Project: AurixOS */
|
|
/* */
|
|
/* Copyright (c) 2018-2025, Rafael Rodrigues Machado, Jozef Nagy */
|
|
/* All rights reserved. */
|
|
/* This program and the accompanying materials are licensed and made available */
|
|
/* under the terms and conditions of the BSD License which accompanies */
|
|
/* this distribution. The full text of the license may be found at */
|
|
/* http://opensource.org/licenses/bsd-license. */
|
|
/* */
|
|
/* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, */
|
|
/* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. */
|
|
/*********************************************************************************/
|
|
|
|
#include <lib/string.h>
|
|
#include <mm/mman.h>
|
|
#include <efi.h>
|
|
#include <efilib.h>
|
|
#include <stdint.h>
|
|
#include <stddef.h>
|
|
#include <print.h>
|
|
|
|
#include <hda.h>
|
|
#include <pciconf.h>
|
|
|
|
// Number of rows that are updated by the timer event for debug purposes
|
|
#define REFRESH_ROWS 9
|
|
#define Bar0 0
|
|
|
|
static uint64_t CorbCommandCount = 0;
|
|
|
|
PCI_HDA_REGION *PcieDeviceConfigSpace;
|
|
uint64_t *DmaPositionBuffer = NULL;
|
|
uint64_t *AddressBSL = NULL;
|
|
int16_t *AudioBuffer = NULL;
|
|
|
|
uint64_t CorbAddress;
|
|
void *CorbMapping = NULL;
|
|
uint8_t CorbLastAddedCommandIndex = 0;
|
|
|
|
uint64_t RirbAddress;
|
|
void *RirbMapping = NULL;
|
|
uint8_t RirbLastProcessedResponseIndex = 0;
|
|
|
|
EFI_STATUS AddCommandToCorb(uint32_t VerbToSend)
|
|
{
|
|
CorbLastAddedCommandIndex += 1;
|
|
if (CorbLastAddedCommandIndex >= 256) {
|
|
CorbLastAddedCommandIndex = 0;
|
|
}
|
|
|
|
WritePciMemory(CorbAddress + (CorbLastAddedCommandIndex * sizeof(uint32_t)), (void *)&VerbToSend, 1, EfiPciWidthUint32);
|
|
WriteControllerRegister(PcieDeviceConfigSpace, HDA_OFFSET_CORBWP, (void *)&CorbLastAddedCommandIndex, 1, Bar0, EfiPciWidthUint32);
|
|
|
|
CorbCommandCount += 1;
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS ReadResponseFromRirb(uint64_t *VerbResponse)
|
|
{
|
|
RirbLastProcessedResponseIndex += 1;
|
|
if (RirbLastProcessedResponseIndex >= 256) {
|
|
RirbLastProcessedResponseIndex = 0;
|
|
}
|
|
|
|
return ReadPciMemory(RirbAddress + (RirbLastProcessedResponseIndex * sizeof(uint64_t)), VerbResponse, 1, EfiPciWidthUint64);
|
|
}
|
|
|
|
EFI_STATUS InitHda()
|
|
{
|
|
EFI_STATUS Status = EFI_SUCCESS;
|
|
Status = GetHdaPciIoHandler();
|
|
if (EFI_ERROR(Status))
|
|
return Status;
|
|
|
|
Status = GetRootBridgeIoHandler();
|
|
if (EFI_ERROR(Status))
|
|
return Status;
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS DisposeHdaLib()
|
|
{
|
|
// TODO: Release CORB and RIRB
|
|
// Close protocols
|
|
// Free Variables
|
|
// Close events
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS AllocateCORBBuffer(PCI_HDA_REGION* PcieDeviceConfigSpace)
|
|
{
|
|
uint8_t *CorbAddressPointer = NULL;
|
|
uint32_t ReadValue32 = 0;
|
|
uint32_t WriteValue = 0;
|
|
uint8_t WriteValue8 = 0;
|
|
|
|
SetupCommonBuffer(&CorbAddressPointer, 1024, &CorbMapping, 16);
|
|
CorbAddress = (uint64_t)CorbAddressPointer;
|
|
|
|
WriteValue = (CorbAddress & 0xFFFFFFFF);
|
|
WriteControllerRegister(PcieDeviceConfigSpace, HDA_OFFSET_CORBLBASE,
|
|
(void *)&WriteValue, 1, Bar0, EfiPciWidthUint32);
|
|
|
|
WriteValue = (CorbAddress >> 32);
|
|
WriteControllerRegister(PcieDeviceConfigSpace, HDA_OFFSET_CORBUBASE,
|
|
(void *)&WriteValue, 1, Bar0, EfiPciWidthUint32);
|
|
|
|
WriteValue = 0;
|
|
WriteControllerRegister(PcieDeviceConfigSpace, HDA_OFFSET_CORBWP,
|
|
(void *)&WriteValue, 1, Bar0, EfiPciWidthUint32);
|
|
|
|
WriteValue = 0x8000;
|
|
WriteControllerRegister(PcieDeviceConfigSpace, HDA_OFFSET_CORBRP,
|
|
(void *)&WriteValue, 1, Bar0, EfiPciWidthUint32);
|
|
|
|
ReadControllerRegister(PcieDeviceConfigSpace, HDA_OFFSET_CORBRP,
|
|
(void *)&ReadValue32, 1, EfiPciWidthUint32);
|
|
|
|
WriteValue = 0;
|
|
WriteControllerRegister(PcieDeviceConfigSpace, HDA_OFFSET_CORBRP,
|
|
(void *)&WriteValue, 1, Bar0, EfiPciWidthUint32);
|
|
|
|
WriteValue8 = 0x3;
|
|
WriteControllerRegister(PcieDeviceConfigSpace, HDA_OFFSET_CORBCTL,
|
|
(void *)&WriteValue8, 1, Bar0, EfiPciWidthUint8);
|
|
|
|
//debug("AllocateCORBBuffer(): CorbAddress=0x%llx\n", CorbAddress);
|
|
//debug("AllocateCORBBuffer(): CorbMapping=0x%llx\n", CorbMapping);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS AllocateRIRBBuffer(PCI_HDA_REGION* PcieDeviceConfigSpace)
|
|
{
|
|
uint8_t *RirbAddressPointer = NULL;
|
|
|
|
uint32_t WriteValue = 0;
|
|
uint8_t WriteValue8 = 0;
|
|
|
|
SetupCommonBuffer(&RirbAddressPointer, 2048, &RirbMapping, 16);
|
|
RirbAddress = (uint64_t)RirbAddressPointer;
|
|
|
|
WriteValue = (RirbAddress & 0xFFFFFFFF);
|
|
WriteControllerRegister(PcieDeviceConfigSpace, HDA_OFFSET_RIRBLBASE,
|
|
(void *)&WriteValue, 1, Bar0, EfiPciWidthUint32);
|
|
|
|
WriteValue = (RirbAddress >> 32);
|
|
WriteControllerRegister(PcieDeviceConfigSpace, HDA_OFFSET_RIRBUBASE,
|
|
(void *)&WriteValue, 1, Bar0, EfiPciWidthUint32);
|
|
|
|
WriteValue = 0;
|
|
WriteControllerRegister(PcieDeviceConfigSpace, HDA_OFFSET_RIRBWP,
|
|
(void *)&WriteValue, 1, Bar0, EfiPciWidthUint32);
|
|
|
|
WriteValue8 = 0x2;
|
|
WriteControllerRegister(PcieDeviceConfigSpace, HDA_OFFSET_RIRBCTL,
|
|
(void *)&WriteValue8, 1, Bar0, EfiPciWidthUint8);
|
|
|
|
//debug("AllocateRIRBBuffer(): RirbAddress=0x%llx\n", RirbAddress);
|
|
//debug("AllocateRIRBBuffer(): RirbMapping=0x%llx\n", RirbMapping);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS FillCodecNode(PCI_HDA_REGION *PcieDeviceConfigSpace,
|
|
uint32_t CurrentNodeId,
|
|
HDA_NODE_TYPE NodeType,
|
|
struct Node *CurrentNode)
|
|
{
|
|
uint32_t CurrentSubordinateNodeCount = 0;
|
|
struct Node TempNode;
|
|
|
|
TempNode.NodeId = CurrentNodeId;
|
|
TempNode.NodeType = NodeType;
|
|
|
|
GetCodecData8BitPayloadCorbRirb(PcieDeviceConfigSpace, 0, CurrentNodeId, HDA_VRB_GET_PARAMETER, HDA_PARAM_VENDOR_ID, &TempNode.VendorId);
|
|
GetCodecData8BitPayloadCorbRirb(PcieDeviceConfigSpace, 0, CurrentNodeId, HDA_VRB_GET_PARAMETER, HDA_PARAM_REVISION_ID, &TempNode.RevisionId);
|
|
GetCodecData8BitPayloadCorbRirb(PcieDeviceConfigSpace, 0, CurrentNodeId, HDA_VRB_GET_PARAMETER, HDA_PARAM_SUBORDINATE_NODE_COUNT, &CurrentSubordinateNodeCount);
|
|
GetCodecData8BitPayloadCorbRirb(PcieDeviceConfigSpace, 0, CurrentNodeId, HDA_VRB_GET_PARAMETER, HDA_PARAM_FUNCTION_GROUP_TYPE, &TempNode.FunctionGroupType);
|
|
GetCodecData8BitPayloadCorbRirb(PcieDeviceConfigSpace, 0, CurrentNodeId, HDA_VRB_GET_PARAMETER, HDA_PARAM_AUDIO_FUNC_CAP, &TempNode.FuncCap);
|
|
GetCodecData8BitPayloadCorbRirb(PcieDeviceConfigSpace, 0, CurrentNodeId, HDA_VRB_GET_PARAMETER, HDA_PARAM_AUDIO_WIDGET_CAP, &TempNode.WidgetCap);
|
|
GetCodecData8BitPayloadCorbRirb(PcieDeviceConfigSpace, 0, CurrentNodeId, HDA_VRB_GET_PARAMETER, HDA_PARAM_SAMPLE_SIZE_RATE_CAP, &TempNode.SampleSizeRateCap);
|
|
GetCodecData8BitPayloadCorbRirb(PcieDeviceConfigSpace, 0, CurrentNodeId, HDA_VRB_GET_PARAMETER, HDA_PARAM_STREAM_FORMATS, &TempNode.StreamFormat);
|
|
GetCodecData8BitPayloadCorbRirb(PcieDeviceConfigSpace, 0, CurrentNodeId, HDA_VRB_GET_PARAMETER, HDA_PARAM_PIN_CAP, &TempNode.PinCap);
|
|
GetCodecData8BitPayloadCorbRirb(PcieDeviceConfigSpace, 0, CurrentNodeId, HDA_VRB_GET_PARAMETER, HDA_PARAM_INPUT_AMP_CAP, &TempNode.InputAmpCap);
|
|
GetCodecData8BitPayloadCorbRirb(PcieDeviceConfigSpace, 0, CurrentNodeId, HDA_VRB_GET_PARAMETER, HDA_PARAM_OUTPUT_AMP_CAP, &TempNode.OutputAmpCap);
|
|
GetCodecData8BitPayloadCorbRirb(PcieDeviceConfigSpace, 0, CurrentNodeId, HDA_VRB_GET_PARAMETER, HDA_PARAM_CONNECTION_LIST_LENGTH, &TempNode.ConnectionListLength);
|
|
GetCodecData8BitPayloadCorbRirb(PcieDeviceConfigSpace, 0, CurrentNodeId, HDA_VRB_GET_PARAMETER, HDA_PARAM_SUPPORTED_POWER_STATES, &TempNode.SupportedPowerStates);
|
|
GetCodecData8BitPayloadCorbRirb(PcieDeviceConfigSpace, 0, CurrentNodeId, HDA_VRB_GET_PARAMETER, HDA_PARAM_PROCESSING_CAP, &TempNode.ProcessingCap);
|
|
GetCodecData8BitPayloadCorbRirb(PcieDeviceConfigSpace, 0, CurrentNodeId, HDA_VRB_GET_PARAMETER, HDA_PARAM_GPIO_COUNT, &TempNode.GPIOCount);
|
|
GetCodecData8BitPayloadCorbRirb(PcieDeviceConfigSpace, 0, CurrentNodeId, HDA_VRB_GET_PARAMETER, HDA_PARAM_VOLUME_KNOB_CAP, &TempNode.VolKnobCap);
|
|
GetCodecData8BitPayloadCorbRirb(PcieDeviceConfigSpace, 0, CurrentNodeId, HDA_VRB_GET_POWER_STATE, 0, &TempNode.PowerState);
|
|
GetCodecData8BitPayloadCorbRirb(PcieDeviceConfigSpace, 0, CurrentNodeId, HDA_VRB_GET_CHANNEL_STREAM_ID, 0, &TempNode.ChannelStreamId);
|
|
|
|
TempNode.StartingChildNodeAddess = HDA_SUB_NODE_COUNT_START_NODE(CurrentSubordinateNodeCount);
|
|
TempNode.SubordinateNodeCount = HDA_SUB_NODE_COUNT_TOTAL_NODE(CurrentSubordinateNodeCount);
|
|
TempNode.WidgetType = HDA_WIDGET_TYPE(TempNode.WidgetCap);
|
|
TempNode.RightGain = GetAmplifierGain(PcieDeviceConfigSpace, TempNode.NodeId, true, false);
|
|
TempNode.LeftGain = GetAmplifierGain(PcieDeviceConfigSpace, TempNode.NodeId, true, true);
|
|
|
|
memcpy(CurrentNode, &TempNode, sizeof(struct Node));
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS GetNodeById(struct Node *RootNode,
|
|
uint32_t NodeIdToSearch,
|
|
struct Node *NodeDetected)
|
|
{
|
|
struct Node *CurrentFunctionGroupNode = NULL;
|
|
struct Node *CurrentWidgetNode = NULL;
|
|
|
|
uint32_t CurrentFunctionGroupId = 0;
|
|
uint32_t CurrentFgArrayIndexer = 0;
|
|
|
|
uint32_t CurrentWidgetId = 0;
|
|
uint32_t CurrentWidgetArrayIndexer = 0;
|
|
|
|
for (CurrentFunctionGroupId = RootNode->StartingChildNodeAddess; CurrentFunctionGroupId < RootNode->StartingChildNodeAddess + RootNode->SubordinateNodeCount; CurrentFunctionGroupId++, CurrentFgArrayIndexer++) {
|
|
CurrentFunctionGroupNode = &(RootNode->ChildNodes[CurrentFgArrayIndexer]);
|
|
|
|
if (CurrentFunctionGroupNode->NodeId == NodeIdToSearch) {
|
|
memcpy(NodeDetected, CurrentFunctionGroupNode, sizeof(struct Node));
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
CurrentWidgetArrayIndexer = 0;
|
|
for (CurrentWidgetId = CurrentFunctionGroupNode->StartingChildNodeAddess; CurrentWidgetId < CurrentFunctionGroupNode->StartingChildNodeAddess + CurrentFunctionGroupNode->SubordinateNodeCount - 1; CurrentWidgetId++, CurrentWidgetArrayIndexer++) {
|
|
CurrentWidgetNode = &(CurrentFunctionGroupNode->ChildNodes[CurrentWidgetArrayIndexer]);
|
|
|
|
if (CurrentWidgetNode->NodeId == NodeIdToSearch) {
|
|
memcpy(NodeDetected, CurrentWidgetNode,sizeof(struct Node));
|
|
return EFI_SUCCESS;
|
|
}
|
|
}
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS GetCodecTree(PCI_HDA_REGION *PcieDeviceConfigSpace,
|
|
struct Node *RootNode)
|
|
{
|
|
struct Node *CurrentFunctionGroupNode = NULL;
|
|
struct Node *CurrentWidgetNode = NULL;
|
|
|
|
uint32_t CurrentFunctionGroupId = 0;
|
|
uint32_t CurrentFgArrayIndexer = 0;
|
|
|
|
uint32_t CurrentWidgetId = 0;
|
|
uint32_t CurrentWidgetArrayIndexer = 0;
|
|
|
|
FillCodecNode(PcieDeviceConfigSpace, 0, HDA_NODE_ROOT, RootNode);
|
|
RootNode->ChildNodes = mem_alloc(sizeof(struct Node) * (RootNode->SubordinateNodeCount - RootNode->StartingChildNodeAddess));
|
|
memset(RootNode->ChildNodes, 0, sizeof(struct Node) * (RootNode->SubordinateNodeCount - RootNode->StartingChildNodeAddess));
|
|
|
|
for (CurrentFunctionGroupId = RootNode->StartingChildNodeAddess; CurrentFunctionGroupId < RootNode->StartingChildNodeAddess + RootNode->SubordinateNodeCount; CurrentFunctionGroupId++, CurrentFgArrayIndexer++) {
|
|
CurrentFunctionGroupNode = &(RootNode->ChildNodes[CurrentFgArrayIndexer]);
|
|
FillCodecNode(PcieDeviceConfigSpace, CurrentFunctionGroupId, HDA_NODE_FUNCTION_GROUP, CurrentFunctionGroupNode);
|
|
CurrentFunctionGroupNode->ChildNodes = mem_alloc(sizeof(struct Node) * CurrentFunctionGroupNode->StartingChildNodeAddess + CurrentFunctionGroupNode->SubordinateNodeCount);
|
|
memset(CurrentFunctionGroupNode->ChildNodes, 0, sizeof(struct Node) * CurrentFunctionGroupNode->StartingChildNodeAddess + CurrentFunctionGroupNode->SubordinateNodeCount);
|
|
|
|
CurrentWidgetArrayIndexer = 0;
|
|
for (CurrentWidgetId = CurrentFunctionGroupNode->StartingChildNodeAddess; CurrentWidgetId < CurrentFunctionGroupNode->StartingChildNodeAddess + CurrentFunctionGroupNode->SubordinateNodeCount - 1; CurrentWidgetId++, CurrentWidgetArrayIndexer++) {
|
|
CurrentWidgetNode = &(CurrentFunctionGroupNode->ChildNodes[CurrentWidgetArrayIndexer]);
|
|
FillCodecNode(PcieDeviceConfigSpace, CurrentWidgetId, HDA_NODE_WIDGET, CurrentWidgetNode);
|
|
}
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS ReleaseCodecTree(PCI_HDA_REGION *PcieDeviceConfigSpace,
|
|
struct Node *RootNode)
|
|
{
|
|
struct Node *CurrentFunctionGroupNode = NULL;
|
|
uint32_t CurrentFunctionGroupId = 0;
|
|
uint32_t CurrentFgArrayIndexer = 0;
|
|
|
|
for (CurrentFunctionGroupId = RootNode->StartingChildNodeAddess; CurrentFunctionGroupId < RootNode->StartingChildNodeAddess + RootNode->SubordinateNodeCount - 1; CurrentFunctionGroupId++, CurrentFgArrayIndexer++) {
|
|
CurrentFunctionGroupNode = &(RootNode->ChildNodes[CurrentFgArrayIndexer]);
|
|
mem_free(CurrentFunctionGroupNode->ChildNodes);
|
|
}
|
|
|
|
mem_free(RootNode->ChildNodes);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS GetCodecData8BitPayload(PCI_HDA_REGION *PcieDeviceConfigSpace,
|
|
uint8_t CodecAddress, uint8_t NodeId,
|
|
HDA_VERB Verb, uint8_t VerbPayload,
|
|
uint32_t *Response)
|
|
{
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS GetCodecData8BitPayloadCorbRirb(PCI_HDA_REGION *PcieDeviceConfigSpace,
|
|
uint8_t CodecAddress, uint8_t NodeId,
|
|
HDA_VERB Verb, uint8_t VerbPayload,
|
|
uint32_t *Response)
|
|
{
|
|
HDA_COMMAND_FIELD_8BIT_PAYLOAD Command;
|
|
HDA_RESPONSE_FIELD *RawResponse;
|
|
|
|
uint32_t VerbToSend = 0;
|
|
uint64_t TempResponse = 0;
|
|
|
|
Command.CAd = CodecAddress;
|
|
Command.NID = NodeId;
|
|
Command.VerbIdent = Verb;
|
|
Command.VerbPayload = VerbPayload;
|
|
|
|
memcpy(&VerbToSend, &Command, sizeof(uint32_t));
|
|
AddCommandToCorb(VerbToSend);
|
|
|
|
gBootServices->Stall(200);
|
|
|
|
ReadResponseFromRirb(&TempResponse);
|
|
|
|
RawResponse = (HDA_RESPONSE_FIELD *)&TempResponse;
|
|
memcpy(Response, &RawResponse->Response, sizeof(uint32_t));
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS GetCodecData16BitPayloadCorbRirb(PCI_HDA_REGION *PcieDeviceConfigSpace,
|
|
uint8_t CodecAddress, uint8_t NodeId,
|
|
HDA_VERB Verb, uint16_t VerbPayload,
|
|
uint32_t *Response)
|
|
{
|
|
HDA_COMMAND_FIELD_16BIT_PAYLOAD Command;
|
|
HDA_RESPONSE_FIELD *RawResponse;
|
|
|
|
uint32_t VerbToSend = 0;
|
|
uint64_t TempResponse = 0;
|
|
|
|
Command.CAd = CodecAddress;
|
|
Command.NID = NodeId;
|
|
Command.VerbIdent = Verb;
|
|
Command.VerbPayload = VerbPayload;
|
|
|
|
memcpy(&VerbToSend, &Command, sizeof(uint32_t));
|
|
AddCommandToCorb(VerbToSend);
|
|
|
|
gBootServices->Stall(200);
|
|
|
|
ReadResponseFromRirb(&TempResponse);
|
|
|
|
RawResponse = (HDA_RESPONSE_FIELD *)&TempResponse;
|
|
memcpy(Response, &RawResponse->Response, sizeof(uint32_t));
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
|
|
EFI_STATUS SendCommandToAllWidgets8BitPayload (
|
|
PCI_HDA_REGION *PcieDeviceConfigSpace,
|
|
HDA_VERB Verb, uint8_t VerbPayload)
|
|
{
|
|
struct Node RootNode;
|
|
uint32_t Response;
|
|
|
|
GetCodecTree(PcieDeviceConfigSpace, &RootNode);
|
|
|
|
struct Node *CurrentFunctionGroupNode = NULL;
|
|
struct Node *CurrentWidgetNode = NULL;
|
|
|
|
uint32_t CurrentFunctionGroupId = 0;
|
|
uint32_t CurrentFgArrayIndexer = 0;
|
|
|
|
uint32_t CurrentWidgetId = 0;
|
|
uint32_t CurrentWidgetArrayIndexer = 0;
|
|
|
|
GetCodecData8BitPayloadCorbRirb(PcieDeviceConfigSpace, 0, 0, Verb, VerbPayload, &Response);
|
|
|
|
debug("Verb 0x%llx with payload 0x%llx sent to node 0x0\n", Verb, VerbPayload);
|
|
for (CurrentFunctionGroupId = RootNode.StartingChildNodeAddess; CurrentFunctionGroupId < RootNode.StartingChildNodeAddess + RootNode.SubordinateNodeCount; CurrentFunctionGroupId++, CurrentFgArrayIndexer++) {
|
|
GetCodecData8BitPayloadCorbRirb(PcieDeviceConfigSpace, 0, CurrentFunctionGroupId, Verb, VerbPayload, &Response);
|
|
CurrentFunctionGroupNode = &(RootNode.ChildNodes[CurrentFgArrayIndexer]);
|
|
CurrentWidgetArrayIndexer = 0;
|
|
|
|
for (CurrentWidgetId = CurrentFunctionGroupNode->StartingChildNodeAddess; CurrentWidgetId < CurrentFunctionGroupNode->StartingChildNodeAddess + CurrentFunctionGroupNode->SubordinateNodeCount - 1; CurrentWidgetId++, CurrentWidgetArrayIndexer++) {
|
|
CurrentWidgetNode = &(CurrentFunctionGroupNode->ChildNodes[CurrentWidgetArrayIndexer]);
|
|
GetCodecData8BitPayloadCorbRirb(PcieDeviceConfigSpace, 0, CurrentWidgetId, Verb, VerbPayload, &Response);
|
|
}
|
|
}
|
|
|
|
ReleaseCodecTree(PcieDeviceConfigSpace, &RootNode);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS SendCommandToAllWidgets16BitPayload (
|
|
PCI_HDA_REGION* PcieDeviceConfigSpace,
|
|
HDA_VERB Verb, uint16_t VerbPayload)
|
|
{
|
|
struct Node RootNode;
|
|
uint32_t Response;
|
|
|
|
GetCodecTree(PcieDeviceConfigSpace, &RootNode);
|
|
|
|
struct Node *CurrentFunctionGroupNode = NULL;
|
|
struct Node *CurrentWidgetNode = NULL;
|
|
|
|
uint32_t CurrentFunctionGroupId = 0;
|
|
uint32_t CurrentFgArrayIndexer = 0;
|
|
|
|
uint32_t CurrentWidgetId = 0;
|
|
uint32_t CurrentWidgetArrayIndexer = 0;
|
|
|
|
GetCodecData16BitPayloadCorbRirb(PcieDeviceConfigSpace, 0, 0, Verb, VerbPayload, &Response);
|
|
|
|
for (CurrentFunctionGroupId = RootNode.StartingChildNodeAddess; CurrentFunctionGroupId < RootNode.StartingChildNodeAddess + RootNode.SubordinateNodeCount; CurrentFunctionGroupId++, CurrentFgArrayIndexer++) {
|
|
GetCodecData16BitPayloadCorbRirb(PcieDeviceConfigSpace, 0, CurrentFunctionGroupId, Verb, VerbPayload, &Response);
|
|
CurrentFunctionGroupNode = &(RootNode.ChildNodes[CurrentFgArrayIndexer]);
|
|
CurrentWidgetArrayIndexer = 0;
|
|
|
|
for (CurrentWidgetId = CurrentFunctionGroupNode->StartingChildNodeAddess; CurrentWidgetId < CurrentFunctionGroupNode->StartingChildNodeAddess + CurrentFunctionGroupNode->SubordinateNodeCount - 1; CurrentWidgetId++, CurrentWidgetArrayIndexer++) {
|
|
CurrentWidgetNode = &(CurrentFunctionGroupNode->ChildNodes[CurrentWidgetArrayIndexer]);
|
|
GetCodecData16BitPayloadCorbRirb(PcieDeviceConfigSpace, 0, CurrentWidgetId, Verb, VerbPayload, &Response);
|
|
}
|
|
}
|
|
|
|
ReleaseCodecTree(PcieDeviceConfigSpace, &RootNode);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS GetCodecData16BitPayload(PCI_HDA_REGION* PcieDeviceConfigSpace,
|
|
uint8_t CodecAddress, uint8_t NodeId,
|
|
HDA_VERB Verb, uint16_t VerbPayload,
|
|
uint32_t *Response)
|
|
{
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
uint32_t GetAmplifierGain(PCI_HDA_REGION *PcieDeviceConfigSpace,
|
|
uint8_t NodeId, bool InputOutput,
|
|
bool LeftRight)
|
|
{
|
|
uint32_t Response = 0;
|
|
uint16_t PayloadToSend = 0;
|
|
|
|
PayloadToSend = NodeId;
|
|
PayloadToSend |= (InputOutput << 15);
|
|
PayloadToSend |= (LeftRight << 13);
|
|
|
|
GetCodecData8BitPayloadCorbRirb(PcieDeviceConfigSpace, 0x0, NodeId, HDA_VRB_GET_AMPLIFIER_GAIN_MUTE, 0x0, &Response);
|
|
return Response;
|
|
}
|
|
|
|
EFI_STATUS DisablePcieInterrupts(PCI_HDA_REGION *PcieDeviceConfigSpace)
|
|
{
|
|
uint16_t CommandRegister = 0;
|
|
|
|
ReadControllerPcieConfiguration(PcieDeviceConfigSpace, HDA_OFFSET_PCIE_PCICMD, &CommandRegister, 1, EfiPciWidthUint16);
|
|
CommandRegister += (1 << 10);
|
|
WriteControllerPcieConfiguration(PcieDeviceConfigSpace, HDA_OFFSET_PCIE_PCICMD, (void *)&CommandRegister, 1, EfiPciWidthUint16);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS EnablePcieNoSnoop(PCI_HDA_REGION *PcieDeviceConfigSpace)
|
|
{
|
|
uint16_t DeviceControlRegister = 0;
|
|
|
|
ReadControllerPcieConfiguration(PcieDeviceConfigSpace, HDA_OFFSET_PCIE_DEVCTL, (void *)&DeviceControlRegister, 1, EfiPciWidthUint16);
|
|
DeviceControlRegister += (1 << 11);
|
|
WriteControllerPcieConfiguration(PcieDeviceConfigSpace, HDA_OFFSET_PCIE_DEVCTL, (void *)&DeviceControlRegister, 1, EfiPciWidthUint16);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS AddDescriptorListEntryOss0(PCI_HDA_REGION *PcieDeviceConfigSpace,
|
|
HDA_CONTROLLER_REGISTER_SET *ControllerRegisterSet,
|
|
uint64_t DataAddress,
|
|
uint32_t DataLength,
|
|
uint8_t BdlEntryIndex,
|
|
uint32_t SdxLastValidIndex)
|
|
{
|
|
EFI_UINT64 BdlAddress;
|
|
EFI_UINT32 BdlLower;
|
|
EFI_UINT64 BdlUpper;
|
|
|
|
HDA_BUFFER_DESCRIPTOR_LIST *DescriptorList = NULL;
|
|
|
|
ReadControllerRegister(PcieDeviceConfigSpace, CALCULATE_OSSN_OFFSET(0, ControllerRegisterSet->GCAP) + HDA_RELATIVE_OFFSET_SDXBDPL,
|
|
(void *)&BdlLower, 1, EfiPciWidthUint32);
|
|
ReadControllerRegister(PcieDeviceConfigSpace, CALCULATE_OSSN_OFFSET(0, ControllerRegisterSet->GCAP) + HDA_RELATIVE_OFFSET_SDXBDPU,
|
|
(void *)&BdlUpper, 1, EfiPciWidthUint32);
|
|
|
|
BdlAddress = BdlLower | (BdlUpper << 32);
|
|
|
|
DescriptorList = (HDA_BUFFER_DESCRIPTOR_LIST *)BdlAddress;
|
|
DescriptorList->BDLEntry[BdlEntryIndex].Address = DataAddress;
|
|
DescriptorList->BDLEntry[BdlEntryIndex].Length = DataLength;
|
|
|
|
// TODO: Enable this after Corb/Rirb start to process unsolicited responses
|
|
DescriptorList->BDLEntry[BdlEntryIndex].IntrptOnComp = 1;
|
|
|
|
return WriteControllerRegister(PcieDeviceConfigSpace, CALCULATE_OSSN_OFFSET(0, ControllerRegisterSet->GCAP) + HDA_RELATIVE_OFFSET_SDXLVI,
|
|
(void *)&SdxLastValidIndex, 1, Bar0, EfiPciWidthUint32);
|
|
}
|
|
|
|
EFI_STATUS AllocateStreamsPages(PCI_HDA_REGION *PcieDeviceConfigSpace,
|
|
HDA_CONTROLLER_REGISTER_SET *ControllerRegisterSet)
|
|
{
|
|
uint8_t *BdlAddressPointer = NULL;
|
|
void *BdlMapping = NULL;
|
|
uint64_t BdlAddress;
|
|
|
|
// DMAPositionBuffer
|
|
uint8_t *DmaAddressPointer = NULL;
|
|
void *DmaMapping = NULL;
|
|
uint64_t DmaAddress;
|
|
|
|
uint32_t WriteValue = 0;
|
|
|
|
uint64_t IssCount = (ControllerRegisterSet->GCAP >> 8) & 0xF;
|
|
uint64_t OssCount = (ControllerRegisterSet->GCAP >> 12) & 0xF;
|
|
uint64_t BssCount = (ControllerRegisterSet->GCAP >> 3) & 0x1F;
|
|
uint64_t Count = 0;
|
|
|
|
for (Count = 0; Count < IssCount; Count++) {
|
|
SetupCommonBuffer(&BdlAddressPointer, sizeof(HDA_BUFFER_DESCRIPTOR_LIST), &BdlMapping, 16);
|
|
|
|
BdlAddress = (uint64_t)BdlAddressPointer;
|
|
WriteValue = (BdlAddress & 0xFFFFFFFF);
|
|
|
|
WriteControllerRegister(PcieDeviceConfigSpace, CALCULATE_ISSN_OFFSET(Count) + HDA_RELATIVE_OFFSET_SDXBDPL,
|
|
(void *)&WriteValue, 1, Bar0, EfiPciWidthUint32);
|
|
WriteValue = (BdlAddress >> 32);
|
|
WriteControllerRegister(PcieDeviceConfigSpace, CALCULATE_ISSN_OFFSET(Count) + HDA_RELATIVE_OFFSET_SDXBDPU,
|
|
(void *)&WriteValue, 1, Bar0, EfiPciWidthUint32);
|
|
}
|
|
|
|
for (Count = 0; Count < OssCount; Count++) {
|
|
SetupCommonBuffer(&BdlAddressPointer, sizeof(HDA_BUFFER_DESCRIPTOR_LIST), &BdlMapping, 16);
|
|
|
|
BdlAddress = (uint64_t)BdlAddressPointer;
|
|
WriteValue = (BdlAddress & 0xFFFFFFFF);
|
|
|
|
WriteControllerRegister(PcieDeviceConfigSpace, CALCULATE_OSSN_OFFSET(Count, ControllerRegisterSet->GCAP) + HDA_RELATIVE_OFFSET_SDXBDPL,
|
|
(void *)&WriteValue, 1, Bar0, EfiPciWidthUint32);
|
|
WriteValue = (BdlAddress >> 32);
|
|
WriteControllerRegister(PcieDeviceConfigSpace, CALCULATE_OSSN_OFFSET(Count, ControllerRegisterSet->GCAP) + HDA_RELATIVE_OFFSET_SDXBDPU,
|
|
(void *)&WriteValue, 1, Bar0, EfiPciWidthUint32);
|
|
}
|
|
|
|
for (Count = 0; Count < BssCount; Count++) {
|
|
SetupCommonBuffer(&BdlAddressPointer, sizeof(HDA_BUFFER_DESCRIPTOR_LIST), &BdlMapping, 16);
|
|
|
|
BdlAddress = (uint64_t)BdlAddressPointer;
|
|
WriteValue = (BdlAddress & 0xFFFFFFFF);
|
|
|
|
WriteControllerRegister(PcieDeviceConfigSpace, CALCULATE_BSSN_OFFSET(Count, ControllerRegisterSet->GCAP) + HDA_RELATIVE_OFFSET_SDXBDPL,
|
|
(void *)&WriteValue, 1, Bar0, EfiPciWidthUint32);
|
|
WriteValue = (BdlAddress >> 32);
|
|
WriteControllerRegister(PcieDeviceConfigSpace, CALCULATE_BSSN_OFFSET(Count, ControllerRegisterSet->GCAP) + HDA_RELATIVE_OFFSET_SDXBDPU,
|
|
(void *)&WriteValue, 1, Bar0, EfiPciWidthUint32);
|
|
}
|
|
|
|
SetupCommonBuffer(&DmaAddressPointer, (IssCount + OssCount + BssCount) * sizeof(uint64_t), &DmaMapping, 16);
|
|
DmaAddress = (uint64_t)DmaAddressPointer;
|
|
|
|
WriteValue = (DmaAddress & 0xFFFFFFFF);
|
|
WriteValue |= 0x01;
|
|
WriteControllerRegister(PcieDeviceConfigSpace, HDA_OFFSET_DPIBLBASE, (void *)&WriteValue, 1, Bar0, EfiPciWidthUint32);
|
|
WriteValue = (DmaAddress >> 32);
|
|
WriteControllerRegister(PcieDeviceConfigSpace, HDA_OFFSET_DPIBUBASE, (void *)&WriteValue, 1, Bar0, EfiPciWidthUint32);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|