ia64/linux-2.6.18-xen.hg

view drivers/acpi/video.c @ 897:329ea0ccb344

balloon: try harder to balloon up under memory pressure.

Currently if the balloon driver is unable to increase the guest's
reservation it assumes the failure was due to reaching its full
allocation, gives up on the ballooning operation and records the limit
it reached as the "hard limit". The driver will not try again until
the target is set again (even to the same value).

However it is possible that ballooning has in fact failed due to
memory pressure in the host and therefore it is desirable to keep
attempting to reach the target in case memory becomes available. The
most likely scenario is that some guests are ballooning down while
others are ballooning up and therefore there is temporary memory
pressure while things stabilise. You would not expect a well behaved
toolstack to ask a domain to balloon to more than its allocation nor
would you expect it to deliberately over-commit memory by setting
balloon targets which exceed the total host memory.

This patch drops the concept of a hard limit and causes the balloon
driver to retry increasing the reservation on a timer in the same
manner as when decreasing the reservation.

Also if we partially succeed in increasing the reservation
(i.e. receive less pages than we asked for) then we may as well keep
those pages rather than returning them to Xen.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jun 05 14:01:20 2009 +0100 (2009-06-05)
parents 831230e53067
children
line source
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 *
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or (at
12 * your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
22 *
23 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24 */
26 #include <linux/kernel.h>
27 #include <linux/module.h>
28 #include <linux/init.h>
29 #include <linux/types.h>
30 #include <linux/list.h>
31 #include <linux/proc_fs.h>
32 #include <linux/seq_file.h>
34 #include <asm/uaccess.h>
36 #include <acpi/acpi_bus.h>
37 #include <acpi/acpi_drivers.h>
39 #define ACPI_VIDEO_COMPONENT 0x08000000
40 #define ACPI_VIDEO_CLASS "video"
41 #define ACPI_VIDEO_DRIVER_NAME "ACPI Video Driver"
42 #define ACPI_VIDEO_BUS_NAME "Video Bus"
43 #define ACPI_VIDEO_DEVICE_NAME "Video Device"
44 #define ACPI_VIDEO_NOTIFY_SWITCH 0x80
45 #define ACPI_VIDEO_NOTIFY_PROBE 0x81
46 #define ACPI_VIDEO_NOTIFY_CYCLE 0x82
47 #define ACPI_VIDEO_NOTIFY_NEXT_OUTPUT 0x83
48 #define ACPI_VIDEO_NOTIFY_PREV_OUTPUT 0x84
50 #define ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS 0x82
51 #define ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS 0x83
52 #define ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS 0x84
53 #define ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS 0x85
54 #define ACPI_VIDEO_NOTIFY_DISPLAY_OFF 0x86
56 #define ACPI_VIDEO_HEAD_INVALID (~0u - 1)
57 #define ACPI_VIDEO_HEAD_END (~0u)
59 #define _COMPONENT ACPI_VIDEO_COMPONENT
60 ACPI_MODULE_NAME("acpi_video")
62 MODULE_AUTHOR("Bruno Ducrot");
63 MODULE_DESCRIPTION(ACPI_VIDEO_DRIVER_NAME);
64 MODULE_LICENSE("GPL");
66 static int acpi_video_bus_add(struct acpi_device *device);
67 static int acpi_video_bus_remove(struct acpi_device *device, int type);
68 static int acpi_video_bus_match(struct acpi_device *device,
69 struct acpi_driver *driver);
71 static struct acpi_driver acpi_video_bus = {
72 .name = ACPI_VIDEO_DRIVER_NAME,
73 .class = ACPI_VIDEO_CLASS,
74 .ops = {
75 .add = acpi_video_bus_add,
76 .remove = acpi_video_bus_remove,
77 .match = acpi_video_bus_match,
78 },
79 };
81 struct acpi_video_bus_flags {
82 u8 multihead:1; /* can switch video heads */
83 u8 rom:1; /* can retrieve a video rom */
84 u8 post:1; /* can configure the head to */
85 u8 reserved:5;
86 };
88 struct acpi_video_bus_cap {
89 u8 _DOS:1; /*Enable/Disable output switching */
90 u8 _DOD:1; /*Enumerate all devices attached to display adapter */
91 u8 _ROM:1; /*Get ROM Data */
92 u8 _GPD:1; /*Get POST Device */
93 u8 _SPD:1; /*Set POST Device */
94 u8 _VPO:1; /*Video POST Options */
95 u8 reserved:2;
96 };
98 struct acpi_video_device_attrib {
99 u32 display_index:4; /* A zero-based instance of the Display */
100 u32 display_port_attachment:4; /*This field differenates displays type */
101 u32 display_type:4; /*Describe the specific type in use */
102 u32 vendor_specific:4; /*Chipset Vendor Specifi */
103 u32 bios_can_detect:1; /*BIOS can detect the device */
104 u32 depend_on_vga:1; /*Non-VGA output device whose power is related to
105 the VGA device. */
106 u32 pipe_id:3; /*For VGA multiple-head devices. */
107 u32 reserved:10; /*Must be 0 */
108 u32 device_id_scheme:1; /*Device ID Scheme */
109 };
111 struct acpi_video_enumerated_device {
112 union {
113 u32 int_val;
114 struct acpi_video_device_attrib attrib;
115 } value;
116 struct acpi_video_device *bind_info;
117 };
119 struct acpi_video_bus {
120 struct acpi_device *device;
121 u8 dos_setting;
122 struct acpi_video_enumerated_device *attached_array;
123 u8 attached_count;
124 struct acpi_video_bus_cap cap;
125 struct acpi_video_bus_flags flags;
126 struct semaphore sem;
127 struct list_head video_device_list;
128 struct proc_dir_entry *dir;
129 };
131 struct acpi_video_device_flags {
132 u8 crt:1;
133 u8 lcd:1;
134 u8 tvout:1;
135 u8 bios:1;
136 u8 unknown:1;
137 u8 reserved:3;
138 };
140 struct acpi_video_device_cap {
141 u8 _ADR:1; /*Return the unique ID */
142 u8 _BCL:1; /*Query list of brightness control levels supported */
143 u8 _BCM:1; /*Set the brightness level */
144 u8 _DDC:1; /*Return the EDID for this device */
145 u8 _DCS:1; /*Return status of output device */
146 u8 _DGS:1; /*Query graphics state */
147 u8 _DSS:1; /*Device state set */
148 u8 _reserved:1;
149 };
151 struct acpi_video_device_brightness {
152 int curr;
153 int count;
154 int *levels;
155 };
157 struct acpi_video_device {
158 unsigned long device_id;
159 struct acpi_video_device_flags flags;
160 struct acpi_video_device_cap cap;
161 struct list_head entry;
162 struct acpi_video_bus *video;
163 struct acpi_device *dev;
164 struct acpi_video_device_brightness *brightness;
165 };
167 /* bus */
168 static int acpi_video_bus_info_open_fs(struct inode *inode, struct file *file);
169 static struct file_operations acpi_video_bus_info_fops = {
170 .open = acpi_video_bus_info_open_fs,
171 .read = seq_read,
172 .llseek = seq_lseek,
173 .release = single_release,
174 };
176 static int acpi_video_bus_ROM_open_fs(struct inode *inode, struct file *file);
177 static struct file_operations acpi_video_bus_ROM_fops = {
178 .open = acpi_video_bus_ROM_open_fs,
179 .read = seq_read,
180 .llseek = seq_lseek,
181 .release = single_release,
182 };
184 static int acpi_video_bus_POST_info_open_fs(struct inode *inode,
185 struct file *file);
186 static struct file_operations acpi_video_bus_POST_info_fops = {
187 .open = acpi_video_bus_POST_info_open_fs,
188 .read = seq_read,
189 .llseek = seq_lseek,
190 .release = single_release,
191 };
193 static int acpi_video_bus_POST_open_fs(struct inode *inode, struct file *file);
194 static struct file_operations acpi_video_bus_POST_fops = {
195 .open = acpi_video_bus_POST_open_fs,
196 .read = seq_read,
197 .llseek = seq_lseek,
198 .release = single_release,
199 };
201 static int acpi_video_bus_DOS_open_fs(struct inode *inode, struct file *file);
202 static struct file_operations acpi_video_bus_DOS_fops = {
203 .open = acpi_video_bus_DOS_open_fs,
204 .read = seq_read,
205 .llseek = seq_lseek,
206 .release = single_release,
207 };
209 /* device */
210 static int acpi_video_device_info_open_fs(struct inode *inode,
211 struct file *file);
212 static struct file_operations acpi_video_device_info_fops = {
213 .open = acpi_video_device_info_open_fs,
214 .read = seq_read,
215 .llseek = seq_lseek,
216 .release = single_release,
217 };
219 static int acpi_video_device_state_open_fs(struct inode *inode,
220 struct file *file);
221 static struct file_operations acpi_video_device_state_fops = {
222 .open = acpi_video_device_state_open_fs,
223 .read = seq_read,
224 .llseek = seq_lseek,
225 .release = single_release,
226 };
228 static int acpi_video_device_brightness_open_fs(struct inode *inode,
229 struct file *file);
230 static struct file_operations acpi_video_device_brightness_fops = {
231 .open = acpi_video_device_brightness_open_fs,
232 .read = seq_read,
233 .llseek = seq_lseek,
234 .release = single_release,
235 };
237 static int acpi_video_device_EDID_open_fs(struct inode *inode,
238 struct file *file);
239 static struct file_operations acpi_video_device_EDID_fops = {
240 .open = acpi_video_device_EDID_open_fs,
241 .read = seq_read,
242 .llseek = seq_lseek,
243 .release = single_release,
244 };
246 static char device_decode[][30] = {
247 "motherboard VGA device",
248 "PCI VGA device",
249 "AGP VGA device",
250 "UNKNOWN",
251 };
253 static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data);
254 static void acpi_video_device_rebind(struct acpi_video_bus *video);
255 static void acpi_video_device_bind(struct acpi_video_bus *video,
256 struct acpi_video_device *device);
257 static int acpi_video_device_enumerate(struct acpi_video_bus *video);
258 static int acpi_video_switch_output(struct acpi_video_bus *video, int event);
259 static int acpi_video_get_next_level(struct acpi_video_device *device,
260 u32 level_current, u32 event);
261 static void acpi_video_switch_brightness(struct acpi_video_device *device,
262 int event);
264 /* --------------------------------------------------------------------------
265 Video Management
266 -------------------------------------------------------------------------- */
268 /* device */
270 static int
271 acpi_video_device_query(struct acpi_video_device *device, unsigned long *state)
272 {
273 int status;
275 status = acpi_evaluate_integer(device->dev->handle, "_DGS", NULL, state);
277 return status;
278 }
280 static int
281 acpi_video_device_get_state(struct acpi_video_device *device,
282 unsigned long *state)
283 {
284 int status;
286 status = acpi_evaluate_integer(device->dev->handle, "_DCS", NULL, state);
288 return status;
289 }
291 static int
292 acpi_video_device_set_state(struct acpi_video_device *device, int state)
293 {
294 int status;
295 union acpi_object arg0 = { ACPI_TYPE_INTEGER };
296 struct acpi_object_list args = { 1, &arg0 };
297 unsigned long ret;
300 arg0.integer.value = state;
301 status = acpi_evaluate_integer(device->dev->handle, "_DSS", &args, &ret);
303 return status;
304 }
306 static int
307 acpi_video_device_lcd_query_levels(struct acpi_video_device *device,
308 union acpi_object **levels)
309 {
310 int status;
311 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
312 union acpi_object *obj;
315 *levels = NULL;
317 status = acpi_evaluate_object(device->dev->handle, "_BCL", NULL, &buffer);
318 if (!ACPI_SUCCESS(status))
319 return status;
320 obj = (union acpi_object *)buffer.pointer;
321 if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) {
322 printk(KERN_ERR PREFIX "Invalid _BCL data\n");
323 status = -EFAULT;
324 goto err;
325 }
327 *levels = obj;
329 return 0;
331 err:
332 kfree(buffer.pointer);
334 return status;
335 }
337 static int
338 acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level)
339 {
340 int status;
341 union acpi_object arg0 = { ACPI_TYPE_INTEGER };
342 struct acpi_object_list args = { 1, &arg0 };
345 arg0.integer.value = level;
346 status = acpi_evaluate_object(device->dev->handle, "_BCM", &args, NULL);
348 printk(KERN_DEBUG "set_level status: %x\n", status);
349 return status;
350 }
352 static int
353 acpi_video_device_lcd_get_level_current(struct acpi_video_device *device,
354 unsigned long *level)
355 {
356 int status;
358 status = acpi_evaluate_integer(device->dev->handle, "_BQC", NULL, level);
360 return status;
361 }
363 static int
364 acpi_video_device_EDID(struct acpi_video_device *device,
365 union acpi_object **edid, ssize_t length)
366 {
367 int status;
368 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
369 union acpi_object *obj;
370 union acpi_object arg0 = { ACPI_TYPE_INTEGER };
371 struct acpi_object_list args = { 1, &arg0 };
374 *edid = NULL;
376 if (!device)
377 return -ENODEV;
378 if (length == 128)
379 arg0.integer.value = 1;
380 else if (length == 256)
381 arg0.integer.value = 2;
382 else
383 return -EINVAL;
385 status = acpi_evaluate_object(device->dev->handle, "_DDC", &args, &buffer);
386 if (ACPI_FAILURE(status))
387 return -ENODEV;
389 obj = (union acpi_object *)buffer.pointer;
391 if (obj && obj->type == ACPI_TYPE_BUFFER)
392 *edid = obj;
393 else {
394 printk(KERN_ERR PREFIX "Invalid _DDC data\n");
395 status = -EFAULT;
396 kfree(obj);
397 }
399 return status;
400 }
402 /* bus */
404 static int
405 acpi_video_bus_set_POST(struct acpi_video_bus *video, unsigned long option)
406 {
407 int status;
408 unsigned long tmp;
409 union acpi_object arg0 = { ACPI_TYPE_INTEGER };
410 struct acpi_object_list args = { 1, &arg0 };
413 arg0.integer.value = option;
415 status = acpi_evaluate_integer(video->device->handle, "_SPD", &args, &tmp);
416 if (ACPI_SUCCESS(status))
417 status = tmp ? (-EINVAL) : (AE_OK);
419 return status;
420 }
422 static int
423 acpi_video_bus_get_POST(struct acpi_video_bus *video, unsigned long *id)
424 {
425 int status;
427 status = acpi_evaluate_integer(video->device->handle, "_GPD", NULL, id);
429 return status;
430 }
432 static int
433 acpi_video_bus_POST_options(struct acpi_video_bus *video,
434 unsigned long *options)
435 {
436 int status;
438 status = acpi_evaluate_integer(video->device->handle, "_VPO", NULL, options);
439 *options &= 3;
441 return status;
442 }
444 /*
445 * Arg:
446 * video : video bus device pointer
447 * bios_flag :
448 * 0. The system BIOS should NOT automatically switch(toggle)
449 * the active display output.
450 * 1. The system BIOS should automatically switch (toggle) the
451 * active display output. No swich event.
452 * 2. The _DGS value should be locked.
453 * 3. The system BIOS should not automatically switch (toggle) the
454 * active display output, but instead generate the display switch
455 * event notify code.
456 * lcd_flag :
457 * 0. The system BIOS should automatically control the brightness level
458 * of the LCD, when the power changes from AC to DC
459 * 1. The system BIOS should NOT automatically control the brightness
460 * level of the LCD, when the power changes from AC to DC.
461 * Return Value:
462 * -1 wrong arg.
463 */
465 static int
466 acpi_video_bus_DOS(struct acpi_video_bus *video, int bios_flag, int lcd_flag)
467 {
468 acpi_integer status = 0;
469 union acpi_object arg0 = { ACPI_TYPE_INTEGER };
470 struct acpi_object_list args = { 1, &arg0 };
473 if (bios_flag < 0 || bios_flag > 3 || lcd_flag < 0 || lcd_flag > 1) {
474 status = -1;
475 goto Failed;
476 }
477 arg0.integer.value = (lcd_flag << 2) | bios_flag;
478 video->dos_setting = arg0.integer.value;
479 acpi_evaluate_object(video->device->handle, "_DOS", &args, NULL);
481 Failed:
482 return status;
483 }
485 /*
486 * Arg:
487 * device : video output device (LCD, CRT, ..)
488 *
489 * Return Value:
490 * None
491 *
492 * Find out all required AML method defined under the output
493 * device.
494 */
496 static void acpi_video_device_find_cap(struct acpi_video_device *device)
497 {
498 acpi_integer status;
499 acpi_handle h_dummy1;
500 int i;
501 union acpi_object *obj = NULL;
502 struct acpi_video_device_brightness *br = NULL;
505 memset(&device->cap, 0, 4);
507 if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_ADR", &h_dummy1))) {
508 device->cap._ADR = 1;
509 }
510 if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_BCL", &h_dummy1))) {
511 device->cap._BCL = 1;
512 }
513 if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_BCM", &h_dummy1))) {
514 device->cap._BCM = 1;
515 }
516 if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DDC", &h_dummy1))) {
517 device->cap._DDC = 1;
518 }
519 if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DCS", &h_dummy1))) {
520 device->cap._DCS = 1;
521 }
522 if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DGS", &h_dummy1))) {
523 device->cap._DGS = 1;
524 }
525 if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DSS", &h_dummy1))) {
526 device->cap._DSS = 1;
527 }
529 status = acpi_video_device_lcd_query_levels(device, &obj);
531 if (obj && obj->type == ACPI_TYPE_PACKAGE && obj->package.count >= 2) {
532 int count = 0;
533 union acpi_object *o;
535 br = kmalloc(sizeof(*br), GFP_KERNEL);
536 if (!br) {
537 printk(KERN_ERR "can't allocate memory\n");
538 } else {
539 memset(br, 0, sizeof(*br));
540 br->levels = kmalloc(obj->package.count *
541 sizeof *(br->levels), GFP_KERNEL);
542 if (!br->levels)
543 goto out;
545 for (i = 0; i < obj->package.count; i++) {
546 o = (union acpi_object *)&obj->package.
547 elements[i];
548 if (o->type != ACPI_TYPE_INTEGER) {
549 printk(KERN_ERR PREFIX "Invalid data\n");
550 continue;
551 }
552 br->levels[count] = (u32) o->integer.value;
553 count++;
554 }
555 out:
556 if (count < 2) {
557 kfree(br->levels);
558 kfree(br);
559 } else {
560 br->count = count;
561 device->brightness = br;
562 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
563 "found %d brightness levels\n",
564 count));
565 }
566 }
567 }
569 kfree(obj);
571 return;
572 }
574 /*
575 * Arg:
576 * device : video output device (VGA)
577 *
578 * Return Value:
579 * None
580 *
581 * Find out all required AML method defined under the video bus device.
582 */
584 static void acpi_video_bus_find_cap(struct acpi_video_bus *video)
585 {
586 acpi_handle h_dummy1;
588 memset(&video->cap, 0, 4);
589 if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_DOS", &h_dummy1))) {
590 video->cap._DOS = 1;
591 }
592 if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_DOD", &h_dummy1))) {
593 video->cap._DOD = 1;
594 }
595 if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_ROM", &h_dummy1))) {
596 video->cap._ROM = 1;
597 }
598 if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_GPD", &h_dummy1))) {
599 video->cap._GPD = 1;
600 }
601 if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_SPD", &h_dummy1))) {
602 video->cap._SPD = 1;
603 }
604 if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_VPO", &h_dummy1))) {
605 video->cap._VPO = 1;
606 }
607 }
609 /*
610 * Check whether the video bus device has required AML method to
611 * support the desired features
612 */
614 static int acpi_video_bus_check(struct acpi_video_bus *video)
615 {
616 acpi_status status = -ENOENT;
619 if (!video)
620 return -EINVAL;
622 /* Since there is no HID, CID and so on for VGA driver, we have
623 * to check well known required nodes.
624 */
626 /* Does this device able to support video switching ? */
627 if (video->cap._DOS) {
628 video->flags.multihead = 1;
629 status = 0;
630 }
632 /* Does this device able to retrieve a retrieve a video ROM ? */
633 if (video->cap._ROM) {
634 video->flags.rom = 1;
635 status = 0;
636 }
638 /* Does this device able to configure which video device to POST ? */
639 if (video->cap._GPD && video->cap._SPD && video->cap._VPO) {
640 video->flags.post = 1;
641 status = 0;
642 }
644 return status;
645 }
647 /* --------------------------------------------------------------------------
648 FS Interface (/proc)
649 -------------------------------------------------------------------------- */
651 static struct proc_dir_entry *acpi_video_dir;
653 /* video devices */
655 static int acpi_video_device_info_seq_show(struct seq_file *seq, void *offset)
656 {
657 struct acpi_video_device *dev =
658 (struct acpi_video_device *)seq->private;
661 if (!dev)
662 goto end;
664 seq_printf(seq, "device_id: 0x%04x\n", (u32) dev->device_id);
665 seq_printf(seq, "type: ");
666 if (dev->flags.crt)
667 seq_printf(seq, "CRT\n");
668 else if (dev->flags.lcd)
669 seq_printf(seq, "LCD\n");
670 else if (dev->flags.tvout)
671 seq_printf(seq, "TVOUT\n");
672 else
673 seq_printf(seq, "UNKNOWN\n");
675 seq_printf(seq, "known by bios: %s\n", dev->flags.bios ? "yes" : "no");
677 end:
678 return 0;
679 }
681 static int
682 acpi_video_device_info_open_fs(struct inode *inode, struct file *file)
683 {
684 return single_open(file, acpi_video_device_info_seq_show,
685 PDE(inode)->data);
686 }
688 static int acpi_video_device_state_seq_show(struct seq_file *seq, void *offset)
689 {
690 int status;
691 struct acpi_video_device *dev =
692 (struct acpi_video_device *)seq->private;
693 unsigned long state;
696 if (!dev)
697 goto end;
699 status = acpi_video_device_get_state(dev, &state);
700 seq_printf(seq, "state: ");
701 if (ACPI_SUCCESS(status))
702 seq_printf(seq, "0x%02lx\n", state);
703 else
704 seq_printf(seq, "<not supported>\n");
706 status = acpi_video_device_query(dev, &state);
707 seq_printf(seq, "query: ");
708 if (ACPI_SUCCESS(status))
709 seq_printf(seq, "0x%02lx\n", state);
710 else
711 seq_printf(seq, "<not supported>\n");
713 end:
714 return 0;
715 }
717 static int
718 acpi_video_device_state_open_fs(struct inode *inode, struct file *file)
719 {
720 return single_open(file, acpi_video_device_state_seq_show,
721 PDE(inode)->data);
722 }
724 static ssize_t
725 acpi_video_device_write_state(struct file *file,
726 const char __user * buffer,
727 size_t count, loff_t * data)
728 {
729 int status;
730 struct seq_file *m = (struct seq_file *)file->private_data;
731 struct acpi_video_device *dev = (struct acpi_video_device *)m->private;
732 char str[12] = { 0 };
733 u32 state = 0;
736 if (!dev || count + 1 > sizeof str)
737 return -EINVAL;
739 if (copy_from_user(str, buffer, count))
740 return -EFAULT;
742 str[count] = 0;
743 state = simple_strtoul(str, NULL, 0);
744 state &= ((1ul << 31) | (1ul << 30) | (1ul << 0));
746 status = acpi_video_device_set_state(dev, state);
748 if (status)
749 return -EFAULT;
751 return count;
752 }
754 static int
755 acpi_video_device_brightness_seq_show(struct seq_file *seq, void *offset)
756 {
757 struct acpi_video_device *dev =
758 (struct acpi_video_device *)seq->private;
759 int i;
762 if (!dev || !dev->brightness) {
763 seq_printf(seq, "<not supported>\n");
764 return 0;
765 }
767 seq_printf(seq, "levels: ");
768 for (i = 0; i < dev->brightness->count; i++)
769 seq_printf(seq, " %d", dev->brightness->levels[i]);
770 seq_printf(seq, "\ncurrent: %d\n", dev->brightness->curr);
772 return 0;
773 }
775 static int
776 acpi_video_device_brightness_open_fs(struct inode *inode, struct file *file)
777 {
778 return single_open(file, acpi_video_device_brightness_seq_show,
779 PDE(inode)->data);
780 }
782 static ssize_t
783 acpi_video_device_write_brightness(struct file *file,
784 const char __user * buffer,
785 size_t count, loff_t * data)
786 {
787 struct seq_file *m = (struct seq_file *)file->private_data;
788 struct acpi_video_device *dev = (struct acpi_video_device *)m->private;
789 char str[4] = { 0 };
790 unsigned int level = 0;
791 int i;
794 if (!dev || !dev->brightness || count + 1 > sizeof str)
795 return -EINVAL;
797 if (copy_from_user(str, buffer, count))
798 return -EFAULT;
800 str[count] = 0;
801 level = simple_strtoul(str, NULL, 0);
803 if (level > 100)
804 return -EFAULT;
806 /* validate though the list of available levels */
807 for (i = 0; i < dev->brightness->count; i++)
808 if (level == dev->brightness->levels[i]) {
809 if (ACPI_SUCCESS
810 (acpi_video_device_lcd_set_level(dev, level)))
811 dev->brightness->curr = level;
812 break;
813 }
815 return count;
816 }
818 static int acpi_video_device_EDID_seq_show(struct seq_file *seq, void *offset)
819 {
820 struct acpi_video_device *dev =
821 (struct acpi_video_device *)seq->private;
822 int status;
823 int i;
824 union acpi_object *edid = NULL;
827 if (!dev)
828 goto out;
830 status = acpi_video_device_EDID(dev, &edid, 128);
831 if (ACPI_FAILURE(status)) {
832 status = acpi_video_device_EDID(dev, &edid, 256);
833 }
835 if (ACPI_FAILURE(status)) {
836 goto out;
837 }
839 if (edid && edid->type == ACPI_TYPE_BUFFER) {
840 for (i = 0; i < edid->buffer.length; i++)
841 seq_putc(seq, edid->buffer.pointer[i]);
842 }
844 out:
845 if (!edid)
846 seq_printf(seq, "<not supported>\n");
847 else
848 kfree(edid);
850 return 0;
851 }
853 static int
854 acpi_video_device_EDID_open_fs(struct inode *inode, struct file *file)
855 {
856 return single_open(file, acpi_video_device_EDID_seq_show,
857 PDE(inode)->data);
858 }
860 static int acpi_video_device_add_fs(struct acpi_device *device)
861 {
862 struct proc_dir_entry *entry = NULL;
863 struct acpi_video_device *vid_dev;
866 if (!device)
867 return -ENODEV;
869 vid_dev = (struct acpi_video_device *)acpi_driver_data(device);
870 if (!vid_dev)
871 return -ENODEV;
873 if (!acpi_device_dir(device)) {
874 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
875 vid_dev->video->dir);
876 if (!acpi_device_dir(device))
877 return -ENODEV;
878 acpi_device_dir(device)->owner = THIS_MODULE;
879 }
881 /* 'info' [R] */
882 entry = create_proc_entry("info", S_IRUGO, acpi_device_dir(device));
883 if (!entry)
884 return -ENODEV;
885 else {
886 entry->proc_fops = &acpi_video_device_info_fops;
887 entry->data = acpi_driver_data(device);
888 entry->owner = THIS_MODULE;
889 }
891 /* 'state' [R/W] */
892 entry =
893 create_proc_entry("state", S_IFREG | S_IRUGO | S_IWUSR,
894 acpi_device_dir(device));
895 if (!entry)
896 return -ENODEV;
897 else {
898 acpi_video_device_state_fops.write = acpi_video_device_write_state;
899 entry->proc_fops = &acpi_video_device_state_fops;
900 entry->data = acpi_driver_data(device);
901 entry->owner = THIS_MODULE;
902 }
904 /* 'brightness' [R/W] */
905 entry =
906 create_proc_entry("brightness", S_IFREG | S_IRUGO | S_IWUSR,
907 acpi_device_dir(device));
908 if (!entry)
909 return -ENODEV;
910 else {
911 acpi_video_device_brightness_fops.write = acpi_video_device_write_brightness;
912 entry->proc_fops = &acpi_video_device_brightness_fops;
913 entry->data = acpi_driver_data(device);
914 entry->owner = THIS_MODULE;
915 }
917 /* 'EDID' [R] */
918 entry = create_proc_entry("EDID", S_IRUGO, acpi_device_dir(device));
919 if (!entry)
920 return -ENODEV;
921 else {
922 entry->proc_fops = &acpi_video_device_EDID_fops;
923 entry->data = acpi_driver_data(device);
924 entry->owner = THIS_MODULE;
925 }
927 return 0;
928 }
930 static int acpi_video_device_remove_fs(struct acpi_device *device)
931 {
932 struct acpi_video_device *vid_dev;
934 vid_dev = (struct acpi_video_device *)acpi_driver_data(device);
935 if (!vid_dev || !vid_dev->video || !vid_dev->video->dir)
936 return -ENODEV;
938 if (acpi_device_dir(device)) {
939 remove_proc_entry("info", acpi_device_dir(device));
940 remove_proc_entry("state", acpi_device_dir(device));
941 remove_proc_entry("brightness", acpi_device_dir(device));
942 remove_proc_entry("EDID", acpi_device_dir(device));
943 remove_proc_entry(acpi_device_bid(device), vid_dev->video->dir);
944 acpi_device_dir(device) = NULL;
945 }
947 return 0;
948 }
950 /* video bus */
951 static int acpi_video_bus_info_seq_show(struct seq_file *seq, void *offset)
952 {
953 struct acpi_video_bus *video = (struct acpi_video_bus *)seq->private;
956 if (!video)
957 goto end;
959 seq_printf(seq, "Switching heads: %s\n",
960 video->flags.multihead ? "yes" : "no");
961 seq_printf(seq, "Video ROM: %s\n",
962 video->flags.rom ? "yes" : "no");
963 seq_printf(seq, "Device to be POSTed on boot: %s\n",
964 video->flags.post ? "yes" : "no");
966 end:
967 return 0;
968 }
970 static int acpi_video_bus_info_open_fs(struct inode *inode, struct file *file)
971 {
972 return single_open(file, acpi_video_bus_info_seq_show,
973 PDE(inode)->data);
974 }
976 static int acpi_video_bus_ROM_seq_show(struct seq_file *seq, void *offset)
977 {
978 struct acpi_video_bus *video = (struct acpi_video_bus *)seq->private;
981 if (!video)
982 goto end;
984 printk(KERN_INFO PREFIX "Please implement %s\n", __FUNCTION__);
985 seq_printf(seq, "<TODO>\n");
987 end:
988 return 0;
989 }
991 static int acpi_video_bus_ROM_open_fs(struct inode *inode, struct file *file)
992 {
993 return single_open(file, acpi_video_bus_ROM_seq_show, PDE(inode)->data);
994 }
996 static int acpi_video_bus_POST_info_seq_show(struct seq_file *seq, void *offset)
997 {
998 struct acpi_video_bus *video = (struct acpi_video_bus *)seq->private;
999 unsigned long options;
1000 int status;
1003 if (!video)
1004 goto end;
1006 status = acpi_video_bus_POST_options(video, &options);
1007 if (ACPI_SUCCESS(status)) {
1008 if (!(options & 1)) {
1009 printk(KERN_WARNING PREFIX
1010 "The motherboard VGA device is not listed as a possible POST device.\n");
1011 printk(KERN_WARNING PREFIX
1012 "This indicate a BIOS bug. Please contact the manufacturer.\n");
1014 printk("%lx\n", options);
1015 seq_printf(seq, "can POST: <intgrated video>");
1016 if (options & 2)
1017 seq_printf(seq, " <PCI video>");
1018 if (options & 4)
1019 seq_printf(seq, " <AGP video>");
1020 seq_putc(seq, '\n');
1021 } else
1022 seq_printf(seq, "<not supported>\n");
1023 end:
1024 return 0;
1027 static int
1028 acpi_video_bus_POST_info_open_fs(struct inode *inode, struct file *file)
1030 return single_open(file, acpi_video_bus_POST_info_seq_show,
1031 PDE(inode)->data);
1034 static int acpi_video_bus_POST_seq_show(struct seq_file *seq, void *offset)
1036 struct acpi_video_bus *video = (struct acpi_video_bus *)seq->private;
1037 int status;
1038 unsigned long id;
1041 if (!video)
1042 goto end;
1044 status = acpi_video_bus_get_POST(video, &id);
1045 if (!ACPI_SUCCESS(status)) {
1046 seq_printf(seq, "<not supported>\n");
1047 goto end;
1049 seq_printf(seq, "device posted is <%s>\n", device_decode[id & 3]);
1051 end:
1052 return 0;
1055 static int acpi_video_bus_DOS_seq_show(struct seq_file *seq, void *offset)
1057 struct acpi_video_bus *video = (struct acpi_video_bus *)seq->private;
1060 seq_printf(seq, "DOS setting: <%d>\n", video->dos_setting);
1062 return 0;
1065 static int acpi_video_bus_POST_open_fs(struct inode *inode, struct file *file)
1067 return single_open(file, acpi_video_bus_POST_seq_show,
1068 PDE(inode)->data);
1071 static int acpi_video_bus_DOS_open_fs(struct inode *inode, struct file *file)
1073 return single_open(file, acpi_video_bus_DOS_seq_show, PDE(inode)->data);
1076 static ssize_t
1077 acpi_video_bus_write_POST(struct file *file,
1078 const char __user * buffer,
1079 size_t count, loff_t * data)
1081 int status;
1082 struct seq_file *m = (struct seq_file *)file->private_data;
1083 struct acpi_video_bus *video = (struct acpi_video_bus *)m->private;
1084 char str[12] = { 0 };
1085 unsigned long opt, options;
1088 if (!video || count + 1 > sizeof str)
1089 return -EINVAL;
1091 status = acpi_video_bus_POST_options(video, &options);
1092 if (!ACPI_SUCCESS(status))
1093 return -EINVAL;
1095 if (copy_from_user(str, buffer, count))
1096 return -EFAULT;
1098 str[count] = 0;
1099 opt = strtoul(str, NULL, 0);
1100 if (opt > 3)
1101 return -EFAULT;
1103 /* just in case an OEM 'forget' the motherboard... */
1104 options |= 1;
1106 if (options & (1ul << opt)) {
1107 status = acpi_video_bus_set_POST(video, opt);
1108 if (!ACPI_SUCCESS(status))
1109 return -EFAULT;
1113 return count;
1116 static ssize_t
1117 acpi_video_bus_write_DOS(struct file *file,
1118 const char __user * buffer,
1119 size_t count, loff_t * data)
1121 int status;
1122 struct seq_file *m = (struct seq_file *)file->private_data;
1123 struct acpi_video_bus *video = (struct acpi_video_bus *)m->private;
1124 char str[12] = { 0 };
1125 unsigned long opt;
1128 if (!video || count + 1 > sizeof str)
1129 return -EINVAL;
1131 if (copy_from_user(str, buffer, count))
1132 return -EFAULT;
1134 str[count] = 0;
1135 opt = strtoul(str, NULL, 0);
1136 if (opt > 7)
1137 return -EFAULT;
1139 status = acpi_video_bus_DOS(video, opt & 0x3, (opt & 0x4) >> 2);
1141 if (!ACPI_SUCCESS(status))
1142 return -EFAULT;
1144 return count;
1147 static int acpi_video_bus_add_fs(struct acpi_device *device)
1149 struct proc_dir_entry *entry = NULL;
1150 struct acpi_video_bus *video;
1153 video = (struct acpi_video_bus *)acpi_driver_data(device);
1155 if (!acpi_device_dir(device)) {
1156 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
1157 acpi_video_dir);
1158 if (!acpi_device_dir(device))
1159 return -ENODEV;
1160 video->dir = acpi_device_dir(device);
1161 acpi_device_dir(device)->owner = THIS_MODULE;
1164 /* 'info' [R] */
1165 entry = create_proc_entry("info", S_IRUGO, acpi_device_dir(device));
1166 if (!entry)
1167 return -ENODEV;
1168 else {
1169 entry->proc_fops = &acpi_video_bus_info_fops;
1170 entry->data = acpi_driver_data(device);
1171 entry->owner = THIS_MODULE;
1174 /* 'ROM' [R] */
1175 entry = create_proc_entry("ROM", S_IRUGO, acpi_device_dir(device));
1176 if (!entry)
1177 return -ENODEV;
1178 else {
1179 entry->proc_fops = &acpi_video_bus_ROM_fops;
1180 entry->data = acpi_driver_data(device);
1181 entry->owner = THIS_MODULE;
1184 /* 'POST_info' [R] */
1185 entry =
1186 create_proc_entry("POST_info", S_IRUGO, acpi_device_dir(device));
1187 if (!entry)
1188 return -ENODEV;
1189 else {
1190 entry->proc_fops = &acpi_video_bus_POST_info_fops;
1191 entry->data = acpi_driver_data(device);
1192 entry->owner = THIS_MODULE;
1195 /* 'POST' [R/W] */
1196 entry =
1197 create_proc_entry("POST", S_IFREG | S_IRUGO | S_IRUSR,
1198 acpi_device_dir(device));
1199 if (!entry)
1200 return -ENODEV;
1201 else {
1202 acpi_video_bus_POST_fops.write = acpi_video_bus_write_POST;
1203 entry->proc_fops = &acpi_video_bus_POST_fops;
1204 entry->data = acpi_driver_data(device);
1205 entry->owner = THIS_MODULE;
1208 /* 'DOS' [R/W] */
1209 entry =
1210 create_proc_entry("DOS", S_IFREG | S_IRUGO | S_IRUSR,
1211 acpi_device_dir(device));
1212 if (!entry)
1213 return -ENODEV;
1214 else {
1215 acpi_video_bus_DOS_fops.write = acpi_video_bus_write_DOS;
1216 entry->proc_fops = &acpi_video_bus_DOS_fops;
1217 entry->data = acpi_driver_data(device);
1218 entry->owner = THIS_MODULE;
1221 return 0;
1224 static int acpi_video_bus_remove_fs(struct acpi_device *device)
1226 struct acpi_video_bus *video;
1229 video = (struct acpi_video_bus *)acpi_driver_data(device);
1231 if (acpi_device_dir(device)) {
1232 remove_proc_entry("info", acpi_device_dir(device));
1233 remove_proc_entry("ROM", acpi_device_dir(device));
1234 remove_proc_entry("POST_info", acpi_device_dir(device));
1235 remove_proc_entry("POST", acpi_device_dir(device));
1236 remove_proc_entry("DOS", acpi_device_dir(device));
1237 remove_proc_entry(acpi_device_bid(device), acpi_video_dir);
1238 acpi_device_dir(device) = NULL;
1241 return 0;
1244 /* --------------------------------------------------------------------------
1245 Driver Interface
1246 -------------------------------------------------------------------------- */
1248 /* device interface */
1250 static int
1251 acpi_video_bus_get_one_device(struct acpi_device *device,
1252 struct acpi_video_bus *video)
1254 unsigned long device_id;
1255 int status;
1256 struct acpi_video_device *data;
1259 if (!device || !video)
1260 return -EINVAL;
1262 status =
1263 acpi_evaluate_integer(device->handle, "_ADR", NULL, &device_id);
1264 if (ACPI_SUCCESS(status)) {
1266 data = kmalloc(sizeof(struct acpi_video_device), GFP_KERNEL);
1267 if (!data)
1268 return -ENOMEM;
1270 memset(data, 0, sizeof(struct acpi_video_device));
1272 strcpy(acpi_device_name(device), ACPI_VIDEO_DEVICE_NAME);
1273 strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS);
1274 acpi_driver_data(device) = data;
1276 data->device_id = device_id;
1277 data->video = video;
1278 data->dev = device;
1280 switch (device_id & 0xffff) {
1281 case 0x0100:
1282 data->flags.crt = 1;
1283 break;
1284 case 0x0400:
1285 data->flags.lcd = 1;
1286 break;
1287 case 0x0200:
1288 data->flags.tvout = 1;
1289 break;
1290 default:
1291 data->flags.unknown = 1;
1292 break;
1295 acpi_video_device_bind(video, data);
1296 acpi_video_device_find_cap(data);
1298 status = acpi_install_notify_handler(device->handle,
1299 ACPI_DEVICE_NOTIFY,
1300 acpi_video_device_notify,
1301 data);
1302 if (ACPI_FAILURE(status)) {
1303 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1304 "Error installing notify handler\n"));
1305 if(data->brightness)
1306 kfree(data->brightness->levels);
1307 kfree(data->brightness);
1308 kfree(data);
1309 return -ENODEV;
1312 down(&video->sem);
1313 list_add_tail(&data->entry, &video->video_device_list);
1314 up(&video->sem);
1316 acpi_video_device_add_fs(device);
1318 return 0;
1321 return -ENOENT;
1324 /*
1325 * Arg:
1326 * video : video bus device
1328 * Return:
1329 * none
1331 * Enumerate the video device list of the video bus,
1332 * bind the ids with the corresponding video devices
1333 * under the video bus.
1334 */
1336 static void acpi_video_device_rebind(struct acpi_video_bus *video)
1338 struct list_head *node, *next;
1339 list_for_each_safe(node, next, &video->video_device_list) {
1340 struct acpi_video_device *dev =
1341 container_of(node, struct acpi_video_device, entry);
1342 acpi_video_device_bind(video, dev);
1346 /*
1347 * Arg:
1348 * video : video bus device
1349 * device : video output device under the video
1350 * bus
1352 * Return:
1353 * none
1355 * Bind the ids with the corresponding video devices
1356 * under the video bus.
1357 */
1359 static void
1360 acpi_video_device_bind(struct acpi_video_bus *video,
1361 struct acpi_video_device *device)
1363 int i;
1365 #define IDS_VAL(i) video->attached_array[i].value.int_val
1366 #define IDS_BIND(i) video->attached_array[i].bind_info
1368 for (i = 0; IDS_VAL(i) != ACPI_VIDEO_HEAD_INVALID &&
1369 i < video->attached_count; i++) {
1370 if (device->device_id == (IDS_VAL(i) & 0xffff)) {
1371 IDS_BIND(i) = device;
1372 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "device_bind %d\n", i));
1375 #undef IDS_VAL
1376 #undef IDS_BIND
1379 /*
1380 * Arg:
1381 * video : video bus device
1383 * Return:
1384 * < 0 : error
1386 * Call _DOD to enumerate all devices attached to display adapter
1388 */
1390 static int acpi_video_device_enumerate(struct acpi_video_bus *video)
1392 int status;
1393 int count;
1394 int i;
1395 struct acpi_video_enumerated_device *active_device_list;
1396 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
1397 union acpi_object *dod = NULL;
1398 union acpi_object *obj;
1400 status = acpi_evaluate_object(video->device->handle, "_DOD", NULL, &buffer);
1401 if (!ACPI_SUCCESS(status)) {
1402 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _DOD"));
1403 return status;
1406 dod = (union acpi_object *)buffer.pointer;
1407 if (!dod || (dod->type != ACPI_TYPE_PACKAGE)) {
1408 ACPI_EXCEPTION((AE_INFO, status, "Invalid _DOD data"));
1409 status = -EFAULT;
1410 goto out;
1413 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d video heads in _DOD\n",
1414 dod->package.count));
1416 active_device_list = kmalloc((1 +
1417 dod->package.count) *
1418 sizeof(struct
1419 acpi_video_enumerated_device),
1420 GFP_KERNEL);
1422 if (!active_device_list) {
1423 status = -ENOMEM;
1424 goto out;
1427 count = 0;
1428 for (i = 0; i < dod->package.count; i++) {
1429 obj = (union acpi_object *)&dod->package.elements[i];
1431 if (obj->type != ACPI_TYPE_INTEGER) {
1432 printk(KERN_ERR PREFIX "Invalid _DOD data\n");
1433 active_device_list[i].value.int_val =
1434 ACPI_VIDEO_HEAD_INVALID;
1436 active_device_list[i].value.int_val = obj->integer.value;
1437 active_device_list[i].bind_info = NULL;
1438 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "dod element[%d] = %d\n", i,
1439 (int)obj->integer.value));
1440 count++;
1442 active_device_list[count].value.int_val = ACPI_VIDEO_HEAD_END;
1444 kfree(video->attached_array);
1446 video->attached_array = active_device_list;
1447 video->attached_count = count;
1448 out:
1449 kfree(buffer.pointer);
1450 return status;
1453 /*
1454 * Arg:
1455 * video : video bus device
1456 * event : Nontify Event
1458 * Return:
1459 * < 0 : error
1461 * 1. Find out the current active output device.
1462 * 2. Identify the next output device to switch
1463 * 3. call _DSS to do actual switch.
1464 */
1466 static int acpi_video_switch_output(struct acpi_video_bus *video, int event)
1468 struct list_head *node, *next;
1469 struct acpi_video_device *dev = NULL;
1470 struct acpi_video_device *dev_next = NULL;
1471 struct acpi_video_device *dev_prev = NULL;
1472 unsigned long state;
1473 int status = 0;
1476 list_for_each_safe(node, next, &video->video_device_list) {
1477 dev = container_of(node, struct acpi_video_device, entry);
1478 status = acpi_video_device_get_state(dev, &state);
1479 if (state & 0x2) {
1480 dev_next =
1481 container_of(node->next, struct acpi_video_device,
1482 entry);
1483 dev_prev =
1484 container_of(node->prev, struct acpi_video_device,
1485 entry);
1486 goto out;
1489 dev_next = container_of(node->next, struct acpi_video_device, entry);
1490 dev_prev = container_of(node->prev, struct acpi_video_device, entry);
1491 out:
1492 switch (event) {
1493 case ACPI_VIDEO_NOTIFY_CYCLE:
1494 case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT:
1495 acpi_video_device_set_state(dev, 0);
1496 acpi_video_device_set_state(dev_next, 0x80000001);
1497 break;
1498 case ACPI_VIDEO_NOTIFY_PREV_OUTPUT:
1499 acpi_video_device_set_state(dev, 0);
1500 acpi_video_device_set_state(dev_prev, 0x80000001);
1501 default:
1502 break;
1505 return status;
1508 static int
1509 acpi_video_get_next_level(struct acpi_video_device *device,
1510 u32 level_current, u32 event)
1512 /*Fix me */
1513 return level_current;
1516 static void
1517 acpi_video_switch_brightness(struct acpi_video_device *device, int event)
1519 unsigned long level_current, level_next;
1520 acpi_video_device_lcd_get_level_current(device, &level_current);
1521 level_next = acpi_video_get_next_level(device, level_current, event);
1522 acpi_video_device_lcd_set_level(device, level_next);
1525 static int
1526 acpi_video_bus_get_devices(struct acpi_video_bus *video,
1527 struct acpi_device *device)
1529 int status = 0;
1530 struct list_head *node, *next;
1533 acpi_video_device_enumerate(video);
1535 list_for_each_safe(node, next, &device->children) {
1536 struct acpi_device *dev =
1537 list_entry(node, struct acpi_device, node);
1539 if (!dev)
1540 continue;
1542 status = acpi_video_bus_get_one_device(dev, video);
1543 if (ACPI_FAILURE(status)) {
1544 ACPI_EXCEPTION((AE_INFO, status, "Cant attach device"));
1545 continue;
1549 return status;
1552 static int acpi_video_bus_put_one_device(struct acpi_video_device *device)
1554 acpi_status status;
1555 struct acpi_video_bus *video;
1558 if (!device || !device->video)
1559 return -ENOENT;
1561 video = device->video;
1563 down(&video->sem);
1564 list_del(&device->entry);
1565 up(&video->sem);
1566 acpi_video_device_remove_fs(device->dev);
1568 status = acpi_remove_notify_handler(device->dev->handle,
1569 ACPI_DEVICE_NOTIFY,
1570 acpi_video_device_notify);
1572 return 0;
1575 static int acpi_video_bus_put_devices(struct acpi_video_bus *video)
1577 int status;
1578 struct list_head *node, *next;
1581 list_for_each_safe(node, next, &video->video_device_list) {
1582 struct acpi_video_device *data =
1583 list_entry(node, struct acpi_video_device, entry);
1584 if (!data)
1585 continue;
1587 status = acpi_video_bus_put_one_device(data);
1588 if (ACPI_FAILURE(status))
1589 printk(KERN_WARNING PREFIX
1590 "hhuuhhuu bug in acpi video driver.\n");
1592 if (data->brightness)
1593 kfree(data->brightness->levels);
1594 kfree(data->brightness);
1595 kfree(data);
1598 return 0;
1601 /* acpi_video interface */
1603 static int acpi_video_bus_start_devices(struct acpi_video_bus *video)
1605 return acpi_video_bus_DOS(video, 1, 0);
1608 static int acpi_video_bus_stop_devices(struct acpi_video_bus *video)
1610 return acpi_video_bus_DOS(video, 0, 1);
1613 static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data)
1615 struct acpi_video_bus *video = (struct acpi_video_bus *)data;
1616 struct acpi_device *device = NULL;
1618 printk("video bus notify\n");
1620 if (!video)
1621 return;
1623 device = video->device;
1625 switch (event) {
1626 case ACPI_VIDEO_NOTIFY_SWITCH: /* User request that a switch occur,
1627 * most likely via hotkey. */
1628 acpi_bus_generate_event(device, event, 0);
1629 break;
1631 case ACPI_VIDEO_NOTIFY_PROBE: /* User plug or remove a video
1632 * connector. */
1633 acpi_video_device_enumerate(video);
1634 acpi_video_device_rebind(video);
1635 acpi_video_switch_output(video, event);
1636 acpi_bus_generate_event(device, event, 0);
1637 break;
1639 case ACPI_VIDEO_NOTIFY_CYCLE: /* Cycle Display output hotkey pressed. */
1640 case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT: /* Next Display output hotkey pressed. */
1641 case ACPI_VIDEO_NOTIFY_PREV_OUTPUT: /* previous Display output hotkey pressed. */
1642 acpi_video_switch_output(video, event);
1643 acpi_bus_generate_event(device, event, 0);
1644 break;
1646 default:
1647 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
1648 "Unsupported event [0x%x]\n", event));
1649 break;
1652 return;
1655 static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data)
1657 struct acpi_video_device *video_device =
1658 (struct acpi_video_device *)data;
1659 struct acpi_device *device = NULL;
1662 printk("video device notify\n");
1663 if (!video_device)
1664 return;
1666 device = video_device->dev;
1668 switch (event) {
1669 case ACPI_VIDEO_NOTIFY_SWITCH: /* change in status (cycle output device) */
1670 case ACPI_VIDEO_NOTIFY_PROBE: /* change in status (output device status) */
1671 acpi_bus_generate_event(device, event, 0);
1672 break;
1673 case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS: /* Cycle brightness */
1674 case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS: /* Increase brightness */
1675 case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS: /* Decrease brightness */
1676 case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS: /* zero brightnesss */
1677 case ACPI_VIDEO_NOTIFY_DISPLAY_OFF: /* display device off */
1678 acpi_video_switch_brightness(video_device, event);
1679 acpi_bus_generate_event(device, event, 0);
1680 break;
1681 default:
1682 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
1683 "Unsupported event [0x%x]\n", event));
1684 break;
1686 return;
1689 static int acpi_video_bus_add(struct acpi_device *device)
1691 int result = 0;
1692 acpi_status status = 0;
1693 struct acpi_video_bus *video = NULL;
1696 if (!device)
1697 return -EINVAL;
1699 video = kmalloc(sizeof(struct acpi_video_bus), GFP_KERNEL);
1700 if (!video)
1701 return -ENOMEM;
1702 memset(video, 0, sizeof(struct acpi_video_bus));
1704 video->device = device;
1705 strcpy(acpi_device_name(device), ACPI_VIDEO_BUS_NAME);
1706 strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS);
1707 acpi_driver_data(device) = video;
1709 acpi_video_bus_find_cap(video);
1710 result = acpi_video_bus_check(video);
1711 if (result)
1712 goto end;
1714 result = acpi_video_bus_add_fs(device);
1715 if (result)
1716 goto end;
1718 init_MUTEX(&video->sem);
1719 INIT_LIST_HEAD(&video->video_device_list);
1721 acpi_video_bus_get_devices(video, device);
1722 acpi_video_bus_start_devices(video);
1724 status = acpi_install_notify_handler(device->handle,
1725 ACPI_DEVICE_NOTIFY,
1726 acpi_video_bus_notify, video);
1727 if (ACPI_FAILURE(status)) {
1728 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1729 "Error installing notify handler\n"));
1730 acpi_video_bus_stop_devices(video);
1731 acpi_video_bus_put_devices(video);
1732 kfree(video->attached_array);
1733 acpi_video_bus_remove_fs(device);
1734 result = -ENODEV;
1735 goto end;
1738 printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s rom: %s post: %s)\n",
1739 ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device),
1740 video->flags.multihead ? "yes" : "no",
1741 video->flags.rom ? "yes" : "no",
1742 video->flags.post ? "yes" : "no");
1744 end:
1745 if (result)
1746 kfree(video);
1748 return result;
1751 static int acpi_video_bus_remove(struct acpi_device *device, int type)
1753 acpi_status status = 0;
1754 struct acpi_video_bus *video = NULL;
1757 if (!device || !acpi_driver_data(device))
1758 return -EINVAL;
1760 video = (struct acpi_video_bus *)acpi_driver_data(device);
1762 acpi_video_bus_stop_devices(video);
1764 status = acpi_remove_notify_handler(video->device->handle,
1765 ACPI_DEVICE_NOTIFY,
1766 acpi_video_bus_notify);
1768 acpi_video_bus_put_devices(video);
1769 acpi_video_bus_remove_fs(device);
1771 kfree(video->attached_array);
1772 kfree(video);
1774 return 0;
1777 static int
1778 acpi_video_bus_match(struct acpi_device *device, struct acpi_driver *driver)
1780 acpi_handle h_dummy1;
1781 acpi_handle h_dummy2;
1782 acpi_handle h_dummy3;
1785 if (!device || !driver)
1786 return -EINVAL;
1788 /* Since there is no HID, CID for ACPI Video drivers, we have
1789 * to check well known required nodes for each feature we support.
1790 */
1792 /* Does this device able to support video switching ? */
1793 if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOD", &h_dummy1)) &&
1794 ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOS", &h_dummy2)))
1795 return 0;
1797 /* Does this device able to retrieve a video ROM ? */
1798 if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_ROM", &h_dummy1)))
1799 return 0;
1801 /* Does this device able to configure which video head to be POSTed ? */
1802 if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_VPO", &h_dummy1)) &&
1803 ACPI_SUCCESS(acpi_get_handle(device->handle, "_GPD", &h_dummy2)) &&
1804 ACPI_SUCCESS(acpi_get_handle(device->handle, "_SPD", &h_dummy3)))
1805 return 0;
1807 return -ENODEV;
1810 static int __init acpi_video_init(void)
1812 int result = 0;
1815 /*
1816 acpi_dbg_level = 0xFFFFFFFF;
1817 acpi_dbg_layer = 0x08000000;
1818 */
1820 acpi_video_dir = proc_mkdir(ACPI_VIDEO_CLASS, acpi_root_dir);
1821 if (!acpi_video_dir)
1822 return -ENODEV;
1823 acpi_video_dir->owner = THIS_MODULE;
1825 result = acpi_bus_register_driver(&acpi_video_bus);
1826 if (result < 0) {
1827 remove_proc_entry(ACPI_VIDEO_CLASS, acpi_root_dir);
1828 return -ENODEV;
1831 return 0;
1834 static void __exit acpi_video_exit(void)
1837 acpi_bus_unregister_driver(&acpi_video_bus);
1839 remove_proc_entry(ACPI_VIDEO_CLASS, acpi_root_dir);
1841 return;
1844 module_init(acpi_video_init);
1845 module_exit(acpi_video_exit);