#pragma once #include #include #include "arch/x86_64/bus/pci.h" /* ── HDA MMIO register offsets ─────────────────────────────────────────────── */ #define HDA_GCAP 0x00 /* u16 Global Capabilities */ #define HDA_VMIN 0x02 /* u8 Minor Version */ #define HDA_VMAJ 0x03 /* u8 Major Version */ #define HDA_OUTPAY 0x04 /* u16 Output Payload Capability */ #define HDA_INPAY 0x06 /* u16 Input Payload Capability */ #define HDA_GCTL 0x08 /* u32 Global Control */ #define HDA_WAKEEN 0x0C /* u16 Wake Enable */ #define HDA_STATESTS 0x0E /* u16 State Change Status (one bit per codec) */ #define HDA_GSTS 0x10 /* u16 Global Status */ #define HDA_INTCTL 0x20 /* u32 Interrupt Control */ #define HDA_INTSTS 0x24 /* u32 Interrupt Status */ #define HDA_WALCLK 0x30 /* u32 Wall Clock Counter */ #define HDA_SSYNC 0x38 /* u32 Stream Synchronisation */ /* CORB */ #define HDA_CORBLBASE 0x40 /* u32 CORB Lower Base Address */ #define HDA_CORBUBASE 0x44 /* u32 CORB Upper Base Address */ #define HDA_CORBWP 0x48 /* u16 CORB Write Pointer */ #define HDA_CORBRP 0x4A /* u16 CORB Read Pointer */ #define HDA_CORBCTL 0x4C /* u8 CORB Control */ #define HDA_CORBSTS 0x4D /* u8 CORB Status */ #define HDA_CORBSIZE 0x4E /* u8 CORB Size */ /* RIRB */ #define HDA_RIRBLBASE 0x50 /* u32 RIRB Lower Base Address */ #define HDA_RIRBUBASE 0x54 /* u32 RIRB Upper Base Address */ #define HDA_RIRBWP 0x58 /* u16 RIRB Write Pointer (hardware-maintained)*/ #define HDA_RINTCNT 0x5A /* u16 Response Interrupt Count */ #define HDA_RIRBCTL 0x5C /* u8 RIRB Control */ #define HDA_RIRBSTS 0x5D /* u8 RIRB Status */ #define HDA_RIRBSIZE 0x5E /* u8 RIRB Size */ /* Stream Descriptor register offsets (relative to the SD's MMIO base) */ #define HDA_SD_CTL0 0x00 /* u8 Control byte 0 (SRST, RUN, IOCE …) */ #define HDA_SD_CTL1 0x01 /* u8 Control byte 1 */ #define HDA_SD_CTL2 0x02 /* u8 Control byte 2 bits[7:4] = stream tag */ #define HDA_SD_STS 0x03 /* u8 Status bit2=BCIS bit3=FIFOE bit4=DESE */ #define HDA_SD_LPIB 0x04 /* u32 Link Position in Buffer */ #define HDA_SD_CBL 0x08 /* u32 Cyclic Buffer Length */ #define HDA_SD_LVI 0x0C /* u16 Last Valid Index */ #define HDA_SD_FIFOS 0x10 /* u16 FIFO Size (read-only) */ #define HDA_SD_FMT 0x12 /* u16 Format */ #define HDA_SD_BDPL 0x18 /* u32 BDL Lower Base Address */ #define HDA_SD_BDPU 0x1C /* u32 BDL Upper Base Address */ #define HDA_SD_STRIDE 0x20 /* Each stream descriptor is 0x20 bytes wide */ /* GCTL bits */ #define HDA_GCTL_CRST (1u << 0) /* Controller Reset (0 = reset, 1 = run) */ #define HDA_GCTL_UNSOL (1u << 8) /* Accept Unsolicited Responses */ /* SD CTL byte-0 bits */ #define HDA_SD_CTL_SRST (1u << 0) /* Stream Reset */ #define HDA_SD_CTL_RUN (1u << 1) /* Stream Run */ #define HDA_SD_CTL_IOCE (1u << 2) /* Interrupt on Completion Enable */ #define HDA_SD_CTL_FEIE (1u << 3) /* FIFO Error Interrupt Enable */ #define HDA_SD_CTL_DEIE (1u << 4) /* Descriptor Error Interrupt Enable */ /* SD STS bits */ #define HDA_SD_STS_BCIS (1u << 2) /* Buffer Completion Interrupt Status */ #define HDA_SD_STS_FIFOE (1u << 3) /* FIFO Error */ #define HDA_SD_STS_DESE (1u << 4) /* Descriptor Error */ /* Codec widget types (from AUDIO_WIDGET_CAP bits[23:20]) */ #define HDA_WTYPE_AUDIO_OUT 0x0 #define HDA_WTYPE_AUDIO_IN 0x1 #define HDA_WTYPE_AUDIO_MIXER 0x2 #define HDA_WTYPE_AUDIO_SEL 0x3 #define HDA_WTYPE_PIN 0x4 /* Codec parameter IDs (used with GET_PARAM verb 0xF00) */ #define HDA_PARAM_VENDOR_ID 0x00 #define HDA_PARAM_NODE_COUNT 0x04 #define HDA_PARAM_FUNC_GROUP_TYPE 0x05 #define HDA_PARAM_AUDIO_WIDGET_CAP 0x09 #define HDA_PARAM_SUPPORTED_PCM 0x0A #define HDA_PARAM_PIN_CAPABILITIES 0x0C #define HDA_PARAM_CONN_LIST_LEN 0x0E #define HDA_PARAM_AMP_CAP_OUTPUT 0x12 /* Pin capability bits */ #define HDA_PINCAP_OUTPUT (1u << 4) #define HDA_PINCAP_INPUT (1u << 5) /* ── Types ─────────────────────────────────────────────────────────────────── */ typedef struct { uint32_t sample_rate; uint8_t channels; /* 1 = mono, 2 = stereo */ uint8_t bits_per_sample; /* 8 / 16 / 20 / 24 / 32 */ } hda_format_t; /* Buffer Descriptor List entry (must be 128-byte aligned; page-aligned is fine) */ typedef struct __attribute__((packed)) { uint64_t addr; /* Physical address of the audio buffer */ uint32_t length; /* Length in bytes */ uint32_t flags; /* Bit 0 = IOC (Interrupt on Completion) */ } hda_bdl_entry_t; /* ── Public API ─────────────────────────────────────────────────────────────── */ /** * hda_init - find, map, and initialise the first HDA controller on the bus. * @dev: PCI device struct returned by pci_find_hda(). * Returns true on success. */ bool hda_init(pci_device_t *dev); /** * hda_play_pcm - set up an output stream and start playback. * @phys_buf : physical address of the audio data (from pmm_alloc). * @size : byte count of the audio data. * @fmt : sample rate / channel count / bit depth. * Returns true if the stream was started successfully. */ bool hda_play_pcm(uintptr_t phys_buf, uint32_t size, hda_format_t fmt); /** * hda_wait_complete - block until the current stream finishes (polls BCIS). * Stops and resets the stream when done. */ void hda_wait_complete(void); /** hda_stop - immediately stop the output stream. */ void hda_stop(void); /** hda_is_playing - returns true while the stream is running and not done. */ bool hda_is_playing(void);