688 lines
20 KiB
C
688 lines
20 KiB
C
/*********************************************************************************/
|
|
/* 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 */
|