intel: refactor display.rs to use IntelRegs trait

Replace all hardcoded Gen9 register constants in display.rs with
IntelRegs trait method calls, making the display code multi-generation.

- display.rs: add regs: &'static dyn IntelRegs to IntelDisplay struct.
  Replace PIPECONF_BASE→regs.pipeconf(), DSPCNTR_BASE→regs.dspcntr(),
  DSPSURF_BASE→regs.dspsurf(), HTOTAL_BASE→regs.htotal(), etc.
  Remove pipe_offset/ddi_offset helper functions (dead code).
  Update detect_pipes(), connected_ports(), detect_connectors(),
  set_mode(), page_flip() to use regs trait.
- mod.rs: pass regs to IntelDisplay::new()

PP_STATUS constant only remaining — replaced with regs.pp_status().

Compiled: 0 new errors (pre-existing redox-driver-sys errors unrelated)
This commit is contained in:
2026-05-30 07:50:16 +03:00
parent 2ee9efd8d0
commit 05fe1ab2b7
2 changed files with 31 additions and 54 deletions
@@ -3,6 +3,7 @@ use std::sync::Mutex;
use log::{debug, info};
use redox_driver_sys::memory::MmioRegion;
use super::regs::IntelRegs;
use crate::driver::{DriverError, Result};
use crate::kms::connector::synthetic_edid;
use crate::kms::{ConnectorInfo, ConnectorStatus, ConnectorType, ModeInfo};
@@ -10,24 +11,6 @@ use crate::kms::{ConnectorInfo, ConnectorStatus, ConnectorType, ModeInfo};
const PIPE_COUNT: usize = 4;
const PORT_COUNT: usize = 6;
const PP_STATUS: usize = 0xC7200;
const PIPECONF_BASE: usize = 0x70008;
const DSPCNTR_BASE: usize = 0x70180;
const DSPSURF_BASE: usize = 0x7019C;
const DDI_BUF_CTL_BASE: usize = 0x64000;
const HTOTAL_BASE: usize = 0x60000;
const HBLANK_BASE: usize = 0x60004;
const HSYNC_BASE: usize = 0x60008;
const VTOTAL_BASE: usize = 0x6000C;
const VBLANK_BASE: usize = 0x60010;
const VSYNC_BASE: usize = 0x60014;
const PIPE_SRC_BASE: usize = 0x6001C;
const PLANE_SIZE_BASE: usize = 0x70190;
const PIPE_STRIDE: usize = 0x1000;
const PORT_STRIDE: usize = 0x100;
const PIPECONF_ENABLE: u32 = 1 << 31;
const DSPCNTR_ENABLE: u32 = 1 << 31;
const DDI_BUF_CTL_ENABLE: u32 = 1 << 31;
@@ -42,11 +25,12 @@ pub struct DisplayPipe {
pub struct IntelDisplay {
mmio: MmioRegion,
pipes: Mutex<Vec<DisplayPipe>>,
regs: &'static dyn IntelRegs,
}
impl IntelDisplay {
pub fn new(mmio: MmioRegion) -> Result<Self> {
let pipes = Self::detect_pipes(&mmio)?;
pub fn new(mmio: MmioRegion, regs: &'static dyn IntelRegs) -> Result<Self> {
let pipes = Self::detect_pipes(&mmio, regs)?;
info!(
"redox-drm: Intel display initialized with {} pipe(s)",
pipes.len()
@@ -54,6 +38,7 @@ impl IntelDisplay {
Ok(Self {
mmio,
pipes: Mutex::new(pipes),
regs,
})
}
@@ -72,13 +57,13 @@ impl IntelDisplay {
.ok_or_else(|| DriverError::NotFound(format!("unknown Intel pipe for CRTC {crtc_id}")))
}
pub fn detect_pipes(mmio: &MmioRegion) -> Result<Vec<DisplayPipe>> {
pub fn detect_pipes(mmio: &MmioRegion, regs: &dyn IntelRegs) -> Result<Vec<DisplayPipe>> {
let mut pipes = Vec::with_capacity(PIPE_COUNT);
let pp_status = read32(mmio, PP_STATUS).unwrap_or(0);
let connected_ports = connected_ports(mmio);
let pp_status = read32(mmio, regs.pp_status()).unwrap_or(0);
let connected_ports = connected_ports(mmio, regs);
for index in 0..PIPE_COUNT {
let conf = read32(mmio, pipe_offset(PIPECONF_BASE, index))?;
let conf = read32(mmio, regs.pipeconf(index as u8))?;
let enabled = conf & PIPECONF_ENABLE != 0;
let mut port = connected_ports.get(index).copied();
@@ -106,12 +91,12 @@ impl IntelDisplay {
}
pub fn detect_connectors(&self) -> Result<Vec<ConnectorInfo>> {
let pp_status = self.read32(PP_STATUS).unwrap_or(0);
let pp_status = self.read32(self.regs.pp_status()).unwrap_or(0);
let pipes = self.refresh_pipes()?;
let mut connectors = Vec::with_capacity(PORT_COUNT);
for port in 0..PORT_COUNT as u8 {
let status = self.read32(ddi_offset(port)).unwrap_or(0);
let status = self.read32(self.regs.ddi_buf_ctl(port)).unwrap_or(0);
let connected = status & DDI_BUF_CTL_ENABLE != 0
|| pipes
.iter()
@@ -167,7 +152,7 @@ impl IntelDisplay {
}
pub fn read_dpcd(&self, port: u8) -> Vec<u8> {
let status = self.read32(ddi_offset(port)).unwrap_or(0);
let status = self.read32(self.regs.ddi_buf_ctl(port)).unwrap_or(0);
if status & DDI_BUF_CTL_ENABLE == 0 {
return Vec::new();
}
@@ -179,50 +164,50 @@ impl IntelDisplay {
pub fn set_mode(&self, pipe: &DisplayPipe, mode: &ModeInfo) -> Result<()> {
let index = usize::from(pipe.index);
self.write32(
pipe_offset(HTOTAL_BASE, index),
self.regs.htotal(index as u8),
pack_pair(mode.htotal, mode.hdisplay),
)?;
self.write32(
pipe_offset(HBLANK_BASE, index),
self.regs.hblank(index as u8),
pack_pair(mode.htotal, mode.hdisplay),
)?;
self.write32(
pipe_offset(HSYNC_BASE, index),
self.regs.hsync(index as u8),
pack_pair(mode.hsync_end, mode.hsync_start),
)?;
self.write32(
pipe_offset(VTOTAL_BASE, index),
self.regs.vtotal(index as u8),
pack_pair(mode.vtotal, mode.vdisplay),
)?;
self.write32(
pipe_offset(VBLANK_BASE, index),
self.regs.vblank(index as u8),
pack_pair(mode.vtotal, mode.vdisplay),
)?;
self.write32(
pipe_offset(VSYNC_BASE, index),
self.regs.vsync(index as u8),
pack_pair(mode.vsync_end, mode.vsync_start),
)?;
self.write32(
pipe_offset(PIPE_SRC_BASE, index),
self.regs.pipe_src(index as u8),
pack_pair(mode.vdisplay, mode.hdisplay),
)?;
self.write32(
pipe_offset(PLANE_SIZE_BASE, index),
self.regs.plane_size(index as u8),
pack_pair(mode.vdisplay, mode.hdisplay),
)?;
let mut dspcntr = self.read32(pipe_offset(DSPCNTR_BASE, index))?;
let mut dspcntr = self.read32(self.regs.dspcntr(index as u8))?;
dspcntr |= DSPCNTR_ENABLE;
self.write32(pipe_offset(DSPCNTR_BASE, index), dspcntr)?;
self.write32(self.regs.dspcntr(index as u8), dspcntr)?;
let mut pipeconf = self.read32(pipe_offset(PIPECONF_BASE, index))?;
let mut pipeconf = self.read32(self.regs.pipeconf(index as u8))?;
pipeconf |= PIPECONF_ENABLE;
self.write32(pipe_offset(PIPECONF_BASE, index), pipeconf)?;
self.write32(self.regs.pipeconf(index as u8), pipeconf)?;
if let Some(port) = pipe.port {
let mut ddi = self.read32(ddi_offset(port))?;
let mut ddi = self.read32(self.regs.ddi_buf_ctl(port))?;
ddi |= DDI_BUF_CTL_ENABLE;
self.write32(ddi_offset(port), ddi)?;
self.write32(self.regs.ddi_buf_ctl(port), ddi)?;
}
self.update_pipe(pipe.index, true, pipe.port)?;
@@ -233,12 +218,12 @@ impl IntelDisplay {
pub fn page_flip(&self, pipe: &DisplayPipe, fb_addr: u64) -> Result<()> {
if fb_addr > u64::from(u32::MAX) {
self.write32(
pipe_offset(DSPSURF_BASE, usize::from(pipe.index)),
self.regs.dspsurf(pipe.index),
(fb_addr >> 32) as u32,
)?;
}
let index = usize::from(pipe.index);
self.write32(pipe_offset(DSPSURF_BASE, index), fb_addr as u32)
self.write32(self.regs.dspsurf(index as u8), fb_addr as u32)
}
fn refresh_pipes(&self) -> Result<Vec<DisplayPipe>> {
@@ -311,10 +296,10 @@ impl IntelDisplay {
}
}
fn connected_ports(mmio: &MmioRegion) -> Vec<u8> {
fn connected_ports(mmio: &MmioRegion, regs: &dyn IntelRegs) -> Vec<u8> {
let mut ports = Vec::new();
for port in 0..PORT_COUNT as u8 {
if read32(mmio, ddi_offset(port)).unwrap_or(0) & DDI_BUF_CTL_ENABLE != 0 {
if read32(mmio, regs.ddi_buf_ctl(port)).unwrap_or(0) & DDI_BUF_CTL_ENABLE != 0 {
ports.push(port);
}
}
@@ -354,14 +339,6 @@ fn ensure_access(mmio_size: usize, offset: usize, width: usize, op: &str) -> Res
Ok(())
}
fn pipe_offset(base: usize, index: usize) -> usize {
base + index * PIPE_STRIDE
}
fn ddi_offset(port: u8) -> usize {
DDI_BUF_CTL_BASE + usize::from(port) * PORT_STRIDE
}
fn pack_pair(upper: u16, lower: u16) -> u32 {
((u32::from(upper).saturating_sub(1)) << 16) | u32::from(lower).saturating_sub(1)
}
@@ -184,7 +184,7 @@ impl IntelDriver {
cdclk_state.frequency_khz, cdclk_state.voltage_level
);
let display = IntelDisplay::new(display_mmio)?;
let display = IntelDisplay::new(display_mmio, regs)?;
let mut gtt = IntelGtt::init(gtt_mmio, gtt_control_mmio)?;
let mut ring = IntelRing::create(ring_mmio, RingType::Render)?;
ring.bind_gtt(&mut gtt)?;