summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZhenyu Wang <zhenyu.z.wang@intel.com>2008-12-09 19:48:11 +0800
committerZhenyu Wang <zhenyu.z.wang@intel.com>2008-12-09 19:48:11 +0800
commit4d7a95959d8223aec41550eb19f60b3edd7210a1 (patch)
treee18c646d2db810046307d722cc1fd98a9f19bc4a
parent0fe61b0b7e3bbe8ced1b0ad2be72c438d200c64b (diff)
Try to add LVDS detect support
This one trys to use lid status for LVDS detect, which works when internal panel is not used as primary display alone, or there's no internal panel at all. ACPI button driver's lid state interface is preferred, and SWF state is also checked if ACPI method failed.
-rw-r--r--src/i830_lvds.c123
1 files changed, 120 insertions, 3 deletions
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index 1799eab1..73993db6 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -35,6 +35,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
@@ -96,6 +97,15 @@ static char *backlight_interfaces[] = {
static int backlight_index;
+enum lid_status {
+ LID_UNKNOWN = -1,
+ LID_OPEN,
+ LID_CLOSE,
+};
+
+#define ACPI_BUTTON "/proc/acpi/button/"
+#define ACPI_LID "/proc/acpi/button/lid/"
+
static Bool
i830_kernel_backlight_available(xf86OutputPtr output)
{
@@ -376,6 +386,105 @@ out_err:
}
/**
+ * Get lid state from ACPI button driver
+ */
+static int
+i830_lvds_acpi_lid_open(xf86OutputPtr output)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+ int fd;
+ DIR *button_dir;
+ DIR *lid_dir;
+ struct dirent *lid_dent;
+ char *state_name;
+ char state[64];
+ enum lid_status ret = LID_UNKNOWN;
+
+ button_dir = opendir(ACPI_BUTTON);
+ /* If acpi button driver is not loaded, bypass ACPI check method */
+ if (button_dir == NULL)
+ goto out;
+ closedir(button_dir);
+
+ lid_dir = opendir(ACPI_LID);
+
+ /* if acpi button loaded, but no lid device, assume no panel */
+ if (lid_dir == NULL) {
+ ret = LID_CLOSE;
+ goto out;
+ }
+
+ while (1) {
+ lid_dent = readdir(lid_dir);
+ if (lid_dent == NULL) {
+ /* no LID object */
+ closedir(lid_dir);
+ goto out;
+ }
+ if (strcmp(lid_dent->d_name, ".") &&
+ strcmp(lid_dent->d_name, "..")) {
+ closedir(lid_dir);
+ break;
+ }
+ }
+ state_name = malloc(strlen(ACPI_LID) + strlen(lid_dent->d_name) + 7);
+ memset(state_name, 0, sizeof(state_name));
+ strcat(state_name, ACPI_LID);
+ strcat(state_name, lid_dent->d_name);
+ strcat(state_name, "/state");
+
+ if ((fd = open(state_name, O_RDONLY)) == -1) {
+ free(state_name);
+ goto out;
+ }
+ free(state_name);
+ if (read(fd, state, 64) == -1) {
+ close(fd);
+ goto out;
+ }
+ close(fd);
+ if (strstr(state, "open"))
+ ret = LID_OPEN;
+ else if (strstr(state, "closed"))
+ ret = LID_CLOSE;
+ else /* "unsupported" */
+ ret = LID_UNKNOWN;
+
+out:
+ if (pI830->debug_modes && (ret != LID_UNKNOWN))
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "LID switch detect %s with ACPI button\n",
+ ret ? "closed" : "open");
+
+ return ret;
+}
+
+/**
+ * Get LID switch close state from SWF
+ */
+static Bool
+i830_lvds_swf_lid_close(xf86OutputPtr output)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ I830Ptr pI830 = I830PTR(pScrn);
+ uint32_t swf14 = INREG(SWF14);
+ Bool ret;
+
+ if (swf14 & SWF14_LID_SWITCH_EN)
+ ret = TRUE;
+ else
+ ret = FALSE;
+
+ if (pI830->debug_modes)
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "LID switch detect %s with SWF14 0x%8x\n",
+ ret ? "closed" : "open", swf14);
+
+ return ret;
+}
+
+/**
* Sets the power state for the panel.
*/
static void
@@ -765,13 +874,21 @@ i830_lvds_mode_set(xf86OutputPtr output, DisplayModePtr mode,
/**
* Detect the LVDS connection.
- *
- * This always returns OUTPUT_STATUS_CONNECTED. This output should only have
- * been set up if the LVDS was actually connected anyway.
*/
static xf86OutputStatus
i830_lvds_detect(xf86OutputPtr output)
{
+ enum lid_status lid;
+
+ lid = i830_lvds_acpi_lid_open(output);
+ if (lid == LID_OPEN)
+ return XF86OutputStatusConnected;
+ else if (lid == LID_CLOSE)
+ return XF86OutputStatusDisconnected;
+
+ if (i830_lvds_swf_lid_close(output))
+ return XF86OutputStatusDisconnected;
+
return XF86OutputStatusConnected;
}