Skip to content

Commit 8ab58e8

Browse files
torvaldsrafaeljw
authored andcommitted
ACPI / video: Fix backlight taking 2 steps on a brightness up/down keypress
In various scenarious userspace will respond to brightness up/down keypresses by increasing/decreasing the backlight brightness itself. If the kernel then also changes the brightness this results in the brightness having changed 2 steps for a single keypress which is undesirable. See e.g. : https://bugs.launchpad.net/gnome-settings-daemon/+bug/527157 http://askubuntu.com/questions/173921/why-does-my-thinkpad-brightness-control-skip-steps This commit delays responding to brightness up/down keypresses by 100 ms and if userspace in that time responds by changing the backlight itself, cancels the kernels own handling of these keypresses, fixing the 2 steps issue. Link: http://marc.info/?l=linux-kernel&m=140535721100839&w=2 [hdegoede@redhat.com: Move the delayed_work struct into struct acpi_video_device instead of having it as a global] [hdegoede@redhat.com: Keep brightness_switch_enabled as a boolean and always delay the keypress handling] Tested-by: Hans de Goede <hdegoede@redhat.com> Tested-by: Bjørn Mork <bjorn@mork.no> Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
1 parent 9a3c414 commit 8ab58e8

File tree

1 file changed

+27
-17
lines changed

1 file changed

+27
-17
lines changed

drivers/acpi/video.c

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,8 @@ struct acpi_video_device {
204204
struct acpi_video_device_flags flags;
205205
struct acpi_video_device_cap cap;
206206
struct list_head entry;
207+
struct delayed_work switch_brightness_work;
208+
int switch_brightness_event;
207209
struct acpi_video_bus *video;
208210
struct acpi_device *dev;
209211
struct acpi_video_device_brightness *brightness;
@@ -230,8 +232,7 @@ static int acpi_video_device_lcd_get_level_current(
230232
unsigned long long *level, bool raw);
231233
static int acpi_video_get_next_level(struct acpi_video_device *device,
232234
u32 level_current, u32 event);
233-
static int acpi_video_switch_brightness(struct acpi_video_device *device,
234-
int event);
235+
static void acpi_video_switch_brightness(struct work_struct *work);
235236

236237
static bool acpi_video_use_native_backlight(void)
237238
{
@@ -275,6 +276,7 @@ static int acpi_video_set_brightness(struct backlight_device *bd)
275276
int request_level = bd->props.brightness + 2;
276277
struct acpi_video_device *vd = bl_get_data(bd);
277278

279+
cancel_delayed_work(&vd->switch_brightness_work);
278280
return acpi_video_device_lcd_set_level(vd,
279281
vd->brightness->levels[request_level]);
280282
}
@@ -1188,6 +1190,8 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
11881190
data->device_id = device_id;
11891191
data->video = video;
11901192
data->dev = device;
1193+
INIT_DELAYED_WORK(&data->switch_brightness_work,
1194+
acpi_video_switch_brightness);
11911195

11921196
attribute = acpi_video_get_device_attr(video, device_id);
11931197

@@ -1410,15 +1414,18 @@ acpi_video_get_next_level(struct acpi_video_device *device,
14101414
}
14111415
}
14121416

1413-
static int
1414-
acpi_video_switch_brightness(struct acpi_video_device *device, int event)
1417+
static void
1418+
acpi_video_switch_brightness(struct work_struct *work)
14151419
{
1420+
struct acpi_video_device *device = container_of(to_delayed_work(work),
1421+
struct acpi_video_device, switch_brightness_work);
14161422
unsigned long long level_current, level_next;
1423+
int event = device->switch_brightness_event;
14171424
int result = -EINVAL;
14181425

14191426
/* no warning message if acpi_backlight=vendor or a quirk is used */
14201427
if (!acpi_video_verify_backlight_support())
1421-
return 0;
1428+
return;
14221429

14231430
if (!device->brightness)
14241431
goto out;
@@ -1440,8 +1447,6 @@ acpi_video_switch_brightness(struct acpi_video_device *device, int event)
14401447
out:
14411448
if (result)
14421449
printk(KERN_ERR PREFIX "Failed to switch the brightness\n");
1443-
1444-
return result;
14451450
}
14461451

14471452
int acpi_video_get_edid(struct acpi_device *device, int type, int device_id,
@@ -1609,6 +1614,16 @@ static void acpi_video_bus_notify(struct acpi_device *device, u32 event)
16091614
return;
16101615
}
16111616

1617+
static void brightness_switch_event(struct acpi_video_device *video_device,
1618+
u32 event)
1619+
{
1620+
if (!brightness_switch_enabled)
1621+
return;
1622+
1623+
video_device->switch_brightness_event = event;
1624+
schedule_delayed_work(&video_device->switch_brightness_work, HZ / 10);
1625+
}
1626+
16121627
static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data)
16131628
{
16141629
struct acpi_video_device *video_device = data;
@@ -1626,28 +1641,23 @@ static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data)
16261641

16271642
switch (event) {
16281643
case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS: /* Cycle brightness */
1629-
if (brightness_switch_enabled)
1630-
acpi_video_switch_brightness(video_device, event);
1644+
brightness_switch_event(video_device, event);
16311645
keycode = KEY_BRIGHTNESS_CYCLE;
16321646
break;
16331647
case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS: /* Increase brightness */
1634-
if (brightness_switch_enabled)
1635-
acpi_video_switch_brightness(video_device, event);
1648+
brightness_switch_event(video_device, event);
16361649
keycode = KEY_BRIGHTNESSUP;
16371650
break;
16381651
case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS: /* Decrease brightness */
1639-
if (brightness_switch_enabled)
1640-
acpi_video_switch_brightness(video_device, event);
1652+
brightness_switch_event(video_device, event);
16411653
keycode = KEY_BRIGHTNESSDOWN;
16421654
break;
16431655
case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS: /* zero brightness */
1644-
if (brightness_switch_enabled)
1645-
acpi_video_switch_brightness(video_device, event);
1656+
brightness_switch_event(video_device, event);
16461657
keycode = KEY_BRIGHTNESS_ZERO;
16471658
break;
16481659
case ACPI_VIDEO_NOTIFY_DISPLAY_OFF: /* display device off */
1649-
if (brightness_switch_enabled)
1650-
acpi_video_switch_brightness(video_device, event);
1660+
brightness_switch_event(video_device, event);
16511661
keycode = KEY_DISPLAY_OFF;
16521662
break;
16531663
default:

0 commit comments

Comments
 (0)