intel: universal plane programming + DP MST topology manager
plane_universal.rs: per-plane enable/disable with format+rotation XRGB8888, ARGB8888, NV12 format support 0/90/180/270 rotation via PLANE_CTL bits Position, stride, surface address, colorkey programming dp_mst.rs: Multi-Stream Transport topology management DPCD MST capability probe (DPCD 0x0021) Upstream MST enable (DPCD 0x0111) VCPI allocation/deallocation (payload table + allocate set) MstBranchDevice tracking for branch device enumeration mod.rs: registered plane_universal and dp_mst modules
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use log::{debug, info};
|
||||
use redox_driver_sys::memory::MmioRegion;
|
||||
|
||||
use super::dp_aux::DpAux;
|
||||
use crate::driver::{DriverError, Result};
|
||||
|
||||
const DP_MST_CAP_OFFSET: u32 = 0x0021;
|
||||
const DP_MST_CTRL_OFFSET: u32 = 0x0111;
|
||||
const DP_MST_CTRL_UPSTREAM_ENABLE: u8 = 1 << 0;
|
||||
const DP_MST_CTRL_UP_REQ_EN: u8 = 1 << 1;
|
||||
|
||||
const DP_MST_VC_PAYLOAD_TABLE_SLOT: u32 = 0x02C0;
|
||||
const DP_MST_VC_PAYLOAD_ALLOCATE_SET: u32 = 0x02C1;
|
||||
const MAX_MST_BRANCH_DEVICES: usize = 8;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct MstTopologyManager {
|
||||
mmio: Arc<MmioRegion>,
|
||||
mst_capable: bool,
|
||||
branch_devices: Vec<MstBranchDevice>,
|
||||
allocated_vcpi: u8,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct MstBranchDevice {
|
||||
pub peer_device_type: u8,
|
||||
pub num_ports: u8,
|
||||
pub mst_cap: bool,
|
||||
}
|
||||
|
||||
impl MstTopologyManager {
|
||||
pub fn new(mmio: Arc<MmioRegion>) -> Self {
|
||||
Self {
|
||||
mmio,
|
||||
mst_capable: false,
|
||||
branch_devices: Vec::new(),
|
||||
allocated_vcpi: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn probe(&mut self, aux: &DpAux) -> Result<bool> {
|
||||
match aux.read_dpcd(DP_MST_CAP_OFFSET, 1) {
|
||||
Ok(data) if !data.is_empty() => {
|
||||
self.mst_capable = data[0] & 0x01 != 0;
|
||||
if self.mst_capable {
|
||||
aux.write_dpcd(DP_MST_CTRL_OFFSET,
|
||||
&[DP_MST_CTRL_UPSTREAM_ENABLE | DP_MST_CTRL_UP_REQ_EN])?;
|
||||
info!("redox-drm-intel: DP MST topology enabled");
|
||||
}
|
||||
Ok(self.mst_capable)
|
||||
}
|
||||
_ => Ok(false),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn allocate_vcpi(&mut self, aux: &DpAux, slot_count: u8, payload_id: u8) -> Result<()> {
|
||||
if !self.mst_capable {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let payload_table = DP_MST_VC_PAYLOAD_TABLE_SLOT;
|
||||
aux.write_dpcd(payload_table + payload_id as u32, &[
|
||||
slot_count,
|
||||
payload_id,
|
||||
])?;
|
||||
|
||||
aux.write_dpcd(DP_MST_VC_PAYLOAD_ALLOCATE_SET, &[
|
||||
self.allocated_vcpi | (1 << payload_id),
|
||||
])?;
|
||||
self.allocated_vcpi |= 1 << payload_id;
|
||||
|
||||
debug!("redox-drm-intel: MST VCPI allocated — slot={} payload_id={}", slot_count, payload_id);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn deallocate_vcpi(&mut self, aux: &DpAux, payload_id: u8) -> Result<()> {
|
||||
if !self.mst_capable {
|
||||
return Ok(());
|
||||
}
|
||||
self.allocated_vcpi &= !(1 << payload_id);
|
||||
aux.write_dpcd(DP_MST_VC_PAYLOAD_ALLOCATE_SET, &[self.allocated_vcpi])?;
|
||||
debug!("redox-drm-intel: MST VCPI deallocated — payload_id={}", payload_id);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn is_mst_capable(&self) -> bool {
|
||||
self.mst_capable
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ pub mod display_transcoder;
|
||||
pub mod display_watermark;
|
||||
pub mod dp_aux;
|
||||
pub mod dp_link;
|
||||
pub mod execbuffer;
|
||||
pub mod dp_mst;
|
||||
pub mod drrs;
|
||||
pub mod execlists;
|
||||
pub mod fbc;
|
||||
@@ -33,6 +33,7 @@ pub mod lmem;
|
||||
pub mod mocs;
|
||||
pub mod panel_pps;
|
||||
pub mod pch;
|
||||
pub mod plane_universal;
|
||||
pub mod psr2;
|
||||
pub mod regs;
|
||||
pub mod regs_gen4_7;
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
use std::sync::Arc;
|
||||
use std::time::Instant;
|
||||
|
||||
use log::debug;
|
||||
use redox_driver_sys::memory::MmioRegion;
|
||||
|
||||
use super::info::IntelDeviceInfo;
|
||||
use crate::driver::Result;
|
||||
use crate::kms::ModeInfo;
|
||||
|
||||
const PLANE_CTL_BASE: usize = 0x70180;
|
||||
const PLANE_STRIDE_OFFSET: usize = 0x70188;
|
||||
const PLANE_SURF_OFFSET: usize = 0x7019C;
|
||||
const PLANE_OFFSET_OFFSET: usize = 0x701A4;
|
||||
const PLANE_SIZE_OFFSET: usize = 0x70190;
|
||||
const PLANE_KEYVAL_OFFSET: usize = 0x70194;
|
||||
const PLANE_KEYMAX_OFFSET: usize = 0x701A0;
|
||||
const PLANE_KEYMSK_OFFSET: usize = 0x70198;
|
||||
const PLANE_STRIDE: usize = 0x1000;
|
||||
|
||||
const PLANE_CTL_ENABLE: u32 = 1 << 31;
|
||||
const PLANE_CTL_GAMMA_DISABLE: u32 = 1 << 13;
|
||||
const PLANE_CTL_PIPE_GAMMA_ENABLE: u32 = 1 << 30;
|
||||
const PLANE_CTL_ROTATE_180: u32 = 1 << 15;
|
||||
const PLANE_CTL_ROTATE_270: u32 = 2 << 15;
|
||||
const PLANE_CTL_ROTATE_90: u32 = 3 << 15;
|
||||
|
||||
const PLANE_CTL_FORMAT_XRGB8888: u32 = 4 << 24;
|
||||
const PLANE_CTL_FORMAT_ARGB8888: u32 = 6 << 24;
|
||||
const PLANE_CTL_FORMAT_NV12: u32 = 9 << 24;
|
||||
|
||||
pub struct UniversalPlane {
|
||||
mmio: Arc<MmioRegion>,
|
||||
pipe: u8,
|
||||
plane: u8,
|
||||
}
|
||||
|
||||
impl UniversalPlane {
|
||||
pub fn new(mmio: Arc<MmioRegion>, pipe: u8, plane: u8) -> Self {
|
||||
Self { mmio, pipe, plane }
|
||||
}
|
||||
|
||||
fn base_offset(&self) -> usize {
|
||||
PLANE_CTL_BASE + self.plane as usize * PLANE_STRIDE
|
||||
}
|
||||
|
||||
pub fn enable(&self, fb_gtt_addr: u64, stride: u32, width: u16, height: u16,
|
||||
format: u32, rotation: u32) -> Result<()> {
|
||||
let base = self.base_offset();
|
||||
|
||||
self.mmio.write32(base + PLANE_SURF_OFFSET, fb_gtt_addr as u32);
|
||||
self.mmio.write32(base + PLANE_SURF_OFFSET + 4, (fb_gtt_addr >> 32) as u32);
|
||||
self.mmio.write32(base + PLANE_STRIDE_OFFSET, stride);
|
||||
self.mmio.write32(base + PLANE_SIZE_OFFSET,
|
||||
((height as u32) << 16) | (width as u32));
|
||||
|
||||
let fmt = match format {
|
||||
0 => PLANE_CTL_FORMAT_XRGB8888,
|
||||
1 => PLANE_CTL_FORMAT_ARGB8888,
|
||||
2 => PLANE_CTL_FORMAT_NV12,
|
||||
_ => PLANE_CTL_FORMAT_XRGB8888,
|
||||
};
|
||||
|
||||
let rot = match rotation {
|
||||
90 => PLANE_CTL_ROTATE_90,
|
||||
180 => PLANE_CTL_ROTATE_180,
|
||||
270 => PLANE_CTL_ROTATE_270,
|
||||
_ => 0,
|
||||
};
|
||||
|
||||
let ctl = PLANE_CTL_ENABLE | PLANE_CTL_GAMMA_DISABLE | fmt | rot;
|
||||
self.mmio.write32(base, ctl);
|
||||
|
||||
debug!("redox-drm-intel: plane enabled pipe={} plane={} {}x{} fmt={:#x} rot={}",
|
||||
self.pipe, self.plane, width, height, fmt, rotation);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn disable(&self) -> Result<()> {
|
||||
let base = self.base_offset();
|
||||
self.mmio.write32(base, 0);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_position(&self, x: u32, y: u32) -> Result<()> {
|
||||
let base = self.base_offset();
|
||||
self.mmio.write32(base + PLANE_OFFSET_OFFSET, (y << 16) | (x & 0x1FFF));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_colorkey(&self, min: u32, max: u32, mask: u32) -> Result<()> {
|
||||
let base = self.base_offset();
|
||||
self.mmio.write32(base + PLANE_KEYVAL_OFFSET, min);
|
||||
self.mmio.write32(base + PLANE_KEYMAX_OFFSET, max);
|
||||
self.mmio.write32(base + PLANE_KEYMSK_OFFSET, mask);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user