Platform: Brightness quirk for samsung laptop driver

On some Samsung laptops the brightness regulation works slightly different.
All SABI commands except for set_brightness work as expected. The behaviour
of set_brightness is as follows:

- Setting a new brightness will only step one level toward the new brightness
  level. For example, setting a level of 5 when the current level is 2 will
  result in a brightness level of 3.
- A spurious KEY_BRIGHTNESS_UP or KEY_BRIGHTNESS_DOWN event is also generated
  along with the change in brightness.
- Neither of the above two issues occur when changing from/to brightness
  level 0.

This patch adds detection and a non-intrusive workaround for the above issues.

Signed-off-by: Jason Stubbs <jasonbstubbs@gmail.com>
Tested-by: David Herrmann <dh.herrmann@googlemail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: Matthew Garrett <mjg@redhat.com>
This commit is contained in:
Jason Stubbs 2011-09-20 09:16:13 -07:00 committed by Matthew Garrett
parent a7ea19926f
commit ac08052314

View File

@ -226,6 +226,7 @@ static struct backlight_device *backlight_device;
static struct mutex sabi_mutex;
static struct platform_device *sdev;
static struct rfkill *rfk;
static bool has_stepping_quirk;
static int force;
module_param(force, bool, 0);
@ -382,6 +383,17 @@ static void set_brightness(u8 user_brightness)
{
u8 user_level = user_brightness + sabi_config->min_brightness;
if (has_stepping_quirk && user_level != 0) {
/*
* short circuit if the specified level is what's already set
* to prevent the screen from flickering needlessly
*/
if (user_brightness == read_brightness())
return;
sabi_set_command(sabi_config->commands.set_brightness, 0);
}
sabi_set_command(sabi_config->commands.set_brightness, user_level);
}
@ -390,6 +402,34 @@ static int get_brightness(struct backlight_device *bd)
return (int)read_brightness();
}
static void check_for_stepping_quirk(void)
{
u8 initial_level = read_brightness();
u8 check_level;
/*
* Some laptops exhibit the strange behaviour of stepping toward
* (rather than setting) the brightness except when changing to/from
* brightness level 0. This behaviour is checked for here and worked
* around in set_brightness.
*/
if (initial_level <= 2)
check_level = initial_level + 2;
else
check_level = initial_level - 2;
has_stepping_quirk = false;
set_brightness(check_level);
if (read_brightness() != check_level) {
has_stepping_quirk = true;
pr_info("enabled workaround for brightness stepping quirk\n");
}
set_brightness(initial_level);
}
static int update_status(struct backlight_device *bd)
{
set_brightness(bd->props.brightness);
@ -805,6 +845,9 @@ static int __init samsung_init(void)
}
}
/* Check for stepping quirk */
check_for_stepping_quirk();
/* knock up a platform device to hang stuff off of */
sdev = platform_device_register_simple("samsung", -1, NULL, 0);
if (IS_ERR(sdev))