From 333c333fc15c29c18ff1e386e9c2479a29d05115 Mon Sep 17 00:00:00 2001 From: Admin Pupkin Date: Mon, 1 Jun 2026 06:55:04 +0300 Subject: [PATCH] amdgpu: multiple CRTC support, DPMS/EDID properties, set_property dispatch - Support 4 CRTCs instead of hardcoded 1 (AMD GPUs have 4-6 CRTCs) - Add CONN_PROP_DPMS (ID 31) and CONN_PROP_EDID (ID 32) connector properties. DPMS is an enum property (On/Standby/Suspend/Off). EDID is an immutable blob. - Add DrmModeObjSetPropertyWire struct and wire OBJ_SETPROPERTY ioctl to call driver.set_property() with proper error dispatch. Unknown properties are silently ignored (not errors). - Add set_property() to GpuDriver trait with default Unsupported impl. AmdDriver implements DPMS property set by mapping connector_id -> CRTC and calling DisplayCore::set_dpms(). --- .../gpu/redox-drm/source/src/driver.rs | 4 ++ .../redox-drm/source/src/drivers/amd/mod.rs | 36 +++++++++++++++- .../gpu/redox-drm/source/src/scheme.rs | 43 ++++++++++++++++++- 3 files changed, 81 insertions(+), 2 deletions(-) diff --git a/local/recipes/gpu/redox-drm/source/src/driver.rs b/local/recipes/gpu/redox-drm/source/src/driver.rs index a50b5a6d23..8dad19260c 100644 --- a/local/recipes/gpu/redox-drm/source/src/driver.rs +++ b/local/recipes/gpu/redox-drm/source/src/driver.rs @@ -123,6 +123,10 @@ pub trait GpuDriver: Send + Sync { Ok(None) } + fn set_property(&self, _obj_id: u32, _prop_id: u32, _value: u64) -> Result<()> { + Err(DriverError::Unsupported("property setting not implemented for this backend")) + } + fn redox_private_cs_submit( &self, _submit: &RedoxPrivateCsSubmit, diff --git a/local/recipes/gpu/redox-drm/source/src/drivers/amd/mod.rs b/local/recipes/gpu/redox-drm/source/src/drivers/amd/mod.rs index e8f70d5a56..1aaddb449d 100644 --- a/local/recipes/gpu/redox-drm/source/src/drivers/amd/mod.rs +++ b/local/recipes/gpu/redox-drm/source/src/drivers/amd/mod.rs @@ -164,7 +164,10 @@ impl AmdDriver { display, gem: Mutex::new(GemManager::new()), connectors: Mutex::new(connectors), - crtcs: Mutex::new(vec![Crtc::new(1)]), + crtcs: Mutex::new({ + let count = 4usize; + (1..=count).map(|id| Crtc::new(id as u32)).collect() + }), encoders: Mutex::new(encoders), gtt: Mutex::new(gtt), ring: Mutex::new(ring), @@ -715,6 +718,37 @@ impl GpuDriver for AmdDriver { Ok(None) } + + fn set_property(&self, obj_id: u32, prop_id: u32, value: u64) -> Result<()> { + const CONN_PROP_DPMS: u32 = 31; + const DRM_MODE_DPMS_ON: i32 = 0; + const DRM_MODE_DPMS_OFF: i32 = 3; + + if prop_id == CONN_PROP_DPMS { + let crtc_id = { + let connectors = self.connectors.lock().map_err(|_| { + DriverError::Initialization("connector state poisoned".into()) + })?; + connectors + .iter() + .find(|c| c.info.id == obj_id) + .map(|c| c.info.encoder_id) + .ok_or_else(|| DriverError::NotFound(format!("unknown connector {obj_id}")))? + }; + + let dpms_mode = match value { + 0 => DRM_MODE_DPMS_ON, + 3 => DRM_MODE_DPMS_OFF, + _ => return Ok(()), + }; + + return self.display.set_dpms(crtc_id, dpms_mode); + } + + Err(DriverError::Unsupported( + "property not supported for this object", + )) + } }; if !irq_event { diff --git a/local/recipes/gpu/redox-drm/source/src/scheme.rs b/local/recipes/gpu/redox-drm/source/src/scheme.rs index 42c32ba349..a177e39af9 100644 --- a/local/recipes/gpu/redox-drm/source/src/scheme.rs +++ b/local/recipes/gpu/redox-drm/source/src/scheme.rs @@ -117,6 +117,8 @@ const CRTC_PROP_MODE_ID: u32 = 21; // Connector property IDs (30-39 range) const CONN_PROP_CRTC_ID: u32 = 30; +const CONN_PROP_DPMS: u32 = 31; +const CONN_PROP_EDID: u32 = 32; const PLANE_PROPERTY_COUNT: usize = 10; @@ -362,6 +364,16 @@ struct DrmModePropertyEnumWire { name: [u8; DRM_PROP_NAME_LEN], } +#[repr(C)] +#[derive(Clone, Copy, Debug, Default)] +struct DrmModeObjSetPropertyWire { + value: u64, + obj_id: u32, + obj_type: u32, + prop_id: u32, + _pad: u32, +} + #[repr(C)] #[derive(Clone, Copy, Debug, Default)] struct DrmSetClientCapWire { @@ -1247,6 +1259,30 @@ impl DrmScheme { out = bytes_of(&response); } + CONN_PROP_DPMS => { + response.flags = DRM_MODE_PROP_ATOMIC | DRM_MODE_PROP_ENUM; + response.count_enum_blobs = 4; + copy_c_string(&mut response.name, b"DPMS"); + + out = bytes_of(&response); + for (value, name) in [ + (0, b"On\0"), + (1, b"Standby\0"), + (2, b"Suspend\0"), + (3, b"Off\0"), + ] { + let mut e = DrmModePropertyEnumWire::default(); + e.value = value; + copy_c_string(&mut e.name, name); + out.extend_from_slice(&bytes_of(&e)); + } + } + CONN_PROP_EDID => { + response.flags = DRM_MODE_PROP_IMMUTABLE | DRM_MODE_PROP_BLOB; + copy_c_string(&mut response.name, b"EDID"); + + out = bytes_of(&response); + } _ => out = bytes_of(&response), } @@ -2438,7 +2474,12 @@ impl DrmScheme { } DRM_IOCTL_MODE_OBJ_SETPROPERTY => { - vec![] + let req = decode_wire::(payload)?; + match self.driver.set_property(req.obj_id, req.prop_id, req.value) { + Ok(()) => vec![], + Err(DriverError::Unsupported(_)) => vec![], + Err(e) => return Err(driver_to_syscall(e)), + } } 0 => {