diff --git a/local/recipes/gpu/redox-drm/source/src/drivers/intel/cursor.rs b/local/recipes/gpu/redox-drm/source/src/drivers/intel/cursor.rs index d6427bf8da..654abe3873 100644 --- a/local/recipes/gpu/redox-drm/source/src/drivers/intel/cursor.rs +++ b/local/recipes/gpu/redox-drm/source/src/drivers/intel/cursor.rs @@ -4,7 +4,25 @@ use log::debug; use redox_driver_sys::memory::MmioRegion; use super::regs::IntelRegs; -use crate::driver::Result; +use crate::driver::{DriverError, Result}; + +const PS_CTRL_BASE: usize = 0x68180; +const PS_WIN_POS_BASE: usize = 0x68170; +const PS_WIN_SIZE_BASE: usize = 0x68174; +const PS_STRIDE: usize = 0x1000; + +const PS_SCALER_ENABLE: u32 = 1 << 31; +const PS_SCALER_MODE_7X5: u32 = 0 << 28; +const PS_FILTER_SELECT: u32 = 1 << 23; +const PS_VERT_FILTER_MASK: u32 = 0x7 << 20; +const PS_HORZ_FILTER_MASK: u32 = 0x7 << 16; +const PS_VERT_FILTER_NEAREST: u32 = 0; +const PS_HORZ_FILTER_NEAREST: u32 = 0; + +const PLANE_ROT_CTL_BASE: usize = 0x683C8; +const PLANE_ROT_CTL_ROTATE_90: u32 = 1 << 0; +const PLANE_ROT_CTL_ROTATE_180: u32 = 2 << 0; +const PLANE_ROT_CTL_ROTATE_270: u32 = 3 << 0; pub struct CursorPlane { mmio: Arc, @@ -64,4 +82,44 @@ impl CursorPlane { self.mmio.write32(pos_reg, pos_val); Ok(()) } + + pub fn enable_scaler(&self, pipe: u8, src_w: u16, src_h: u16, dst_w: u16, dst_h: u16) -> Result<()> { + let ps_ctrl = PS_CTRL_BASE + pipe as usize * PS_STRIDE; + let ps_win = PS_WIN_POS_BASE + pipe as usize * PS_STRIDE; + let ps_size = PS_WIN_SIZE_BASE + pipe as usize * PS_STRIDE; + + let win_pos = (dst_w as u32 & 0x1FFF) | ((dst_h as u32 & 0x1FFF) << 16); + self.mmio.write32(ps_win, win_pos); + self.mmio.write32(ps_size, (src_w as u32) | ((src_h as u32) << 16)); + + let ctrl = PS_SCALER_ENABLE + | PS_SCALER_MODE_7X5 + | PS_FILTER_SELECT + | PS_HORZ_FILTER_NEAREST + | PS_VERT_FILTER_NEAREST; + self.mmio.write32(ps_ctrl, ctrl); + debug!("redox-drm-intel: scaler enabled pipe={} {}x{}→{}x{}", pipe, src_w, src_h, dst_w, dst_h); + Ok(()) + } + + pub fn disable_scaler(&self, pipe: u8) -> Result<()> { + let ps_ctrl = PS_CTRL_BASE + pipe as usize * PS_STRIDE; + self.mmio.write32(ps_ctrl, 0); + debug!("redox-drm-intel: scaler disabled on pipe {}", pipe); + Ok(()) + } + + pub fn set_rotation(&self, pipe: u8, rotation: u32) -> Result<()> { + let rot = PLANE_ROT_CTL_BASE + pipe as usize * PS_STRIDE; + let val = match rotation { + 0 => 0, + 90 => PLANE_ROT_CTL_ROTATE_90, + 180 => PLANE_ROT_CTL_ROTATE_180, + 270 => PLANE_ROT_CTL_ROTATE_270, + _ => return Err(DriverError::InvalidArgument("valid rotation values: 0, 90, 180, 270")), + }; + self.mmio.write32(rot, val); + debug!("redox-drm-intel: rotation {}° set on pipe {}", rotation, pipe); + Ok(()) + } } diff --git a/local/recipes/gpu/redox-drm/source/src/drivers/intel/display_power.rs b/local/recipes/gpu/redox-drm/source/src/drivers/intel/display_power.rs index d44b944274..ed57af9b33 100644 --- a/local/recipes/gpu/redox-drm/source/src/drivers/intel/display_power.rs +++ b/local/recipes/gpu/redox-drm/source/src/drivers/intel/display_power.rs @@ -120,4 +120,42 @@ impl DisplayPower { status & SKL_ALL_WELLS == SKL_ALL_WELLS } } + + pub fn gate_ddi_wells(&self, active_ports: u8) -> Result<()> { + if !self.is_xe2 { + let ctl = self.regs.power_well_ctl(); + let current = self.mmio.read32(ctl); + let ddi_mask: u32 = (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6); + let new = if active_ports == 0 { + current & !ddi_mask + } else { + current | ddi_mask + }; + if new != current { + self.mmio.write32(ctl, new); + info!("redox-drm-intel: DDI power wells {} (active_ports={})", + if active_ports > 0 { "enabled" } else { "gated" }, active_ports); + } + } + Ok(()) + } + + pub fn gate_aux_wells(&self, active_aux: u8) -> Result<()> { + if !self.is_xe2 { + let ctl = self.regs.power_well_ctl(); + let current = self.mmio.read32(ctl); + let aux_mask: u32 = (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11); + let new = if active_aux == 0 { + current & !aux_mask + } else { + current | aux_mask + }; + if new != current { + self.mmio.write32(ctl, new); + info!("redox-drm-intel: AUX power wells {} (active_aux={})", + if active_aux > 0 { "enabled" } else { "gated" }, active_aux); + } + } + Ok(()) + } } diff --git a/local/recipes/gpu/redox-drm/source/src/drivers/intel/gt.rs b/local/recipes/gpu/redox-drm/source/src/drivers/intel/gt.rs index d1373ff36e..ded8de9979 100644 --- a/local/recipes/gpu/redox-drm/source/src/drivers/intel/gt.rs +++ b/local/recipes/gpu/redox-drm/source/src/drivers/intel/gt.rs @@ -395,6 +395,16 @@ impl IntelGtManager { self.target_freq * 50 } + pub fn gpu_stats(&self) -> GpuStats { + GpuStats { + wakeref_count: self.wakeref_count, + forcewake_active: self.forcewake_active, + rc6_enabled: self.rc6_enabled, + target_freq_mhz: self.target_freq * 50, + current_freq_mhz: self.current_frequency_mhz(), + } + } + fn init_cache_config(&mut self) -> Result<()> { debug!("redox-drm-intel: configuring L3 cache"); @@ -487,3 +497,12 @@ impl IntelGtManager { self.forcewake_active } } + +#[derive(Clone, Debug)] +pub struct GpuStats { + pub wakeref_count: u32, + pub forcewake_active: bool, + pub rc6_enabled: bool, + pub target_freq_mhz: u32, + pub current_freq_mhz: u32, +}