Skip to content

Commit

Permalink
Merge branch 'acpi-video'
Browse files Browse the repository at this point in the history
* acpi-video:
  ACPI / video: Add 4 new models to the use_native_backlight DMI list
  ACPI / video: Add use native backlight quirk for the ThinkPad W530
  ACPI / video: Unregister the backlight device if a raw one shows up later
  backlight: Add backlight device (un)registration notification
  nouveau: Don't check acpi_video_backlight_support() before registering backlight
  acer-wmi: Add Aspire 5741 to video_vendor_dmi_table
  acer-wmi: Switch to acpi_video_unregister_backlight
  ACPI / video: Add an acpi_video_unregister_backlight function
  ACPI / video: Don't register acpi_video_resume notifier without backlight devices
  ACPI / video: change acpi-video brightness_switch_enabled default to 0
  • Loading branch information
Rafael J. Wysocki committed Jun 3, 2014
2 parents 0e36d43 + 0dc6b96 commit d9bd449
Show file tree
Hide file tree
Showing 7 changed files with 245 additions and 77 deletions.
2 changes: 1 addition & 1 deletion Documentation/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3481,7 +3481,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
the allocated input device; If set to 0, video driver
will only send out the event without touching backlight
brightness level.
default: 1
default: 0

virtio_mmio.device=
[VMMIO] Memory mapped virtio (platform) device.
Expand Down
252 changes: 186 additions & 66 deletions drivers/acpi/video.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ MODULE_AUTHOR("Bruno Ducrot");
MODULE_DESCRIPTION("ACPI Video Driver");
MODULE_LICENSE("GPL");

static bool brightness_switch_enabled = 1;
static bool brightness_switch_enabled;
module_param(brightness_switch_enabled, bool, 0644);

/*
Expand Down Expand Up @@ -150,6 +150,8 @@ struct acpi_video_enumerated_device {

struct acpi_video_bus {
struct acpi_device *device;
bool backlight_registered;
bool backlight_notifier_registered;
u8 dos_setting;
struct acpi_video_enumerated_device *attached_array;
u8 attached_count;
Expand All @@ -161,6 +163,7 @@ struct acpi_video_bus {
struct input_dev *input;
char phys[32]; /* for input device */
struct notifier_block pm_nb;
struct notifier_block backlight_nb;
};

