aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/video.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/video.c')
-rw-r--r--drivers/acpi/video.c336
1 files changed, 256 insertions, 80 deletions
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index 67cc36dc9b82..ab06143672bc 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -37,6 +37,8 @@
37#include <linux/thermal.h> 37#include <linux/thermal.h>
38#include <linux/video_output.h> 38#include <linux/video_output.h>
39#include <linux/sort.h> 39#include <linux/sort.h>
40#include <linux/pci.h>
41#include <linux/pci_ids.h>
40#include <asm/uaccess.h> 42#include <asm/uaccess.h>
41 43
42#include <acpi/acpi_bus.h> 44#include <acpi/acpi_bus.h>
@@ -162,16 +164,26 @@ struct acpi_video_device_cap {
162 u8 _BCL:1; /*Query list of brightness control levels supported */ 164 u8 _BCL:1; /*Query list of brightness control levels supported */
163 u8 _BCM:1; /*Set the brightness level */ 165 u8 _BCM:1; /*Set the brightness level */
164 u8 _BQC:1; /* Get current brightness level */ 166 u8 _BQC:1; /* Get current brightness level */
167 u8 _BCQ:1; /* Some buggy BIOS uses _BCQ instead of _BQC */
165 u8 _DDC:1; /*Return the EDID for this device */ 168 u8 _DDC:1; /*Return the EDID for this device */
166 u8 _DCS:1; /*Return status of output device */ 169 u8 _DCS:1; /*Return status of output device */
167 u8 _DGS:1; /*Query graphics state */ 170 u8 _DGS:1; /*Query graphics state */
168 u8 _DSS:1; /*Device state set */ 171 u8 _DSS:1; /*Device state set */
169}; 172};
170 173
174struct acpi_video_brightness_flags {
175 u8 _BCL_no_ac_battery_levels:1; /* no AC/Battery levels in _BCL */
176 u8 _BCL_reversed:1; /* _BCL package is in a reversed order*/
177 u8 _BCL_use_index:1; /* levels in _BCL are index values */
178 u8 _BCM_use_index:1; /* input of _BCM is an index value */
179 u8 _BQC_use_index:1; /* _BQC returns an index value */
180};
181
171struct acpi_video_device_brightness { 182struct acpi_video_device_brightness {
172 int curr; 183 int curr;
173 int count; 184 int count;
174 int *levels; 185 int *levels;
186 struct acpi_video_brightness_flags flags;
175}; 187};
176 188
177struct acpi_video_device { 189struct acpi_video_device {
@@ -189,7 +201,7 @@ struct acpi_video_device {
189 201
190/* bus */ 202/* bus */
191static int acpi_video_bus_info_open_fs(struct inode *inode, struct file *file); 203static int acpi_video_bus_info_open_fs(struct inode *inode, struct file *file);
192static struct file_operations acpi_video_bus_info_fops = { 204static const struct file_operations acpi_video_bus_info_fops = {
193 .owner = THIS_MODULE, 205 .owner = THIS_MODULE,
194 .open = acpi_video_bus_info_open_fs, 206 .open = acpi_video_bus_info_open_fs,
195 .read = seq_read, 207 .read = seq_read,
@@ -198,7 +210,7 @@ static struct file_operations acpi_video_bus_info_fops = {
198}; 210};
199 211
200static int acpi_video_bus_ROM_open_fs(struct inode *inode, struct file *file); 212static int acpi_video_bus_ROM_open_fs(struct inode *inode, struct file *file);
201static struct file_operations acpi_video_bus_ROM_fops = { 213static const struct file_operations acpi_video_bus_ROM_fops = {
202 .owner = THIS_MODULE, 214 .owner = THIS_MODULE,
203 .open = acpi_video_bus_ROM_open_fs, 215 .open = acpi_video_bus_ROM_open_fs,
204 .read = seq_read, 216 .read = seq_read,
@@ -208,7 +220,7 @@ static struct file_operations acpi_video_bus_ROM_fops = {
208 220
209static int acpi_video_bus_POST_info_open_fs(struct inode *inode, 221static int acpi_video_bus_POST_info_open_fs(struct inode *inode,
210 struct file *file); 222 struct file *file);
211static struct file_operations acpi_video_bus_POST_info_fops = { 223static const struct file_operations acpi_video_bus_POST_info_fops = {
212 .owner = THIS_MODULE, 224 .owner = THIS_MODULE,
213 .open = acpi_video_bus_POST_info_open_fs, 225 .open = acpi_video_bus_POST_info_open_fs,
214 .read = seq_read, 226 .read = seq_read,
@@ -217,19 +229,25 @@ static struct file_operations acpi_video_bus_POST_info_fops = {
217}; 229};
218 230
219static int acpi_video_bus_POST_open_fs(struct inode *inode, struct file *file); 231static int acpi_video_bus_POST_open_fs(struct inode *inode, struct file *file);
220static struct file_operations acpi_video_bus_POST_fops = { 232static ssize_t acpi_video_bus_write_POST(struct file *file,
233 const char __user *buffer, size_t count, loff_t *data);
234static const struct file_operations acpi_video_bus_POST_fops = {
221 .owner = THIS_MODULE, 235 .owner = THIS_MODULE,
222 .open = acpi_video_bus_POST_open_fs, 236 .open = acpi_video_bus_POST_open_fs,
223 .read = seq_read, 237 .read = seq_read,
238 .write = acpi_video_bus_write_POST,
224 .llseek = seq_lseek, 239 .llseek = seq_lseek,
225 .release = single_release, 240 .release = single_release,
226}; 241};
227 242
228static int acpi_video_bus_DOS_open_fs(struct inode *inode, struct file *file); 243static int acpi_video_bus_DOS_open_fs(struct inode *inode, struct file *file);
229static struct file_operations acpi_video_bus_DOS_fops = { 244static ssize_t acpi_video_bus_write_DOS(struct file *file,
245 const char __user *buffer, size_t count, loff_t *data);
246static const struct file_operations acpi_video_bus_DOS_fops = {
230 .owner = THIS_MODULE, 247 .owner = THIS_MODULE,
231 .open = acpi_video_bus_DOS_open_fs, 248 .open = acpi_video_bus_DOS_open_fs,
232 .read = seq_read, 249 .read = seq_read,
250 .write = acpi_video_bus_write_DOS,
233 .llseek = seq_lseek, 251 .llseek = seq_lseek,
234 .release = single_release, 252 .release = single_release,
235}; 253};
@@ -237,7 +255,7 @@ static struct file_operations acpi_video_bus_DOS_fops = {
237/* device */ 255/* device */
238static int acpi_video_device_info_open_fs(struct inode *inode, 256static int acpi_video_device_info_open_fs(struct inode *inode,
239 struct file *file); 257 struct file *file);
240static struct file_operations acpi_video_device_info_fops = { 258static const struct file_operations acpi_video_device_info_fops = {
241 .owner = THIS_MODULE, 259 .owner = THIS_MODULE,
242 .open = acpi_video_device_info_open_fs, 260 .open = acpi_video_device_info_open_fs,
243 .read = seq_read, 261 .read = seq_read,
@@ -247,27 +265,33 @@ static struct file_operations acpi_video_device_info_fops = {
247 265
248static int acpi_video_device_state_open_fs(struct inode *inode, 266static int acpi_video_device_state_open_fs(struct inode *inode,
249 struct file *file); 267 struct file *file);
250static struct file_operations acpi_video_device_state_fops = { 268static ssize_t acpi_video_device_write_state(struct file *file,
269 const char __user *buffer, size_t count, loff_t *data);
270static const struct file_operations acpi_video_device_state_fops = {
251 .owner = THIS_MODULE, 271 .owner = THIS_MODULE,
252 .open = acpi_video_device_state_open_fs, 272 .open = acpi_video_device_state_open_fs,
253 .read = seq_read, 273 .read = seq_read,
274 .write = acpi_video_device_write_state,
254 .llseek = seq_lseek, 275 .llseek = seq_lseek,
255 .release = single_release, 276 .release = single_release,
256}; 277};
257 278
258static int acpi_video_device_brightness_open_fs(struct inode *inode, 279static int acpi_video_device_brightness_open_fs(struct inode *inode,
259 struct file *file); 280 struct file *file);
281static ssize_t acpi_video_device_write_brightness(struct file *file,
282 const char __user *buffer, size_t count, loff_t *data);
260static struct file_operations acpi_video_device_brightness_fops = { 283static struct file_operations acpi_video_device_brightness_fops = {
261 .owner = THIS_MODULE, 284 .owner = THIS_MODULE,
262 .open = acpi_video_device_brightness_open_fs, 285 .open = acpi_video_device_brightness_open_fs,
263 .read = seq_read, 286 .read = seq_read,
287 .write = acpi_video_device_write_brightness,
264 .llseek = seq_lseek, 288 .llseek = seq_lseek,
265 .release = single_release, 289 .release = single_release,
266}; 290};
267 291
268static int acpi_video_device_EDID_open_fs(struct inode *inode, 292static int acpi_video_device_EDID_open_fs(struct inode *inode,
269 struct file *file); 293 struct file *file);
270static struct file_operations acpi_video_device_EDID_fops = { 294static const struct file_operations acpi_video_device_EDID_fops = {
271 .owner = THIS_MODULE, 295 .owner = THIS_MODULE,
272 .open = acpi_video_device_EDID_open_fs, 296 .open = acpi_video_device_EDID_open_fs,
273 .read = seq_read, 297 .read = seq_read,
@@ -275,7 +299,7 @@ static struct file_operations acpi_video_device_EDID_fops = {
275 .release = single_release, 299 .release = single_release,
276}; 300};
277 301
278static char device_decode[][30] = { 302static const char device_decode[][30] = {
279 "motherboard VGA device", 303 "motherboard VGA device",
280 "PCI VGA device", 304 "PCI VGA device",
281 "AGP VGA device", 305 "AGP VGA device",
@@ -294,7 +318,7 @@ static int acpi_video_device_lcd_get_level_current(
294 unsigned long long *level); 318 unsigned long long *level);
295static int acpi_video_get_next_level(struct acpi_video_device *device, 319static int acpi_video_get_next_level(struct acpi_video_device *device,
296 u32 level_current, u32 event); 320 u32 level_current, u32 event);
297static void acpi_video_switch_brightness(struct acpi_video_device *device, 321static int acpi_video_switch_brightness(struct acpi_video_device *device,
298 int event); 322 int event);
299static int acpi_video_device_get_state(struct acpi_video_device *device, 323static int acpi_video_device_get_state(struct acpi_video_device *device,
300 unsigned long long *state); 324 unsigned long long *state);
@@ -308,7 +332,9 @@ static int acpi_video_get_brightness(struct backlight_device *bd)
308 int i; 332 int i;
309 struct acpi_video_device *vd = 333 struct acpi_video_device *vd =
310 (struct acpi_video_device *)bl_get_data(bd); 334 (struct acpi_video_device *)bl_get_data(bd);
311 acpi_video_device_lcd_get_level_current(vd, &cur_level); 335
336 if (acpi_video_device_lcd_get_level_current(vd, &cur_level))
337 return -EINVAL;
312 for (i = 2; i < vd->brightness->count; i++) { 338 for (i = 2; i < vd->brightness->count; i++) {
313 if (vd->brightness->levels[i] == cur_level) 339 if (vd->brightness->levels[i] == cur_level)
314 /* The first two entries are special - see page 575 340 /* The first two entries are special - see page 575
@@ -320,12 +346,12 @@ static int acpi_video_get_brightness(struct backlight_device *bd)
320 346
321static int acpi_video_set_brightness(struct backlight_device *bd) 347static int acpi_video_set_brightness(struct backlight_device *bd)
322{ 348{
323 int request_level = bd->props.brightness+2; 349 int request_level = bd->props.brightness + 2;
324 struct acpi_video_device *vd = 350 struct acpi_video_device *vd =
325 (struct acpi_video_device *)bl_get_data(bd); 351 (struct acpi_video_device *)bl_get_data(bd);
326 acpi_video_device_lcd_set_level(vd, 352
327 vd->brightness->levels[request_level]); 353 return acpi_video_device_lcd_set_level(vd,
328 return 0; 354 vd->brightness->levels[request_level]);
329} 355}
330 356
331static struct backlight_ops acpi_backlight_ops = { 357static struct backlight_ops acpi_backlight_ops = {
@@ -358,32 +384,37 @@ static struct output_properties acpi_output_properties = {
358 384
359 385
360/* thermal cooling device callbacks */ 386/* thermal cooling device callbacks */
361static int video_get_max_state(struct thermal_cooling_device *cdev, char *buf) 387static int video_get_max_state(struct thermal_cooling_device *cdev, unsigned
388 long *state)
362{ 389{
363 struct acpi_device *device = cdev->devdata; 390 struct acpi_device *device = cdev->devdata;
364 struct acpi_video_device *video = acpi_driver_data(device); 391 struct acpi_video_device *video = acpi_driver_data(device);
365 392
366 return sprintf(buf, "%d\n", video->brightness->count - 3); 393 *state = video->brightness->count - 3;
394 return 0;
367} 395}
368 396
369static int video_get_cur_state(struct thermal_cooling_device *cdev, char *buf) 397static int video_get_cur_state(struct thermal_cooling_device *cdev, unsigned
398 long *state)
370{ 399{
371 struct acpi_device *device = cdev->devdata; 400 struct acpi_device *device = cdev->devdata;
372 struct acpi_video_device *video = acpi_driver_data(device); 401 struct acpi_video_device *video = acpi_driver_data(device);
373 unsigned long long level; 402 unsigned long long level;
374 int state; 403 int offset;
375 404
376 acpi_video_device_lcd_get_level_current(video, &level); 405 if (acpi_video_device_lcd_get_level_current(video, &level))
377 for (state = 2; state < video->brightness->count; state++) 406 return -EINVAL;
378 if (level == video->brightness->levels[state]) 407 for (offset = 2; offset < video->brightness->count; offset++)
379 return sprintf(buf, "%d\n", 408 if (level == video->brightness->levels[offset]) {
380 video->brightness->count - state - 1); 409 *state = video->brightness->count - offset - 1;
410 return 0;
411 }
381 412
382 return -EINVAL; 413 return -EINVAL;
383} 414}
384 415
385static int 416static int
386video_set_cur_state(struct thermal_cooling_device *cdev, unsigned int state) 417video_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state)
387{ 418{
388 struct acpi_device *device = cdev->devdata; 419 struct acpi_device *device = cdev->devdata;
389 struct acpi_video_device *video = acpi_driver_data(device); 420 struct acpi_video_device *video = acpi_driver_data(device);
@@ -479,34 +510,68 @@ acpi_video_device_lcd_query_levels(struct acpi_video_device *device,
479static int 510static int
480acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level) 511acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level)
481{ 512{
482 int status = AE_OK; 513 int status;
483 union acpi_object arg0 = { ACPI_TYPE_INTEGER }; 514 union acpi_object arg0 = { ACPI_TYPE_INTEGER };
484 struct acpi_object_list args = { 1, &arg0 }; 515 struct acpi_object_list args = { 1, &arg0 };
485 int state; 516 int state;
486 517
487
488 arg0.integer.value = level; 518 arg0.integer.value = level;
489 519
490 if (device->cap._BCM) 520 status = acpi_evaluate_object(device->dev->handle, "_BCM",
491 status = acpi_evaluate_object(device->dev->handle, "_BCM", 521 &args, NULL);
492 &args, NULL); 522 if (ACPI_FAILURE(status)) {
523 ACPI_ERROR((AE_INFO, "Evaluating _BCM failed"));
524 return -EIO;
525 }
526
493 device->brightness->curr = level; 527 device->brightness->curr = level;
494 for (state = 2; state < device->brightness->count; state++) 528 for (state = 2; state < device->brightness->count; state++)
495 if (level == device->brightness->levels[state]) 529 if (level == device->brightness->levels[state]) {
496 device->backlight->props.brightness = state - 2; 530 if (device->backlight)
531 device->backlight->props.brightness = state - 2;
532 return 0;
533 }
497 534
498 return status; 535 ACPI_ERROR((AE_INFO, "Current brightness invalid"));
536 return -EINVAL;
499} 537}
500 538
501static int 539static int
502acpi_video_device_lcd_get_level_current(struct acpi_video_device *device, 540acpi_video_device_lcd_get_level_current(struct acpi_video_device *device,
503 unsigned long long *level) 541 unsigned long long *level)
504{ 542{
505 if (device->cap._BQC) 543 acpi_status status = AE_OK;
506 return acpi_evaluate_integer(device->dev->handle, "_BQC", NULL, 544
507 level); 545 if (device->cap._BQC || device->cap._BCQ) {
546 char *buf = device->cap._BQC ? "_BQC" : "_BCQ";
547
548 status = acpi_evaluate_integer(device->dev->handle, buf,
549 NULL, level);
550 if (ACPI_SUCCESS(status)) {
551 if (device->brightness->flags._BQC_use_index) {
552 if (device->brightness->flags._BCL_reversed)
553 *level = device->brightness->count
554 - 3 - (*level);
555 *level = device->brightness->levels[*level + 2];
556
557 }
558 device->brightness->curr = *level;
559 return 0;
560 } else {
561 /* Fixme:
562 * should we return an error or ignore this failure?
563 * dev->brightness->curr is a cached value which stores
564 * the correct current backlight level in most cases.
565 * ACPI video backlight still works w/ buggy _BQC.
566 * http://bugzilla.kernel.org/show_bug.cgi?id=12233
567 */
568 ACPI_WARNING((AE_INFO, "Evaluating %s failed", buf));
569 device->cap._BQC = device->cap._BCQ = 0;
570 }
571 }
572
508 *level = device->brightness->curr; 573 *level = device->brightness->curr;
509 return AE_OK; 574 return 0;
510} 575}
511 576
512static int 577static int
@@ -655,9 +720,11 @@ static int
655acpi_video_init_brightness(struct acpi_video_device *device) 720acpi_video_init_brightness(struct acpi_video_device *device)
656{ 721{
657 union acpi_object *obj = NULL; 722 union acpi_object *obj = NULL;
658 int i, max_level = 0, count = 0; 723 int i, max_level = 0, count = 0, level_ac_battery = 0;
724 unsigned long long level, level_old;
659 union acpi_object *o; 725 union acpi_object *o;
660 struct acpi_video_device_brightness *br = NULL; 726 struct acpi_video_device_brightness *br = NULL;
727 int result = -EINVAL;
661 728
662 if (!ACPI_SUCCESS(acpi_video_device_lcd_query_levels(device, &obj))) { 729 if (!ACPI_SUCCESS(acpi_video_device_lcd_query_levels(device, &obj))) {
663 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Could not query available " 730 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Could not query available "
@@ -671,13 +738,16 @@ acpi_video_init_brightness(struct acpi_video_device *device)
671 br = kzalloc(sizeof(*br), GFP_KERNEL); 738 br = kzalloc(sizeof(*br), GFP_KERNEL);
672 if (!br) { 739 if (!br) {
673 printk(KERN_ERR "can't allocate memory\n"); 740 printk(KERN_ERR "can't allocate memory\n");
741 result = -ENOMEM;
674 goto out; 742 goto out;
675 } 743 }
676 744
677 br->levels = kmalloc(obj->package.count * sizeof *(br->levels), 745 br->levels = kmalloc((obj->package.count + 2) * sizeof *(br->levels),
678 GFP_KERNEL); 746 GFP_KERNEL);
679 if (!br->levels) 747 if (!br->levels) {
748 result = -ENOMEM;
680 goto out_free; 749 goto out_free;
750 }
681 751
682 for (i = 0; i < obj->package.count; i++) { 752 for (i = 0; i < obj->package.count; i++) {
683 o = (union acpi_object *)&obj->package.elements[i]; 753 o = (union acpi_object *)&obj->package.elements[i];
@@ -692,18 +762,86 @@ acpi_video_init_brightness(struct acpi_video_device *device)
692 count++; 762 count++;
693 } 763 }
694 764
695 /* don't sort the first two brightness levels */ 765 /*
696 sort(&br->levels[2], count - 2, sizeof(br->levels[2]), 766 * some buggy BIOS don't export the levels
697 acpi_video_cmp_level, NULL); 767 * when machine is on AC/Battery in _BCL package.
698 768 * In this case, the first two elements in _BCL packages
699 if (count < 2) 769 * are also supported brightness levels that OS should take care of.
700 goto out_free_levels; 770 */
771 for (i = 2; i < count; i++)
772 if (br->levels[i] == br->levels[0] ||
773 br->levels[i] == br->levels[1])
774 level_ac_battery++;
775
776 if (level_ac_battery < 2) {
777 level_ac_battery = 2 - level_ac_battery;
778 br->flags._BCL_no_ac_battery_levels = 1;
779 for (i = (count - 1 + level_ac_battery); i >= 2; i--)
780 br->levels[i] = br->levels[i - level_ac_battery];
781 count += level_ac_battery;
782 } else if (level_ac_battery > 2)
783 ACPI_ERROR((AE_INFO, "Too many duplicates in _BCL package\n"));
784
785 /* Check if the _BCL package is in a reversed order */
786 if (max_level == br->levels[2]) {
787 br->flags._BCL_reversed = 1;
788 sort(&br->levels[2], count - 2, sizeof(br->levels[2]),
789 acpi_video_cmp_level, NULL);
790 } else if (max_level != br->levels[count - 1])
791 ACPI_ERROR((AE_INFO,
792 "Found unordered _BCL package\n"));
701 793
702 br->count = count; 794 br->count = count;
703 device->brightness = br; 795 device->brightness = br;
704 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "found %d brightness levels\n", count)); 796
797 /* Check the input/output of _BQC/_BCL/_BCM */
798 if ((max_level < 100) && (max_level <= (count - 2)))
799 br->flags._BCL_use_index = 1;
800
801 /*
802 * _BCM is always consistent with _BCL,
803 * at least for all the laptops we have ever seen.
804 */
805 br->flags._BCM_use_index = br->flags._BCL_use_index;
806
807 /* _BQC uses INDEX while _BCL uses VALUE in some laptops */
808 br->curr = max_level;
809 result = acpi_video_device_lcd_get_level_current(device, &level_old);
810 if (result)
811 goto out_free_levels;
812
813 result = acpi_video_device_lcd_set_level(device, br->curr);
814 if (result)
815 goto out_free_levels;
816
817 result = acpi_video_device_lcd_get_level_current(device, &level);
818 if (result)
819 goto out_free_levels;
820
821 if ((level != level_old) && !br->flags._BCM_use_index) {
822 /* Note:
823 * This piece of code does not work correctly if the current
824 * brightness levels is 0.
825 * But I guess boxes that boot with such a dark screen are rare
826 * and no more code is needed to cover this specifial case.
827 */
828
829 if (level_ac_battery != 2) {
830 /*
831 * For now, we don't support the _BCL like this:
832 * 16, 15, 0, 1, 2, 3, ..., 14, 15, 16
833 * because we may mess up the index returned by _BQC.
834 * Plus: we have not got a box like this.
835 */
836 ACPI_ERROR((AE_INFO, "_BCL not supported\n"));
837 }
838 br->flags._BQC_use_index = 1;
839 }
840
841 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
842 "found %d brightness levels\n", count - 2));
705 kfree(obj); 843 kfree(obj);
706 return max_level; 844 return result;
707 845
708out_free_levels: 846out_free_levels:
709 kfree(br->levels); 847 kfree(br->levels);
@@ -712,7 +850,7 @@ out_free:
712out: 850out:
713 device->brightness = NULL; 851 device->brightness = NULL;
714 kfree(obj); 852 kfree(obj);
715 return 0; 853 return result;
716} 854}
717 855
718/* 856/*
@@ -729,7 +867,6 @@ out:
729static void acpi_video_device_find_cap(struct acpi_video_device *device) 867static void acpi_video_device_find_cap(struct acpi_video_device *device)
730{ 868{
731 acpi_handle h_dummy1; 869 acpi_handle h_dummy1;
732 u32 max_level = 0;
733 870
734 871
735 memset(&device->cap, 0, sizeof(device->cap)); 872 memset(&device->cap, 0, sizeof(device->cap));
@@ -745,6 +882,12 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
745 } 882 }
746 if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle,"_BQC",&h_dummy1))) 883 if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle,"_BQC",&h_dummy1)))
747 device->cap._BQC = 1; 884 device->cap._BQC = 1;
885 else if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_BCQ",
886 &h_dummy1))) {
887 printk(KERN_WARNING FW_BUG "_BCQ is used instead of _BQC\n");
888 device->cap._BCQ = 1;
889 }
890
748 if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DDC", &h_dummy1))) { 891 if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DDC", &h_dummy1))) {
749 device->cap._DDC = 1; 892 device->cap._DDC = 1;
750 } 893 }
@@ -758,13 +901,14 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
758 device->cap._DSS = 1; 901 device->cap._DSS = 1;
759 } 902 }
760 903
761 if (acpi_video_backlight_support()) 904 if (acpi_video_backlight_support()) {
762 max_level = acpi_video_init_brightness(device);
763
764 if (device->cap._BCL && device->cap._BCM && max_level > 0) {
765 int result; 905 int result;
766 static int count = 0; 906 static int count = 0;
767 char *name; 907 char *name;
908
909 result = acpi_video_init_brightness(device);
910 if (result)
911 return;
768 name = kzalloc(MAX_NAME_LEN, GFP_KERNEL); 912 name = kzalloc(MAX_NAME_LEN, GFP_KERNEL);
769 if (!name) 913 if (!name)
770 return; 914 return;
@@ -773,18 +917,6 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
773 device->backlight = backlight_device_register(name, 917 device->backlight = backlight_device_register(name,
774 NULL, device, &acpi_backlight_ops); 918 NULL, device, &acpi_backlight_ops);
775 device->backlight->props.max_brightness = device->brightness->count-3; 919 device->backlight->props.max_brightness = device->brightness->count-3;
776 /*
777 * If there exists the _BQC object, the _BQC object will be
778 * called to get the current backlight brightness. Otherwise
779 * the brightness will be set to the maximum.
780 */
781 if (device->cap._BQC)
782 device->backlight->props.brightness =
783 acpi_video_get_brightness(device->backlight);
784 else
785 device->backlight->props.brightness =
786 device->backlight->props.max_brightness;
787 backlight_update_status(device->backlight);
788 kfree(name); 920 kfree(name);
789 921
790 device->cdev = thermal_cooling_device_register("LCD", 922 device->cdev = thermal_cooling_device_register("LCD",
@@ -1061,13 +1193,12 @@ acpi_video_device_write_brightness(struct file *file,
1061 /* validate through the list of available levels */ 1193 /* validate through the list of available levels */
1062 for (i = 2; i < dev->brightness->count; i++) 1194 for (i = 2; i < dev->brightness->count; i++)
1063 if (level == dev->brightness->levels[i]) { 1195 if (level == dev->brightness->levels[i]) {
1064 if (ACPI_SUCCESS 1196 if (!acpi_video_device_lcd_set_level(dev, level))
1065 (acpi_video_device_lcd_set_level(dev, level))) 1197 return count;
1066 dev->brightness->curr = level;
1067 break; 1198 break;
1068 } 1199 }
1069 1200
1070 return count; 1201 return -EINVAL;
1071} 1202}
1072 1203
1073static int acpi_video_device_EDID_seq_show(struct seq_file *seq, void *offset) 1204static int acpi_video_device_EDID_seq_show(struct seq_file *seq, void *offset)
@@ -1132,7 +1263,6 @@ static int acpi_video_device_add_fs(struct acpi_device *device)
1132 goto err_remove_dir; 1263 goto err_remove_dir;
1133 1264
1134 /* 'state' [R/W] */ 1265 /* 'state' [R/W] */
1135 acpi_video_device_state_fops.write = acpi_video_device_write_state;
1136 entry = proc_create_data("state", S_IFREG | S_IRUGO | S_IWUSR, 1266 entry = proc_create_data("state", S_IFREG | S_IRUGO | S_IWUSR,
1137 device_dir, 1267 device_dir,
1138 &acpi_video_device_state_fops, 1268 &acpi_video_device_state_fops,
@@ -1141,8 +1271,6 @@ static int acpi_video_device_add_fs(struct acpi_device *device)
1141 goto err_remove_info; 1271 goto err_remove_info;
1142 1272
1143 /* 'brightness' [R/W] */ 1273 /* 'brightness' [R/W] */
1144 acpi_video_device_brightness_fops.write =
1145 acpi_video_device_write_brightness;
1146 entry = proc_create_data("brightness", S_IFREG | S_IRUGO | S_IWUSR, 1274 entry = proc_create_data("brightness", S_IFREG | S_IRUGO | S_IWUSR,
1147 device_dir, 1275 device_dir,
1148 &acpi_video_device_brightness_fops, 1276 &acpi_video_device_brightness_fops,
@@ -1423,7 +1551,6 @@ static int acpi_video_bus_add_fs(struct acpi_device *device)
1423 goto err_remove_rom; 1551 goto err_remove_rom;
1424 1552
1425 /* 'POST' [R/W] */ 1553 /* 'POST' [R/W] */
1426 acpi_video_bus_POST_fops.write = acpi_video_bus_write_POST;
1427 entry = proc_create_data("POST", S_IFREG | S_IRUGO | S_IWUSR, 1554 entry = proc_create_data("POST", S_IFREG | S_IRUGO | S_IWUSR,
1428 device_dir, 1555 device_dir,
1429 &acpi_video_bus_POST_fops, 1556 &acpi_video_bus_POST_fops,
@@ -1432,7 +1559,6 @@ static int acpi_video_bus_add_fs(struct acpi_device *device)
1432 goto err_remove_post_info; 1559 goto err_remove_post_info;
1433 1560
1434 /* 'DOS' [R/W] */ 1561 /* 'DOS' [R/W] */
1435 acpi_video_bus_DOS_fops.write = acpi_video_bus_write_DOS;
1436 entry = proc_create_data("DOS", S_IFREG | S_IRUGO | S_IWUSR, 1562 entry = proc_create_data("DOS", S_IFREG | S_IRUGO | S_IWUSR,
1437 device_dir, 1563 device_dir,
1438 &acpi_video_bus_DOS_fops, 1564 &acpi_video_bus_DOS_fops,
@@ -1745,15 +1871,29 @@ acpi_video_get_next_level(struct acpi_video_device *device,
1745 } 1871 }
1746} 1872}
1747 1873
1748static void 1874static int
1749acpi_video_switch_brightness(struct acpi_video_device *device, int event) 1875acpi_video_switch_brightness(struct acpi_video_device *device, int event)
1750{ 1876{
1751 unsigned long long level_current, level_next; 1877 unsigned long long level_current, level_next;
1878 int result = -EINVAL;
1879
1752 if (!device->brightness) 1880 if (!device->brightness)
1753 return; 1881 goto out;
1754 acpi_video_device_lcd_get_level_current(device, &level_current); 1882
1883 result = acpi_video_device_lcd_get_level_current(device,
1884 &level_current);
1885 if (result)
1886 goto out;
1887
1755 level_next = acpi_video_get_next_level(device, level_current, event); 1888 level_next = acpi_video_get_next_level(device, level_current, event);
1756 acpi_video_device_lcd_set_level(device, level_next); 1889
1890 result = acpi_video_device_lcd_set_level(device, level_next);
1891
1892out:
1893 if (result)
1894 printk(KERN_ERR PREFIX "Failed to switch the brightness\n");
1895
1896 return result;
1757} 1897}
1758 1898
1759static int 1899static int
@@ -2120,7 +2260,27 @@ static int acpi_video_bus_remove(struct acpi_device *device, int type)
2120 return 0; 2260 return 0;
2121} 2261}
2122 2262
2123static int __init acpi_video_init(void) 2263static int __init intel_opregion_present(void)
2264{
2265#if defined(CONFIG_DRM_I915) || defined(CONFIG_DRM_I915_MODULE)
2266 struct pci_dev *dev = NULL;
2267 u32 address;
2268
2269 for_each_pci_dev(dev) {
2270 if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
2271 continue;
2272 if (dev->vendor != PCI_VENDOR_ID_INTEL)
2273 continue;
2274 pci_read_config_dword(dev, 0xfc, &address);
2275 if (!address)
2276 continue;
2277 return 1;
2278 }
2279#endif
2280 return 0;
2281}
2282
2283int acpi_video_register(void)
2124{ 2284{
2125 int result = 0; 2285 int result = 0;
2126 2286
@@ -2136,6 +2296,22 @@ static int __init acpi_video_init(void)
2136 2296
2137 return 0; 2297 return 0;
2138} 2298}
2299EXPORT_SYMBOL(acpi_video_register);
2300
2301/*
2302 * This is kind of nasty. Hardware using Intel chipsets may require
2303 * the video opregion code to be run first in order to initialise
2304 * state before any ACPI video calls are made. To handle this we defer
2305 * registration of the video class until the opregion code has run.
2306 */
2307
2308static int __init acpi_video_init(void)
2309{
2310 if (intel_opregion_present())
2311 return 0;
2312
2313 return acpi_video_register();
2314}
2139 2315
2140static void __exit acpi_video_exit(void) 2316static void __exit acpi_video_exit(void)
2141{ 2317{