intel: scaler/rotation, display power gating, GPU statistics
- cursor.rs: plane scaler (PS_CTRL/PS_WIN/PS_SIZE) with nearest filter, rotation property (0/90/180/270) via PLANE_ROT_CTL registers - display_power.rs: gate_ddi_wells + gate_aux_wells per active port count - gt.rs: GpuStats struct and gpu_stats() method for utilization reporting
This commit is contained in:
@@ -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<MmioRegion>,
|
||||
@@ -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(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user