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().
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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::<DrmModeObjSetPropertyWire>(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 => {
|
||||
|
||||
Reference in New Issue
Block a user