Index: xserver-xorg-video-intel-2.19.0/src/intel_display.c =================================================================== --- xserver-xorg-video-intel-2.19.0.orig/src/intel_display.c 2012-07-07 21:15:02.000000000 +0300 +++ xserver-xorg-video-intel-2.19.0/src/intel_display.c 2012-07-07 21:19:25.000000000 +0300 @@ -121,7 +121,8 @@ #define BACKLIGHT_CLASS "/sys/class/backlight" /* - * List of available kernel interfaces in priority order + * List of available kernel interfaces in priority order. + * May be overridden by a model-specific workaround. */ static const char *backlight_interfaces[] = { "asus-laptop", @@ -243,28 +244,126 @@ return max; } +static Bool +intel_output_backlight_probe(xf86OutputPtr output, const char *iface) +{ + struct intel_output *intel_output = output->driver_private; + char path[BACKLIGHT_PATH_LEN]; + struct stat buf; + + sprintf(path, "%s/%s", BACKLIGHT_CLASS, iface); + if (!stat(path, &buf)) { + intel_output->backlight_iface = iface; + intel_output->backlight_max = intel_output_backlight_get_max(output); + if (intel_output->backlight_max > 0) { + intel_output->backlight_active_level = intel_output_backlight_get(output); + xf86DrvMsg(output->scrn->scrnIndex, X_INFO, + "found backlight control interface %s\n", path); + return TRUE; + } + } + + return FALSE; +} + +static Bool +intel_output_dmi_match(xf86OutputPtr output, const char *pathname, + const char *expect) +{ + /* This buffer is large enough for the strings we recognize. + * Longer strings will be truncated. */ + char buf[50]; + int fd; + ssize_t size; + Bool match = FALSE; + + fd = open(pathname, O_RDONLY); + if (fd != -1) { + /* Leave room for '\0'. */ + size = read(fd, buf, sizeof(buf) - 1); + if (size != -1) { + /* Remove trailing newlines and spaces. */ + while (size > 0 && (buf[size - 1] == '\n' + || buf[size - 1] == ' ')) + --size; + + buf[size] = '\0'; + xf86DrvMsg(output->scrn->scrnIndex, X_INFO, + "DMI ID in %s: %s\n", pathname, buf); + if (strcmp(buf, expect) == 0) + match = TRUE; + } + close(fd); + } + + return match; +} + +static Bool +intel_output_prefer_intel_backlight(xf86OutputPtr output) +{ + intel_screen_private *intel = intel_get_screen_private(output->scrn); + + /* With Linux 3.1.0 on Sony VAIO VPCYA1V9E, both acpi_video0 + * and intel_backlight exist and can be adjusted, but only + * intel_backlight affects the display. Reported at: + * - http://bugs.debian.org/651741 + * - https://bugs.freedesktop.org/show_bug.cgi?id=44809 + * DMI information: + * - bios_date: 11/02/2010 + * - bios_vendor: INSYDE + * - bios_version: R0070Z6 + * - board_name: VAIO + * - board_vendor: Sony Corporation + * - board_version: N/A + * - chassis_type: 10 + * - chassis_vendor: Sony Corporation + * - chassis_version: N/A + * - product_name: VPCYA1V9E + * - product_version: C9006WUT + * - sys_vendor: Sony Corporation + */ + if (VENDOR_ID(intel->PciInfo) == 0x8086 /* Intel */ + && DEVICE_ID(intel->PciInfo) == PCI_CHIP_IRONLAKE_M_G + && CHIP_REVISION(intel->PciInfo) == 0x02 + && SUBVENDOR_ID(intel->PciInfo) == 0x104d /* Sony */ + && SUBSYS_ID(intel->PciInfo) == 0x907c + && intel_output_dmi_match(output, "/sys/class/dmi/id/sys_vendor", "Sony Corporation") + && intel_output_dmi_match(output, "/sys/class/dmi/id/product_name", "VPCYA1V9E") + && intel_output_dmi_match(output, "/sys/class/dmi/id/product_version", "C9006WUT")) + return TRUE; + + if (VENDOR_ID(intel->PciInfo) == 0x8086 /* Intel */ + && DEVICE_ID(intel->PciInfo) == PCI_CHIP_IRONLAKE_M_G + && CHIP_REVISION(intel->PciInfo) == 0x18 + && SUBVENDOR_ID(intel->PciInfo) == 0x17aa /* Lenovo */ + && SUBSYS_ID(intel->PciInfo) == 0x3920 + && intel_output_dmi_match(output, "/sys/class/dmi/id/sys_vendor", "LENOVO") + && intel_output_dmi_match(output, "/sys/class/dmi/id/product_name", "G360") + && intel_output_dmi_match(output, "/sys/class/dmi/id/product_version", "Rev 1.0")) + return TRUE; + + return FALSE; +} + static void intel_output_backlight_init(xf86OutputPtr output) { struct intel_output *intel_output = output->driver_private; int i; - for (i = 0; backlight_interfaces[i] != NULL; i++) { - char path[BACKLIGHT_PATH_LEN]; - struct stat buf; + if (intel_output_prefer_intel_backlight(output)) { + xf86DrvMsg(output->scrn->scrnIndex, X_INFO, + "will prefer intel_backlight on this computer\n"); + if (intel_output_backlight_probe(output, "intel_backlight")) + return; + } - sprintf(path, "%s/%s", BACKLIGHT_CLASS, backlight_interfaces[i]); - if (!stat(path, &buf)) { - intel_output->backlight_iface = backlight_interfaces[i]; - intel_output->backlight_max = intel_output_backlight_get_max(output); - if (intel_output->backlight_max > 0) { - intel_output->backlight_active_level = intel_output_backlight_get(output); - xf86DrvMsg(output->scrn->scrnIndex, X_INFO, - "found backlight control interface %s\n", path); - return; - } - } + for (i = 0; backlight_interfaces[i] != NULL; i++) { + if (intel_output_backlight_probe(output, backlight_interfaces[i])) + return; } + intel_output->backlight_iface = NULL; }