Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.28-rc5 2130 lines 54 kB view raw
1/* 2 * video.c - ACPI Video Driver ($Revision:$) 3 * 4 * Copyright (C) 2004 Luming Yu <luming.yu@intel.com> 5 * Copyright (C) 2004 Bruno Ducrot <ducrot@poupinou.org> 6 * Copyright (C) 2006 Thomas Tuttle <linux-kernel@ttuttle.net> 7 * 8 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2 of the License, or (at 13 * your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, but 16 * WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License along 21 * with this program; if not, write to the Free Software Foundation, Inc., 22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 23 * 24 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 25 */ 26 27#include <linux/kernel.h> 28#include <linux/module.h> 29#include <linux/init.h> 30#include <linux/types.h> 31#include <linux/list.h> 32#include <linux/mutex.h> 33#include <linux/proc_fs.h> 34#include <linux/seq_file.h> 35#include <linux/input.h> 36#include <linux/backlight.h> 37#include <linux/thermal.h> 38#include <linux/video_output.h> 39#include <asm/uaccess.h> 40 41#include <acpi/acpi_bus.h> 42#include <acpi/acpi_drivers.h> 43 44#define ACPI_VIDEO_CLASS "video" 45#define ACPI_VIDEO_BUS_NAME "Video Bus" 46#define ACPI_VIDEO_DEVICE_NAME "Video Device" 47#define ACPI_VIDEO_NOTIFY_SWITCH 0x80 48#define ACPI_VIDEO_NOTIFY_PROBE 0x81 49#define ACPI_VIDEO_NOTIFY_CYCLE 0x82 50#define ACPI_VIDEO_NOTIFY_NEXT_OUTPUT 0x83 51#define ACPI_VIDEO_NOTIFY_PREV_OUTPUT 0x84 52 53#define ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS 0x85 54#define ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS 0x86 55#define ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS 0x87 56#define ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS 0x88 57#define ACPI_VIDEO_NOTIFY_DISPLAY_OFF 0x89 58 59#define MAX_NAME_LEN 20 60 61#define ACPI_VIDEO_DISPLAY_CRT 1 62#define ACPI_VIDEO_DISPLAY_TV 2 63#define ACPI_VIDEO_DISPLAY_DVI 3 64#define ACPI_VIDEO_DISPLAY_LCD 4 65 66#define _COMPONENT ACPI_VIDEO_COMPONENT 67ACPI_MODULE_NAME("video"); 68 69MODULE_AUTHOR("Bruno Ducrot"); 70MODULE_DESCRIPTION("ACPI Video Driver"); 71MODULE_LICENSE("GPL"); 72 73static int brightness_switch_enabled = 1; 74module_param(brightness_switch_enabled, bool, 0644); 75 76static int acpi_video_bus_add(struct acpi_device *device); 77static int acpi_video_bus_remove(struct acpi_device *device, int type); 78static int acpi_video_resume(struct acpi_device *device); 79 80static const struct acpi_device_id video_device_ids[] = { 81 {ACPI_VIDEO_HID, 0}, 82 {"", 0}, 83}; 84MODULE_DEVICE_TABLE(acpi, video_device_ids); 85 86static struct acpi_driver acpi_video_bus = { 87 .name = "video", 88 .class = ACPI_VIDEO_CLASS, 89 .ids = video_device_ids, 90 .ops = { 91 .add = acpi_video_bus_add, 92 .remove = acpi_video_bus_remove, 93 .resume = acpi_video_resume, 94 }, 95}; 96 97struct acpi_video_bus_flags { 98 u8 multihead:1; /* can switch video heads */ 99 u8 rom:1; /* can retrieve a video rom */ 100 u8 post:1; /* can configure the head to */ 101 u8 reserved:5; 102}; 103 104struct acpi_video_bus_cap { 105 u8 _DOS:1; /*Enable/Disable output switching */ 106 u8 _DOD:1; /*Enumerate all devices attached to display adapter */ 107 u8 _ROM:1; /*Get ROM Data */ 108 u8 _GPD:1; /*Get POST Device */ 109 u8 _SPD:1; /*Set POST Device */ 110 u8 _VPO:1; /*Video POST Options */ 111 u8 reserved:2; 112}; 113 114struct acpi_video_device_attrib { 115 u32 display_index:4; /* A zero-based instance of the Display */ 116 u32 display_port_attachment:4; /*This field differentiates the display type */ 117 u32 display_type:4; /*Describe the specific type in use */ 118 u32 vendor_specific:4; /*Chipset Vendor Specific */ 119 u32 bios_can_detect:1; /*BIOS can detect the device */ 120 u32 depend_on_vga:1; /*Non-VGA output device whose power is related to 121 the VGA device. */ 122 u32 pipe_id:3; /*For VGA multiple-head devices. */ 123 u32 reserved:10; /*Must be 0 */ 124 u32 device_id_scheme:1; /*Device ID Scheme */ 125}; 126 127struct acpi_video_enumerated_device { 128 union { 129 u32 int_val; 130 struct acpi_video_device_attrib attrib; 131 } value; 132 struct acpi_video_device *bind_info; 133}; 134 135struct acpi_video_bus { 136 struct acpi_device *device; 137 u8 dos_setting; 138 struct acpi_video_enumerated_device *attached_array; 139 u8 attached_count; 140 struct acpi_video_bus_cap cap; 141 struct acpi_video_bus_flags flags; 142 struct list_head video_device_list; 143 struct mutex device_list_lock; /* protects video_device_list */ 144 struct proc_dir_entry *dir; 145 struct input_dev *input; 146 char phys[32]; /* for input device */ 147}; 148 149struct acpi_video_device_flags { 150 u8 crt:1; 151 u8 lcd:1; 152 u8 tvout:1; 153 u8 dvi:1; 154 u8 bios:1; 155 u8 unknown:1; 156 u8 reserved:2; 157}; 158 159struct acpi_video_device_cap { 160 u8 _ADR:1; /*Return the unique ID */ 161 u8 _BCL:1; /*Query list of brightness control levels supported */ 162 u8 _BCM:1; /*Set the brightness level */ 163 u8 _BQC:1; /* Get current brightness level */ 164 u8 _DDC:1; /*Return the EDID for this device */ 165 u8 _DCS:1; /*Return status of output device */ 166 u8 _DGS:1; /*Query graphics state */ 167 u8 _DSS:1; /*Device state set */ 168}; 169 170struct acpi_video_device_brightness { 171 int curr; 172 int count; 173 int *levels; 174}; 175 176struct acpi_video_device { 177 unsigned long device_id; 178 struct acpi_video_device_flags flags; 179 struct acpi_video_device_cap cap; 180 struct list_head entry; 181 struct acpi_video_bus *video; 182 struct acpi_device *dev; 183 struct acpi_video_device_brightness *brightness; 184 struct backlight_device *backlight; 185 struct thermal_cooling_device *cdev; 186 struct output_device *output_dev; 187}; 188 189/* bus */ 190static int acpi_video_bus_info_open_fs(struct inode *inode, struct file *file); 191static struct file_operations acpi_video_bus_info_fops = { 192 .owner = THIS_MODULE, 193 .open = acpi_video_bus_info_open_fs, 194 .read = seq_read, 195 .llseek = seq_lseek, 196 .release = single_release, 197}; 198 199static int acpi_video_bus_ROM_open_fs(struct inode *inode, struct file *file); 200static struct file_operations acpi_video_bus_ROM_fops = { 201 .owner = THIS_MODULE, 202 .open = acpi_video_bus_ROM_open_fs, 203 .read = seq_read, 204 .llseek = seq_lseek, 205 .release = single_release, 206}; 207 208static int acpi_video_bus_POST_info_open_fs(struct inode *inode, 209 struct file *file); 210static struct file_operations acpi_video_bus_POST_info_fops = { 211 .owner = THIS_MODULE, 212 .open = acpi_video_bus_POST_info_open_fs, 213 .read = seq_read, 214 .llseek = seq_lseek, 215 .release = single_release, 216}; 217 218static int acpi_video_bus_POST_open_fs(struct inode *inode, struct file *file); 219static struct file_operations acpi_video_bus_POST_fops = { 220 .owner = THIS_MODULE, 221 .open = acpi_video_bus_POST_open_fs, 222 .read = seq_read, 223 .llseek = seq_lseek, 224 .release = single_release, 225}; 226 227static int acpi_video_bus_DOS_open_fs(struct inode *inode, struct file *file); 228static struct file_operations acpi_video_bus_DOS_fops = { 229 .owner = THIS_MODULE, 230 .open = acpi_video_bus_DOS_open_fs, 231 .read = seq_read, 232 .llseek = seq_lseek, 233 .release = single_release, 234}; 235 236/* device */ 237static int acpi_video_device_info_open_fs(struct inode *inode, 238 struct file *file); 239static struct file_operations acpi_video_device_info_fops = { 240 .owner = THIS_MODULE, 241 .open = acpi_video_device_info_open_fs, 242 .read = seq_read, 243 .llseek = seq_lseek, 244 .release = single_release, 245}; 246 247static int acpi_video_device_state_open_fs(struct inode *inode, 248 struct file *file); 249static struct file_operations acpi_video_device_state_fops = { 250 .owner = THIS_MODULE, 251 .open = acpi_video_device_state_open_fs, 252 .read = seq_read, 253 .llseek = seq_lseek, 254 .release = single_release, 255}; 256 257static int acpi_video_device_brightness_open_fs(struct inode *inode, 258 struct file *file); 259static struct file_operations acpi_video_device_brightness_fops = { 260 .owner = THIS_MODULE, 261 .open = acpi_video_device_brightness_open_fs, 262 .read = seq_read, 263 .llseek = seq_lseek, 264 .release = single_release, 265}; 266 267static int acpi_video_device_EDID_open_fs(struct inode *inode, 268 struct file *file); 269static struct file_operations acpi_video_device_EDID_fops = { 270 .owner = THIS_MODULE, 271 .open = acpi_video_device_EDID_open_fs, 272 .read = seq_read, 273 .llseek = seq_lseek, 274 .release = single_release, 275}; 276 277static char device_decode[][30] = { 278 "motherboard VGA device", 279 "PCI VGA device", 280 "AGP VGA device", 281 "UNKNOWN", 282}; 283 284static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data); 285static void acpi_video_device_rebind(struct acpi_video_bus *video); 286static void acpi_video_device_bind(struct acpi_video_bus *video, 287 struct acpi_video_device *device); 288static int acpi_video_device_enumerate(struct acpi_video_bus *video); 289static int acpi_video_device_lcd_set_level(struct acpi_video_device *device, 290 int level); 291static int acpi_video_device_lcd_get_level_current( 292 struct acpi_video_device *device, 293 unsigned long long *level); 294static int acpi_video_get_next_level(struct acpi_video_device *device, 295 u32 level_current, u32 event); 296static void acpi_video_switch_brightness(struct acpi_video_device *device, 297 int event); 298static int acpi_video_device_get_state(struct acpi_video_device *device, 299 unsigned long long *state); 300static int acpi_video_output_get(struct output_device *od); 301static int acpi_video_device_set_state(struct acpi_video_device *device, int state); 302 303/*backlight device sysfs support*/ 304static int acpi_video_get_brightness(struct backlight_device *bd) 305{ 306 unsigned long long cur_level; 307 int i; 308 struct acpi_video_device *vd = 309 (struct acpi_video_device *)bl_get_data(bd); 310 acpi_video_device_lcd_get_level_current(vd, &cur_level); 311 for (i = 2; i < vd->brightness->count; i++) { 312 if (vd->brightness->levels[i] == cur_level) 313 /* The first two entries are special - see page 575 314 of the ACPI spec 3.0 */ 315 return i-2; 316 } 317 return 0; 318} 319 320static int acpi_video_set_brightness(struct backlight_device *bd) 321{ 322 int request_level = bd->props.brightness+2; 323 struct acpi_video_device *vd = 324 (struct acpi_video_device *)bl_get_data(bd); 325 acpi_video_device_lcd_set_level(vd, 326 vd->brightness->levels[request_level]); 327 return 0; 328} 329 330static struct backlight_ops acpi_backlight_ops = { 331 .get_brightness = acpi_video_get_brightness, 332 .update_status = acpi_video_set_brightness, 333}; 334 335/*video output device sysfs support*/ 336static int acpi_video_output_get(struct output_device *od) 337{ 338 unsigned long long state; 339 struct acpi_video_device *vd = 340 (struct acpi_video_device *)dev_get_drvdata(&od->dev); 341 acpi_video_device_get_state(vd, &state); 342 return (int)state; 343} 344 345static int acpi_video_output_set(struct output_device *od) 346{ 347 unsigned long state = od->request_state; 348 struct acpi_video_device *vd= 349 (struct acpi_video_device *)dev_get_drvdata(&od->dev); 350 return acpi_video_device_set_state(vd, state); 351} 352 353static struct output_properties acpi_output_properties = { 354 .set_state = acpi_video_output_set, 355 .get_status = acpi_video_output_get, 356}; 357 358 359/* thermal cooling device callbacks */ 360static int video_get_max_state(struct thermal_cooling_device *cdev, char *buf) 361{ 362 struct acpi_device *device = cdev->devdata; 363 struct acpi_video_device *video = acpi_driver_data(device); 364 365 return sprintf(buf, "%d\n", video->brightness->count - 3); 366} 367 368static int video_get_cur_state(struct thermal_cooling_device *cdev, char *buf) 369{ 370 struct acpi_device *device = cdev->devdata; 371 struct acpi_video_device *video = acpi_driver_data(device); 372 unsigned long long level; 373 int state; 374 375 acpi_video_device_lcd_get_level_current(video, &level); 376 for (state = 2; state < video->brightness->count; state++) 377 if (level == video->brightness->levels[state]) 378 return sprintf(buf, "%d\n", 379 video->brightness->count - state - 1); 380 381 return -EINVAL; 382} 383 384static int 385video_set_cur_state(struct thermal_cooling_device *cdev, unsigned int state) 386{ 387 struct acpi_device *device = cdev->devdata; 388 struct acpi_video_device *video = acpi_driver_data(device); 389 int level; 390 391 if ( state >= video->brightness->count - 2) 392 return -EINVAL; 393 394 state = video->brightness->count - state; 395 level = video->brightness->levels[state -1]; 396 return acpi_video_device_lcd_set_level(video, level); 397} 398 399static struct thermal_cooling_device_ops video_cooling_ops = { 400 .get_max_state = video_get_max_state, 401 .get_cur_state = video_get_cur_state, 402 .set_cur_state = video_set_cur_state, 403}; 404 405/* -------------------------------------------------------------------------- 406 Video Management 407 -------------------------------------------------------------------------- */ 408 409/* device */ 410 411static int 412acpi_video_device_query(struct acpi_video_device *device, unsigned long long *state) 413{ 414 int status; 415 416 status = acpi_evaluate_integer(device->dev->handle, "_DGS", NULL, state); 417 418 return status; 419} 420 421static int 422acpi_video_device_get_state(struct acpi_video_device *device, 423 unsigned long long *state) 424{ 425 int status; 426 427 status = acpi_evaluate_integer(device->dev->handle, "_DCS", NULL, state); 428 429 return status; 430} 431 432static int 433acpi_video_device_set_state(struct acpi_video_device *device, int state) 434{ 435 int status; 436 union acpi_object arg0 = { ACPI_TYPE_INTEGER }; 437 struct acpi_object_list args = { 1, &arg0 }; 438 unsigned long long ret; 439 440 441 arg0.integer.value = state; 442 status = acpi_evaluate_integer(device->dev->handle, "_DSS", &args, &ret); 443 444 return status; 445} 446 447static int 448acpi_video_device_lcd_query_levels(struct acpi_video_device *device, 449 union acpi_object **levels) 450{ 451 int status; 452 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 453 union acpi_object *obj; 454 455 456 *levels = NULL; 457 458 status = acpi_evaluate_object(device->dev->handle, "_BCL", NULL, &buffer); 459 if (!ACPI_SUCCESS(status)) 460 return status; 461 obj = (union acpi_object *)buffer.pointer; 462 if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) { 463 printk(KERN_ERR PREFIX "Invalid _BCL data\n"); 464 status = -EFAULT; 465 goto err; 466 } 467 468 *levels = obj; 469 470 return 0; 471 472 err: 473 kfree(buffer.pointer); 474 475 return status; 476} 477 478static int 479acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level) 480{ 481 int status = AE_OK; 482 union acpi_object arg0 = { ACPI_TYPE_INTEGER }; 483 struct acpi_object_list args = { 1, &arg0 }; 484 485 486 arg0.integer.value = level; 487 488 if (device->cap._BCM) 489 status = acpi_evaluate_object(device->dev->handle, "_BCM", 490 &args, NULL); 491 device->brightness->curr = level; 492 return status; 493} 494 495static int 496acpi_video_device_lcd_get_level_current(struct acpi_video_device *device, 497 unsigned long long *level) 498{ 499 if (device->cap._BQC) 500 return acpi_evaluate_integer(device->dev->handle, "_BQC", NULL, 501 level); 502 *level = device->brightness->curr; 503 return AE_OK; 504} 505 506static int 507acpi_video_device_EDID(struct acpi_video_device *device, 508 union acpi_object **edid, ssize_t length) 509{ 510 int status; 511 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 512 union acpi_object *obj; 513 union acpi_object arg0 = { ACPI_TYPE_INTEGER }; 514 struct acpi_object_list args = { 1, &arg0 }; 515 516 517 *edid = NULL; 518 519 if (!device) 520 return -ENODEV; 521 if (length == 128) 522 arg0.integer.value = 1; 523 else if (length == 256) 524 arg0.integer.value = 2; 525 else 526 return -EINVAL; 527 528 status = acpi_evaluate_object(device->dev->handle, "_DDC", &args, &buffer); 529 if (ACPI_FAILURE(status)) 530 return -ENODEV; 531 532 obj = buffer.pointer; 533 534 if (obj && obj->type == ACPI_TYPE_BUFFER) 535 *edid = obj; 536 else { 537 printk(KERN_ERR PREFIX "Invalid _DDC data\n"); 538 status = -EFAULT; 539 kfree(obj); 540 } 541 542 return status; 543} 544 545/* bus */ 546 547static int 548acpi_video_bus_set_POST(struct acpi_video_bus *video, unsigned long option) 549{ 550 int status; 551 unsigned long long tmp; 552 union acpi_object arg0 = { ACPI_TYPE_INTEGER }; 553 struct acpi_object_list args = { 1, &arg0 }; 554 555 556 arg0.integer.value = option; 557 558 status = acpi_evaluate_integer(video->device->handle, "_SPD", &args, &tmp); 559 if (ACPI_SUCCESS(status)) 560 status = tmp ? (-EINVAL) : (AE_OK); 561 562 return status; 563} 564 565static int 566acpi_video_bus_get_POST(struct acpi_video_bus *video, unsigned long long *id) 567{ 568 int status; 569 570 status = acpi_evaluate_integer(video->device->handle, "_GPD", NULL, id); 571 572 return status; 573} 574 575static int 576acpi_video_bus_POST_options(struct acpi_video_bus *video, 577 unsigned long long *options) 578{ 579 int status; 580 581 status = acpi_evaluate_integer(video->device->handle, "_VPO", NULL, options); 582 *options &= 3; 583 584 return status; 585} 586 587/* 588 * Arg: 589 * video : video bus device pointer 590 * bios_flag : 591 * 0. The system BIOS should NOT automatically switch(toggle) 592 * the active display output. 593 * 1. The system BIOS should automatically switch (toggle) the 594 * active display output. No switch event. 595 * 2. The _DGS value should be locked. 596 * 3. The system BIOS should not automatically switch (toggle) the 597 * active display output, but instead generate the display switch 598 * event notify code. 599 * lcd_flag : 600 * 0. The system BIOS should automatically control the brightness level 601 * of the LCD when the power changes from AC to DC 602 * 1. The system BIOS should NOT automatically control the brightness 603 * level of the LCD when the power changes from AC to DC. 604 * Return Value: 605 * -1 wrong arg. 606 */ 607 608static int 609acpi_video_bus_DOS(struct acpi_video_bus *video, int bios_flag, int lcd_flag) 610{ 611 acpi_integer status = 0; 612 union acpi_object arg0 = { ACPI_TYPE_INTEGER }; 613 struct acpi_object_list args = { 1, &arg0 }; 614 615 616 if (bios_flag < 0 || bios_flag > 3 || lcd_flag < 0 || lcd_flag > 1) { 617 status = -1; 618 goto Failed; 619 } 620 arg0.integer.value = (lcd_flag << 2) | bios_flag; 621 video->dos_setting = arg0.integer.value; 622 acpi_evaluate_object(video->device->handle, "_DOS", &args, NULL); 623 624 Failed: 625 return status; 626} 627 628/* 629 * Arg: 630 * device : video output device (LCD, CRT, ..) 631 * 632 * Return Value: 633 * Maximum brightness level 634 * 635 * Allocate and initialize device->brightness. 636 */ 637 638static int 639acpi_video_init_brightness(struct acpi_video_device *device) 640{ 641 union acpi_object *obj = NULL; 642 int i, max_level = 0, count = 0; 643 union acpi_object *o; 644 struct acpi_video_device_brightness *br = NULL; 645 646 if (!ACPI_SUCCESS(acpi_video_device_lcd_query_levels(device, &obj))) { 647 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Could not query available " 648 "LCD brightness level\n")); 649 goto out; 650 } 651 652 if (obj->package.count < 2) 653 goto out; 654 655 br = kzalloc(sizeof(*br), GFP_KERNEL); 656 if (!br) { 657 printk(KERN_ERR "can't allocate memory\n"); 658 goto out; 659 } 660 661 br->levels = kmalloc(obj->package.count * sizeof *(br->levels), 662 GFP_KERNEL); 663 if (!br->levels) 664 goto out_free; 665 666 for (i = 0; i < obj->package.count; i++) { 667 o = (union acpi_object *)&obj->package.elements[i]; 668 if (o->type != ACPI_TYPE_INTEGER) { 669 printk(KERN_ERR PREFIX "Invalid data\n"); 670 continue; 671 } 672 br->levels[count] = (u32) o->integer.value; 673 674 if (br->levels[count] > max_level) 675 max_level = br->levels[count]; 676 count++; 677 } 678 679 if (count < 2) 680 goto out_free_levels; 681 682 br->count = count; 683 device->brightness = br; 684 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "found %d brightness levels\n", count)); 685 kfree(obj); 686 return max_level; 687 688out_free_levels: 689 kfree(br->levels); 690out_free: 691 kfree(br); 692out: 693 device->brightness = NULL; 694 kfree(obj); 695 return 0; 696} 697 698/* 699 * Arg: 700 * device : video output device (LCD, CRT, ..) 701 * 702 * Return Value: 703 * None 704 * 705 * Find out all required AML methods defined under the output 706 * device. 707 */ 708 709static void acpi_video_device_find_cap(struct acpi_video_device *device) 710{ 711 acpi_handle h_dummy1; 712 u32 max_level = 0; 713 714 715 memset(&device->cap, 0, sizeof(device->cap)); 716 717 if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_ADR", &h_dummy1))) { 718 device->cap._ADR = 1; 719 } 720 if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_BCL", &h_dummy1))) { 721 device->cap._BCL = 1; 722 } 723 if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_BCM", &h_dummy1))) { 724 device->cap._BCM = 1; 725 } 726 if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle,"_BQC",&h_dummy1))) 727 device->cap._BQC = 1; 728 if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DDC", &h_dummy1))) { 729 device->cap._DDC = 1; 730 } 731 if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DCS", &h_dummy1))) { 732 device->cap._DCS = 1; 733 } 734 if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DGS", &h_dummy1))) { 735 device->cap._DGS = 1; 736 } 737 if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DSS", &h_dummy1))) { 738 device->cap._DSS = 1; 739 } 740 741 if (acpi_video_backlight_support()) 742 max_level = acpi_video_init_brightness(device); 743 744 if (device->cap._BCL && device->cap._BCM && max_level > 0) { 745 int result; 746 static int count = 0; 747 char *name; 748 name = kzalloc(MAX_NAME_LEN, GFP_KERNEL); 749 if (!name) 750 return; 751 752 sprintf(name, "acpi_video%d", count++); 753 device->backlight = backlight_device_register(name, 754 NULL, device, &acpi_backlight_ops); 755 device->backlight->props.max_brightness = device->brightness->count-3; 756 /* 757 * If there exists the _BQC object, the _BQC object will be 758 * called to get the current backlight brightness. Otherwise 759 * the brightness will be set to the maximum. 760 */ 761 if (device->cap._BQC) 762 device->backlight->props.brightness = 763 acpi_video_get_brightness(device->backlight); 764 else 765 device->backlight->props.brightness = 766 device->backlight->props.max_brightness; 767 backlight_update_status(device->backlight); 768 kfree(name); 769 770 device->cdev = thermal_cooling_device_register("LCD", 771 device->dev, &video_cooling_ops); 772 if (IS_ERR(device->cdev)) 773 return; 774 775 dev_info(&device->dev->dev, "registered as cooling_device%d\n", 776 device->cdev->id); 777 result = sysfs_create_link(&device->dev->dev.kobj, 778 &device->cdev->device.kobj, 779 "thermal_cooling"); 780 if (result) 781 printk(KERN_ERR PREFIX "Create sysfs link\n"); 782 result = sysfs_create_link(&device->cdev->device.kobj, 783 &device->dev->dev.kobj, "device"); 784 if (result) 785 printk(KERN_ERR PREFIX "Create sysfs link\n"); 786 787 } 788 789 if (acpi_video_display_switch_support()) { 790 791 if (device->cap._DCS && device->cap._DSS) { 792 static int count; 793 char *name; 794 name = kzalloc(MAX_NAME_LEN, GFP_KERNEL); 795 if (!name) 796 return; 797 sprintf(name, "acpi_video%d", count++); 798 device->output_dev = video_output_register(name, 799 NULL, device, &acpi_output_properties); 800 kfree(name); 801 } 802 } 803} 804 805/* 806 * Arg: 807 * device : video output device (VGA) 808 * 809 * Return Value: 810 * None 811 * 812 * Find out all required AML methods defined under the video bus device. 813 */ 814 815static void acpi_video_bus_find_cap(struct acpi_video_bus *video) 816{ 817 acpi_handle h_dummy1; 818 819 memset(&video->cap, 0, sizeof(video->cap)); 820 if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_DOS", &h_dummy1))) { 821 video->cap._DOS = 1; 822 } 823 if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_DOD", &h_dummy1))) { 824 video->cap._DOD = 1; 825 } 826 if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_ROM", &h_dummy1))) { 827 video->cap._ROM = 1; 828 } 829 if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_GPD", &h_dummy1))) { 830 video->cap._GPD = 1; 831 } 832 if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_SPD", &h_dummy1))) { 833 video->cap._SPD = 1; 834 } 835 if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_VPO", &h_dummy1))) { 836 video->cap._VPO = 1; 837 } 838} 839 840/* 841 * Check whether the video bus device has required AML method to 842 * support the desired features 843 */ 844 845static int acpi_video_bus_check(struct acpi_video_bus *video) 846{ 847 acpi_status status = -ENOENT; 848 struct device *dev; 849 850 if (!video) 851 return -EINVAL; 852 853 dev = acpi_get_physical_pci_device(video->device->handle); 854 if (!dev) 855 return -ENODEV; 856 put_device(dev); 857 858 /* Since there is no HID, CID and so on for VGA driver, we have 859 * to check well known required nodes. 860 */ 861 862 /* Does this device support video switching? */ 863 if (video->cap._DOS) { 864 video->flags.multihead = 1; 865 status = 0; 866 } 867 868 /* Does this device support retrieving a video ROM? */ 869 if (video->cap._ROM) { 870 video->flags.rom = 1; 871 status = 0; 872 } 873 874 /* Does this device support configuring which video device to POST? */ 875 if (video->cap._GPD && video->cap._SPD && video->cap._VPO) { 876 video->flags.post = 1; 877 status = 0; 878 } 879 880 return status; 881} 882 883/* -------------------------------------------------------------------------- 884 FS Interface (/proc) 885 -------------------------------------------------------------------------- */ 886 887static struct proc_dir_entry *acpi_video_dir; 888 889/* video devices */ 890 891static int acpi_video_device_info_seq_show(struct seq_file *seq, void *offset) 892{ 893 struct acpi_video_device *dev = seq->private; 894 895 896 if (!dev) 897 goto end; 898 899 seq_printf(seq, "device_id: 0x%04x\n", (u32) dev->device_id); 900 seq_printf(seq, "type: "); 901 if (dev->flags.crt) 902 seq_printf(seq, "CRT\n"); 903 else if (dev->flags.lcd) 904 seq_printf(seq, "LCD\n"); 905 else if (dev->flags.tvout) 906 seq_printf(seq, "TVOUT\n"); 907 else if (dev->flags.dvi) 908 seq_printf(seq, "DVI\n"); 909 else 910 seq_printf(seq, "UNKNOWN\n"); 911 912 seq_printf(seq, "known by bios: %s\n", dev->flags.bios ? "yes" : "no"); 913 914 end: 915 return 0; 916} 917 918static int 919acpi_video_device_info_open_fs(struct inode *inode, struct file *file) 920{ 921 return single_open(file, acpi_video_device_info_seq_show, 922 PDE(inode)->data); 923} 924 925static int acpi_video_device_state_seq_show(struct seq_file *seq, void *offset) 926{ 927 int status; 928 struct acpi_video_device *dev = seq->private; 929 unsigned long long state; 930 931 932 if (!dev) 933 goto end; 934 935 status = acpi_video_device_get_state(dev, &state); 936 seq_printf(seq, "state: "); 937 if (ACPI_SUCCESS(status)) 938 seq_printf(seq, "0x%02llx\n", state); 939 else 940 seq_printf(seq, "<not supported>\n"); 941 942 status = acpi_video_device_query(dev, &state); 943 seq_printf(seq, "query: "); 944 if (ACPI_SUCCESS(status)) 945 seq_printf(seq, "0x%02llx\n", state); 946 else 947 seq_printf(seq, "<not supported>\n"); 948 949 end: 950 return 0; 951} 952 953static int 954acpi_video_device_state_open_fs(struct inode *inode, struct file *file) 955{ 956 return single_open(file, acpi_video_device_state_seq_show, 957 PDE(inode)->data); 958} 959 960static ssize_t 961acpi_video_device_write_state(struct file *file, 962 const char __user * buffer, 963 size_t count, loff_t * data) 964{ 965 int status; 966 struct seq_file *m = file->private_data; 967 struct acpi_video_device *dev = m->private; 968 char str[12] = { 0 }; 969 u32 state = 0; 970 971 972 if (!dev || count + 1 > sizeof str) 973 return -EINVAL; 974 975 if (copy_from_user(str, buffer, count)) 976 return -EFAULT; 977 978 str[count] = 0; 979 state = simple_strtoul(str, NULL, 0); 980 state &= ((1ul << 31) | (1ul << 30) | (1ul << 0)); 981 982 status = acpi_video_device_set_state(dev, state); 983 984 if (status) 985 return -EFAULT; 986 987 return count; 988} 989 990static int 991acpi_video_device_brightness_seq_show(struct seq_file *seq, void *offset) 992{ 993 struct acpi_video_device *dev = seq->private; 994 int i; 995 996 997 if (!dev || !dev->brightness) { 998 seq_printf(seq, "<not supported>\n"); 999 return 0; 1000 } 1001 1002 seq_printf(seq, "levels: "); 1003 for (i = 0; i < dev->brightness->count; i++) 1004 seq_printf(seq, " %d", dev->brightness->levels[i]); 1005 seq_printf(seq, "\ncurrent: %d\n", dev->brightness->curr); 1006 1007 return 0; 1008} 1009 1010static int 1011acpi_video_device_brightness_open_fs(struct inode *inode, struct file *file) 1012{ 1013 return single_open(file, acpi_video_device_brightness_seq_show, 1014 PDE(inode)->data); 1015} 1016 1017static ssize_t 1018acpi_video_device_write_brightness(struct file *file, 1019 const char __user * buffer, 1020 size_t count, loff_t * data) 1021{ 1022 struct seq_file *m = file->private_data; 1023 struct acpi_video_device *dev = m->private; 1024 char str[5] = { 0 }; 1025 unsigned int level = 0; 1026 int i; 1027 1028 1029 if (!dev || !dev->brightness || count + 1 > sizeof str) 1030 return -EINVAL; 1031 1032 if (copy_from_user(str, buffer, count)) 1033 return -EFAULT; 1034 1035 str[count] = 0; 1036 level = simple_strtoul(str, NULL, 0); 1037 1038 if (level > 100) 1039 return -EFAULT; 1040 1041 /* validate through the list of available levels */ 1042 for (i = 0; i < dev->brightness->count; i++) 1043 if (level == dev->brightness->levels[i]) { 1044 if (ACPI_SUCCESS 1045 (acpi_video_device_lcd_set_level(dev, level))) 1046 dev->brightness->curr = level; 1047 break; 1048 } 1049 1050 return count; 1051} 1052 1053static int acpi_video_device_EDID_seq_show(struct seq_file *seq, void *offset) 1054{ 1055 struct acpi_video_device *dev = seq->private; 1056 int status; 1057 int i; 1058 union acpi_object *edid = NULL; 1059 1060 1061 if (!dev) 1062 goto out; 1063 1064 status = acpi_video_device_EDID(dev, &edid, 128); 1065 if (ACPI_FAILURE(status)) { 1066 status = acpi_video_device_EDID(dev, &edid, 256); 1067 } 1068 1069 if (ACPI_FAILURE(status)) { 1070 goto out; 1071 } 1072 1073 if (edid && edid->type == ACPI_TYPE_BUFFER) { 1074 for (i = 0; i < edid->buffer.length; i++) 1075 seq_putc(seq, edid->buffer.pointer[i]); 1076 } 1077 1078 out: 1079 if (!edid) 1080 seq_printf(seq, "<not supported>\n"); 1081 else 1082 kfree(edid); 1083 1084 return 0; 1085} 1086 1087static int 1088acpi_video_device_EDID_open_fs(struct inode *inode, struct file *file) 1089{ 1090 return single_open(file, acpi_video_device_EDID_seq_show, 1091 PDE(inode)->data); 1092} 1093 1094static int acpi_video_device_add_fs(struct acpi_device *device) 1095{ 1096 struct proc_dir_entry *entry, *device_dir; 1097 struct acpi_video_device *vid_dev; 1098 1099 vid_dev = acpi_driver_data(device); 1100 if (!vid_dev) 1101 return -ENODEV; 1102 1103 device_dir = proc_mkdir(acpi_device_bid(device), 1104 vid_dev->video->dir); 1105 if (!device_dir) 1106 return -ENOMEM; 1107 1108 device_dir->owner = THIS_MODULE; 1109 1110 /* 'info' [R] */ 1111 entry = proc_create_data("info", S_IRUGO, device_dir, 1112 &acpi_video_device_info_fops, acpi_driver_data(device)); 1113 if (!entry) 1114 goto err_remove_dir; 1115 1116 /* 'state' [R/W] */ 1117 acpi_video_device_state_fops.write = acpi_video_device_write_state; 1118 entry = proc_create_data("state", S_IFREG | S_IRUGO | S_IWUSR, 1119 device_dir, 1120 &acpi_video_device_state_fops, 1121 acpi_driver_data(device)); 1122 if (!entry) 1123 goto err_remove_info; 1124 1125 /* 'brightness' [R/W] */ 1126 acpi_video_device_brightness_fops.write = 1127 acpi_video_device_write_brightness; 1128 entry = proc_create_data("brightness", S_IFREG | S_IRUGO | S_IWUSR, 1129 device_dir, 1130 &acpi_video_device_brightness_fops, 1131 acpi_driver_data(device)); 1132 if (!entry) 1133 goto err_remove_state; 1134 1135 /* 'EDID' [R] */ 1136 entry = proc_create_data("EDID", S_IRUGO, device_dir, 1137 &acpi_video_device_EDID_fops, 1138 acpi_driver_data(device)); 1139 if (!entry) 1140 goto err_remove_brightness; 1141 1142 acpi_device_dir(device) = device_dir; 1143 1144 return 0; 1145 1146 err_remove_brightness: 1147 remove_proc_entry("brightness", device_dir); 1148 err_remove_state: 1149 remove_proc_entry("state", device_dir); 1150 err_remove_info: 1151 remove_proc_entry("info", device_dir); 1152 err_remove_dir: 1153 remove_proc_entry(acpi_device_bid(device), vid_dev->video->dir); 1154 return -ENOMEM; 1155} 1156 1157static int acpi_video_device_remove_fs(struct acpi_device *device) 1158{ 1159 struct acpi_video_device *vid_dev; 1160 struct proc_dir_entry *device_dir; 1161 1162 vid_dev = acpi_driver_data(device); 1163 if (!vid_dev || !vid_dev->video || !vid_dev->video->dir) 1164 return -ENODEV; 1165 1166 device_dir = acpi_device_dir(device); 1167 if (device_dir) { 1168 remove_proc_entry("info", device_dir); 1169 remove_proc_entry("state", device_dir); 1170 remove_proc_entry("brightness", device_dir); 1171 remove_proc_entry("EDID", device_dir); 1172 remove_proc_entry(acpi_device_bid(device), vid_dev->video->dir); 1173 acpi_device_dir(device) = NULL; 1174 } 1175 1176 return 0; 1177} 1178 1179/* video bus */ 1180static int acpi_video_bus_info_seq_show(struct seq_file *seq, void *offset) 1181{ 1182 struct acpi_video_bus *video = seq->private; 1183 1184 1185 if (!video) 1186 goto end; 1187 1188 seq_printf(seq, "Switching heads: %s\n", 1189 video->flags.multihead ? "yes" : "no"); 1190 seq_printf(seq, "Video ROM: %s\n", 1191 video->flags.rom ? "yes" : "no"); 1192 seq_printf(seq, "Device to be POSTed on boot: %s\n", 1193 video->flags.post ? "yes" : "no"); 1194 1195 end: 1196 return 0; 1197} 1198 1199static int acpi_video_bus_info_open_fs(struct inode *inode, struct file *file) 1200{ 1201 return single_open(file, acpi_video_bus_info_seq_show, 1202 PDE(inode)->data); 1203} 1204 1205static int acpi_video_bus_ROM_seq_show(struct seq_file *seq, void *offset) 1206{ 1207 struct acpi_video_bus *video = seq->private; 1208 1209 1210 if (!video) 1211 goto end; 1212 1213 printk(KERN_INFO PREFIX "Please implement %s\n", __func__); 1214 seq_printf(seq, "<TODO>\n"); 1215 1216 end: 1217 return 0; 1218} 1219 1220static int acpi_video_bus_ROM_open_fs(struct inode *inode, struct file *file) 1221{ 1222 return single_open(file, acpi_video_bus_ROM_seq_show, PDE(inode)->data); 1223} 1224 1225static int acpi_video_bus_POST_info_seq_show(struct seq_file *seq, void *offset) 1226{ 1227 struct acpi_video_bus *video = seq->private; 1228 unsigned long long options; 1229 int status; 1230 1231 1232 if (!video) 1233 goto end; 1234 1235 status = acpi_video_bus_POST_options(video, &options); 1236 if (ACPI_SUCCESS(status)) { 1237 if (!(options & 1)) { 1238 printk(KERN_WARNING PREFIX 1239 "The motherboard VGA device is not listed as a possible POST device.\n"); 1240 printk(KERN_WARNING PREFIX 1241 "This indicates a BIOS bug. Please contact the manufacturer.\n"); 1242 } 1243 printk("%llx\n", options); 1244 seq_printf(seq, "can POST: <integrated video>"); 1245 if (options & 2) 1246 seq_printf(seq, " <PCI video>"); 1247 if (options & 4) 1248 seq_printf(seq, " <AGP video>"); 1249 seq_putc(seq, '\n'); 1250 } else 1251 seq_printf(seq, "<not supported>\n"); 1252 end: 1253 return 0; 1254} 1255 1256static int 1257acpi_video_bus_POST_info_open_fs(struct inode *inode, struct file *file) 1258{ 1259 return single_open(file, acpi_video_bus_POST_info_seq_show, 1260 PDE(inode)->data); 1261} 1262 1263static int acpi_video_bus_POST_seq_show(struct seq_file *seq, void *offset) 1264{ 1265 struct acpi_video_bus *video = seq->private; 1266 int status; 1267 unsigned long long id; 1268 1269 1270 if (!video) 1271 goto end; 1272 1273 status = acpi_video_bus_get_POST(video, &id); 1274 if (!ACPI_SUCCESS(status)) { 1275 seq_printf(seq, "<not supported>\n"); 1276 goto end; 1277 } 1278 seq_printf(seq, "device POSTed is <%s>\n", device_decode[id & 3]); 1279 1280 end: 1281 return 0; 1282} 1283 1284static int acpi_video_bus_DOS_seq_show(struct seq_file *seq, void *offset) 1285{ 1286 struct acpi_video_bus *video = seq->private; 1287 1288 1289 seq_printf(seq, "DOS setting: <%d>\n", video->dos_setting); 1290 1291 return 0; 1292} 1293 1294static int acpi_video_bus_POST_open_fs(struct inode *inode, struct file *file) 1295{ 1296 return single_open(file, acpi_video_bus_POST_seq_show, 1297 PDE(inode)->data); 1298} 1299 1300static int acpi_video_bus_DOS_open_fs(struct inode *inode, struct file *file) 1301{ 1302 return single_open(file, acpi_video_bus_DOS_seq_show, PDE(inode)->data); 1303} 1304 1305static ssize_t 1306acpi_video_bus_write_POST(struct file *file, 1307 const char __user * buffer, 1308 size_t count, loff_t * data) 1309{ 1310 int status; 1311 struct seq_file *m = file->private_data; 1312 struct acpi_video_bus *video = m->private; 1313 char str[12] = { 0 }; 1314 unsigned long long opt, options; 1315 1316 1317 if (!video || count + 1 > sizeof str) 1318 return -EINVAL; 1319 1320 status = acpi_video_bus_POST_options(video, &options); 1321 if (!ACPI_SUCCESS(status)) 1322 return -EINVAL; 1323 1324 if (copy_from_user(str, buffer, count)) 1325 return -EFAULT; 1326 1327 str[count] = 0; 1328 opt = strtoul(str, NULL, 0); 1329 if (opt > 3) 1330 return -EFAULT; 1331 1332 /* just in case an OEM 'forgot' the motherboard... */ 1333 options |= 1; 1334 1335 if (options & (1ul << opt)) { 1336 status = acpi_video_bus_set_POST(video, opt); 1337 if (!ACPI_SUCCESS(status)) 1338 return -EFAULT; 1339 1340 } 1341 1342 return count; 1343} 1344 1345static ssize_t 1346acpi_video_bus_write_DOS(struct file *file, 1347 const char __user * buffer, 1348 size_t count, loff_t * data) 1349{ 1350 int status; 1351 struct seq_file *m = file->private_data; 1352 struct acpi_video_bus *video = m->private; 1353 char str[12] = { 0 }; 1354 unsigned long opt; 1355 1356 1357 if (!video || count + 1 > sizeof str) 1358 return -EINVAL; 1359 1360 if (copy_from_user(str, buffer, count)) 1361 return -EFAULT; 1362 1363 str[count] = 0; 1364 opt = strtoul(str, NULL, 0); 1365 if (opt > 7) 1366 return -EFAULT; 1367 1368 status = acpi_video_bus_DOS(video, opt & 0x3, (opt & 0x4) >> 2); 1369 1370 if (!ACPI_SUCCESS(status)) 1371 return -EFAULT; 1372 1373 return count; 1374} 1375 1376static int acpi_video_bus_add_fs(struct acpi_device *device) 1377{ 1378 struct acpi_video_bus *video = acpi_driver_data(device); 1379 struct proc_dir_entry *device_dir; 1380 struct proc_dir_entry *entry; 1381 1382 device_dir = proc_mkdir(acpi_device_bid(device), acpi_video_dir); 1383 if (!device_dir) 1384 return -ENOMEM; 1385 1386 device_dir->owner = THIS_MODULE; 1387 1388 /* 'info' [R] */ 1389 entry = proc_create_data("info", S_IRUGO, device_dir, 1390 &acpi_video_bus_info_fops, 1391 acpi_driver_data(device)); 1392 if (!entry) 1393 goto err_remove_dir; 1394 1395 /* 'ROM' [R] */ 1396 entry = proc_create_data("ROM", S_IRUGO, device_dir, 1397 &acpi_video_bus_ROM_fops, 1398 acpi_driver_data(device)); 1399 if (!entry) 1400 goto err_remove_info; 1401 1402 /* 'POST_info' [R] */ 1403 entry = proc_create_data("POST_info", S_IRUGO, device_dir, 1404 &acpi_video_bus_POST_info_fops, 1405 acpi_driver_data(device)); 1406 if (!entry) 1407 goto err_remove_rom; 1408 1409 /* 'POST' [R/W] */ 1410 acpi_video_bus_POST_fops.write = acpi_video_bus_write_POST; 1411 entry = proc_create_data("POST", S_IFREG | S_IRUGO | S_IWUSR, 1412 device_dir, 1413 &acpi_video_bus_POST_fops, 1414 acpi_driver_data(device)); 1415 if (!entry) 1416 goto err_remove_post_info; 1417 1418 /* 'DOS' [R/W] */ 1419 acpi_video_bus_DOS_fops.write = acpi_video_bus_write_DOS; 1420 entry = proc_create_data("DOS", S_IFREG | S_IRUGO | S_IWUSR, 1421 device_dir, 1422 &acpi_video_bus_DOS_fops, 1423 acpi_driver_data(device)); 1424 if (!entry) 1425 goto err_remove_post; 1426 1427 video->dir = acpi_device_dir(device) = device_dir; 1428 return 0; 1429 1430 err_remove_post: 1431 remove_proc_entry("POST", device_dir); 1432 err_remove_post_info: 1433 remove_proc_entry("POST_info", device_dir); 1434 err_remove_rom: 1435 remove_proc_entry("ROM", device_dir); 1436 err_remove_info: 1437 remove_proc_entry("info", device_dir); 1438 err_remove_dir: 1439 remove_proc_entry(acpi_device_bid(device), acpi_video_dir); 1440 return -ENOMEM; 1441} 1442 1443static int acpi_video_bus_remove_fs(struct acpi_device *device) 1444{ 1445 struct proc_dir_entry *device_dir = acpi_device_dir(device); 1446 1447 if (device_dir) { 1448 remove_proc_entry("info", device_dir); 1449 remove_proc_entry("ROM", device_dir); 1450 remove_proc_entry("POST_info", device_dir); 1451 remove_proc_entry("POST", device_dir); 1452 remove_proc_entry("DOS", device_dir); 1453 remove_proc_entry(acpi_device_bid(device), acpi_video_dir); 1454 acpi_device_dir(device) = NULL; 1455 } 1456 1457 return 0; 1458} 1459 1460/* -------------------------------------------------------------------------- 1461 Driver Interface 1462 -------------------------------------------------------------------------- */ 1463 1464/* device interface */ 1465static struct acpi_video_device_attrib* 1466acpi_video_get_device_attr(struct acpi_video_bus *video, unsigned long device_id) 1467{ 1468 struct acpi_video_enumerated_device *ids; 1469 int i; 1470 1471 for (i = 0; i < video->attached_count; i++) { 1472 ids = &video->attached_array[i]; 1473 if ((ids->value.int_val & 0xffff) == device_id) 1474 return &ids->value.attrib; 1475 } 1476 1477 return NULL; 1478} 1479 1480static int 1481acpi_video_bus_get_one_device(struct acpi_device *device, 1482 struct acpi_video_bus *video) 1483{ 1484 unsigned long long device_id; 1485 int status; 1486 struct acpi_video_device *data; 1487 struct acpi_video_device_attrib* attribute; 1488 1489 if (!device || !video) 1490 return -EINVAL; 1491 1492 status = 1493 acpi_evaluate_integer(device->handle, "_ADR", NULL, &device_id); 1494 if (ACPI_SUCCESS(status)) { 1495 1496 data = kzalloc(sizeof(struct acpi_video_device), GFP_KERNEL); 1497 if (!data) 1498 return -ENOMEM; 1499 1500 strcpy(acpi_device_name(device), ACPI_VIDEO_DEVICE_NAME); 1501 strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS); 1502 device->driver_data = data; 1503 1504 data->device_id = device_id; 1505 data->video = video; 1506 data->dev = device; 1507 1508 attribute = acpi_video_get_device_attr(video, device_id); 1509 1510 if((attribute != NULL) && attribute->device_id_scheme) { 1511 switch (attribute->display_type) { 1512 case ACPI_VIDEO_DISPLAY_CRT: 1513 data->flags.crt = 1; 1514 break; 1515 case ACPI_VIDEO_DISPLAY_TV: 1516 data->flags.tvout = 1; 1517 break; 1518 case ACPI_VIDEO_DISPLAY_DVI: 1519 data->flags.dvi = 1; 1520 break; 1521 case ACPI_VIDEO_DISPLAY_LCD: 1522 data->flags.lcd = 1; 1523 break; 1524 default: 1525 data->flags.unknown = 1; 1526 break; 1527 } 1528 if(attribute->bios_can_detect) 1529 data->flags.bios = 1; 1530 } else 1531 data->flags.unknown = 1; 1532 1533 acpi_video_device_bind(video, data); 1534 acpi_video_device_find_cap(data); 1535 1536 status = acpi_install_notify_handler(device->handle, 1537 ACPI_DEVICE_NOTIFY, 1538 acpi_video_device_notify, 1539 data); 1540 if (ACPI_FAILURE(status)) { 1541 printk(KERN_ERR PREFIX 1542 "Error installing notify handler\n"); 1543 if(data->brightness) 1544 kfree(data->brightness->levels); 1545 kfree(data->brightness); 1546 kfree(data); 1547 return -ENODEV; 1548 } 1549 1550 mutex_lock(&video->device_list_lock); 1551 list_add_tail(&data->entry, &video->video_device_list); 1552 mutex_unlock(&video->device_list_lock); 1553 1554 acpi_video_device_add_fs(device); 1555 1556 return 0; 1557 } 1558 1559 return -ENOENT; 1560} 1561 1562/* 1563 * Arg: 1564 * video : video bus device 1565 * 1566 * Return: 1567 * none 1568 * 1569 * Enumerate the video device list of the video bus, 1570 * bind the ids with the corresponding video devices 1571 * under the video bus. 1572 */ 1573 1574static void acpi_video_device_rebind(struct acpi_video_bus *video) 1575{ 1576 struct acpi_video_device *dev; 1577 1578 mutex_lock(&video->device_list_lock); 1579 1580 list_for_each_entry(dev, &video->video_device_list, entry) 1581 acpi_video_device_bind(video, dev); 1582 1583 mutex_unlock(&video->device_list_lock); 1584} 1585 1586/* 1587 * Arg: 1588 * video : video bus device 1589 * device : video output device under the video 1590 * bus 1591 * 1592 * Return: 1593 * none 1594 * 1595 * Bind the ids with the corresponding video devices 1596 * under the video bus. 1597 */ 1598 1599static void 1600acpi_video_device_bind(struct acpi_video_bus *video, 1601 struct acpi_video_device *device) 1602{ 1603 struct acpi_video_enumerated_device *ids; 1604 int i; 1605 1606 for (i = 0; i < video->attached_count; i++) { 1607 ids = &video->attached_array[i]; 1608 if (device->device_id == (ids->value.int_val & 0xffff)) { 1609 ids->bind_info = device; 1610 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "device_bind %d\n", i)); 1611 } 1612 } 1613} 1614 1615/* 1616 * Arg: 1617 * video : video bus device 1618 * 1619 * Return: 1620 * < 0 : error 1621 * 1622 * Call _DOD to enumerate all devices attached to display adapter 1623 * 1624 */ 1625 1626static int acpi_video_device_enumerate(struct acpi_video_bus *video) 1627{ 1628 int status; 1629 int count; 1630 int i; 1631 struct acpi_video_enumerated_device *active_list; 1632 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 1633 union acpi_object *dod = NULL; 1634 union acpi_object *obj; 1635 1636 status = acpi_evaluate_object(video->device->handle, "_DOD", NULL, &buffer); 1637 if (!ACPI_SUCCESS(status)) { 1638 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _DOD")); 1639 return status; 1640 } 1641 1642 dod = buffer.pointer; 1643 if (!dod || (dod->type != ACPI_TYPE_PACKAGE)) { 1644 ACPI_EXCEPTION((AE_INFO, status, "Invalid _DOD data")); 1645 status = -EFAULT; 1646 goto out; 1647 } 1648 1649 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d video heads in _DOD\n", 1650 dod->package.count)); 1651 1652 active_list = kcalloc(1 + dod->package.count, 1653 sizeof(struct acpi_video_enumerated_device), 1654 GFP_KERNEL); 1655 if (!active_list) { 1656 status = -ENOMEM; 1657 goto out; 1658 } 1659 1660 count = 0; 1661 for (i = 0; i < dod->package.count; i++) { 1662 obj = &dod->package.elements[i]; 1663 1664 if (obj->type != ACPI_TYPE_INTEGER) { 1665 printk(KERN_ERR PREFIX 1666 "Invalid _DOD data in element %d\n", i); 1667 continue; 1668 } 1669 1670 active_list[count].value.int_val = obj->integer.value; 1671 active_list[count].bind_info = NULL; 1672 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "dod element[%d] = %d\n", i, 1673 (int)obj->integer.value)); 1674 count++; 1675 } 1676 1677 kfree(video->attached_array); 1678 1679 video->attached_array = active_list; 1680 video->attached_count = count; 1681 1682 out: 1683 kfree(buffer.pointer); 1684 return status; 1685} 1686 1687static int 1688acpi_video_get_next_level(struct acpi_video_device *device, 1689 u32 level_current, u32 event) 1690{ 1691 int min, max, min_above, max_below, i, l, delta = 255; 1692 max = max_below = 0; 1693 min = min_above = 255; 1694 /* Find closest level to level_current */ 1695 for (i = 0; i < device->brightness->count; i++) { 1696 l = device->brightness->levels[i]; 1697 if (abs(l - level_current) < abs(delta)) { 1698 delta = l - level_current; 1699 if (!delta) 1700 break; 1701 } 1702 } 1703 /* Ajust level_current to closest available level */ 1704 level_current += delta; 1705 for (i = 0; i < device->brightness->count; i++) { 1706 l = device->brightness->levels[i]; 1707 if (l < min) 1708 min = l; 1709 if (l > max) 1710 max = l; 1711 if (l < min_above && l > level_current) 1712 min_above = l; 1713 if (l > max_below && l < level_current) 1714 max_below = l; 1715 } 1716 1717 switch (event) { 1718 case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS: 1719 return (level_current < max) ? min_above : min; 1720 case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS: 1721 return (level_current < max) ? min_above : max; 1722 case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS: 1723 return (level_current > min) ? max_below : min; 1724 case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS: 1725 case ACPI_VIDEO_NOTIFY_DISPLAY_OFF: 1726 return 0; 1727 default: 1728 return level_current; 1729 } 1730} 1731 1732static void 1733acpi_video_switch_brightness(struct acpi_video_device *device, int event) 1734{ 1735 unsigned long long level_current, level_next; 1736 if (!device->brightness) 1737 return; 1738 acpi_video_device_lcd_get_level_current(device, &level_current); 1739 level_next = acpi_video_get_next_level(device, level_current, event); 1740 acpi_video_device_lcd_set_level(device, level_next); 1741} 1742 1743static int 1744acpi_video_bus_get_devices(struct acpi_video_bus *video, 1745 struct acpi_device *device) 1746{ 1747 int status = 0; 1748 struct acpi_device *dev; 1749 1750 acpi_video_device_enumerate(video); 1751 1752 list_for_each_entry(dev, &device->children, node) { 1753 1754 status = acpi_video_bus_get_one_device(dev, video); 1755 if (ACPI_FAILURE(status)) { 1756 printk(KERN_WARNING PREFIX 1757 "Cant attach device"); 1758 continue; 1759 } 1760 } 1761 return status; 1762} 1763 1764static int acpi_video_bus_put_one_device(struct acpi_video_device *device) 1765{ 1766 acpi_status status; 1767 struct acpi_video_bus *video; 1768 1769 1770 if (!device || !device->video) 1771 return -ENOENT; 1772 1773 video = device->video; 1774 1775 acpi_video_device_remove_fs(device->dev); 1776 1777 status = acpi_remove_notify_handler(device->dev->handle, 1778 ACPI_DEVICE_NOTIFY, 1779 acpi_video_device_notify); 1780 backlight_device_unregister(device->backlight); 1781 if (device->cdev) { 1782 sysfs_remove_link(&device->dev->dev.kobj, 1783 "thermal_cooling"); 1784 sysfs_remove_link(&device->cdev->device.kobj, 1785 "device"); 1786 thermal_cooling_device_unregister(device->cdev); 1787 device->cdev = NULL; 1788 } 1789 video_output_unregister(device->output_dev); 1790 1791 return 0; 1792} 1793 1794static int acpi_video_bus_put_devices(struct acpi_video_bus *video) 1795{ 1796 int status; 1797 struct acpi_video_device *dev, *next; 1798 1799 mutex_lock(&video->device_list_lock); 1800 1801 list_for_each_entry_safe(dev, next, &video->video_device_list, entry) { 1802 1803 status = acpi_video_bus_put_one_device(dev); 1804 if (ACPI_FAILURE(status)) 1805 printk(KERN_WARNING PREFIX 1806 "hhuuhhuu bug in acpi video driver.\n"); 1807 1808 if (dev->brightness) { 1809 kfree(dev->brightness->levels); 1810 kfree(dev->brightness); 1811 } 1812 list_del(&dev->entry); 1813 kfree(dev); 1814 } 1815 1816 mutex_unlock(&video->device_list_lock); 1817 1818 return 0; 1819} 1820 1821/* acpi_video interface */ 1822 1823static int acpi_video_bus_start_devices(struct acpi_video_bus *video) 1824{ 1825 return acpi_video_bus_DOS(video, 0, 0); 1826} 1827 1828static int acpi_video_bus_stop_devices(struct acpi_video_bus *video) 1829{ 1830 return acpi_video_bus_DOS(video, 0, 1); 1831} 1832 1833static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data) 1834{ 1835 struct acpi_video_bus *video = data; 1836 struct acpi_device *device = NULL; 1837 struct input_dev *input; 1838 int keycode; 1839 1840 if (!video) 1841 return; 1842 1843 device = video->device; 1844 input = video->input; 1845 1846 switch (event) { 1847 case ACPI_VIDEO_NOTIFY_SWITCH: /* User requested a switch, 1848 * most likely via hotkey. */ 1849 acpi_bus_generate_proc_event(device, event, 0); 1850 keycode = KEY_SWITCHVIDEOMODE; 1851 break; 1852 1853 case ACPI_VIDEO_NOTIFY_PROBE: /* User plugged in or removed a video 1854 * connector. */ 1855 acpi_video_device_enumerate(video); 1856 acpi_video_device_rebind(video); 1857 acpi_bus_generate_proc_event(device, event, 0); 1858 keycode = KEY_SWITCHVIDEOMODE; 1859 break; 1860 1861 case ACPI_VIDEO_NOTIFY_CYCLE: /* Cycle Display output hotkey pressed. */ 1862 acpi_bus_generate_proc_event(device, event, 0); 1863 keycode = KEY_SWITCHVIDEOMODE; 1864 break; 1865 case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT: /* Next Display output hotkey pressed. */ 1866 acpi_bus_generate_proc_event(device, event, 0); 1867 keycode = KEY_VIDEO_NEXT; 1868 break; 1869 case ACPI_VIDEO_NOTIFY_PREV_OUTPUT: /* previous Display output hotkey pressed. */ 1870 acpi_bus_generate_proc_event(device, event, 0); 1871 keycode = KEY_VIDEO_PREV; 1872 break; 1873 1874 default: 1875 keycode = KEY_UNKNOWN; 1876 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 1877 "Unsupported event [0x%x]\n", event)); 1878 break; 1879 } 1880 1881 acpi_notifier_call_chain(device, event, 0); 1882 input_report_key(input, keycode, 1); 1883 input_sync(input); 1884 input_report_key(input, keycode, 0); 1885 input_sync(input); 1886 1887 return; 1888} 1889 1890static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data) 1891{ 1892 struct acpi_video_device *video_device = data; 1893 struct acpi_device *device = NULL; 1894 struct acpi_video_bus *bus; 1895 struct input_dev *input; 1896 int keycode; 1897 1898 if (!video_device) 1899 return; 1900 1901 device = video_device->dev; 1902 bus = video_device->video; 1903 input = bus->input; 1904 1905 switch (event) { 1906 case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS: /* Cycle brightness */ 1907 if (brightness_switch_enabled) 1908 acpi_video_switch_brightness(video_device, event); 1909 acpi_bus_generate_proc_event(device, event, 0); 1910 keycode = KEY_BRIGHTNESS_CYCLE; 1911 break; 1912 case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS: /* Increase brightness */ 1913 if (brightness_switch_enabled) 1914 acpi_video_switch_brightness(video_device, event); 1915 acpi_bus_generate_proc_event(device, event, 0); 1916 keycode = KEY_BRIGHTNESSUP; 1917 break; 1918 case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS: /* Decrease brightness */ 1919 if (brightness_switch_enabled) 1920 acpi_video_switch_brightness(video_device, event); 1921 acpi_bus_generate_proc_event(device, event, 0); 1922 keycode = KEY_BRIGHTNESSDOWN; 1923 break; 1924 case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS: /* zero brightnesss */ 1925 if (brightness_switch_enabled) 1926 acpi_video_switch_brightness(video_device, event); 1927 acpi_bus_generate_proc_event(device, event, 0); 1928 keycode = KEY_BRIGHTNESS_ZERO; 1929 break; 1930 case ACPI_VIDEO_NOTIFY_DISPLAY_OFF: /* display device off */ 1931 if (brightness_switch_enabled) 1932 acpi_video_switch_brightness(video_device, event); 1933 acpi_bus_generate_proc_event(device, event, 0); 1934 keycode = KEY_DISPLAY_OFF; 1935 break; 1936 default: 1937 keycode = KEY_UNKNOWN; 1938 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 1939 "Unsupported event [0x%x]\n", event)); 1940 break; 1941 } 1942 1943 acpi_notifier_call_chain(device, event, 0); 1944 input_report_key(input, keycode, 1); 1945 input_sync(input); 1946 input_report_key(input, keycode, 0); 1947 input_sync(input); 1948 1949 return; 1950} 1951 1952static int instance; 1953static int acpi_video_resume(struct acpi_device *device) 1954{ 1955 struct acpi_video_bus *video; 1956 struct acpi_video_device *video_device; 1957 int i; 1958 1959 if (!device || !acpi_driver_data(device)) 1960 return -EINVAL; 1961 1962 video = acpi_driver_data(device); 1963 1964 for (i = 0; i < video->attached_count; i++) { 1965 video_device = video->attached_array[i].bind_info; 1966 if (video_device && video_device->backlight) 1967 acpi_video_set_brightness(video_device->backlight); 1968 } 1969 return AE_OK; 1970} 1971 1972static int acpi_video_bus_add(struct acpi_device *device) 1973{ 1974 acpi_status status; 1975 struct acpi_video_bus *video; 1976 struct input_dev *input; 1977 int error; 1978 1979 video = kzalloc(sizeof(struct acpi_video_bus), GFP_KERNEL); 1980 if (!video) 1981 return -ENOMEM; 1982 1983 /* a hack to fix the duplicate name "VID" problem on T61 */ 1984 if (!strcmp(device->pnp.bus_id, "VID")) { 1985 if (instance) 1986 device->pnp.bus_id[3] = '0' + instance; 1987 instance ++; 1988 } 1989 1990 video->device = device; 1991 strcpy(acpi_device_name(device), ACPI_VIDEO_BUS_NAME); 1992 strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS); 1993 device->driver_data = video; 1994 1995 acpi_video_bus_find_cap(video); 1996 error = acpi_video_bus_check(video); 1997 if (error) 1998 goto err_free_video; 1999 2000 error = acpi_video_bus_add_fs(device); 2001 if (error) 2002 goto err_free_video; 2003 2004 mutex_init(&video->device_list_lock); 2005 INIT_LIST_HEAD(&video->video_device_list); 2006 2007 acpi_video_bus_get_devices(video, device); 2008 acpi_video_bus_start_devices(video); 2009 2010 status = acpi_install_notify_handler(device->handle, 2011 ACPI_DEVICE_NOTIFY, 2012 acpi_video_bus_notify, video); 2013 if (ACPI_FAILURE(status)) { 2014 printk(KERN_ERR PREFIX 2015 "Error installing notify handler\n"); 2016 error = -ENODEV; 2017 goto err_stop_video; 2018 } 2019 2020 video->input = input = input_allocate_device(); 2021 if (!input) { 2022 error = -ENOMEM; 2023 goto err_uninstall_notify; 2024 } 2025 2026 snprintf(video->phys, sizeof(video->phys), 2027 "%s/video/input0", acpi_device_hid(video->device)); 2028 2029 input->name = acpi_device_name(video->device); 2030 input->phys = video->phys; 2031 input->id.bustype = BUS_HOST; 2032 input->id.product = 0x06; 2033 input->dev.parent = &device->dev; 2034 input->evbit[0] = BIT(EV_KEY); 2035 set_bit(KEY_SWITCHVIDEOMODE, input->keybit); 2036 set_bit(KEY_VIDEO_NEXT, input->keybit); 2037 set_bit(KEY_VIDEO_PREV, input->keybit); 2038 set_bit(KEY_BRIGHTNESS_CYCLE, input->keybit); 2039 set_bit(KEY_BRIGHTNESSUP, input->keybit); 2040 set_bit(KEY_BRIGHTNESSDOWN, input->keybit); 2041 set_bit(KEY_BRIGHTNESS_ZERO, input->keybit); 2042 set_bit(KEY_DISPLAY_OFF, input->keybit); 2043 set_bit(KEY_UNKNOWN, input->keybit); 2044 2045 error = input_register_device(input); 2046 if (error) 2047 goto err_free_input_dev; 2048 2049 printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s rom: %s post: %s)\n", 2050 ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device), 2051 video->flags.multihead ? "yes" : "no", 2052 video->flags.rom ? "yes" : "no", 2053 video->flags.post ? "yes" : "no"); 2054 2055 return 0; 2056 2057 err_free_input_dev: 2058 input_free_device(input); 2059 err_uninstall_notify: 2060 acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, 2061 acpi_video_bus_notify); 2062 err_stop_video: 2063 acpi_video_bus_stop_devices(video); 2064 acpi_video_bus_put_devices(video); 2065 kfree(video->attached_array); 2066 acpi_video_bus_remove_fs(device); 2067 err_free_video: 2068 kfree(video); 2069 device->driver_data = NULL; 2070 2071 return error; 2072} 2073 2074static int acpi_video_bus_remove(struct acpi_device *device, int type) 2075{ 2076 acpi_status status = 0; 2077 struct acpi_video_bus *video = NULL; 2078 2079 2080 if (!device || !acpi_driver_data(device)) 2081 return -EINVAL; 2082 2083 video = acpi_driver_data(device); 2084 2085 acpi_video_bus_stop_devices(video); 2086 2087 status = acpi_remove_notify_handler(video->device->handle, 2088 ACPI_DEVICE_NOTIFY, 2089 acpi_video_bus_notify); 2090 2091 acpi_video_bus_put_devices(video); 2092 acpi_video_bus_remove_fs(device); 2093 2094 input_unregister_device(video->input); 2095 kfree(video->attached_array); 2096 kfree(video); 2097 2098 return 0; 2099} 2100 2101static int __init acpi_video_init(void) 2102{ 2103 int result = 0; 2104 2105 acpi_video_dir = proc_mkdir(ACPI_VIDEO_CLASS, acpi_root_dir); 2106 if (!acpi_video_dir) 2107 return -ENODEV; 2108 acpi_video_dir->owner = THIS_MODULE; 2109 2110 result = acpi_bus_register_driver(&acpi_video_bus); 2111 if (result < 0) { 2112 remove_proc_entry(ACPI_VIDEO_CLASS, acpi_root_dir); 2113 return -ENODEV; 2114 } 2115 2116 return 0; 2117} 2118 2119static void __exit acpi_video_exit(void) 2120{ 2121 2122 acpi_bus_unregister_driver(&acpi_video_bus); 2123 2124 remove_proc_entry(ACPI_VIDEO_CLASS, acpi_root_dir); 2125 2126 return; 2127} 2128 2129module_init(acpi_video_init); 2130module_exit(acpi_video_exit);