fix: internal laptop screen stuck on vendor logo with external monitor
This commit is contained in:
parent
dacdc3db39
commit
a9f2427c00
2 changed files with 85 additions and 35 deletions
|
|
@ -77,24 +77,6 @@ pub fn display_configuration(
|
||||||
let mut req = AtomicModeReq::new();
|
let mut req = AtomicModeReq::new();
|
||||||
let plane_handles = device.plane_handles()?;
|
let plane_handles = device.plane_handles()?;
|
||||||
|
|
||||||
for conn in connectors
|
|
||||||
.iter()
|
|
||||||
.flat_map(|conn| device.get_connector(*conn, false).ok())
|
|
||||||
.filter(|conn| {
|
|
||||||
if let Some(enc) = conn.current_encoder()
|
|
||||||
&& let Ok(enc) = device.get_encoder(enc)
|
|
||||||
&& let Some(crtc) = enc.crtc()
|
|
||||||
{
|
|
||||||
return cleanup.contains(&crtc);
|
|
||||||
}
|
|
||||||
false
|
|
||||||
})
|
|
||||||
.map(|info| info.handle())
|
|
||||||
{
|
|
||||||
let crtc_id = get_prop(device, conn, "CRTC_ID")?;
|
|
||||||
req.add_property(conn, crtc_id, property::Value::CRTC(None));
|
|
||||||
}
|
|
||||||
|
|
||||||
// We cannot just shortcut and use the legacy api for all cleanups because of this.
|
// We cannot just shortcut and use the legacy api for all cleanups because of this.
|
||||||
// (Technically a device does not need to be atomic for planes to be used, but nobody does this otherwise.)
|
// (Technically a device does not need to be atomic for planes to be used, but nobody does this otherwise.)
|
||||||
for plane in plane_handles {
|
for plane in plane_handles {
|
||||||
|
|
@ -108,7 +90,7 @@ pub fn display_configuration(
|
||||||
_ => false,
|
_ => false,
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
if cleanup.contains(&crtc) || !is_primary {
|
if !is_primary && !cleanup.contains(&crtc) {
|
||||||
let crtc_id = get_prop(device, plane, "CRTC_ID")?;
|
let crtc_id = get_prop(device, plane, "CRTC_ID")?;
|
||||||
let fb_id = get_prop(device, plane, "FB_ID")?;
|
let fb_id = get_prop(device, plane, "FB_ID")?;
|
||||||
req.add_property(plane, crtc_id, property::Value::CRTC(None));
|
req.add_property(plane, crtc_id, property::Value::CRTC(None));
|
||||||
|
|
@ -116,27 +98,80 @@ pub fn display_configuration(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for crtc in cleanup {
|
|
||||||
let mode_id = get_prop(device, crtc, "MODE_ID")?;
|
|
||||||
let active = get_prop(device, crtc, "ACTIVE")?;
|
|
||||||
req.add_property(crtc, active, property::Value::Boolean(false));
|
|
||||||
req.add_property(crtc, mode_id, property::Value::Unknown(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
device.atomic_commit(AtomicCommitFlags::ALLOW_MODESET, req)?;
|
device.atomic_commit(AtomicCommitFlags::ALLOW_MODESET, req)?;
|
||||||
} else {
|
} else {
|
||||||
for crtc in res_handles.crtcs() {
|
for crtc in res_handles.crtcs() {
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
let _ = device.set_cursor(*crtc, Option::<&DumbBuffer>::None);
|
let _ = device.set_cursor(*crtc, Option::<&DumbBuffer>::None);
|
||||||
}
|
}
|
||||||
for crtc in cleanup {
|
}
|
||||||
|
disable_crtcs(device, supports_atomic, &cleanup)?;
|
||||||
|
|
||||||
|
Ok(map)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Disables the given CRTCs and detaches their connectors/planes.
|
||||||
|
pub fn disable_crtcs(
|
||||||
|
device: &mut impl ControlDevice,
|
||||||
|
supports_atomic: bool,
|
||||||
|
crtcs: &[crtc::Handle],
|
||||||
|
) -> Result<()> {
|
||||||
|
if crtcs.is_empty() {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let res_handles = device.resource_handles()?;
|
||||||
|
|
||||||
|
if supports_atomic {
|
||||||
|
let mut req = AtomicModeReq::new();
|
||||||
|
|
||||||
|
for conn in res_handles
|
||||||
|
.connectors()
|
||||||
|
.iter()
|
||||||
|
.flat_map(|conn| device.get_connector(*conn, false).ok())
|
||||||
|
.filter(|conn| {
|
||||||
|
if let Some(enc) = conn.current_encoder()
|
||||||
|
&& let Ok(enc) = device.get_encoder(enc)
|
||||||
|
&& let Some(crtc) = enc.crtc()
|
||||||
|
{
|
||||||
|
return crtcs.contains(&crtc);
|
||||||
|
}
|
||||||
|
false
|
||||||
|
})
|
||||||
|
.map(|info| info.handle())
|
||||||
|
{
|
||||||
|
let crtc_id = get_prop(device, conn, "CRTC_ID")?;
|
||||||
|
req.add_property(conn, crtc_id, property::Value::CRTC(None));
|
||||||
|
}
|
||||||
|
|
||||||
|
for plane in device.plane_handles()? {
|
||||||
|
let info = device.get_plane(plane)?;
|
||||||
|
if let Some(crtc) = info.crtc()
|
||||||
|
&& crtcs.contains(&crtc)
|
||||||
|
{
|
||||||
|
let crtc_id = get_prop(device, plane, "CRTC_ID")?;
|
||||||
|
let fb_id = get_prop(device, plane, "FB_ID")?;
|
||||||
|
req.add_property(plane, crtc_id, property::Value::CRTC(None));
|
||||||
|
req.add_property(plane, fb_id, property::Value::Framebuffer(None));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for crtc in crtcs {
|
||||||
|
let mode_id = get_prop(device, *crtc, "MODE_ID")?;
|
||||||
|
let active = get_prop(device, *crtc, "ACTIVE")?;
|
||||||
|
req.add_property(*crtc, active, property::Value::Boolean(false));
|
||||||
|
req.add_property(*crtc, mode_id, property::Value::Unknown(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
device.atomic_commit(AtomicCommitFlags::ALLOW_MODESET, req)?;
|
||||||
|
} else {
|
||||||
|
for crtc in crtcs {
|
||||||
// null commit (necessary to trigger removal on the kernel side with the legacy api.)
|
// null commit (necessary to trigger removal on the kernel side with the legacy api.)
|
||||||
let _ = device.set_crtc(crtc, None, (0, 0), &[], None);
|
let _ = device.set_crtc(*crtc, None, (0, 0), &[], None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(map)
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn interface_name(device: &impl ControlDevice, connector: connector::Handle) -> Result<String> {
|
pub fn interface_name(device: &impl ControlDevice, connector: connector::Handle) -> Result<String> {
|
||||||
|
|
|
||||||
|
|
@ -852,11 +852,26 @@ impl KmsGuard<'_> {
|
||||||
|
|
||||||
// first drop old surfaces
|
// first drop old surfaces
|
||||||
if !test_only {
|
if !test_only {
|
||||||
for output in outputs.iter().filter(|o| !o.is_enabled()) {
|
let mut disabled_crtcs = Vec::new();
|
||||||
device
|
device.inner.surfaces.retain(|crtc, surface| {
|
||||||
.inner
|
if outputs
|
||||||
.surfaces
|
.iter()
|
||||||
.retain(|_, surface| surface.output != *output);
|
.any(|o| !o.is_enabled() && surface.output == *o)
|
||||||
|
{
|
||||||
|
disabled_crtcs.push(*crtc);
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let supports_atomic = device.drm.device().is_atomic();
|
||||||
|
if let Err(err) = drm_helpers::disable_crtcs(
|
||||||
|
device.drm.device_mut(),
|
||||||
|
supports_atomic,
|
||||||
|
&disabled_crtcs,
|
||||||
|
) {
|
||||||
|
warn!("Failed to disable crtcs for disabled outputs: {err}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue