Files
2026-05-18 04:02:59 -04:00

133 lines
7.0 KiB
C

#pragma once
#include <stdint.h>
#include <stdbool.h>
#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);