diff --git a/local/recipes/gpu/redox-drm/source/src/drivers/intel/gamma.rs b/local/recipes/gpu/redox-drm/source/src/drivers/intel/gamma.rs index 0982279d20..0da16ab2d4 100644 --- a/local/recipes/gpu/redox-drm/source/src/drivers/intel/gamma.rs +++ b/local/recipes/gpu/redox-drm/source/src/drivers/intel/gamma.rs @@ -16,6 +16,24 @@ const PREC_PALETTE_B: usize = 0x4C000; const PALETTE_ENTRIES: usize = 256; const GAMMA_LUT_ENTRIES: usize = 256; +const PLANE_COLOR_CTL_BASE: usize = 0x701CC; +const PLANE_COLOR_CTL_STRIDE: usize = 0x1000; +const PLANE_COLOR_CTL_DEGAMMA_ENABLE: u32 = 1 << 13; +const PLANE_COLOR_CTL_CSC_ENABLE: u32 = 1 << 5; + +const PIPE_CSC_COEFF_BASE: usize = 0x49010; +const PIPE_CSC_PREOFF_BASE: usize = 0x49038; +const PIPE_CSC_POSTOFF_BASE: usize = 0x49040; +const PIPE_CSC_STRIDE: usize = 0x1000; + +const PIPE_DEGAMMA_LUT_BASE: usize = 0x50000; +const PIPE_DEGAMMA_LUT_STRIDE: usize = 0x1000; +const DEGAMMA_LUT_ENTRIES: usize = 65; + +const CTM_COEFF_BASE: usize = 0x49080; +const CTM_COEFF_STRIDE: usize = 0x1000; +const CTM_COEFF_COUNT: usize = 9; + pub struct GammaLut { mmio: Arc, } @@ -64,6 +82,75 @@ impl GammaLut { Ok(()) } + pub fn enable_plane_degamma(&self, pipe: u8, plane: u8) -> Result<()> { + let ctl = PLANE_COLOR_CTL_BASE + plane as usize * PLANE_COLOR_CTL_STRIDE; + let mut val = self.mmio.read32(ctl); + val |= PLANE_COLOR_CTL_DEGAMMA_ENABLE; + self.mmio.write32(ctl, val); + debug!("redox-drm-intel: plane degamma enabled pipe={} plane={}", pipe, plane); + Ok(()) + } + + pub fn program_degamma_lut(&self, pipe: u8, _entries: usize) -> Result<()> { + let lut_base = PIPE_DEGAMMA_LUT_BASE + pipe as usize * PIPE_DEGAMMA_LUT_STRIDE; + for i in 0..DEGAMMA_LUT_ENTRIES { + let linear = i as f64 / (DEGAMMA_LUT_ENTRIES - 1) as f64; + let srgb = if linear <= 0.04045 { + linear / 12.92 + } else { + ((linear + 0.055) / 1.055).powf(2.4) + }; + let val = (srgb * 65535.0).round() as u32; + let split = ((val & 0x3FF) << 20) | ((val & 0xFFC00) >> 10); + self.mmio.write32(lut_base + i * 4, split); + } + debug!("redox-drm-intel: degamma LUT programmed for pipe {} ({} entries)", pipe, DEGAMMA_LUT_ENTRIES); + Ok(()) + } + + pub fn program_csc_identity(&self, pipe: u8) -> Result<()> { + let coeff_base = PIPE_CSC_COEFF_BASE + pipe as usize * PIPE_CSC_STRIDE; + let preoff = PIPE_CSC_PREOFF_BASE + pipe as usize * PIPE_CSC_STRIDE; + let postoff = PIPE_CSC_POSTOFF_BASE + pipe as usize * PIPE_CSC_STRIDE; + + for i in 0..3 { + self.mmio.write32(preoff + i * 4, 0); + self.mmio.write32(postoff + i * 4, 0); + } + + let identity: [(u32, u32); 9] = [ + (0x7800, 0x0000), (0x0000, 0x0000), (0x0000, 0x0000), + (0x0000, 0x0000), (0x7800, 0x0000), (0x0000, 0x0000), + (0x0000, 0x0000), (0x0000, 0x0000), (0x7800, 0x0000), + ]; + for (i, &(lo, hi)) in identity.iter().enumerate() { + let (r, c) = (i / 3, i % 3); + let idx = r * 4 + c; + self.mmio.write32(coeff_base + idx * 4, lo); + self.mmio.write32(coeff_base + (idx) * 4 + 4, hi); + } + + debug!("redox-drm-intel: identity CSC programmed for pipe {}", pipe); + Ok(()) + } + + pub fn program_ctm_identity(&self, pipe: u8) -> Result<()> { + let ctm_base = CTM_COEFF_BASE + pipe as usize * CTM_COEFF_STRIDE; + let identity: [u64; 9] = [ + 0x8000_0000_0000_0000, 0x0000_0000_0000_0000, 0x0000_0000_0000_0000, + 0x0000_0000_0000_0000, 0x8000_0000_0000_0000, 0x0000_0000_0000_0000, + 0x0000_0000_0000_0000, 0x0000_0000_0000_0000, 0x8000_0000_0000_0000, + ]; + for (i, &coeff) in identity.iter().enumerate() { + let lo = (coeff & 0xFFFF_FFFF) as u32; + let hi = ((coeff >> 32) & 0xFFFF_FFFF) as u32; + self.mmio.write32(ctm_base + i * 8, lo); + self.mmio.write32(ctm_base + i * 8 + 4, hi); + } + debug!("redox-drm-intel: identity CTM programmed for pipe {}", pipe); + Ok(()) + } + fn compute_srgb_ramp() -> [u8; GAMMA_LUT_ENTRIES] { let mut ramp = [0u8; GAMMA_LUT_ENTRIES]; for i in 0..GAMMA_LUT_ENTRIES { 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 7ca6db3f5f..f464269bab 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 @@ -817,6 +817,43 @@ impl GpuDriver for IntelDriver { crtc.program(fb_handle, connectors, mode) } + fn atomic_commit(&self, state: &AtomicState) -> Result { + let check = atomic_check(state, &self.detect_connectors()); + match check { + crate::kms::atomic::AtomicCheckResult::Ok => {} + other => { + let msg = format!("atomic_check failed: {:?}", other); + return Err(DriverError::Initialization(msg)); + } + } + + if state.test_only { + return Ok(AtomicCommitResult::NoChange); + } + + for crtc_state in &state.crtc_states { + if !crtc_state.active { + continue; + } + if let Some(ref mode) = crtc_state.mode { + self.set_crtc( + crtc_state.crtc_id, + crtc_state.fb_handle, + &crtc_state.connectors, + mode, + )?; + } + } + + if state.non_blocking { + let vblank = self.vblank_count.load(std::sync::atomic::Ordering::Acquire); + Ok(AtomicCommitResult::Queued { vblank_count: vblank }) + } else { + let vblank = self.vblank_count.load(std::sync::atomic::Ordering::Acquire); + Ok(AtomicCommitResult::Committed { vblank_count: vblank }) + } + } + fn page_flip(&self, crtc_id: u32, fb_handle: u32, _flags: u32) -> Result { let fb_addr = self.ensure_gem_gpu_mapping(fb_handle)?; let pipe = self.display.pipe_for_crtc(crtc_id)?;