struct acpi_video_device_flags {
Expand Down Expand Up @@ -471,6 +474,14 @@ static struct dmi_system_id video_dmi_table[] __initdata = {
DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X230"),
},
},
{
.callback = video_set_use_native_backlight,
.ident = "ThinkPad W530",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad W530"),
},
},
{
.callback = video_set_use_native_backlight,
.ident = "ThinkPad X1 Carbon",
Expand All @@ -487,6 +498,14 @@ static struct dmi_system_id video_dmi_table[] __initdata = {
DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo IdeaPad Yoga 13"),
},
},
{
.callback = video_set_use_native_backlight,
.ident = "Lenovo Yoga 2 11",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 2 11"),
},
},
{
.callback = video_set_use_native_backlight,
.ident = "Thinkpad Helix",
Expand Down Expand Up @@ -519,6 +538,14 @@ static struct dmi_system_id video_dmi_table[] __initdata = {
DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5742G"),
},
},
{
.callback = video_set_use_native_backlight,
.ident = "Acer Aspire V5-171",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
DMI_MATCH(DMI_PRODUCT_NAME, "V5-171"),
},
},
{
.callback = video_set_use_native_backlight,
.ident = "Acer Aspire V5-431",
Expand All @@ -527,6 +554,14 @@ static struct dmi_system_id video_dmi_table[] __initdata = {
DMI_MATCH(DMI_PRODUCT_NAME, "Aspire V5-431"),
},
},
{
.callback = video_set_use_native_backlight,
.ident = "Acer Aspire V5-471G",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
DMI_MATCH(DMI_PRODUCT_NAME, "Aspire V5-471G"),
},
},
{
.callback = video_set_use_native_backlight,
.ident = "HP ProBook 4340s",
Expand Down Expand Up @@ -579,6 +614,14 @@ static struct dmi_system_id video_dmi_table[] __initdata = {
},
{
.callback = video_set_use_native_backlight,
.ident = "HP EliteBook 8470p",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook 8470p"),
},
},
{
.callback = video_set_use_native_backlight,
.ident = "HP EliteBook 8780w",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
Expand Down Expand Up @@ -1658,88 +1701,92 @@ acpi_video_bus_match(acpi_handle handle, u32 level, void *context,

static void acpi_video_dev_register_backlight(struct acpi_video_device *device)
{
if (acpi_video_verify_backlight_support()) {
struct backlight_properties props;
struct pci_dev *pdev;
acpi_handle acpi_parent;
struct device *parent = NULL;
int result;
static int count;
char *name;

result = acpi_video_init_brightness(device);
if (result)
return;
name = kasprintf(GFP_KERNEL, "acpi_video%d", count);
if (!name)
return;
count++;
struct backlight_properties props;
struct pci_dev *pdev;
acpi_handle acpi_parent;
struct device *parent = NULL;
int result;
static int count;
char *name;

acpi_get_parent(device->dev->handle, &acpi_parent);
result = acpi_video_init_brightness(device);
if (result)
return;
name = kasprintf(GFP_KERNEL, "acpi_video%d", count);
if (!name)
return;
count++;

pdev = acpi_get_pci_dev(acpi_parent);
if (pdev) {
parent = &pdev->dev;
pci_dev_put(pdev);
}
acpi_get_parent(device->dev->handle, &acpi_parent);

memset(&props, 0, sizeof(struct backlight_properties));
props.type = BACKLIGHT_FIRMWARE;
props.max_brightness = device->brightness->count - 3;
device->backlight = backlight_device_register(name,
parent,
device,
&acpi_backlight_ops,
&props);
kfree(name);
if (IS_ERR(device->backlight))
return;
pdev = acpi_get_pci_dev(acpi_parent);
if (pdev) {
parent = &pdev->dev;
pci_dev_put(pdev);
}

/*
* Save current brightness level in case we have to restore it
* before acpi_video_device_lcd_set_level() is called next time.
*/
device->backlight->props.brightness =
acpi_video_get_brightness(device->backlight);
memset(&props, 0, sizeof(struct backlight_properties));
props.type = BACKLIGHT_FIRMWARE;
props.max_brightness = device->brightness->count - 3;
device->backlight = backlight_device_register(name,
parent,
device,
&acpi_backlight_ops,
&props);
kfree(name);
if (IS_ERR(device->backlight))
return;

device->cooling_dev = thermal_cooling_device_register("LCD",
device->dev, &video_cooling_ops);
if (IS_ERR(device->cooling_dev)) {
/*
* Set cooling_dev to NULL so we don't crash trying to
* free it.
* Also, why the hell we are returning early and
* not attempt to register video output if cooling
* device registration failed?
* -- dtor
*/
device->cooling_dev = NULL;
return;
}
/*
* Save current brightness level in case we have to restore it
* before acpi_video_device_lcd_set_level() is called next time.
*/
device->backlight->props.brightness =
acpi_video_get_brightness(device->backlight);

dev_info(&device->dev->dev, "registered as cooling_device%d\n",
device->cooling_dev->id);
result = sysfs_create_link(&device->dev->dev.kobj,
&device->cooling_dev->device.kobj,
"thermal_cooling");
if (result)
printk(KERN_ERR PREFIX "Create sysfs link\n");
result = sysfs_create_link(&device->cooling_dev->device.kobj,
&device->dev->dev.kobj, "device");
if (result)
printk(KERN_ERR PREFIX "Create sysfs link\n");
device->cooling_dev = thermal_cooling_device_register("LCD",
device->dev, &video_cooling_ops);
if (IS_ERR(device->cooling_dev)) {
/*
* Set cooling_dev to NULL so we don't crash trying to free it.
* Also, why the hell we are returning early and not attempt to
* register video output if cooling device registration failed?
* -- dtor
*/
device->cooling_dev = NULL;
return;
}

dev_info(&device->dev->dev, "registered as cooling_device%d\n",
device->cooling_dev->id);
result = sysfs_create_link(&device->dev->dev.kobj,
&device->cooling_dev->device.kobj,
"thermal_cooling");
if (result)
printk(KERN_ERR PREFIX "Create sysfs link\n");
result = sysfs_create_link(&device->cooling_dev->device.kobj,
&device->dev->dev.kobj, "device");
if (result)
printk(KERN_ERR PREFIX "Create sysfs link\n");
}

static int acpi_video_bus_register_backlight(struct acpi_video_bus *video)
{
struct acpi_video_device *dev;

if (video->backlight_registered)
return 0;

if (!acpi_video_verify_backlight_support())
return 0;

mutex_lock(&video->device_list_lock);
list_for_each_entry(dev, &video->video_device_list, entry)
acpi_video_dev_register_backlight(dev);
mutex_unlock(&video->device_list_lock);

video->backlight_registered = true;

video->pm_nb.notifier_call = acpi_video_resume;
video->pm_nb.priority = 0;
return register_pm_notifier(&video->pm_nb);
Expand Down Expand Up @@ -1767,13 +1814,20 @@ static void acpi_video_dev_unregister_backlight(struct acpi_video_device *device
static int acpi_video_bus_unregister_backlight(struct acpi_video_bus *video)
{
struct acpi_video_device *dev;
int error = unregister_pm_notifier(&video->pm_nb);
int error;

if (!video->backlight_registered)
return 0;

error = unregister_pm_notifier(&video->pm_nb);

mutex_lock(&video->device_list_lock);
list_for_each_entry(dev, &video->video_device_list, entry)
acpi_video_dev_unregister_backlight(dev);
mutex_unlock(&video->device_list_lock);

video->backlight_registered = false;

return error;
}

Expand Down Expand Up @@ -1867,6 +1921,56 @@ static void acpi_video_bus_remove_notify_handler(struct acpi_video_bus *video)
video->input = NULL;
}

static int acpi_video_backlight_notify(struct notifier_block *nb,
unsigned long val, void *bd)
{
struct backlight_device *backlight = bd;
struct acpi_video_bus *video;

/* acpi_video_verify_backlight_support only cares about raw devices */
if (backlight->props.type != BACKLIGHT_RAW)
return NOTIFY_DONE;

video = container_of(nb, struct acpi_video_bus, backlight_nb);

switch (val) {
case BACKLIGHT_REGISTERED:
if (!acpi_video_verify_backlight_support())
acpi_video_bus_unregister_backlight(video);
break;
case BACKLIGHT_UNREGISTERED:
acpi_video_bus_register_backlight(video);
break;
}

return NOTIFY_OK;
}

static int acpi_video_bus_add_backlight_notify_handler(
struct acpi_video_bus *video)
{
int error;

video->backlight_nb.notifier_call = acpi_video_backlight_notify;
video->backlight_nb.priority = 0;
error = backlight_register_notifier(&video->backlight_nb);
if (error == 0)
video->backlight_notifier_registered = true;

return error;
}

static int acpi_video_bus_remove_backlight_notify_handler(
struct acpi_video_bus *video)
{
if (!video->backlight_notifier_registered)
return 0;

video->backlight_notifier_registered = false;

return backlight_unregister_notifier(&video->backlight_nb);
}

static int acpi_video_bus_put_devices(struct acpi_video_bus *video)
{
struct acpi_video_device *dev, *next;
Expand Down Expand Up @@ -1948,6 +2052,7 @@ static int acpi_video_bus_add(struct acpi_device *device)

acpi_video_bus_register_backlight(video);
acpi_video_bus_add_notify_handler(video);
acpi_video_bus_add_backlight_notify_handler(video);

return 0;

Expand All @@ -1971,6 +2076,7 @@ static int acpi_video_bus_remove(struct acpi_device *device)

video = acpi_driver_data(device);

acpi_video_bus_remove_backlight_notify_handler(video);
acpi_video_bus_remove_notify_handler(video);
acpi_video_bus_unregister_backlight(video);
acpi_video_bus_put_devices(video);
Expand Down Expand Up @@ -2061,6 +2167,20 @@ void acpi_video_unregister(void)
}
EXPORT_SYMBOL(acpi_video_unregister);

void acpi_video_unregister_backlight(void)
{
struct acpi_video_bus *video;

if (!register_count)
return;

mutex_lock(&video_list_lock);
list_for_each_entry(video, &video_bus_head, entry)
acpi_video_bus_unregister_backlight(video);
mutex_unlock(&video_list_lock);
}
EXPORT_SYMBOL(acpi_video_unregister_backlight);

/*
* This is kind of nasty. Hardware using Intel chipsets may require
* the video opregion code to be run first in order to initialise
Expand Down
Loading

0 comments on commit d9bd449

Please sign in to comment.