Added TrueType base and HDA driver
This commit is contained in:
parent
aa3f734406
commit
42cc0d9f40
30 changed files with 7120 additions and 35 deletions
33
boot/platform/uefi/drivers/Makefile
Normal file
33
boot/platform/uefi/drivers/Makefile
Normal file
|
@ -0,0 +1,33 @@
|
|||
###################################################################################
|
||||
## Module Name: Makefile ##
|
||||
## Project: AurixOS ##
|
||||
## ##
|
||||
## Copyright (c) 2024-2025 Jozef Nagy ##
|
||||
## ##
|
||||
## This source is subject to the MIT License. ##
|
||||
## See License.txt in the root of this repository. ##
|
||||
## All other rights reserved. ##
|
||||
## ##
|
||||
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ##
|
||||
## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ##
|
||||
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ##
|
||||
## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ##
|
||||
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ##
|
||||
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ##
|
||||
## SOFTWARE. ##
|
||||
###################################################################################
|
||||
|
||||
SUBDIRS := $(wildcard */)
|
||||
|
||||
.PHONY: all
|
||||
all:
|
||||
@for d in $(SUBDIRS); do \
|
||||
printf ">>> Building $$d...\n"; \
|
||||
$(MAKE) -C $$d; \
|
||||
done
|
||||
|
||||
.PHONY: install
|
||||
install: $(SUBDIRS)
|
||||
@for d in $(SUBDIRS); do \
|
||||
$(MAKE) -C $$d install; \
|
||||
done
|
11
boot/platform/uefi/drivers/intel-hda/License.txt
Normal file
11
boot/platform/uefi/drivers/intel-hda/License.txt
Normal file
|
@ -0,0 +1,11 @@
|
|||
Copyright 2018-2025 Rafael Rodrigues Machado, Jozef Nagy
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
77
boot/platform/uefi/drivers/intel-hda/Makefile
Normal file
77
boot/platform/uefi/drivers/intel-hda/Makefile
Normal file
|
@ -0,0 +1,77 @@
|
|||
###################################################################################
|
||||
## Module Name: Makefile ##
|
||||
## Project: AurixOS ##
|
||||
## ##
|
||||
## Copyright (c) 2024-2025 Jozef Nagy ##
|
||||
## ##
|
||||
## This source is subject to the MIT License. ##
|
||||
## See License.txt in the root of this repository. ##
|
||||
## All other rights reserved. ##
|
||||
## ##
|
||||
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ##
|
||||
## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ##
|
||||
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ##
|
||||
## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ##
|
||||
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ##
|
||||
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ##
|
||||
## SOFTWARE. ##
|
||||
###################################################################################
|
||||
|
||||
UEFI_DRIVER := $(BUILD_DIR)/boot/uefi/drivers/intel-hda.efi
|
||||
|
||||
INCLUDE_DIRS += $(BOOT_ROOT)/drivers/intel-hda \
|
||||
$(BOOT_ROOT)/drivers/intel-hda/include \
|
||||
$(BOOT_ROOT)/platform/uefi/libefi
|
||||
|
||||
UEFI_CC := clang
|
||||
UEFI_LD := clang
|
||||
|
||||
UEFI_ASFLAGS := $(ASFLAGS) \
|
||||
-DAXBOOT_UEFI=1 \
|
||||
$(foreach d, $(INCLUDE_DIRS), -I$d)
|
||||
|
||||
UEFI_CFLAGS := $(CFLAGS) \
|
||||
-DAXBOOT_UEFI=1 \
|
||||
$(foreach d, $(INCLUDE_DIRS), -I$d) \
|
||||
-target $(ARCH)-unknown-windows \
|
||||
-fshort-wchar \
|
||||
-mno-red-zone \
|
||||
-mno-stack-arg-probe
|
||||
|
||||
ifneq (,$(filter $(ARCH),i686 x86_64))
|
||||
UEFI_CFLAGS += -mno-80387 \
|
||||
-mno-mmx \
|
||||
-mno-sse \
|
||||
-mno-sse2
|
||||
endif
|
||||
|
||||
UEFI_LDFLAGS := $(LDFLAGS) \
|
||||
-target $(ARCH)-unknown-windows \
|
||||
-fuse-ld=lld-link \
|
||||
-Wl,-subsystem:efi_boot_service_driver \
|
||||
-Wl,-entry:InitHda
|
||||
|
||||
DRIVER_CFILES := $(shell find $(BOOT_ROOT)/drivers/intel-hda -name '*.c')
|
||||
|
||||
UEFI_OBJ := $(DRIVER_CFILES:$(BOOT_ROOT)/drivers/intel-hda/%.c=$(BUILD_DIR)/boot/uefi/drivers/intel-hda/%.c.o)
|
||||
|
||||
.PHONY: all
|
||||
all: $(UEFI_DRIVER)
|
||||
|
||||
.PHONY: install
|
||||
install: $(UEFI_DRIVER)
|
||||
@mkdir -p $(SYSROOT_DIR)/AxBoot/drivers
|
||||
@printf " INSTALL\t/AxBoot/drivers/$(shell basename $(UEFI_DRIVER))\n"
|
||||
@cp $(UEFI_DRIVER) $(SYSROOT_DIR)/AxBoot/drivers/
|
||||
|
||||
$(UEFI_DRIVER): $(UEFI_OBJ)
|
||||
@mkdir -p $(@D)
|
||||
@printf " LD\t$(notdir $@)\n"
|
||||
@$(UEFI_LD) $(UEFI_LDFLAGS) $^ -o $@
|
||||
|
||||
-include $(wildcard $(BUILD_DIR)/boot/*.d)
|
||||
|
||||
$(BUILD_DIR)/boot/uefi/drivers/intel-hda/%.c.o: $(BOOT_ROOT)/drivers/intel-hda/%.c
|
||||
@mkdir -p $(@D)
|
||||
@printf " CC\t$(subst $(ROOT_DIR)/,,$<)\n"
|
||||
@$(UEFI_CC) $(UEFI_CFLAGS) -c $< -o $@
|
571
boot/platform/uefi/drivers/intel-hda/hda.c
Normal file
571
boot/platform/uefi/drivers/intel-hda/hda.c
Normal file
|
@ -0,0 +1,571 @@
|
|||
/*********************************************************************************/
|
||||
/* 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;
|
||||
}
|
688
boot/platform/uefi/drivers/intel-hda/hda.h
Normal file
688
boot/platform/uefi/drivers/intel-hda/hda.h
Normal file
|
@ -0,0 +1,688 @@
|
|||
/*********************************************************************************/
|
||||
/* Module Name: hda.h */
|
||||
/* 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. */
|
||||
/*********************************************************************************/
|
||||
|
||||
#ifndef _HDA_HDA_H
|
||||
#define _HDA_HDA_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
// Intel HDA Controller location
|
||||
#define HDA_BUS 0
|
||||
#define HDA_DEV 27
|
||||
#define HDA_FUNC 0
|
||||
|
||||
// HDA Spec page 57
|
||||
#define HDA_BUFFER_DESC_LIST_MAX_ENTRIES 256
|
||||
|
||||
// IO-Controller_Hub-7-hd-audio-ac97 manual, page 13
|
||||
typedef struct {
|
||||
uint16_t VID;
|
||||
uint16_t DID;
|
||||
uint16_t PCICMD;
|
||||
uint16_t PCISTS;
|
||||
uint8_t RID;
|
||||
uint8_t PI;
|
||||
uint8_t SC;
|
||||
uint8_t BCC;
|
||||
uint8_t CLS;
|
||||
uint8_t LT;
|
||||
uint8_t HEADTYP;
|
||||
uint8_t RES0;
|
||||
uint32_t HDBARL;
|
||||
uint32_t HDBARU;
|
||||
uint8_t RESV1[20];
|
||||
uint16_t SVID;
|
||||
uint16_t SID;
|
||||
uint8_t RESV2[4];
|
||||
uint8_t CAPPTR;
|
||||
uint8_t RESV3[7];
|
||||
uint8_t INTLN;
|
||||
uint8_t INTPN;
|
||||
uint8_t RESV4[2];
|
||||
uint8_t HDCTL;
|
||||
uint8_t RESV5[3];
|
||||
uint8_t TCSEL;
|
||||
uint8_t RESV6[8];
|
||||
uint8_t DCKSTS;
|
||||
uint8_t RESV7[2];
|
||||
uint16_t PID;
|
||||
uint16_t PC;
|
||||
uint32_t PCS;
|
||||
uint8_t RESV8[8];
|
||||
uint16_t MID;
|
||||
uint16_t MMC;
|
||||
uint32_t MMLA;
|
||||
uint32_t MMUA;
|
||||
uint16_t MMD;
|
||||
uint8_t RESV9[2];
|
||||
uint16_t PXID;
|
||||
uint16_t PXC;
|
||||
uint32_t DEVCAP;
|
||||
uint16_t DEVCTL;
|
||||
uint16_t DEVS;
|
||||
uint8_t RESV10[132];
|
||||
uint32_t VCCAP;
|
||||
uint32_t PVCCAP1;
|
||||
uint32_t PVCCAP2;
|
||||
uint16_t PVCCTL;
|
||||
uint16_t PVCSTS;
|
||||
uint32_t VC0CAP;
|
||||
uint32_t VC0CTL;
|
||||
uint8_t RESV11[2];
|
||||
uint16_t VC0STS;
|
||||
uint32_t VciCAP;
|
||||
uint32_t VciCTL;
|
||||
uint8_t RESV12[2];
|
||||
uint16_t VciSTS;
|
||||
uint8_t RESV13[8];
|
||||
uint32_t RCCAP;
|
||||
uint32_t ESD;
|
||||
uint8_t RESV14[8];
|
||||
uint32_t L1DESC;
|
||||
uint8_t RESV15[4];
|
||||
uint32_t L1ADDL;
|
||||
uint32_t L1ADDU;
|
||||
} PCI_HDA_REGION;
|
||||
|
||||
// Register offsets defined at HDA PCIe config space
|
||||
#define HDA_OFFSET_PCIE_VID 0x0
|
||||
#define HDA_OFFSET_PCIE_DID 0x2
|
||||
#define HDA_OFFSET_PCIE_PCICMD 0x4
|
||||
#define HDA_OFFSET_PCIE_PCISTS 0x6
|
||||
#define HDA_OFFSET_PCIE_RID 0x8
|
||||
#define HDA_OFFSET_PCIE_PI 0x9
|
||||
#define HDA_OFFSET_PCIE_SCC 0xA
|
||||
#define HDA_OFFSET_PCIE_BCC 0xB
|
||||
#define HDA_OFFSET_PCIE_CLS 0xC
|
||||
#define HDA_OFFSET_PCIE_LT 0xD
|
||||
#define HDA_OFFSET_PCIE_HEADTYP 0xE
|
||||
#define HDA_OFFSET_PCIE_HDBARL 0x10
|
||||
#define HDA_OFFSET_PCIE_HDBARU 0x14
|
||||
#define HDA_OFFSET_PCIE_SVID 0x2C
|
||||
#define HDA_OFFSET_PCIE_SID 0x2E
|
||||
#define HDA_OFFSET_PCIE_CAPPTR 0x34
|
||||
#define HDA_OFFSET_PCIE_INTLN 0x3C
|
||||
#define HDA_OFFSET_PCIE_INTPN 0x3D
|
||||
#define HDA_OFFSET_PCIE_HDCTL 0x40
|
||||
#define HDA_OFFSET_PCIE_TCSEL 0x44
|
||||
#define HDA_OFFSET_PCIE_DCKSTS 0x4D
|
||||
#define HDA_OFFSET_PCIE_PID 0x50
|
||||
#define HDA_OFFSET_PCIE_PC 0x52
|
||||
#define HDA_OFFSET_PCIE_PCS 0x54
|
||||
#define HDA_OFFSET_PCIE_MID 0x60
|
||||
#define HDA_OFFSET_PCIE_MMC 0x62
|
||||
#define HDA_OFFSET_PCIE_MMLA 0x64
|
||||
#define HDA_OFFSET_PCIE_MMUA 0x68
|
||||
#define HDA_OFFSET_PCIE_MMD 0x6C
|
||||
#define HDA_OFFSET_PCIE_PXID 0x70
|
||||
#define HDA_OFFSET_PCIE_PXC 0x72
|
||||
#define HDA_OFFSET_PCIE_DEVCAP 0x74
|
||||
#define HDA_OFFSET_PCIE_DEVCTL 0x78
|
||||
#define HDA_OFFSET_PCIE_DEVS 0x7A
|
||||
#define HDA_OFFSET_PCIE_VCCAP 0x100
|
||||
#define HDA_OFFSET_PCIE_PVCCAP1 0x104
|
||||
#define HDA_OFFSET_PCIE_PVCCAP2 0x108
|
||||
#define HDA_OFFSET_PCIE_PVCCTL 0x10C
|
||||
#define HDA_OFFSET_PCIE_PVCSTS 0x10E
|
||||
#define HDA_OFFSET_PCIE_VC0CAP 0x110
|
||||
#define HDA_OFFSET_PCIE_VC0CTL 0x114
|
||||
#define HDA_OFFSET_PCIE_VC0STS 0x11A
|
||||
#define HDA_OFFSET_PCIE_VciCAP 0x11C
|
||||
#define HDA_OFFSET_PCIE_VciCTL 0x120
|
||||
#define HDA_OFFSET_PCIE_VciSTS 0x126
|
||||
#define HDA_OFFSET_PCIE_RCCAP 0x130
|
||||
#define HDA_OFFSET_PCIE_ESD 0x134
|
||||
#define HDA_OFFSET_PCIE_L1DESC 0x140
|
||||
#define HDA_OFFSET_PCIE_L1ADDL 0x148
|
||||
#define HDA_OFFSET_PCIE_L1ADDU 0x14C
|
||||
|
||||
/* Offsets of the registers defined at HDA
|
||||
* compatible controllers.
|
||||
* Details can be found at the page 27 of the
|
||||
* HDA Specification Rev 1.0a
|
||||
*/
|
||||
// Register offsets defined at HDA compatible controllers
|
||||
#define HDA_OFFSET_GCAP 0x0
|
||||
#define HDA_OFFSET_VMIN 0x2
|
||||
#define HDA_OFFSET_VMAJ 0x3
|
||||
#define HDA_OFFSET_OUTPAY 0x4
|
||||
#define HDA_OFFSET_INPAY 0x6
|
||||
#define HDA_OFFSET_GCTL 0x8
|
||||
#define HDA_OFFSET_WAKEEN 0x0C
|
||||
#define HDA_OFFSET_WAKESTS 0x0E
|
||||
#define HDA_OFFSET_GSTS 0x10
|
||||
#define HDA_OFFSET_Rsvd 0x12
|
||||
#define HDA_OFFSET_OUTSTRMPAY 0x18
|
||||
#define HDA_OFFSET_INSTRMPAY 0x1A
|
||||
#define HDA_OFFSET_INTCTL 0x20
|
||||
#define HDA_OFFSET_INTSTS 0x24
|
||||
#define HDA_OFFSET_WALCLK 0x30
|
||||
#define HDA_OFFSET_SSYNC 0x38
|
||||
#define HDA_OFFSET_CORBLBASE 0x40
|
||||
#define HDA_OFFSET_CORBUBASE 0x44
|
||||
#define HDA_OFFSET_CORBWP 0x48
|
||||
#define HDA_OFFSET_CORBRP 0x4A
|
||||
#define HDA_OFFSET_CORBCTL 0x4C
|
||||
#define HDA_OFFSET_CORBSTS 0x4D
|
||||
#define HDA_OFFSET_CORBSIZE 0x4E
|
||||
#define HDA_OFFSET_RIRBLBASE 0x50
|
||||
#define HDA_OFFSET_RIRBUBASE 0x54
|
||||
#define HDA_OFFSET_RIRBWP 0x58
|
||||
#define HDA_OFFSET_RINTCNT 0x5A
|
||||
#define HDA_OFFSET_RIRBCTL 0x5C
|
||||
#define HDA_OFFSET_RIRBSTS 0x5D
|
||||
#define HDA_OFFSET_RIRBSIZE 0x5E
|
||||
#define HDA_OFFSET_ICOI 0x60
|
||||
#define HDA_OFFSET_ICII 0x64
|
||||
#define HDA_OFFSET_ICIS 0x68
|
||||
#define HDA_OFFSET_DPIBLBASE 0x70
|
||||
#define HDA_OFFSET_DPIBUBASE 0x74
|
||||
|
||||
#define HDA_OFFSET_SD0CTL 0x80
|
||||
#define HDA_OFFSET_SD0STS 0x83
|
||||
#define HDA_OFFSET_SD0LPIB 0x84
|
||||
#define HDA_OFFSET_SD0CBL 0x88
|
||||
#define HDA_OFFSET_SD0LVI 0x8C
|
||||
#define HDA_OFFSET_SD0FIFOS 0x90
|
||||
#define HDA_OFFSET_SD0FMT 0x92
|
||||
#define HDA_OFFSET_SD0BDPL 0x98
|
||||
#define HDA_OFFSET_SD0BDPU 0x9C
|
||||
|
||||
// HDA Spec 1.0a page 27
|
||||
#define HDA_RELATIVE_OFFSET_SDXCTL 0
|
||||
#define HDA_RELATIVE_OFFSET_SDXSTS 0x3
|
||||
#define HDA_RELATIVE_OFFSET_SDXLPIB 0x4
|
||||
#define HDA_RELATIVE_OFFSET_SDXCBL 0x8
|
||||
#define HDA_RELATIVE_OFFSET_SDXLVI 0xC
|
||||
#define HDA_RELATIVE_OFFSET_SDXFIFOS 0x10
|
||||
#define HDA_RELATIVE_OFFSET_SDXFMT 0x12
|
||||
#define HDA_RELATIVE_OFFSET_SDXBDPL 0x18
|
||||
#define HDA_RELATIVE_OFFSET_SDXBDPU 0x1C
|
||||
|
||||
// Extract OSS count from controller's global capabilities register
|
||||
#define HDA_OSS_COUNT(GCAP) ((GCAP >> 12) & 0xF)
|
||||
|
||||
// Extract ISS count from controller's global capabilities register
|
||||
#define HDA_ISS_COUNT(GCAP) ((GCAP >> 8) & 0xF)
|
||||
|
||||
// Extract BSS count from controller's global capabilities register
|
||||
#define HDA_BSS_COUNT(GCAP) ((GCAP >> 3) & 0x1F)
|
||||
|
||||
///
|
||||
// Calculate offset of stream descriptors
|
||||
#define CALCULATE_ISSN_OFFSET(StreamIndex) (HDA_OFFSET_SD0CTL + (StreamIndex * 0x20))
|
||||
#define CALCULATE_OSSN_OFFSET(StreamIndex,GCAP) (HDA_OFFSET_SD0CTL + (HDA_ISS_COUNT(GCAP) * 0x20 ) + (StreamIndex * 0x20))
|
||||
#define CALCULATE_BSSN_OFFSET(StreamIndex,GCAP) (HDA_OFFSET_SD0CTL + (HDA_ISS_COUNT(GCAP) * 0x20) + (HDA_OSS_COUNT(GCAP) * 0x20) + (StreamIndex * 0x20))
|
||||
|
||||
typedef struct {
|
||||
uint8_t StreamReset: 1;
|
||||
uint8_t StreamRun: 1;
|
||||
uint8_t InterruptOnCompletionEnable: 1;
|
||||
uint8_t FIFOErrorInterruptEnable: 1;
|
||||
uint8_t DescriptorErrorInterruptEnable: 1;
|
||||
uint8_t Reserved1: 3;
|
||||
uint8_t Reserved2;
|
||||
uint8_t StrippeControl: 2;
|
||||
uint8_t TrafficPriority: 1;
|
||||
uint8_t BidirectionalDirectionControl: 1;
|
||||
uint8_t StreamNumber: 4;
|
||||
} HDA_CONTROLLER_STREAM_DESCRIPTOR_CONTROL;
|
||||
|
||||
typedef struct {
|
||||
uint8_t SD0CTL[3]; // HDA_CONTROLLER_STREAM_DESCRIPTOR_CONTROL
|
||||
uint8_t SD0STS;
|
||||
uint32_t SD0LPIB;
|
||||
uint32_t SD0CBL;
|
||||
uint16_t SD0LVI;
|
||||
uint16_t Rsvd8;
|
||||
uint16_t SD0FIFOS;
|
||||
uint16_t SD0FMT;
|
||||
uint32_t Rsvd9;
|
||||
uint32_t SD0BDPL;
|
||||
uint32_t SD0BDPU;
|
||||
} HDA_CONTROLLER_STREAM_DESCRIPTOR;
|
||||
|
||||
// HDA controller register set
|
||||
// HDA Specification 1.0a page 27
|
||||
typedef struct {
|
||||
uint16_t GCAP;
|
||||
uint8_t VMIN;
|
||||
uint8_t VMAJ;
|
||||
uint16_t OUTPAY;
|
||||
uint16_t INPAY;
|
||||
uint32_t GCTL;
|
||||
uint16_t WAKEEN;
|
||||
uint16_t STATESTS;
|
||||
uint16_t GSTS;
|
||||
uint8_t Rsvd0[6];
|
||||
uint16_t OUTSTRMPAY;
|
||||
uint16_t INSTRMPAY;
|
||||
uint32_t Rsvd;
|
||||
uint32_t INTCTL;
|
||||
uint32_t INTSTS;
|
||||
uint8_t Rsvd1[8];
|
||||
uint32_t WALCLK;
|
||||
uint32_t Rsvd2;
|
||||
uint32_t SSYNC;
|
||||
uint32_t Rsvd3;
|
||||
uint32_t CORBLBASE;
|
||||
uint32_t CORBUBASE;
|
||||
uint16_t CORBWP;
|
||||
uint16_t CORBRP;
|
||||
uint8_t CORBCTL;
|
||||
uint8_t CORBSTS;
|
||||
uint8_t CORBSIZE;
|
||||
uint8_t Rsvd4;
|
||||
uint32_t RIRBLBASE;
|
||||
uint32_t RIRBUBASE;
|
||||
uint16_t RIRBWP;
|
||||
uint16_t RINTCNT;
|
||||
uint8_t RIRBCTL;
|
||||
uint8_t RIRBSTS;
|
||||
uint8_t RIRBSIZE;
|
||||
uint8_t Rsvd5;
|
||||
uint32_t ICOI;
|
||||
uint32_t ICII;
|
||||
uint16_t ICIS;
|
||||
uint8_t Rsvd6[6];
|
||||
uint32_t DPIBLBASE;
|
||||
uint32_t DPIBUBASE;
|
||||
uint8_t Rsvd7[8];
|
||||
|
||||
HDA_CONTROLLER_STREAM_DESCRIPTOR *ISS;
|
||||
HDA_CONTROLLER_STREAM_DESCRIPTOR *OSS;
|
||||
HDA_CONTROLLER_STREAM_DESCRIPTOR *BSS;
|
||||
|
||||
} HDA_CONTROLLER_REGISTER_SET;
|
||||
|
||||
// Executable verbs of widgets on a HDA compatible codec
|
||||
// HDA Specification 1.0a page 218
|
||||
typedef enum {
|
||||
HDA_VRB_GET_PARAMETER = 0xF00,
|
||||
HDA_VRB_GET_CONNECTION_SELECT = 0xF01,
|
||||
HDA_VRB_GET_GET_CONNECTION_LIST_ENTRY = 0xF02,
|
||||
HDA_VRB_GET_PROCESSING_STATE = 0xF03,
|
||||
|
||||
// These are widget dependent
|
||||
HDA_VRB_GET_COEFFICIENT_INDEX = 0xD,
|
||||
HDA_VRB_GET_PROCESSING_COEFFICIENT = 0xC,
|
||||
HDA_VRB_GET_AMPLIFIER_GAIN_MUTE = 0xBA0,
|
||||
HDA_VRB_GET_STREAM_FORMAT = 0xA,
|
||||
|
||||
HDA_VRB_GET_DIGITAL_CONVERTER_1 = 0xF0D,
|
||||
//HDA_VRB_GET_DIGITAL_CONVERTER_2 = 0xF0D,
|
||||
//HDA_VRB_GET_DIGITAL_CONVERTER_3 = 0xF0D,
|
||||
//HDA_VRB_GET_DIGITAL_CONVERTER_4 = 0xF0D,
|
||||
|
||||
HDA_VRB_GET_POWER_STATE = 0xF05,
|
||||
HDA_VRB_GET_CHANNEL_STREAM_ID = 0xF06,
|
||||
HDA_VRB_GET_SDI_SELECT = 0xF04,
|
||||
HDA_VRB_GET_PIN_WIDGET_CONTROL = 0xF07,
|
||||
HDA_VRB_GET_UNSOLICITED_ENABLE = 0xF08,
|
||||
HDA_VRB_GET_PIN_SENSE = 0xF09,
|
||||
HDA_VRB_GET_EAPD_BTL_ENABLE = 0xF0C,
|
||||
HDA_VRB_GET_ALL_GPI_CONTROLS_F10 = 0xF10,
|
||||
HDA_VRB_GET_ALL_GPI_CONTROLS_F11 = 0xF11,
|
||||
HDA_VRB_GET_ALL_GPI_CONTROLS_F12 = 0xF12,
|
||||
HDA_VRB_GET_ALL_GPI_CONTROLS_F13 = 0xF13,
|
||||
HDA_VRB_GET_ALL_GPI_CONTROLS_F14 = 0xF14,
|
||||
HDA_VRB_GET_ALL_GPI_CONTROLS_F15 = 0xF15,
|
||||
HDA_VRB_GET_ALL_GPI_CONTROLS_F16 = 0xF16,
|
||||
HDA_VRB_GET_ALL_GPI_CONTROLS_F17 = 0xF17,
|
||||
HDA_VRB_GET_ALL_GPI_CONTROLS_F18 = 0xF18,
|
||||
HDA_VRB_GET_ALL_GPI_CONTROLS_F19 = 0xF19,
|
||||
HDA_VRB_GET_ALL_GPI_CONTROLS_F1A = 0xF1A,
|
||||
HDA_VRB_GET_BEEP_GENERATION_CONTROL = 0xF0A,
|
||||
HDA_VRB_GET_VOLUME_KNOB_CONTROL = 0xF0F,
|
||||
HDA_VRB_GET_IMPLEMENTATION_ID_BYTE_0 = 0xF20,
|
||||
//HDA_VRB_GET_IMPLEMENTATION_ID_BYTE_1 = 0xF20,
|
||||
//HDA_VRB_GET_IMPLEMENTATION_ID_BYTE_2 = 0xF20,
|
||||
//HDA_VRB_GET_IMPLEMENTATION_ID_BYTE_3 = 0xF20,
|
||||
HDA_VRB_GET_CONFIG_DEFAULT_BYTE_0 = 0xF1C,
|
||||
//HDA_VRB_GET_CONFIG_DEFAULT_BYTE_1 = 0xF1C,
|
||||
//HDA_VRB_GET_CONFIG_DEFAULT_BYTE_2 = 0xF1C,
|
||||
//HDA_VRB_GET_CONFIG_DEFAULT_BYTE_3 = 0xF1C,
|
||||
HDA_VRB_GET_STRIPE_CONTROL = 0xF24,
|
||||
HDA_VRB_GET_CONVERTER_CHANNEL_COUNT = 0xF2D,
|
||||
HDA_VRB_GET_DIP_SIZE = 0xF2E,
|
||||
HDA_VRB_GET_ELD_DATA = 0xF2F,
|
||||
HDA_VRB_GET_DIP_INDEX = 0xF30,
|
||||
HDA_VRB_GET_DIP_DATA = 0xF31,
|
||||
HDA_VRB_GET_DIP_XMITCTRL = 0xF32,
|
||||
HDA_VRB_GET_CONTENT_PROTECTION_CONTROL = 0xF33,
|
||||
HDA_VRB_GET_ASP_CHANNEL_MAPPING = 0xF34,
|
||||
|
||||
HDA_VRB_SET_CONNECTION_SELECT = 0x701,
|
||||
|
||||
// These are widget dependent
|
||||
HDA_VRB_SET_COEFFICIENT_INDEX = 0x5,
|
||||
HDA_VRB_SET_PROCESSING_COEFFICIENT = 0x4,
|
||||
HDA_VRB_SET_AMPLIFIER_GAIN_MUTE = 0x3B0,
|
||||
HDA_VRB_SET_STREAM_FORMAT = 0x2,
|
||||
|
||||
HDA_VRB_SET_DIGITAL_CONVERTER_1 = 0x70D,
|
||||
HDA_VRB_SET_DIGITAL_CONVERTER_2 = 0x70E,
|
||||
HDA_VRB_SET_DIGITAL_CONVERTER_3 = 0x73E,
|
||||
HDA_VRB_SET_DIGITAL_CONVERTER_4 = 0x73F,
|
||||
HDA_VRB_SET_POWER_STATE = 0x705,
|
||||
HDA_VRB_SET_CHANNEL_STREAM_ID = 0x706,
|
||||
HDA_VRB_SET_SDI_SELECT = 0x704,
|
||||
HDA_VRB_SET_PIN_WIDGET_CONTROL = 0x707,
|
||||
HDA_VRB_SET_UNSOLICITED_ENABLE = 0x708,
|
||||
HDA_VRB_SET_PIN_SENSE = 0x709,
|
||||
HDA_VRB_SET_EAPD_BTL_ENABLE = 0x70C,
|
||||
HDA_VRB_SET_ALL_GPI_CONTROLS_710 = 0x710,
|
||||
HDA_VRB_SET_ALL_GPI_CONTROLS_711 = 0x711,
|
||||
HDA_VRB_SET_ALL_GPI_CONTROLS_712 = 0x712,
|
||||
HDA_VRB_SET_ALL_GPI_CONTROLS_713 = 0x713,
|
||||
HDA_VRB_SET_ALL_GPI_CONTROLS_714 = 0x714,
|
||||
HDA_VRB_SET_ALL_GPI_CONTROLS_715 = 0x715,
|
||||
HDA_VRB_SET_ALL_GPI_CONTROLS_716 = 0x716,
|
||||
HDA_VRB_SET_ALL_GPI_CONTROLS_717 = 0x717,
|
||||
HDA_VRB_SET_ALL_GPI_CONTROLS_718 = 0x718,
|
||||
HDA_VRB_SET_ALL_GPI_CONTROLS_719 = 0x719,
|
||||
HDA_VRB_SET_ALL_GPI_CONTROLS_71A = 0x71A,
|
||||
HDA_VRB_SET_BEEP_GENERATION_CONTROL = 0x70A,
|
||||
HDA_VRB_SET_VOLUME_KNOB_CONTROL = 0x70F,
|
||||
HDA_VRB_SET_IMPLEMENTATION_ID_BYTE_0 = 0x720,
|
||||
HDA_VRB_SET_IMPLEMENTATION_ID_BYTE_1 = 0x721,
|
||||
HDA_VRB_SET_IMPLEMENTATION_ID_BYTE_2 = 0x722,
|
||||
HDA_VRB_SET_IMPLEMENTATION_ID_BYTE_3 = 0x723,
|
||||
HDA_VRB_SET_CONFIG_DEFAULT_BYTE_0 = 0x71C,
|
||||
HDA_VRB_SET_CONFIG_DEFAULT_BYTE_1 = 0x71D,
|
||||
HDA_VRB_SET_CONFIG_DEFAULT_BYTE_2 = 0x71E,
|
||||
HDA_VRB_SET_CONFIG_DEFAULT_BYTE_3 = 0x723,
|
||||
HDA_VRB_SET_STRIPE_CONTROL = 0x724,
|
||||
HDA_VRB_SET_CONVERTER_CHANNEL_COUNT = 0x72D,
|
||||
HDA_VRB_SET_DIP_INDEX = 0x730,
|
||||
HDA_VRB_SET_DIP_DATA = 0x731,
|
||||
HDA_VRB_SET_DIP_XMITCTRL = 0x732,
|
||||
HDA_VRB_SET_CONTENT_PROTECTION_CONTROL = 0x733,
|
||||
HDA_VRB_SET_ASP_CHANNEL_MAPPING = 0x734,
|
||||
|
||||
HDA_VRB_SET_RESET = 0x7FF
|
||||
} HDA_VERB;
|
||||
|
||||
#define HDA_START_PROCESSING_IMMEDIATE_COMMAND 0x01
|
||||
|
||||
// Extract the total node count from a SubordinateNodeCount property
|
||||
#define HDA_SUB_NODE_COUNT_TOTAL_NODE(Subordinate) (Subordinate & 0xFF)
|
||||
|
||||
// Extract the total node count from a SubordinateNodeCount poperty
|
||||
#define HDA_SUB_NODE_COUNT_START_NODE(Subordinate) ((Subordinate >> 16) & 0xFF)
|
||||
|
||||
// Extract the node type from a FunctionGroup property
|
||||
#define HDA_NODE_TYPE(FunctionGroupType) (FunctionGroupType & 0xFF)
|
||||
|
||||
// Check if a given function group can generate unsolicited responses
|
||||
#define HDA_UNSOLICITED_RESPONSE_CAPABLE(FunctionGroupType) ((FunctionGroupType >> 8) & 0x01)
|
||||
|
||||
// Extract widget type from widget capabilities information
|
||||
#define HDA_WIDGET_TYPE(WidgetCap) ((WidgetCap >> 20) & 0xF)
|
||||
|
||||
// HDA command with an 8-bit payload
|
||||
typedef struct {
|
||||
uint32_t VerbPayload : 8;
|
||||
uint32_t VerbIdent : 12; // verb
|
||||
uint32_t NID : 8; // node ID
|
||||
uint32_t CAd : 4; // codec address
|
||||
uint8_t Reserved;
|
||||
} HDA_COMMAND_FIELD_8BIT_PAYLOAD;
|
||||
|
||||
// HDA command with an 16-bit payload
|
||||
typedef struct {
|
||||
uint32_t VerbPayload : 16;
|
||||
uint32_t VerbIdent : 4; // verb
|
||||
uint32_t NID : 8; // node ID
|
||||
uint32_t CAd : 4; // codec address
|
||||
uint8_t Reserved;
|
||||
} HDA_COMMAND_FIELD_16BIT_PAYLOAD;
|
||||
|
||||
// Stream format
|
||||
// HDA Specification 1.0a page 58
|
||||
typedef struct {
|
||||
uint16_t NumberOfChannels : 4;
|
||||
uint16_t BitsPerSample : 3;
|
||||
uint16_t Reserved : 1;
|
||||
uint16_t SampleBaseRateBaseDivisor : 3;
|
||||
uint16_t SampleBaseRateMultiple : 3;
|
||||
uint16_t SampleBaseRate : 1;
|
||||
uint16_t StreamType : 1;
|
||||
} HDA_STREAM_FORMAT;
|
||||
|
||||
// Stream descriptor format
|
||||
// HDA Specification 1.0a page 48
|
||||
typedef struct {
|
||||
uint16_t NumberOfChannels : 4;
|
||||
uint16_t BitsPerSample : 3;
|
||||
uint16_t Reserved : 1;
|
||||
uint16_t SampleBaseRateBaseDivisor : 3;
|
||||
uint16_t SampleBaseRateMultiple : 3;
|
||||
uint16_t SampleBaseRate : 1;
|
||||
uint16_t Reserved2 : 1;
|
||||
} HDA_STREAM_DESCRIPTOR_FORMAT;
|
||||
|
||||
#define PCM_STRUCT_BITS_PER_SAMPLE_8 0
|
||||
#define PCM_STRUCT_BITS_PER_SAMPLE_16 1
|
||||
#define PCM_STRUCT_BITS_PER_SAMPLE_20 2
|
||||
#define PCM_STRUCT_BITS_PER_SAMPLE_24 3
|
||||
#define PCM_STRUCT_BITS_PER_SAMPLE_32 4
|
||||
|
||||
#define PCM_STRUCT_SAMPLE_BASE_DIV_BY_1 0
|
||||
#define PCM_STRUCT_SAMPLE_BASE_DIV_BY_2 1
|
||||
#define PCM_STRUCT_SAMPLE_BASE_DIV_BY_3 2
|
||||
#define PCM_STRUCT_SAMPLE_BASE_DIV_BY_4 3
|
||||
#define PCM_STRUCT_SAMPLE_BASE_DIV_BY_5 4
|
||||
#define PCM_STRUCT_SAMPLE_BASE_DIV_BY_6 5
|
||||
#define PCM_STRUCT_SAMPLE_BASE_DIV_BY_7 6
|
||||
|
||||
//192 kHz, 176.4 kHz
|
||||
#define PCM_STRUCT_SAMPLE_BASE_MULTIPLE_X4 3
|
||||
//144 kHz
|
||||
#define PCM_STRUCT_SAMPLE_BASE_MULTIPLE_X3 2
|
||||
//96 kHz, 88.2 kHz, 32 kHz
|
||||
#define PCM_STRUCT_SAMPLE_BASE_MULTIPLE_X2 1
|
||||
//48KHz/44.1kHz or less
|
||||
#define PCM_STRUCT_SAMPLE_BASE_MULTIPLE_48_OR_LESS 0
|
||||
|
||||
#define PCM_STRUCT_SAMPLE_BASE_44_1KHZ 1
|
||||
#define PCM_STRUCT_SAMPLE_BASE_48KHZ 0
|
||||
|
||||
#define PCM_STRUCT_TYPE_PCM 0
|
||||
#define PCM_STRUCT_TYPE_NON_PCM 1
|
||||
|
||||
// All possible parameters for executing HDA_VRB_GET_PARAMETER
|
||||
// HDA Specification 1.0a page 217
|
||||
typedef enum {
|
||||
HDA_PARAM_VENDOR_ID = 0x00,
|
||||
HDA_PARAM_REVISION_ID = 0x02,
|
||||
HDA_PARAM_SUBORDINATE_NODE_COUNT = 0x04,
|
||||
HDA_PARAM_FUNCTION_GROUP_TYPE = 0x05,
|
||||
HDA_PARAM_AUDIO_FUNC_CAP = 0x08,
|
||||
HDA_PARAM_AUDIO_WIDGET_CAP = 0x09,
|
||||
HDA_PARAM_SAMPLE_SIZE_RATE_CAP = 0x0A,
|
||||
HDA_PARAM_STREAM_FORMATS = 0x0B,
|
||||
HDA_PARAM_PIN_CAP = 0x0C,
|
||||
HDA_PARAM_INPUT_AMP_CAP = 0x0D,
|
||||
HDA_PARAM_OUTPUT_AMP_CAP = 0x12,
|
||||
HDA_PARAM_CONNECTION_LIST_LENGTH = 0x0E,
|
||||
HDA_PARAM_SUPPORTED_POWER_STATES = 0x0F,
|
||||
HDA_PARAM_PROCESSING_CAP = 0x10,
|
||||
HDA_PARAM_GPIO_COUNT = 0x11,
|
||||
HDA_PARAM_VOLUME_KNOB_CAP = 0x13
|
||||
} HDA_PARAMETER;
|
||||
|
||||
// All possible parameters widget types present
|
||||
typedef enum {
|
||||
HDA_WIDGET_TYPE_AUDIO_OUTPUT = 0x0,
|
||||
HDA_WIDGET_TYPE_AUDIO_INPUT = 0x1,
|
||||
HDA_WIDGET_TYPE_AUDIO_MIXER = 0x2,
|
||||
HDA_WIDGET_TYPE_AUDIO_SELECTOR = 0x3,
|
||||
HDA_WIDGET_TYPE_AUDIO_PIN_CONPLEX = 0x4,
|
||||
HDA_WIDGET_TYPE_AUDIO_POWER = 0x5,
|
||||
HDA_WIDGET_TYPE_AUDIO_VOLUME_KNOB = 0x6,
|
||||
HDA_WIDGET_TYPE_AUDIO_BEEP_GENERATOR = 0x7,
|
||||
HDA_WIDGET_TYPE_AUDIO_VENDOR_DEFINED = 0xF
|
||||
} HDA_WIDGET_TYPE;
|
||||
|
||||
// Function group types
|
||||
typedef enum {
|
||||
HDA_FUNCTION_GROUP_TYPE_AUDIO = 0x1,
|
||||
HDA_FUNCTION_GROUP_TYPE_MODEM = 0x2
|
||||
} HDA_FUNCTION_GROUP_TYPE;
|
||||
|
||||
// All possible node types available at a codec
|
||||
typedef enum {
|
||||
HDA_NODE_ROOT = 0x0,
|
||||
HDA_NODE_FUNCTION_GROUP = 0x1,
|
||||
HDA_NODE_WIDGET = 0x2,
|
||||
HDA_UNKNOWN = 0xFF
|
||||
} HDA_NODE_TYPE;
|
||||
|
||||
// Empty payload
|
||||
#define HDA_VRB_EMPTY_PAYLOAD 0
|
||||
|
||||
// All possible power stats a node can present
|
||||
// HDA Specification 1.0a page 151
|
||||
typedef enum {
|
||||
HDA_POWER_D0 = 0x0,
|
||||
HDA_POWER_D1 = 0x1,
|
||||
HDA_POWER_D2 = 0x2,
|
||||
HDA_POWER_D3 = 0x3,
|
||||
HDA_POWER_D3_COLD = 0x4,
|
||||
} HDA_POWER_STATE;
|
||||
|
||||
// HDA codec node
|
||||
struct Node {
|
||||
uint32_t NodeId;
|
||||
HDA_NODE_TYPE NodeType;
|
||||
HDA_WIDGET_TYPE WidgetType;
|
||||
uint32_t VendorId;
|
||||
uint32_t RevisionId;
|
||||
uint32_t StartingChildNodeAddess;
|
||||
uint32_t SubordinateNodeCount;
|
||||
uint32_t FunctionGroupType;
|
||||
uint32_t FuncCap;
|
||||
uint32_t WidgetCap;
|
||||
uint32_t SampleSizeRateCap;
|
||||
uint32_t StreamFormat;
|
||||
uint32_t PinCap;
|
||||
uint32_t InputAmpCap;
|
||||
uint32_t OutputAmpCap;
|
||||
uint32_t ConnectionListLength;
|
||||
uint32_t SupportedPowerStates;
|
||||
uint32_t ProcessingCap;
|
||||
uint32_t GPIOCount;
|
||||
uint32_t VolKnobCap;
|
||||
|
||||
uint32_t PowerState;
|
||||
|
||||
uint32_t RightGain;
|
||||
uint32_t LeftGain;
|
||||
|
||||
uint32_t ChannelStreamId;
|
||||
|
||||
struct Node *ChildNodes;
|
||||
};
|
||||
|
||||
// HDA Specification 1.0a page 142
|
||||
typedef struct {
|
||||
uint32_t Response;
|
||||
uint8_t Reserved : 2;
|
||||
uint8_t UnSol : 1;
|
||||
uint8_t Valid : 1;
|
||||
uint8_t Unused : 4;
|
||||
} HDA_RESPONSE_FIELD;
|
||||
|
||||
typedef struct {
|
||||
uint64_t Address;
|
||||
uint32_t Length;
|
||||
uint32_t IntrptOnComp : 1;
|
||||
uint32_t Resv : 31;
|
||||
} HDA_BUFFER_DESCRIPTOR_LIST_ENTRY;
|
||||
|
||||
typedef struct {
|
||||
HDA_BUFFER_DESCRIPTOR_LIST_ENTRY BDLEntry[HDA_BUFFER_DESC_LIST_MAX_ENTRIES];
|
||||
} HDA_BUFFER_DESCRIPTOR_LIST;
|
||||
|
||||
EFI_STATUS InitHda();
|
||||
|
||||
EFI_STATUS AllocateCORBBuffer(PCI_HDA_REGION* PcieDeviceConfigSpace);
|
||||
EFI_STATUS AllocateRIRBBuffer(PCI_HDA_REGION* PcieDeviceConfigSpace);
|
||||
|
||||
EFI_STATUS FillCodecNode(PCI_HDA_REGION *PcieDeviceConfigSpace,
|
||||
uint32_t CurrentNodeId,
|
||||
HDA_NODE_TYPE NodeType,
|
||||
struct Node *CurrentNode);
|
||||
|
||||
EFI_STATUS GetNodeById(struct Node *RootNode,
|
||||
uint32_t NodeIdToSearch,
|
||||
struct Node *NodeDetected);
|
||||
|
||||
EFI_STATUS GetCodecTree(PCI_HDA_REGION *PcieDeviceConfigSpace,
|
||||
struct Node *RootNode);
|
||||
|
||||
EFI_STATUS ReleaseCodecTree(PCI_HDA_REGION *PcieDeviceConfigSpace,
|
||||
struct Node *RootNode);
|
||||
|
||||
EFI_STATUS GetCodecData8BitPayload(PCI_HDA_REGION *PcieDeviceConfigSpace,
|
||||
uint8_t CodecAddress, uint8_t NodeId,
|
||||
HDA_VERB Verb, uint8_t VerbPayload,
|
||||
uint32_t *Response);
|
||||
|
||||
EFI_STATUS GetCodecData8BitPayloadCorbRirb(PCI_HDA_REGION *PcieDeviceConfigSpace,
|
||||
uint8_t CodecAddress, uint8_t NodeId,
|
||||
HDA_VERB Verb, uint8_t VerbPayload,
|
||||
uint32_t *Response);
|
||||
|
||||
EFI_STATUS GetCodecData16BitPayloadCorbRirb(PCI_HDA_REGION *PcieDeviceConfigSpace,
|
||||
uint8_t CodecAddress, uint8_t NodeId,
|
||||
HDA_VERB Verb, uint16_t VerbPayload,
|
||||
uint32_t *Response);
|
||||
|
||||
|
||||
EFI_STATUS SendCommandToAllWidgets8BitPayload (
|
||||
PCI_HDA_REGION *PcieDeviceConfigSpace,
|
||||
HDA_VERB Verb, uint8_t VerbPayload);
|
||||
|
||||
EFI_STATUS SendCommandToAllWidgets16BitPayload (
|
||||
PCI_HDA_REGION* PcieDeviceConfigSpace,
|
||||
HDA_VERB Verb, uint16_t VerbPayload);
|
||||
|
||||
EFI_STATUS GetCodecData16BitPayload(PCI_HDA_REGION* PcieDeviceConfigSpace,
|
||||
uint8_t CodecAddress, uint8_t NodeId,
|
||||
HDA_VERB Verb, uint16_t VerbPayload,
|
||||
uint32_t *Response);
|
||||
|
||||
uint32_t GetAmplifierGain(PCI_HDA_REGION *PcieDeviceConfigSpace,
|
||||
uint8_t NodeId, bool InputOutput,
|
||||
bool LeftRight);
|
||||
|
||||
EFI_STATUS DisablePcieInterrupts(PCI_HDA_REGION *PcieDeviceConfigSpace);
|
||||
|
||||
EFI_STATUS EnablePcieNoSnoop(PCI_HDA_REGION *PcieDeviceConfigSpace);
|
||||
|
||||
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_STATUS AllocateStreamsPages(PCI_HDA_REGION *PcieDeviceConfigSpace,
|
||||
HDA_CONTROLLER_REGISTER_SET *ControllerRegisterSet);
|
||||
|
||||
#endif /* _HDA_HDA_H */
|
289
boot/platform/uefi/drivers/intel-hda/pciconf.c
Normal file
289
boot/platform/uefi/drivers/intel-hda/pciconf.c
Normal file
|
@ -0,0 +1,289 @@
|
|||
/*********************************************************************************/
|
||||
/* Module Name: pciconf.h */
|
||||
/* 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 <print.h>
|
||||
|
||||
#include <hda.h>
|
||||
#include <pciconf.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
EFI_PCI_IO_PROTOCOL *HdaPciIoProtocol = NULL;
|
||||
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *RootBridgePciIoProtocol = NULL;
|
||||
|
||||
EFI_STATUS TearDownCommonBuffer(uint8_t *HostAddress,
|
||||
uint64_t Length,
|
||||
void *Mapping)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
Status = HdaPciIoProtocol->Unmap(HdaPciIoProtocol, Mapping);
|
||||
if (EFI_ERROR(Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = HdaPciIoProtocol->FreeBuffer(HdaPciIoProtocol, EFI_SIZE_TO_PAGES(Length), (void *)HostAddress);
|
||||
return Status;
|
||||
}
|
||||
|
||||
EFI_STATUS ReleaseHdaPciIoHandler()
|
||||
{
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
|
||||
// TODO
|
||||
/*
|
||||
Status = TearDownCommonBuffer((uint8_t *)CorbAddress, 1024, CorbMapping);
|
||||
if (!EFI_ERROR(Status)) {
|
||||
Status = TearDownCommonBuffer((uint8_t *)RirbAddress, 2048, RirbMapping);
|
||||
}
|
||||
*/
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
EFI_STATUS SetupCommonBuffer(uint8_t **HostAddress,
|
||||
uint64_t Length,
|
||||
void **Mapping,
|
||||
uint64_t Alignment)
|
||||
{
|
||||
(void)Mapping;
|
||||
(void)Alignment;
|
||||
|
||||
*HostAddress = mem_alloc(Length);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS GetHdaPciIoHandler()
|
||||
{
|
||||
EFI_HANDLE *DetectedHandles = NULL;
|
||||
EFI_UINTN DetectedHandlesCount = 0;
|
||||
EFI_UINTN CurrentHandle = 0;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
EFI_GUID PciIoProtocolGuid = EFI_PCI_IO_PROTOCOL_GUID;
|
||||
|
||||
EFI_UINTN SegmentNumber;
|
||||
EFI_UINTN BusNumber;
|
||||
EFI_UINTN DeviceNumber;
|
||||
EFI_UINTN FunctionNumber;
|
||||
|
||||
if (HdaPciIoProtocol == NULL) {
|
||||
Status = gBootServices->LocateHandleBuffer(ByProtocol,
|
||||
&PciIoProtocolGuid,
|
||||
NULL,
|
||||
&DetectedHandlesCount,
|
||||
&DetectedHandles);
|
||||
|
||||
if (!EFI_ERROR(Status)) {
|
||||
for (CurrentHandle = 0; CurrentHandle < DetectedHandlesCount; CurrentHandle++) {
|
||||
Status = gBootServices->OpenProtocol(DetectedHandles[CurrentHandle],
|
||||
&PciIoProtocolGuid,
|
||||
(VOID**) &HdaPciIoProtocol,
|
||||
gImageHandle,
|
||||
NULL,
|
||||
EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL);
|
||||
|
||||
Status = HdaPciIoProtocol->GetLocation(HdaPciIoProtocol,
|
||||
&SegmentNumber,
|
||||
&BusNumber,
|
||||
&DeviceNumber,
|
||||
&FunctionNumber);
|
||||
|
||||
debug("GetHdaPciIoHandler(): Found device %llu:%llu:%llu\n", SegmentNumber, BusNumber, DeviceNumber, FunctionNumber);
|
||||
|
||||
// This means a HDA controller was detected
|
||||
if (BusNumber == HDA_BUS && DeviceNumber == HDA_DEV && FunctionNumber == HDA_FUNC) {
|
||||
debug("Handle detected\r\n");
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
gBootServices->CloseProtocol(DetectedHandles[CurrentHandle],
|
||||
&PciIoProtocolGuid,
|
||||
gImageHandle,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
EFI_STATUS GetRootBridgeIoHandler()
|
||||
{
|
||||
EFI_UINTN handleCount = 0;
|
||||
EFI_HANDLE *DetectedHandles = NULL;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
EFI_GUID PciRootBridgeIoProtocolGuid = EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID;
|
||||
|
||||
if (RootBridgePciIoProtocol == NULL) {
|
||||
Status = gBootServices->LocateHandleBuffer(ByProtocol,
|
||||
&PciRootBridgeIoProtocolGuid,
|
||||
NULL,
|
||||
&handleCount,
|
||||
&DetectedHandles);
|
||||
|
||||
if (!EFI_ERROR(Status)) {
|
||||
Status = gBootServices->OpenProtocol(DetectedHandles[0],
|
||||
&PciRootBridgeIoProtocolGuid,
|
||||
(void **)&RootBridgePciIoProtocol,
|
||||
gImageHandle,
|
||||
NULL,
|
||||
EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL);
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
EFI_STATUS GetControllerRegisterSet(PCI_HDA_REGION *PcieDeviceConfigSpace,
|
||||
HDA_CONTROLLER_REGISTER_SET *ControllerRegisterSet)
|
||||
{
|
||||
uint64_t IssCount = 0;
|
||||
uint64_t OssCount = 0;
|
||||
uint64_t BssCount = 0;
|
||||
|
||||
uint64_t HdaControllerBar = (PcieDeviceConfigSpace->HDBARL & 0xFFFFFFF0);
|
||||
|
||||
RootBridgePciIoProtocol->Mem.Read(RootBridgePciIoProtocol, EfiPciWidthUint8, HdaControllerBar, sizeof(HDA_CONTROLLER_REGISTER_SET) / sizeof(uint8_t), (void *)ControllerRegisterSet);
|
||||
IssCount = HDA_ISS_COUNT(ControllerRegisterSet->GCAP);
|
||||
OssCount = HDA_OSS_COUNT(ControllerRegisterSet->GCAP);
|
||||
BssCount = HDA_BSS_COUNT(ControllerRegisterSet->GCAP);
|
||||
|
||||
if (IssCount > 0) {
|
||||
ControllerRegisterSet->ISS = mem_alloc(IssCount * sizeof(HDA_CONTROLLER_STREAM_DESCRIPTOR));
|
||||
memset(ControllerRegisterSet->ISS, 0, IssCount * sizeof(HDA_CONTROLLER_STREAM_DESCRIPTOR));
|
||||
RootBridgePciIoProtocol->Mem.Read(RootBridgePciIoProtocol, EfiPciWidthUint8, HdaControllerBar + CALCULATE_ISSN_OFFSET(0), (sizeof(HDA_CONTROLLER_STREAM_DESCRIPTOR) * IssCount) / sizeof(uint8_t), (void *)ControllerRegisterSet->ISS);
|
||||
}
|
||||
|
||||
if (OssCount > 0) {
|
||||
ControllerRegisterSet->OSS = mem_alloc(OssCount * sizeof(HDA_CONTROLLER_STREAM_DESCRIPTOR));
|
||||
memset(ControllerRegisterSet->OSS, 0, OssCount * sizeof(HDA_CONTROLLER_STREAM_DESCRIPTOR));
|
||||
RootBridgePciIoProtocol->Mem.Read(RootBridgePciIoProtocol, EfiPciWidthUint8, HdaControllerBar + CALCULATE_OSSN_OFFSET(0, ControllerRegisterSet->GCAP), (sizeof(HDA_CONTROLLER_STREAM_DESCRIPTOR) * OssCount) / sizeof(uint8_t), (void *)ControllerRegisterSet->OSS);
|
||||
}
|
||||
|
||||
if (BssCount > 0) {
|
||||
ControllerRegisterSet->BSS = mem_alloc(BssCount * sizeof(HDA_CONTROLLER_STREAM_DESCRIPTOR));
|
||||
RootBridgePciIoProtocol->Mem.Read(RootBridgePciIoProtocol, EfiPciWidthUint8, HdaControllerBar + CALCULATE_BSSN_OFFSET(0, ControllerRegisterSet->GCAP), (sizeof(HDA_CONTROLLER_STREAM_DESCRIPTOR) * BssCount) / sizeof(uint8_t), (void *)ControllerRegisterSet->BSS);
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS WritePciMemory(uint64_t Address,
|
||||
void *Value,
|
||||
uint64_t Count,
|
||||
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width)
|
||||
{
|
||||
return RootBridgePciIoProtocol->Mem.Write(RootBridgePciIoProtocol, Width, Address, Count, Value);
|
||||
}
|
||||
|
||||
EFI_STATUS ReadPciMemory(uint64_t Address,
|
||||
void *Value,
|
||||
uint64_t Count,
|
||||
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width)
|
||||
{
|
||||
return RootBridgePciIoProtocol->Mem.Read(RootBridgePciIoProtocol, Width, Address, Count, Value);
|
||||
}
|
||||
|
||||
EFI_STATUS WriteControllerRegister(PCI_HDA_REGION *PcieDeviceConfigSpace,
|
||||
uint64_t Offset,
|
||||
void *Value,
|
||||
uint64_t Count,
|
||||
uint8_t BarIndex,
|
||||
EFI_PCI_IO_PROTOCOL_WIDTH Width)
|
||||
{
|
||||
(void)PcieDeviceConfigSpace;
|
||||
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
EFI_UINTN VariableWidth = 0;
|
||||
|
||||
switch (Width) {
|
||||
case EfiPciWidthUint32:
|
||||
VariableWidth = sizeof(uint32_t);
|
||||
break;
|
||||
case EfiPciWidthUint16:
|
||||
VariableWidth = sizeof(uint16_t);
|
||||
break;
|
||||
case EfiPciWidthUint8:
|
||||
VariableWidth = sizeof(uint8_t);
|
||||
break;
|
||||
default:
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
void *ReadValue = mem_alloc(VariableWidth);
|
||||
memset(ReadValue, 0, VariableWidth);
|
||||
|
||||
HdaPciIoProtocol->Mem.Write(HdaPciIoProtocol, Width, BarIndex, Offset, Count, Value);
|
||||
Status = HdaPciIoProtocol->Mem.Read(HdaPciIoProtocol, Width, BarIndex, Offset, Count, ReadValue);
|
||||
|
||||
mem_free(ReadValue);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
EFI_STATUS ReadControllerRegister(PCI_HDA_REGION *PcieDeviceConfigSpace,
|
||||
EFI_UINT64 Offset,
|
||||
void *Value,
|
||||
EFI_UINTN Count,
|
||||
EFI_PCI_IO_PROTOCOL_WIDTH Width)
|
||||
{
|
||||
EFI_UINT64 HdaControllerBar = (PcieDeviceConfigSpace->HDBARL & 0xFFFFFFF0);
|
||||
return RootBridgePciIoProtocol->Mem.Read(RootBridgePciIoProtocol, (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)Width, HdaControllerBar + Offset, Count, Value);
|
||||
}
|
||||
|
||||
EFI_STATUS ReadControllerPcieConfiguration(PCI_HDA_REGION *PcieDeviceConfigSpace,
|
||||
uint64_t Offset,
|
||||
void *Value,
|
||||
uint64_t Count,
|
||||
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width)
|
||||
{
|
||||
EFI_UINT64 Address = (HDA_BUS << 24) | (HDA_DEV << 16) | (HDA_FUNC << 8) | Offset;
|
||||
return RootBridgePciIoProtocol->Pci.Read(RootBridgePciIoProtocol, Width, Address, Count, Value);
|
||||
}
|
||||
|
||||
EFI_STATUS WriteControllerPcieConfiguration(PCI_HDA_REGION *PcieDeviceConfigSpace,
|
||||
uint64_t Offset,
|
||||
void *Value,
|
||||
uint64_t Count,
|
||||
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width)
|
||||
{
|
||||
EFI_UINT64 Address = (HDA_BUS << 24) | (HDA_DEV << 16) | (HDA_FUNC << 8) | Offset;
|
||||
return RootBridgePciIoProtocol->Pci.Write(RootBridgePciIoProtocol, Width, Address, Count, Value);
|
||||
}
|
||||
|
||||
EFI_STATUS GetPcieConfigSpace(EFI_UINTN Bus,
|
||||
EFI_UINTN Device,
|
||||
EFI_UINTN Function,
|
||||
PCI_HDA_REGION *PcieDeviceConfigSpace)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
if (PcieDeviceConfigSpace == NULL) {
|
||||
debug("PcieDeviceConfigSpace==NULL\n");
|
||||
}
|
||||
debug("Width=%u\n", (sizeof(PCI_HDA_REGION) / sizeof(uint8_t)));
|
||||
Status = RootBridgePciIoProtocol->Pci.Read(RootBridgePciIoProtocol, EfiPciIoWidthUint8,
|
||||
EFI_PCI_ADDRESS(Bus, Device, Function, 0),
|
||||
sizeof(PCI_HDA_REGION) / sizeof(EFI_UINT8),
|
||||
(void *)PcieDeviceConfigSpace);
|
||||
if (EFI_ERROR(Status)) {
|
||||
debug("GetPcieConfigSpace(): %s (%x)\n", efi_status_to_str(Status), Status);
|
||||
}
|
||||
return Status;
|
||||
}
|
79
boot/platform/uefi/drivers/intel-hda/pciconf.h
Normal file
79
boot/platform/uefi/drivers/intel-hda/pciconf.h
Normal file
|
@ -0,0 +1,79 @@
|
|||
/*********************************************************************************/
|
||||
/* Module Name: pciconf.h */
|
||||
/* 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. */
|
||||
/*********************************************************************************/
|
||||
|
||||
#ifndef _HDA_PCICONF_H
|
||||
#define _HDA_PCICONF_H
|
||||
|
||||
#include <hda.h>
|
||||
#include <efi.h>
|
||||
#include <efilib.h>
|
||||
|
||||
EFI_STATUS TearDownCommonBuffer(uint8_t *HostAddress,
|
||||
uint64_t Length,
|
||||
void *Mapping);
|
||||
|
||||
EFI_STATUS ReleaseHdaPciIoHandler();
|
||||
|
||||
EFI_STATUS SetupCommonBuffer(uint8_t **HostAddress,
|
||||
uint64_t Length,
|
||||
void **Mapping,
|
||||
uint64_t Alignment);
|
||||
|
||||
EFI_STATUS GetHdaPciIoHandler();
|
||||
EFI_STATUS GetRootBridgeIoHandler();
|
||||
EFI_STATUS GetControllerRegisterSet(PCI_HDA_REGION *PcieDeviceConfigSpace,
|
||||
HDA_CONTROLLER_REGISTER_SET *ControllerRegisterSet);
|
||||
|
||||
EFI_STATUS WritePciMemory(uint64_t Address,
|
||||
void *Value,
|
||||
uint64_t Count,
|
||||
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width);
|
||||
|
||||
EFI_STATUS ReadPciMemory(uint64_t Address,
|
||||
void *Value,
|
||||
uint64_t Count,
|
||||
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width);
|
||||
|
||||
EFI_STATUS WriteControllerRegister(PCI_HDA_REGION *PcieDeviceConfigSpace,
|
||||
uint64_t Offset,
|
||||
void *Value,
|
||||
uint64_t Count,
|
||||
uint8_t BarIndex,
|
||||
EFI_PCI_IO_PROTOCOL_WIDTH Width);
|
||||
|
||||
EFI_STATUS ReadControllerRegister(PCI_HDA_REGION *PcieDeviceConfigSpace,
|
||||
EFI_UINT64 Offset,
|
||||
void *Value,
|
||||
EFI_UINTN Count,
|
||||
EFI_PCI_IO_PROTOCOL_WIDTH Width);
|
||||
|
||||
EFI_STATUS ReadControllerPcieConfiguration(PCI_HDA_REGION *PcieDeviceConfigSpace,
|
||||
uint64_t Offset,
|
||||
void *Value,
|
||||
uint64_t Count,
|
||||
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width);
|
||||
|
||||
EFI_STATUS WriteControllerPcieConfiguration(PCI_HDA_REGION *PcieDeviceConfigSpace,
|
||||
uint64_t Offset,
|
||||
void *Value,
|
||||
uint64_t Count,
|
||||
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width);
|
||||
|
||||
EFI_STATUS GetPcieConfigSpace(EFI_UINTN Bus,
|
||||
EFI_UINTN Device,
|
||||
EFI_UINTN Function,
|
||||
PCI_HDA_REGION *PcieDeviceConfigSpace);
|
||||
|
||||
#endif /* _HDA_PCICONF_H */
|
1
boot/platform/uefi/drivers/note.txt
Normal file
1
boot/platform/uefi/drivers/note.txt
Normal file
|
@ -0,0 +1 @@
|
|||
This place is for UEFI drivers only.
|
Loading…
Add table
Add a link
Reference in a new issue