CloverBootloader/Drivers/AudioDxe/HdaController/HdaController.h

464 lines
11 KiB
C
Raw Normal View History

/*
* File: HdaController.h
*
* Copyright (c) 2018 John Davis
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* 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.
*/
#ifndef _EFI_HDA_CONTROLLER_H_
#define _EFI_HDA_CONTROLLER_H_
#include "AudioDxe.h"
#include <Library/HdaRegisters.h>
//#include <Library/HdaModels.h>
//
// Consumed protocols.
//
#include <Protocol/PciIo.h>
#include <IndustryStandard/Pci.h>
//
// Structs.
//
typedef struct _HDA_CONTROLLER_DEV HDA_CONTROLLER_DEV;
typedef struct _HDA_IO_PRIVATE_DATA HDA_IO_PRIVATE_DATA;
typedef struct _HDA_CONTROLLER_INFO_PRIVATE_DATA HDA_CONTROLLER_INFO_PRIVATE_DATA;
// Signature for private data structures.
#define HDA_CONTROLLER_PRIVATE_DATA_SIGNATURE SIGNATURE_32('H','d','a','C')
//
// PCI support.
//
// Structure used for PCI class code parsing.
#pragma pack(1)
typedef struct {
UINT8 ProgInterface;
UINT8 SubClass;
UINT8 Class;
} HDA_PCI_CLASSREG;
#pragma pack()
// HDA controller subclass.
#define PCI_CLASS_MEDIA_HDA 0x3
// HDA controller is accessed via MMIO on BAR #0.
#define PCI_HDA_BAR 0
// Min supported version.
#define HDA_VERSION_MIN_MAJOR 0x1
#define HDA_VERSION_MIN_MINOR 0x0
#define HDA_MAX_CODECS 15
#define PCI_HDA_TCSEL_OFFSET 0x44
#define PCI_HDA_TCSEL_TC0_MASK ~(BIT0 | BIT1 | BIT2)
#define PCI_HDA_DEVC_OFFSET 0x78
#define PCI_HDA_DEVC_NOSNOOPEN BIT11
//
// CORB and RIRB.
//
// Entry sizes.
#define HDA_CORB_ENTRY_SIZE sizeof(UINT32)
#define HDA_RIRB_ENTRY_SIZE sizeof(UINT64)
// Misc.
#define HDA_CORB_VERB(Cad, Nid, Verb) ((((UINT32)Cad) << 28) | (((UINT32)Nid) << 20) | (Verb & 0xFFFFF))
#define HDA_RIRB_RESP(Response) ((UINT32)Response)
#define HDA_RIRB_CAD(Response) ((Response >> 32) & 0xF)
#define HDA_RIRB_UNSOL(Response) ((Response >> 36) & 0x1)
//
// Streams.
//
// Buffer Descriptor List Entry.
#pragma pack(1)
typedef struct {
UINT32 Address;
UINT32 AddressHigh;
UINT32 Length;
UINT32 InterruptOnCompletion;
} HDA_BDL_ENTRY;
#pragma pack()
// Buffer Descriptor List sizes. Max number of entries is 256, min is 2.
#define HDA_BDL_ENTRY_IOC BIT0
#define HDA_BDL_ENTRY_COUNT 8
#define HDA_BDL_SIZE (sizeof(HDA_BDL_ENTRY) * HDA_BDL_ENTRY_COUNT)
#define HDA_BDL_ENTRY_HALF ((HDA_BDL_ENTRY_COUNT / 2) - 1)
#define HDA_BDL_ENTRY_LAST (HDA_BDL_ENTRY_COUNT - 1)
// Buffer size and block size.
#define HDA_STREAM_BUF_SIZE BASE_512KB
#define HDA_STREAM_BUF_SIZE_HALF (HDA_STREAM_BUF_SIZE / 2)
#define HDA_BDL_BLOCKSIZE (HDA_STREAM_BUF_SIZE / HDA_BDL_ENTRY_COUNT)
#define HDA_STREAM_POLL_TIME (EFI_TIMER_PERIOD_MILLISECONDS(100))
// DMA position structure.
#pragma pack(1)
typedef struct {
UINT32 Position;
UINT32 Reserved;
} HDA_DMA_POS_ENTRY;
#pragma pack()
// Stream types.
#define HDA_STREAM_TYPE_BIDIR 0
#define HDA_STREAM_TYPE_IN 1
#define HDA_STREAM_TYPE_OUT 2
#define HDA_STREAM_ID_MIN 1
#define HDA_STREAM_ID_MAX 15
// Stream structure.
typedef struct {
// Parent controller, type, and index.
HDA_CONTROLLER_DEV *HdaControllerDev;
UINT8 Type;
UINT8 Index;
BOOLEAN Output;
// Buffer Descriptor List.
HDA_BDL_ENTRY *BufferList;
VOID *BufferListMapping;
EFI_PHYSICAL_ADDRESS BufferListPhysAddr;
// DMA data buffer fed into BDL.
UINT8 *BufferData;
VOID *BufferDataMapping;
EFI_PHYSICAL_ADDRESS BufferDataPhysAddr;
// Source buffer.
UINT8 *BufferSource;
UINTN BufferSourceLength;
UINTN BufferSourcePosition;
BOOLEAN BufferSourceDone;
// Timing elements for buffer filling.
EFI_EVENT PollTimer;
EFI_HDA_IO_STREAM_CALLBACK Callback;
VOID *CallbackContext1;
VOID *CallbackContext2;
VOID *CallbackContext3;
} HDA_STREAM;
typedef struct {
EFI_HANDLE Handle;
HDA_IO_PRIVATE_DATA *PrivateData;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
} HDA_IO_CHILD;
struct _HDA_CONTROLLER_DEV {
// Signature.
UINTN Signature;
// Consumed protocols and handles.
EFI_PCI_IO_PROTOCOL *PciIo;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
EFI_HANDLE ControllerHandle;
// PCI.
UINT64 OriginalPciAttributes;
BOOLEAN OriginalPciAttributesSaved;
// Published info protocol.
HDA_CONTROLLER_INFO_PRIVATE_DATA *HdaControllerInfoData;
HDA_IO_CHILD HdaIoChildren[HDA_MAX_CODECS];
// Capabilites.
UINT32 VendorId;
CHAR16 *Name;
UINT8 MajorVersion;
UINT8 MinorVersion;
UINT16 Capabilities;
// Command output buffer (CORB).
UINT32 *CorbBuffer;
UINT32 CorbEntryCount;
VOID *CorbMapping;
EFI_PHYSICAL_ADDRESS CorbPhysAddr;
UINT16 CorbWritePointer;
// Response input buffer (RIRB).
UINT64 *RirbBuffer;
UINT32 RirbEntryCount;
VOID *RirbMapping;
EFI_PHYSICAL_ADDRESS RirbPhysAddr;
UINT16 RirbReadPointer;
// Streams.
UINT8 TotalStreamsCount;
UINT8 BidirStreamsCount;
UINT8 InputStreamsCount;
UINT8 OutputStreamsCount;
HDA_STREAM *BidirStreams;
HDA_STREAM *InputStreams;
HDA_STREAM *OutputStreams;
// DMA positions.
HDA_DMA_POS_ENTRY *DmaPositions;
UINTN DmaPositionsSize;
VOID *DmaPositionsMapping;
EFI_PHYSICAL_ADDRESS DmaPositionsPhysAddr;
// Bitmap for stream ID allocation.
UINT16 StreamIdMapping;
// Events.
EFI_EVENT ResponsePollTimer;
EFI_EVENT ExitBootServiceEvent;
SPIN_LOCK SpinLock;
};
// HDA I/O private data.
struct _HDA_IO_PRIVATE_DATA {
// Signature.
UINTN Signature;
// HDA I/O protocol.
EFI_HDA_IO_PROTOCOL HdaIo;
UINT8 HdaCodecAddress;
// Assigned streams.
HDA_STREAM *HdaOutputStream;
HDA_STREAM *HdaInputStream;
// HDA controller device.
HDA_CONTROLLER_DEV *HdaControllerDev;
};
#define HDA_IO_PRIVATE_DATA_FROM_THIS(This) \
CR(This, HDA_IO_PRIVATE_DATA, HdaIo, HDA_CONTROLLER_PRIVATE_DATA_SIGNATURE)
// HDA Codec Info private data.
struct _HDA_CONTROLLER_INFO_PRIVATE_DATA {
// Signature.
UINTN Signature;
// HDA Codec Info protocol.
EFI_HDA_CONTROLLER_INFO_PROTOCOL HdaControllerInfo;
// HDA controller device.
HDA_CONTROLLER_DEV *HdaControllerDev;
};
#define HDA_CONTROLLER_INFO_PRIVATE_DATA_FROM_THIS(This) \
CR(This, HDA_CONTROLLER_INFO_PRIVATE_DATA, HdaControllerInfo, HDA_CONTROLLER_PRIVATE_DATA_SIGNATURE)
//
// HDA I/O protocol functions.
//
EFI_STATUS
EFIAPI
HdaControllerHdaIoGetAddress(
IN EFI_HDA_IO_PROTOCOL *This,
OUT UINT8 *CodecAddress);
EFI_STATUS
EFIAPI
HdaControllerHdaIoSendCommand(
IN EFI_HDA_IO_PROTOCOL *This,
IN UINT8 Node,
IN UINT32 Verb,
OUT UINT32 *Response);
EFI_STATUS
EFIAPI
HdaControllerHdaIoSendCommands(
IN EFI_HDA_IO_PROTOCOL *This,
IN UINT8 Node,
IN EFI_HDA_IO_VERB_LIST *Verbs);
EFI_STATUS
EFIAPI
HdaControllerHdaIoSetupStream(
IN EFI_HDA_IO_PROTOCOL *This,
IN EFI_HDA_IO_PROTOCOL_TYPE Type,
IN UINT16 Format,
OUT UINT8 *StreamId);
EFI_STATUS
EFIAPI
HdaControllerHdaIoCloseStream(
IN EFI_HDA_IO_PROTOCOL *This,
IN EFI_HDA_IO_PROTOCOL_TYPE Type);
EFI_STATUS
EFIAPI
HdaControllerHdaIoGetStream(
IN EFI_HDA_IO_PROTOCOL *This,
IN EFI_HDA_IO_PROTOCOL_TYPE Type,
OUT BOOLEAN *State);
EFI_STATUS
EFIAPI
HdaControllerHdaIoStartStream(
IN EFI_HDA_IO_PROTOCOL *This,
IN EFI_HDA_IO_PROTOCOL_TYPE Type,
IN VOID *Buffer,
IN UINTN BufferLength,
IN UINTN BufferPosition OPTIONAL,
IN EFI_HDA_IO_STREAM_CALLBACK Callback OPTIONAL,
IN VOID *Context1 OPTIONAL,
IN VOID *Context2 OPTIONAL,
IN VOID *Context3 OPTIONAL);
EFI_STATUS
EFIAPI
HdaControllerHdaIoStopStream(
IN EFI_HDA_IO_PROTOCOL *This,
IN EFI_HDA_IO_PROTOCOL_TYPE Type);
//
// HDA Controller Info protcol functions.
//
EFI_STATUS
EFIAPI
HdaControllerInfoGetName(
IN EFI_HDA_CONTROLLER_INFO_PROTOCOL *This,
OUT CHAR16 **ControllerName);
//
// HDA controller internal functions.
//
VOID
EFIAPI
HdaControllerStreamPollTimerHandler(
IN EFI_EVENT Event,
IN VOID *Context);
EFI_STATUS
EFIAPI
HdaControllerReset(
IN HDA_CONTROLLER_DEV *HdaControllerDev);
EFI_STATUS
EFIAPI
HdaControllerSendCommands(
IN HDA_CONTROLLER_DEV *HdaDev,
IN UINT8 CodecAddress,
IN UINT8 Node,
IN EFI_HDA_IO_VERB_LIST *Verbs);
EFI_STATUS
EFIAPI
HdaControllerInitCorb(
IN HDA_CONTROLLER_DEV *HdaDev);
EFI_STATUS
EFIAPI
HdaControllerCleanupCorb(
IN HDA_CONTROLLER_DEV *HdaDev);
EFI_STATUS
EFIAPI
HdaControllerSetCorb(
IN HDA_CONTROLLER_DEV *HdaDev,
IN BOOLEAN Enable);
EFI_STATUS
EFIAPI
HdaControllerInitRirb(
IN HDA_CONTROLLER_DEV *HdaDev);
EFI_STATUS
EFIAPI
HdaControllerCleanupRirb(
IN HDA_CONTROLLER_DEV *HdaDev);
EFI_STATUS
EFIAPI
HdaControllerSetRirb(
IN HDA_CONTROLLER_DEV *HdaDev,
IN BOOLEAN Enable);
EFI_STATUS
EFIAPI
HdaControllerInitStreams(
IN HDA_CONTROLLER_DEV *HdaDev);
EFI_STATUS
EFIAPI
HdaControllerResetStream(
IN HDA_STREAM *HdaStream);
VOID
EFIAPI
HdaControllerCleanupStreams(
IN HDA_CONTROLLER_DEV *HdaControllerDev);
EFI_STATUS
EFIAPI
HdaControllerGetStream(
IN HDA_STREAM *HdaStream,
OUT BOOLEAN *Run);
EFI_STATUS
EFIAPI
HdaControllerSetStream(
IN HDA_STREAM *HdaStream,
IN BOOLEAN Run);
EFI_STATUS
EFIAPI
HdaControllerGetStreamLinkPos(
IN HDA_STREAM *HdaStream,
OUT UINT32 *Position);
EFI_STATUS
EFIAPI
HdaControllerGetStreamId(
IN HDA_STREAM *HdaStream,
OUT UINT8 *Index);
EFI_STATUS
EFIAPI
HdaControllerSetStreamId(
IN HDA_STREAM *HdaStream,
IN UINT8 Index);
//
// Driver Binding protocol functions.
//
EFI_STATUS
EFIAPI
HdaControllerDriverBindingSupported(
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL);
EFI_STATUS
EFIAPI
HdaControllerDriverBindingStart(
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL);
EFI_STATUS
EFIAPI
HdaControllerDriverBindingStop(
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer OPTIONAL);
#endif