aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/video.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/video.c')
-rw-r--r--drivers/acpi/video.c166
1 files changed, 113 insertions, 53 deletions
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index 3d54680d0333..e0b97add8c63 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -32,6 +32,7 @@
32#include <linux/proc_fs.h> 32#include <linux/proc_fs.h>
33#include <linux/seq_file.h> 33#include <linux/seq_file.h>
34 34
35#include <linux/backlight.h>
35#include <asm/uaccess.h> 36#include <asm/uaccess.h>
36 37
37#include <acpi/acpi_bus.h> 38#include <acpi/acpi_bus.h>
@@ -56,6 +57,12 @@
56 57
57#define ACPI_VIDEO_HEAD_INVALID (~0u - 1) 58#define ACPI_VIDEO_HEAD_INVALID (~0u - 1)
58#define ACPI_VIDEO_HEAD_END (~0u) 59#define ACPI_VIDEO_HEAD_END (~0u)
60#define MAX_NAME_LEN 20
61
62#define ACPI_VIDEO_DISPLAY_CRT 1
63#define ACPI_VIDEO_DISPLAY_TV 2
64#define ACPI_VIDEO_DISPLAY_DVI 3
65#define ACPI_VIDEO_DISPLAY_LCD 4
59 66
60#define _COMPONENT ACPI_VIDEO_COMPONENT 67#define _COMPONENT ACPI_VIDEO_COMPONENT
61ACPI_MODULE_NAME("acpi_video") 68ACPI_MODULE_NAME("acpi_video")
@@ -66,16 +73,14 @@ MODULE_LICENSE("GPL");
66 73
67static int acpi_video_bus_add(struct acpi_device *device); 74static int acpi_video_bus_add(struct acpi_device *device);
68static int acpi_video_bus_remove(struct acpi_device *device, int type); 75static int acpi_video_bus_remove(struct acpi_device *device, int type);
69static int acpi_video_bus_match(struct acpi_device *device,
70 struct acpi_driver *driver);
71 76
72static struct acpi_driver acpi_video_bus = { 77static struct acpi_driver acpi_video_bus = {
73 .name = ACPI_VIDEO_DRIVER_NAME, 78 .name = ACPI_VIDEO_DRIVER_NAME,
74 .class = ACPI_VIDEO_CLASS, 79 .class = ACPI_VIDEO_CLASS,
80 .ids = ACPI_VIDEO_HID,
75 .ops = { 81 .ops = {
76 .add = acpi_video_bus_add, 82 .add = acpi_video_bus_add,
77 .remove = acpi_video_bus_remove, 83 .remove = acpi_video_bus_remove,
78 .match = acpi_video_bus_match,
79 }, 84 },
80}; 85};
81 86
@@ -133,20 +138,21 @@ struct acpi_video_device_flags {
133 u8 crt:1; 138 u8 crt:1;
134 u8 lcd:1; 139 u8 lcd:1;
135 u8 tvout:1; 140 u8 tvout:1;
141 u8 dvi:1;
136 u8 bios:1; 142 u8 bios:1;
137 u8 unknown:1; 143 u8 unknown:1;
138 u8 reserved:3; 144 u8 reserved:2;
139}; 145};
140 146
141struct acpi_video_device_cap { 147struct acpi_video_device_cap {
142 u8 _ADR:1; /*Return the unique ID */ 148 u8 _ADR:1; /*Return the unique ID */
143 u8 _BCL:1; /*Query list of brightness control levels supported */ 149 u8 _BCL:1; /*Query list of brightness control levels supported */
144 u8 _BCM:1; /*Set the brightness level */ 150 u8 _BCM:1; /*Set the brightness level */
151 u8 _BQC:1; /* Get current brightness level */
145 u8 _DDC:1; /*Return the EDID for this device */ 152 u8 _DDC:1; /*Return the EDID for this device */
146 u8 _DCS:1; /*Return status of output device */ 153 u8 _DCS:1; /*Return status of output device */
147 u8 _DGS:1; /*Query graphics state */ 154 u8 _DGS:1; /*Query graphics state */
148 u8 _DSS:1; /*Device state set */ 155 u8 _DSS:1; /*Device state set */
149 u8 _reserved:1;
150}; 156};
151 157
152struct acpi_video_device_brightness { 158struct acpi_video_device_brightness {
@@ -163,6 +169,8 @@ struct acpi_video_device {
163 struct acpi_video_bus *video; 169 struct acpi_video_bus *video;
164 struct acpi_device *dev; 170 struct acpi_device *dev;
165 struct acpi_video_device_brightness *brightness; 171 struct acpi_video_device_brightness *brightness;
172 struct backlight_device *backlight;
173 struct backlight_properties *data;
166}; 174};
167 175
168/* bus */ 176/* bus */
@@ -257,11 +265,35 @@ static void acpi_video_device_bind(struct acpi_video_bus *video,
257 struct acpi_video_device *device); 265 struct acpi_video_device *device);
258static int acpi_video_device_enumerate(struct acpi_video_bus *video); 266static int acpi_video_device_enumerate(struct acpi_video_bus *video);
259static int acpi_video_switch_output(struct acpi_video_bus *video, int event); 267static int acpi_video_switch_output(struct acpi_video_bus *video, int event);
268static int acpi_video_device_lcd_set_level(struct acpi_video_device *device,
269 int level);
270static int acpi_video_device_lcd_get_level_current(
271 struct acpi_video_device *device,
272 unsigned long *level);
260static int acpi_video_get_next_level(struct acpi_video_device *device, 273static int acpi_video_get_next_level(struct acpi_video_device *device,
261 u32 level_current, u32 event); 274 u32 level_current, u32 event);
262static void acpi_video_switch_brightness(struct acpi_video_device *device, 275static void acpi_video_switch_brightness(struct acpi_video_device *device,
263 int event); 276 int event);
264 277
278/*backlight device sysfs support*/
279static int acpi_video_get_brightness(struct backlight_device *bd)
280{
281 unsigned long cur_level;
282 struct acpi_video_device *vd =
283 (struct acpi_video_device *)class_get_devdata(&bd->class_dev);
284 acpi_video_device_lcd_get_level_current(vd, &cur_level);
285 return (int) cur_level;
286}
287
288static int acpi_video_set_brightness(struct backlight_device *bd)
289{
290 int request_level = bd->props->brightness;
291 struct acpi_video_device *vd =
292 (struct acpi_video_device *)class_get_devdata(&bd->class_dev);
293 acpi_video_device_lcd_set_level(vd, request_level);
294 return 0;
295}
296
265/* -------------------------------------------------------------------------- 297/* --------------------------------------------------------------------------
266 Video Management 298 Video Management
267 -------------------------------------------------------------------------- */ 299 -------------------------------------------------------------------------- */
@@ -499,6 +531,7 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
499 acpi_integer status; 531 acpi_integer status;
500 acpi_handle h_dummy1; 532 acpi_handle h_dummy1;
501 int i; 533 int i;
534 u32 max_level = 0;
502 union acpi_object *obj = NULL; 535 union acpi_object *obj = NULL;
503 struct acpi_video_device_brightness *br = NULL; 536 struct acpi_video_device_brightness *br = NULL;
504 537
@@ -514,6 +547,8 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
514 if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_BCM", &h_dummy1))) { 547 if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_BCM", &h_dummy1))) {
515 device->cap._BCM = 1; 548 device->cap._BCM = 1;
516 } 549 }
550 if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle,"_BQC",&h_dummy1)))
551 device->cap._BQC = 1;
517 if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DDC", &h_dummy1))) { 552 if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DDC", &h_dummy1))) {
518 device->cap._DDC = 1; 553 device->cap._DDC = 1;
519 } 554 }
@@ -550,6 +585,8 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
550 continue; 585 continue;
551 } 586 }
552 br->levels[count] = (u32) o->integer.value; 587 br->levels[count] = (u32) o->integer.value;
588 if (br->levels[count] > max_level)
589 max_level = br->levels[count];
553 count++; 590 count++;
554 } 591 }
555 out: 592 out:
@@ -568,6 +605,37 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
568 605
569 kfree(obj); 606 kfree(obj);
570 607
608 if (device->cap._BCL && device->cap._BCM && device->cap._BQC){
609 unsigned long tmp;
610 static int count = 0;
611 char *name;
612 struct backlight_properties *acpi_video_data;
613
614 name = kzalloc(MAX_NAME_LEN, GFP_KERNEL);
615 if (!name)
616 return;
617
618 acpi_video_data = kzalloc(
619 sizeof(struct backlight_properties),
620 GFP_KERNEL);
621 if (!acpi_video_data){
622 kfree(name);
623 return;
624 }
625 acpi_video_data->owner = THIS_MODULE;
626 acpi_video_data->get_brightness =
627 acpi_video_get_brightness;
628 acpi_video_data->update_status =
629 acpi_video_set_brightness;
630 sprintf(name, "acpi_video%d", count++);
631 device->data = acpi_video_data;
632 acpi_video_data->max_brightness = max_level;
633 acpi_video_device_lcd_get_level_current(device, &tmp);
634 acpi_video_data->brightness = (int)tmp;
635 device->backlight = backlight_device_register(name,
636 NULL, device, acpi_video_data);
637 kfree(name);
638 }
571 return; 639 return;
572} 640}
573 641
@@ -668,6 +736,8 @@ static int acpi_video_device_info_seq_show(struct seq_file *seq, void *offset)
668 seq_printf(seq, "LCD\n"); 736 seq_printf(seq, "LCD\n");
669 else if (dev->flags.tvout) 737 else if (dev->flags.tvout)
670 seq_printf(seq, "TVOUT\n"); 738 seq_printf(seq, "TVOUT\n");
739 else if (dev->flags.dvi)
740 seq_printf(seq, "DVI\n");
671 else 741 else
672 seq_printf(seq, "UNKNOWN\n"); 742 seq_printf(seq, "UNKNOWN\n");
673 743
@@ -1242,6 +1312,16 @@ static int acpi_video_bus_remove_fs(struct acpi_device *device)
1242 -------------------------------------------------------------------------- */ 1312 -------------------------------------------------------------------------- */
1243 1313
1244/* device interface */ 1314/* device interface */
1315static struct acpi_video_device_attrib*
1316acpi_video_get_device_attr(struct acpi_video_bus *video, unsigned long device_id)
1317{
1318 int count;
1319
1320 for(count = 0; count < video->attached_count; count++)
1321 if((video->attached_array[count].value.int_val & 0xffff) == device_id)
1322 return &(video->attached_array[count].value.attrib);
1323 return NULL;
1324}
1245 1325
1246static int 1326static int
1247acpi_video_bus_get_one_device(struct acpi_device *device, 1327acpi_video_bus_get_one_device(struct acpi_device *device,
@@ -1250,7 +1330,7 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
1250 unsigned long device_id; 1330 unsigned long device_id;
1251 int status; 1331 int status;
1252 struct acpi_video_device *data; 1332 struct acpi_video_device *data;
1253 1333 struct acpi_video_device_attrib* attribute;
1254 1334
1255 if (!device || !video) 1335 if (!device || !video)
1256 return -EINVAL; 1336 return -EINVAL;
@@ -1271,20 +1351,30 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
1271 data->video = video; 1351 data->video = video;
1272 data->dev = device; 1352 data->dev = device;
1273 1353
1274 switch (device_id & 0xffff) { 1354 attribute = acpi_video_get_device_attr(video, device_id);
1275 case 0x0100: 1355
1276 data->flags.crt = 1; 1356 if((attribute != NULL) && attribute->device_id_scheme) {
1277 break; 1357 switch (attribute->display_type) {
1278 case 0x0400: 1358 case ACPI_VIDEO_DISPLAY_CRT:
1279 data->flags.lcd = 1; 1359 data->flags.crt = 1;
1280 break; 1360 break;
1281 case 0x0200: 1361 case ACPI_VIDEO_DISPLAY_TV:
1282 data->flags.tvout = 1; 1362 data->flags.tvout = 1;
1283 break; 1363 break;
1284 default: 1364 case ACPI_VIDEO_DISPLAY_DVI:
1365 data->flags.dvi = 1;
1366 break;
1367 case ACPI_VIDEO_DISPLAY_LCD:
1368 data->flags.lcd = 1;
1369 break;
1370 default:
1371 data->flags.unknown = 1;
1372 break;
1373 }
1374 if(attribute->bios_can_detect)
1375 data->flags.bios = 1;
1376 } else
1285 data->flags.unknown = 1; 1377 data->flags.unknown = 1;
1286 break;
1287 }
1288 1378
1289 acpi_video_device_bind(video, data); 1379 acpi_video_device_bind(video, data);
1290 acpi_video_device_find_cap(data); 1380 acpi_video_device_find_cap(data);
@@ -1588,7 +1678,10 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device)
1588 status = acpi_remove_notify_handler(device->dev->handle, 1678 status = acpi_remove_notify_handler(device->dev->handle,
1589 ACPI_DEVICE_NOTIFY, 1679 ACPI_DEVICE_NOTIFY,
1590 acpi_video_device_notify); 1680 acpi_video_device_notify);
1591 1681 if (device->backlight){
1682 backlight_device_unregister(device->backlight);
1683 kfree(device->data);
1684 }
1592 return 0; 1685 return 0;
1593} 1686}
1594 1687
@@ -1790,39 +1883,6 @@ static int acpi_video_bus_remove(struct acpi_device *device, int type)
1790 return 0; 1883 return 0;
1791} 1884}
1792 1885
1793static int
1794acpi_video_bus_match(struct acpi_device *device, struct acpi_driver *driver)
1795{
1796 acpi_handle h_dummy1;
1797 acpi_handle h_dummy2;
1798 acpi_handle h_dummy3;
1799
1800
1801 if (!device || !driver)
1802 return -EINVAL;
1803
1804 /* Since there is no HID, CID for ACPI Video drivers, we have
1805 * to check well known required nodes for each feature we support.
1806 */
1807
1808 /* Does this device able to support video switching ? */
1809 if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOD", &h_dummy1)) &&
1810 ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOS", &h_dummy2)))
1811 return 0;
1812
1813 /* Does this device able to retrieve a video ROM ? */
1814 if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_ROM", &h_dummy1)))
1815 return 0;
1816
1817 /* Does this device able to configure which video head to be POSTed ? */
1818 if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_VPO", &h_dummy1)) &&
1819 ACPI_SUCCESS(acpi_get_handle(device->handle, "_GPD", &h_dummy2)) &&
1820 ACPI_SUCCESS(acpi_get_handle(device->handle, "_SPD", &h_dummy3)))
1821 return 0;
1822
1823 return -ENODEV;
1824}
1825
1826static int __init acpi_video_init(void) 1886static int __init acpi_video_init(void)
1827{ 1887{
1828 int result = 0; 1888 int result = 0;