kms: Handle max bpc property
This commit is contained in:
parent
2fde693cce
commit
1a8432395c
3 changed files with 57 additions and 2 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::{anyhow, Result};
|
||||||
use smithay::reexports::drm::control::{
|
use smithay::reexports::drm::control::{
|
||||||
atomic::AtomicModeReq,
|
atomic::AtomicModeReq,
|
||||||
connector::{self, State as ConnectorState},
|
connector::{self, State as ConnectorState},
|
||||||
|
|
@ -9,7 +9,7 @@ use smithay::reexports::drm::control::{
|
||||||
property, AtomicCommitFlags, Device as ControlDevice, Mode, ModeFlags, PlaneType,
|
property, AtomicCommitFlags, Device as ControlDevice, Mode, ModeFlags, PlaneType,
|
||||||
ResourceHandle,
|
ResourceHandle,
|
||||||
};
|
};
|
||||||
use std::collections::HashMap;
|
use std::{collections::HashMap, ops::Range};
|
||||||
|
|
||||||
pub fn display_configuration(
|
pub fn display_configuration(
|
||||||
device: &mut impl ControlDevice,
|
device: &mut impl ControlDevice,
|
||||||
|
|
@ -360,3 +360,43 @@ pub fn set_vrr(
|
||||||
Ok(false)
|
Ok(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_max_bpc(
|
||||||
|
dev: &impl ControlDevice,
|
||||||
|
conn: connector::Handle,
|
||||||
|
) -> Result<Option<(u32, Range<u32>)>> {
|
||||||
|
let Some(handle) = get_prop(dev, conn, "max bpc").ok() else {
|
||||||
|
return Ok(None);
|
||||||
|
};
|
||||||
|
|
||||||
|
let info = dev.get_property(handle)?;
|
||||||
|
let range = match info.value_type() {
|
||||||
|
property::ValueType::UnsignedRange(x, y) => (x as u32)..(y as u32),
|
||||||
|
_ => return Err(anyhow!("max bpc has wrong value type")),
|
||||||
|
};
|
||||||
|
|
||||||
|
let value = get_property_val(dev, conn, "max bpc").map(|(val_type, val)| {
|
||||||
|
match val_type.convert_value(val) {
|
||||||
|
property::Value::UnsignedRange(res) => res as u32,
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(Some((value, range)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_max_bpc(dev: &impl ControlDevice, conn: connector::Handle, bpc: u32) -> Result<u32> {
|
||||||
|
let (_, range) =
|
||||||
|
get_max_bpc(dev, conn)?.ok_or(anyhow!("max bpc does not exist for connector"))?;
|
||||||
|
dev.set_property(
|
||||||
|
conn,
|
||||||
|
get_prop(dev, conn, "max bpc")?,
|
||||||
|
property::Value::UnsignedRange(bpc.clamp(range.start, range.end) as u64).into(),
|
||||||
|
)
|
||||||
|
.map_err(Into::<anyhow::Error>::into)
|
||||||
|
.and_then(|_| get_property_val(dev, conn, "max bpc"))
|
||||||
|
.map(|(val_type, val)| match val_type.convert_value(val) {
|
||||||
|
property::Value::UnsignedRange(val) => val as u32,
|
||||||
|
_ => unreachable!(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -826,6 +826,7 @@ impl Device {
|
||||||
let crtc_info = drm.get_crtc(crtc)?;
|
let crtc_info = drm.get_crtc(crtc)?;
|
||||||
let conn_info = drm.get_connector(conn, false)?;
|
let conn_info = drm.get_connector(conn, false)?;
|
||||||
let vrr = drm_helpers::set_vrr(drm, crtc, conn, false).unwrap_or(false);
|
let vrr = drm_helpers::set_vrr(drm, crtc, conn, false).unwrap_or(false);
|
||||||
|
let max_bpc = drm_helpers::get_max_bpc(drm, conn)?.map(|(_val, range)| range.end.min(16));
|
||||||
let interface = drm_helpers::interface_name(drm, conn)?;
|
let interface = drm_helpers::interface_name(drm, conn)?;
|
||||||
let edid_info = drm_helpers::edid_info(drm, conn);
|
let edid_info = drm_helpers::edid_info(drm, conn);
|
||||||
let mode = crtc_info.mode().unwrap_or_else(|| {
|
let mode = crtc_info.mode().unwrap_or_else(|| {
|
||||||
|
|
@ -879,6 +880,7 @@ impl Device {
|
||||||
mode: ((output_mode.size.w, output_mode.size.h), Some(refresh_rate)),
|
mode: ((output_mode.size.w, output_mode.size.h), Some(refresh_rate)),
|
||||||
vrr,
|
vrr,
|
||||||
position,
|
position,
|
||||||
|
max_bpc,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
@ -1268,6 +1270,16 @@ impl KmsState {
|
||||||
} else {
|
} else {
|
||||||
surface.vrr = drm_helpers::set_vrr(drm, *crtc, conn, output_config.vrr)
|
surface.vrr = drm_helpers::set_vrr(drm, *crtc, conn, output_config.vrr)
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
|
if let Some(bpc) = output_config.max_bpc {
|
||||||
|
if let Err(err) = drm_helpers::set_max_bpc(drm, conn, bpc) {
|
||||||
|
warn!(
|
||||||
|
?bpc,
|
||||||
|
?err,
|
||||||
|
"Failed to set max_bpc on connector: {}",
|
||||||
|
output.name()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
surface.refresh_rate = drm_helpers::calculate_refresh_rate(*mode);
|
surface.refresh_rate = drm_helpers::calculate_refresh_rate(*mode);
|
||||||
|
|
||||||
let drm_surface = drm.create_surface(*crtc, *mode, &[conn])?;
|
let drm_surface = drm.create_surface(*crtc, *mode, &[conn])?;
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,8 @@ pub struct OutputConfig {
|
||||||
pub position: (i32, i32),
|
pub position: (i32, i32),
|
||||||
#[serde(default = "default_enabled")]
|
#[serde(default = "default_enabled")]
|
||||||
pub enabled: bool,
|
pub enabled: bool,
|
||||||
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
|
pub max_bpc: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for OutputConfig {
|
impl Default for OutputConfig {
|
||||||
|
|
@ -110,6 +112,7 @@ impl Default for OutputConfig {
|
||||||
transform: Transform::Normal,
|
transform: Transform::Normal,
|
||||||
position: (0, 0),
|
position: (0, 0),
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
max_bpc: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue