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:
@@ -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)?;
|
||||
|
||||
Reference in New Issue
Block a user