ttuttle.net

The ttuttle.net blog

Categories

Fri, 24 Nov 2006

Dell Inspiron e1405 with BIOS A05 + Linux: Brightness hotkey fix

I have a Dell Inspiron e1405, and I just upgraded it to the latest BIOS version, A05. It went well (Dell has a Linux BIOS bootdisk tool that can create a physical floppy or a bootable kernel + ramdisk for GRUB that will update your BIOS!), but I found that when I loaded the video kernel module, which implements ACPI Video support, the brightness hotkeys stopped working.

I eventually tracked the problem down to the following pieces of code:

#define ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS      0x82
#define ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS        0x83
#define ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS        0x84
#define ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS       0x85
#define ACPI_VIDEO_NOTIFY_DISPLAY_OFF           0x86

and

static int
acpi_video_get_next_level(struct acpi_video_device *device,
                          u32 level_current, u32 event)
{
        /*Fix me */
        return level_current;
}

both in drivers/acpi/video.c. Basically, acpi_video_get_next_level is supposed to take the current brightness level and the ACPI video event number as parameters, and return the next brightness level that should be used, but nobody implemented it.

So I did. Here's the patch:

diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index 56666a9..2fc78ca 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -3,6 +3,7 @@
  *
  *  Copyright (C) 2004 Luming Yu 
  *  Copyright (C) 2004 Bruno Ducrot 
+ *  Copyright (C) 2006 Thomas Tuttle 
  *
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  *
@@ -47,11 +48,11 @@ #define ACPI_VIDEO_NOTIFY_CYCLE             0x82
 #define ACPI_VIDEO_NOTIFY_NEXT_OUTPUT  0x83
 #define ACPI_VIDEO_NOTIFY_PREV_OUTPUT  0x84

-#define ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS     0x82
-#define        ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS        0x83
-#define ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS       0x84
-#define ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS      0x85
-#define ACPI_VIDEO_NOTIFY_DISPLAY_OFF          0x86
+#define ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS     0x85
+#define        ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS        0x86
+#define ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS       0x87
+#define ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS      0x88
+#define ACPI_VIDEO_NOTIFY_DISPLAY_OFF          0x89

 #define ACPI_VIDEO_HEAD_INVALID                (~0u - 1)
 #define ACPI_VIDEO_HEAD_END            (~0u)
@@ -1509,8 +1510,30 @@ static int
 acpi_video_get_next_level(struct acpi_video_device *device,
                          u32 level_current, u32 event)
 {
-       /*Fix me */
-       return level_current;
+       int min, max, min_above, max_below, i, l;
+       max = max_below = 0;
+       min = min_above = 255;
+       for (i = 0; i < device->brightness->count; i++) {
+               l = device->brightness->levels[i];
+               if (l < min) min = l;
+               if (l > max) max = l;
+               if (l < min_above && l > level_current) min_above = l;
+               if (l > max_below && l < level_current) max_below = l;
+       }
+
+       switch (event) {
+       case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS:
+               return (level_current < max) ? min_above : min;
+       case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS:
+               return (level_current < max) ? min_above : max;
+       case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS:
+               return (level_current > min) ? max_below : min;
+       case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS:
+       case ACPI_VIDEO_NOTIFY_DISPLAY_OFF:
+               return 0;
+       default:
+               return level_current;
+       }
 }

 static void

I've submitted it to all the mailing lists I can find, so it should be in the kernel eventually. It works on my laptop, but I imagine few others actually use ACPI video hotkey events if nobody's bothered to implement them fully yet.

posted on Nov 24, 2006 at 20:27 in /computers/software | permalink