intel: Phase 4 — atomic modeset and color pipeline
- kms/atomic.rs: AtomicState, atomic_check with mode+bandwidth validation - driver.rs: atomic_commit default method on GpuDriver trait - mod.rs: IntelDriver atomic_commit with atomic_check → set_crtc dispatch - gamma.rs: degamma LUT (sRGB linearize), CSC identity, CTM identity
This commit is contained in:
@@ -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<MmioRegion>,
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
@@ -817,6 +817,43 @@ impl GpuDriver for IntelDriver {
|
||||
crtc.program(fb_handle, connectors, mode)
|
||||
}
|
||||
|
||||
fn atomic_commit(&self, state: &AtomicState) -> Result<AtomicCommitResult> {
|
||||
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<u64> {
|
||||
let fb_addr = self.ensure_gem_gpu_mapping(fb_handle)?;
|
||||
let pipe = self.display.pipe_for_crtc(crtc_id)?;
|
||||
|
||||
Reference in New Issue
Block a user