===================================================================
@@ -171,6 +171,9 @@ struct acpi_video_device_cap {
struct acpi_video_brightness_flags {
u8 _BCL_no_ac_battery_levels:1; /* no AC/Battery levels in _BCL */
u8 _BCL_reversed:1; /* _BCL package is in a reversed order*/
+ u8 _BCL_use_index:1; /* levels in _BCL are index values */
+ u8 _BCM_use_index:1; /* input of _BCM is an index value */
+ u8 _BQC_use_index:1; /* _BQC returns an index value */
};
struct acpi_video_device_brightness {
@@ -505,7 +508,8 @@ acpi_video_device_lcd_set_level(struct a
device->brightness->curr = level;
for (state = 2; state < device->brightness->count; state++)
if (level == device->brightness->levels[state]) {
- device->backlight->props.brightness = state - 2;
+ if (device->backlight)
+ device->backlight->props.brightness = state - 2;
return 0;
}
@@ -523,6 +527,13 @@ acpi_video_device_lcd_get_level_current(
status = acpi_evaluate_integer(device->dev->handle, "_BQC",
NULL, level);
if (ACPI_SUCCESS(status)) {
+ if (device->brightness->flags._BQC_use_index) {
+ if (device->brightness->flags._BCL_reversed)
+ *level = device->brightness->count
+ - 3 - (*level);
+ *level = device->brightness->levels[*level + 2];
+
+ }
device->brightness->curr = *level;
return 0;
} else {
@@ -689,6 +700,7 @@ acpi_video_init_brightness(struct acpi_v
{
union acpi_object *obj = NULL;
int i, max_level = 0, count = 0, level_ac_battery = 0;
+ unsigned long long level;
union acpi_object *o;
struct acpi_video_device_brightness *br = NULL;
@@ -760,6 +772,38 @@ acpi_video_init_brightness(struct acpi_v
br->count = count;
device->brightness = br;
+
+ /* Check the input/output of _BQC/_BCL/_BCM */
+ if ((max_level < 100) && (max_level <= (count - 2)))
+ br->flags._BCL_use_index = 1;
+
+ /*
+ * _BCM is always consistent with _BCL,
+ * at least for all the laptops we have ever seen.
+ */
+ br->flags._BCM_use_index = br->flags._BCL_use_index;
+
+ /* _BQC uses INDEX while _BCL uses VALUE in some laptops */
+ if (acpi_video_device_lcd_set_level(device, max_level))
+ goto out_free_levels;
+
+ if (acpi_video_device_lcd_get_level_current(device, &level))
+ goto out_free_levels;
+
+ if ((level != max_level) && !br->flags._BCM_use_index) {
+ if (level_ac_battery != 2) {
+ /*
+ * For now, we don't support the _BCL like this:
+ * 16, 15, 0, 1, 2, 3, ..., 14, 15, 16
+ * because we may mess up the index returned by _BQC.
+ * Plus: we have not got a box like this.
+ */
+ ACPI_ERROR((AE_INFO, "_BCL not supported\n"));
+ goto out_free_levels;
+ }
+ br->flags._BQC_use_index = 1;
+ }
+
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"found %d brightness levels\n", count - 2));
kfree(obj);