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 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.
|
||||
// (Technically a device does not need to be atomic for planes to be used, but nobody does this otherwise.)
|
||||
for plane in plane_handles {
|
||||
|
|
@ -108,7 +90,7 @@ pub fn display_configuration(
|
|||
_ => false,
|
||||
},
|
||||
)?;
|
||||
if cleanup.contains(&crtc) || !is_primary {
|
||||
if !is_primary && !cleanup.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));
|
||||
|
|
@ -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)?;
|
||||
} else {
|
||||
for crtc in res_handles.crtcs() {
|
||||
#[allow(deprecated)]
|
||||
let _ = device.set_cursor(*crtc, Option::<&DumbBuffer>::None);
|
||||
}
|
||||
for crtc in cleanup {
|
||||
// null commit (necessary to trigger removal on the kernel side with the legacy api.)
|
||||
let _ = device.set_crtc(crtc, None, (0, 0), &[], None);
|
||||
}
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(map)
|
||||
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.)
|
||||
let _ = device.set_crtc(*crtc, None, (0, 0), &[], None);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn interface_name(device: &impl ControlDevice, connector: connector::Handle) -> Result<String> {
|
||||
|
|
|
|||
|
|
@ -852,11 +852,26 @@ impl KmsGuard<'_> {
|
|||
|
||||
// first drop old surfaces
|
||||
if !test_only {
|
||||
for output in outputs.iter().filter(|o| !o.is_enabled()) {
|
||||
device
|
||||
.inner
|
||||
.surfaces
|
||||
.retain(|_, surface| surface.output != *output);
|
||||
let mut disabled_crtcs = Vec::new();
|
||||
device.inner.surfaces.retain(|crtc, surface| {
|
||||
if outputs
|
||||
.iter()
|
||||
.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