OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [acpi/] [video.c] - Blame information for rev 62

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.