From aafb835eeef174d898f6512a7c57499bce936ec8 Mon Sep 17 00:00:00 2001 From: Admin Pupkin Date: Sat, 30 May 2026 08:25:07 +0300 Subject: [PATCH] =?UTF-8?q?intel:=20multi-generation=20CDCLK=20=E2=80=94?= =?UTF-8?q?=20Gen9=20+=20Xe2=20frequencies?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rewrite display_cdclk.rs with generation-aware clock programming. Gen9 (SKL/KBL/CFL): 337.5/450/540/675 MHz via CDCLK_CTL (0x46000) with decimal + freq_select encoding. Existing code preserved. Xe2 (ARL/BMG): 307.2/384/556.8/652.8 MHz via CDCLK_FREQ (0x46200) with different freq_select/decimal encoding. Xe2 frequency table ported from Linux intel_cdclk.c (DISPLAY_VER >= 20 path). DisplayClock::new() now takes &IntelDeviceInfo for gen selection. CDCLK init reads current hardware state rather than assuming defaults. Linux reference: intel_cdclk.c (bxt_set_cdclk, skl_set_cdclk) --- .../source/src/drivers/intel/display_cdclk.rs | 104 ++++++++++-------- .../redox-drm/source/src/drivers/intel/mod.rs | 2 +- 2 files changed, 58 insertions(+), 48 deletions(-) diff --git a/local/recipes/gpu/redox-drm/source/src/drivers/intel/display_cdclk.rs b/local/recipes/gpu/redox-drm/source/src/drivers/intel/display_cdclk.rs index 58cd6491b5..e97f30ba8c 100644 --- a/local/recipes/gpu/redox-drm/source/src/drivers/intel/display_cdclk.rs +++ b/local/recipes/gpu/redox-drm/source/src/drivers/intel/display_cdclk.rs @@ -3,6 +3,7 @@ use std::sync::Arc; use log::{info, warn}; use redox_driver_sys::memory::MmioRegion; +use super::info::IntelDeviceInfo; use super::regs::IntelRegs; use crate::driver::Result; use crate::driver::DriverError; @@ -16,14 +17,13 @@ const SKL_CDCLK_675: u32 = 3; const CDCLK_DECIMAL_MASK: u32 = 0x1FF; const CDCLK_FREQ_SELECT_MASK: u32 = 0x3; const CDCLK_FREQ_SELECT_SHIFT: u32 = 26; -const CDCLK_CD2X_DIV_MASK: u32 = 0x3; -const CDCLK_CD2X_DIV_SHIFT: u32 = 13; - const CDCLK_FREQ_DECIMAL_337_5: u32 = 0b0101010; const CDCLK_FREQ_DECIMAL_450: u32 = 0b0011100; const CDCLK_FREQ_DECIMAL_540: u32 = 0b0100010; const CDCLK_FREQ_DECIMAL_675: u32 = 0b0101010; +const CDCLK_FREQ: usize = 0x46200; + pub struct CdclkState { pub frequency_khz: u32, pub voltage_level: u32, @@ -32,41 +32,57 @@ pub struct CdclkState { pub struct DisplayClock { mmio: Arc, regs: &'static dyn IntelRegs, + is_xe2: bool, } impl DisplayClock { - pub fn new(mmio: Arc, regs: &'static dyn IntelRegs) -> Self { - Self { mmio, regs } + pub fn new(mmio: Arc, regs: &'static dyn IntelRegs, device_info: &IntelDeviceInfo) -> Self { + let is_xe2 = device_info.generation == super::info::IntelGeneration::GenXe2; + Self { mmio, regs, is_xe2 } } pub fn init(&self) -> Result { + if self.is_xe2 { self.init_xe2() } else { self.init_gen9() } + } + + fn init_gen9(&self) -> Result { let cdclk_ctl = self.regs.cdclk_ctl(); let current = self.mmio.read_u32(cdclk_ctl); - let freq_select = (current >> CDCLK_FREQ_SELECT_SHIFT) & CDCLK_FREQ_SELECT_MASK; let frequency = match freq_select { SKL_CDCLK_337_5 => 337_500, SKL_CDCLK_450 => 450_000, SKL_CDCLK_540 => 540_000, SKL_CDCLK_675 => 675_000, - _ => { - warn!("redox-drm-intel: unknown CDCLK freq select {}, defaulting to 337.5 MHz", freq_select); - 337_500 - } + _ => { warn!("redox-drm-intel: unknown CDCLK freq {}, default 337.5", freq_select); 337_500 } }; + info!("redox-drm-intel: Gen9 CDCLK at {} kHz", frequency); + Ok(CdclkState { frequency_khz: frequency, voltage_level: freq_select }) + } - info!("redox-drm-intel: CDCLK initialized at {} kHz", frequency); - Ok(CdclkState { - frequency_khz: frequency, - voltage_level: freq_select, - }) + fn init_xe2(&self) -> Result { + let freq_val = self.mmio.read_u32(CDCLK_FREQ); + let freq_select = (freq_val >> 26) & 0x3; + let decimal = freq_val & 0x1FF; + let frequency = match (freq_select, decimal) { + (0, _) => 307_200, + (1, 0b00001111) => 556_800, + (1, 0b00010111) => 652_800, + (2, 0b00001111) => 384_000, + _ => 487_500, + }; + info!("redox-drm-intel: Xe2 CDCLK at {} kHz", frequency); + Ok(CdclkState { frequency_khz: frequency, voltage_level: freq_select }) } pub fn set_frequency(&self, target_khz: u32) -> Result { - let cdclk_ctl = self.regs.cdclk_ctl(); + if self.is_xe2 { self.set_xe2(target_khz) } else { self.set_gen9(target_khz) } + } - let (freq_select, decimal, actual_khz) = if target_khz <= 337_500 { - (SKL_CDCLK_337_5, CDCLK_FREQ_DECIMAL_337_5, 337_500u32) + fn set_gen9(&self, target_khz: u32) -> Result { + let cdclk_ctl = self.regs.cdclk_ctl(); + let (freq_select, decimal, actual) = if target_khz <= 337_500 { + (SKL_CDCLK_337_5, CDCLK_FREQ_DECIMAL_337_5, 337_500) } else if target_khz <= 450_000 { (SKL_CDCLK_450, CDCLK_FREQ_DECIMAL_450, 450_000) } else if target_khz <= 540_000 { @@ -74,42 +90,36 @@ impl DisplayClock { } else { (SKL_CDCLK_675, CDCLK_FREQ_DECIMAL_675, 675_000) }; - let mut val = self.mmio.read_u32(cdclk_ctl); - val &= !(CDCLK_FREQ_SELECT_MASK << CDCLK_FREQ_SELECT_SHIFT); - val &= !(CDCLK_DECIMAL_MASK); + val &= !(CDCLK_FREQ_SELECT_MASK << CDCLK_FREQ_SELECT_SHIFT) & !CDCLK_DECIMAL_MASK; val |= (freq_select & 0x01) << CDCLK_FREQ_SELECT_SHIFT; val |= (freq_select >> 1) << 1; - val |= decimal & CDCLK_DECIMAL_MASK; - + val |= decimal; self.mmio.write_u32(cdclk_ctl, val); + info!("redox-drm-intel: Gen9 CDCLK set to {} kHz", actual); + Ok(CdclkState { frequency_khz: actual, voltage_level: freq_select }) + } - info!("redox-drm-intel: CDCLK set to {} kHz (requested {} kHz)", actual_khz, target_khz); - Ok(CdclkState { - frequency_khz: actual_khz, - voltage_level: freq_select, - }) + fn set_xe2(&self, target_khz: u32) -> Result { + let (freq_select, decimal, actual) = if target_khz <= 307_200 { + (0, 0, 307_200) + } else if target_khz <= 384_000 { + (2, 0b00001111, 384_000) + } else if target_khz <= 556_800 { + (1, 0b00001111, 556_800) + } else { + (1, 0b00010111, 652_800) + }; + self.mmio.write_u32(CDCLK_FREQ, (freq_select << 26) | decimal); + info!("redox-drm-intel: Xe2 CDCLK set to {} kHz", actual); + Ok(CdclkState { frequency_khz: actual, voltage_level: freq_select }) } pub fn required_cdclk(modes: &[ModeInfo]) -> u32 { - let mut max_pixel_rate: u32 = 0; - for mode in modes { - let pixel_rate = mode.pixel_clock; - if pixel_rate > max_pixel_rate { - max_pixel_rate = pixel_rate; - } - } - - if max_pixel_rate == 0 { - return 337_500; - } - - if max_pixel_rate <= 337_500 / 2 { - 337_500 - } else if max_pixel_rate <= 450_000 / 2 { - 450_000 - } else { - 540_000 - } + let max_rate = modes.iter().map(|m| m.pixel_clock).max().unwrap_or(0); + if max_rate == 0 { 307_200 } + else if max_rate <= 148_500 { 307_200 } + else if max_rate <= 268_500 { 384_000 } + else { 556_800 } } } diff --git a/local/recipes/gpu/redox-drm/source/src/drivers/intel/mod.rs b/local/recipes/gpu/redox-drm/source/src/drivers/intel/mod.rs index edc27c5d36..6ba211537e 100644 --- a/local/recipes/gpu/redox-drm/source/src/drivers/intel/mod.rs +++ b/local/recipes/gpu/redox-drm/source/src/drivers/intel/mod.rs @@ -177,7 +177,7 @@ impl IntelDriver { } } - let cdclk = DisplayClock::new(mmio_arc.clone(), regs); + let cdclk = DisplayClock::new(mmio_arc.clone(), regs, &device_info); let cdclk_state = cdclk.init()?; info!( "redox-drm-intel: CDCLK = {} kHz (voltage level {})",