If more than one output is connected, and there's only one ACPI lid device, proxy the state of the lid into the LVDS / eDP connectivity. This way we don't suffer from broken lid-status from the firmware in a way that would result in nothing lighting up.
This is terribly Linux-specific and I don't think we should merge it as-is, I'm mostly trying to generate some discussion. There's some weird corner cases that come out of this since we're still doing the "poke one thing at a time" model, and we don't explicitly turn _off_ outputs during initial setup, so X and kernel's view of the world gets out of sync. I think ideally we'd do this in the DRM, but I was unable to come up with a clean way to do it there. Maybe it just needs to be ugly. Signed-off-by: Adam Jackson <[email protected]> --- hw/xfree86/modes/xf86Crtc.c | 80 ++++++++++++++++++++++++++++++++++++++---- 1 files changed, 72 insertions(+), 8 deletions(-) diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c index 7d80264..0c9bc8d 100644 --- a/hw/xfree86/modes/xf86Crtc.c +++ b/hw/xfree86/modes/xf86Crtc.c @@ -32,6 +32,11 @@ #include <stddef.h> #include <string.h> #include <stdio.h> +#include <glob.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> #include "xf86.h" #include "xf86DDC.h" @@ -1521,11 +1526,44 @@ handle_detailed_monrec(struct detailed_monitor_section *det_mon, void *data) } } +static int +lvds_lid_status(void) +{ + glob_t g = {0, }; + int ret = XF86OutputStatusConnected; +#ifdef linux + int fd; + char buf[80]; + + memset(buf, '\0', sizeof(buf)); + + if (glob("/proc/acpi/button/lid/*/state", GLOB_NOSORT, NULL, &g) != 0) + goto out; + + if (g.gl_pathc != 1) + goto out; + + fd = open(g.gl_pathv[0], O_RDONLY); + if (fd == -1) + goto out; + + read(fd, buf, sizeof(buf)-1); + close(fd); + if (strstr(buf, "closed")) + ret = XF86OutputStatusDisconnected; +#endif + +out: + globfree(&g); + return ret; +} + void xf86ProbeOutputModes(ScrnInfoPtr scrn, int maxX, int maxY) { xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); int o; + int num_connected = 0; /* When canGrow was TRUE in the initial configuration we have to * compare against the maximum values so that we don't drop modes. @@ -1537,6 +1575,40 @@ xf86ProbeOutputModes(ScrnInfoPtr scrn, int maxX, int maxY) maxY = config->maxHeight; } + /* clean the mode list */ + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + while (output->probed_modes != NULL) + xf86DeleteMode(&output->probed_modes, output->probed_modes); + } + + /* scan for connectivity */ + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + output->status = output->funcs->detect(output); + + if (output->status == XF86OutputStatusConnected) + num_connected++; + } + + /* + * Hack for LVDS/eDP. We want to consider these disconnected if the + * lid is closed, but only if more than one output is connected (lest + * we darken the only available output, since lid status is unreliable) + */ + if (num_connected > 1) + { + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + if (strstr(output->name, "LVDS") || strstr(output->name, "eDP")) + if (output->status == XF86OutputStatusConnected) + output->status = lvds_lid_status(); + } + } + /* Probe the list of modes for each output. */ for (o = 0; o < config->num_output; o++) { xf86OutputPtr output = config->output[o]; @@ -1553,14 +1625,6 @@ xf86ProbeOutputModes(ScrnInfoPtr scrn, int maxX, int maxY) Bool debug_modes = config->debug_modes || xf86Initialising; enum det_monrec_source sync_source = sync_default; - while (output->probed_modes != NULL) - xf86DeleteMode(&output->probed_modes, output->probed_modes); - - /* - * Check connection status - */ - output->status = (*output->funcs->detect) (output); - if (output->status == XF86OutputStatusDisconnected && !xf86ReturnOptValBool(output->options, OPTION_ENABLE, FALSE)) { xf86OutputSetEDID(output, NULL); -- 1.7.7.6 _______________________________________________ [email protected]: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel
