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