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