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.c129
1 files changed, 112 insertions, 17 deletions
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index 3d54680d0333..a695aeb8b2a7 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")
@@ -133,20 +140,21 @@ struct acpi_video_device_flags {
133 u8 crt:1; 140 u8 crt:1;
134 u8 lcd:1; 141 u8 lcd:1;
135 u8 tvout:1; 142 u8 tvout:1;
143 u8 dvi:1;
136 u8 bios:1; 144 u8 bios:1;
137 u8 unknown:1; 145 u8 unknown:1;
138 u8 reserved:3; 146 u8 reserved:2;
139}; 147};
140 148
141struct acpi_video_device_cap { 149struct acpi_video_device_cap {
142 u8 _ADR:1; /*Return the unique ID */ 150 u8 _ADR:1; /*Return the unique ID */
143 u8 _BCL:1; /*Query list of brightness control levels supported */ 151 u8 _BCL:1; /*Query list of brightness control levels supported */
144 u8 _BCM:1; /*Set the brightness level */ 152 u8 _BCM:1; /*Set the brightness level */
153 u8 _BQC:1; /* Get current brightness level */
145 u8 _DDC:1; /*Return the EDID for this device */ 154 u8 _DDC:1; /*Return the EDID for this device */
146 u8 _DCS:1; /*Return status of output device */ 155 u8 _DCS:1; /*Return status of output device */
147 u8 _DGS:1; /*Query graphics state */ 156 u8 _DGS:1; /*Query graphics state */
148 u8 _DSS:1; /*Device state set */ 157 u8 _DSS:1; /*Device state set */
149 u8 _reserved:1;
150}; 158};
151 159
152struct acpi_video_device_brightness { 160struct acpi_video_device_brightness {
@@ -163,6 +171,8 @@ struct acpi_video_device {
163 struct acpi_video_bus *video; 171 struct acpi_video_bus *video;
164 struct acpi_device *dev; 172 struct acpi_device *dev;
165 struct acpi_video_device_brightness *brightness; 173 struct acpi_video_device_brightness *brightness;
174 struct backlight_device *backlight;
175 struct backlight_properties *data;
166}; 176};
167 177
168/* bus */ 178/* bus */
@@ -257,11 +267,35 @@ static void acpi_video_device_bind(struct acpi_video_bus *video,
257 struct acpi_video_device *device); 267 struct acpi_video_device *device);
258static int acpi_video_device_enumerate(struct acpi_video_bus *video); 268static int acpi_video_device_enumerate(struct acpi_video_bus *video);
259static int acpi_video_switch_output(struct acpi_video_bus *video, int event); 269static int acpi_video_switch_output(struct acpi_video_bus *video, int event);
270static int acpi_video_device_lcd_set_level(struct acpi_video_device *device,
271 int level);
272static int acpi_video_device_lcd_get_level_current(
273 struct acpi_video_device *device,
274 unsigned long *level);
260static int acpi_video_get_next_level(struct acpi_video_device *device, 275static int acpi_video_get_next_level(struct acpi_video_device *device,
261 u32 level_current, u32 event); 276 u32 level_current, u32 event);
262static void acpi_video_switch_brightness(struct acpi_video_device *device, 277static void acpi_video_switch_brightness(struct acpi_video_device *device,
263 int event); 278 int event);
264 279
280/*backlight device sysfs support*/
281static int acpi_video_get_brightness(struct backlight_device *bd)
282{
283 unsigned long cur_level;
284 struct acpi_video_device *vd =
285 (struct acpi_video_device *)class_get_devdata(&bd->class_dev);
286 acpi_video_device_lcd_get_level_current(vd, &cur_level);
287 return (int) cur_level;
288}
289
290static int acpi_video_set_brightness(struct backlight_device *bd)
291{
292 int request_level = bd->props->brightness;
293 struct acpi_video_device *vd =
294 (struct acpi_video_device *)class_get_devdata(&bd->class_dev);
295 acpi_video_device_lcd_set_level(vd, request_level);
296 return 0;
297}
298
265/* -------------------------------------------------------------------------- 299/* --------------------------------------------------------------------------
266 Video Management 300 Video Management
267 -------------------------------------------------------------------------- */ 301 -------------------------------------------------------------------------- */
@@ -499,6 +533,7 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
499 acpi_integer status; 533 acpi_integer status;
500 acpi_handle h_dummy1; 534 acpi_handle h_dummy1;
501 int i; 535 int i;
536 u32 max_level = 0;
502 union acpi_object *obj = NULL; 537 union acpi_object *obj = NULL;
503 struct acpi_video_device_brightness *br = NULL; 538 struct acpi_video_device_brightness *br = NULL;
504 539
@@ -514,6 +549,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))) { 549 if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_BCM", &h_dummy1))) {
515 device->cap._BCM = 1; 550 device->cap._BCM = 1;
516 } 551 }
552 if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle,"_BQC",&h_dummy1)))
553 device->cap._BQC = 1;
517 if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DDC", &h_dummy1))) { 554 if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DDC", &h_dummy1))) {
518 device->cap._DDC = 1; 555 device->cap._DDC = 1;
519 } 556 }
@@ -550,6 +587,8 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
550 continue; 587 continue;
551 } 588 }
552 br->levels[count] = (u32) o->integer.value; 589 br->levels[count] = (u32) o->integer.value;
590 if (br->levels[count] > max_level)
591 max_level = br->levels[count];
553 count++; 592 count++;
554 } 593 }
555 out: 594 out:
@@ -568,6 +607,37 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
568 607
569 kfree(obj); 608 kfree(obj);
570 609
610 if (device->cap._BCL && device->cap._BCM && device->cap._BQC){
611 unsigned long tmp;
612 static int count = 0;
613 char *name;
614 struct backlight_properties *acpi_video_data;
615
616 name = kzalloc(MAX_NAME_LEN, GFP_KERNEL);
617 if (!name)
618 return;
619
620 acpi_video_data = kzalloc(
621 sizeof(struct backlight_properties),
622 GFP_KERNEL);
623 if (!acpi_video_data){
624 kfree(name);
625 return;
626 }
627 acpi_video_data->owner = THIS_MODULE;
628 acpi_video_data->get_brightness =
629 acpi_video_get_brightness;
630 acpi_video_data->update_status =
631 acpi_video_set_brightness;
632 sprintf(name, "acpi_video%d", count++);
633 device->data = acpi_video_data;
634 acpi_video_data->max_brightness = max_level;
635 acpi_video_device_lcd_get_level_current(device, &tmp);
636 acpi_video_data->brightness = (int)tmp;
637 device->backlight = backlight_device_register(name,
638 NULL, device, acpi_video_data);
639 kfree(name);
640 }
571 return; 641 return;
572} 642}
573 643
@@ -668,6 +738,8 @@ static int acpi_video_device_info_seq_show(struct seq_file *seq, void *offset)
668 seq_printf(seq, "LCD\n"); 738 seq_printf(seq, "LCD\n");
669 else if (dev->flags.tvout) 739 else if (dev->flags.tvout)
670 seq_printf(seq, "TVOUT\n"); 740 seq_printf(seq, "TVOUT\n");
741 else if (dev->flags.dvi)
742 seq_printf(seq, "DVI\n");
671 else 743 else
672 seq_printf(seq, "UNKNOWN\n"); 744 seq_printf(seq, "UNKNOWN\n");
673 745
@@ -1242,6 +1314,16 @@ static int acpi_video_bus_remove_fs(struct acpi_device *device)
1242 -------------------------------------------------------------------------- */ 1314 -------------------------------------------------------------------------- */
1243 1315
1244/* device interface */ 1316/* device interface */
1317static struct acpi_video_device_attrib*
1318acpi_video_get_device_attr(struct acpi_video_bus *video, unsigned long device_id)
1319{
1320 int count;
1321
1322 for(count = 0; count < video->attached_count; count++)
1323 if((video->attached_array[count].value.int_val & 0xffff) == device_id)
1324 return &(video->attached_array[count].value.attrib);
1325 return NULL;
1326}
1245 1327
1246static int 1328static int
1247acpi_video_bus_get_one_device(struct acpi_device *device, 1329acpi_video_bus_get_one_device(struct acpi_device *device,
@@ -1250,7 +1332,7 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
1250 unsigned long device_id; 1332 unsigned long device_id;
1251 int status; 1333 int status;
1252 struct acpi_video_device *data; 1334 struct acpi_video_device *data;
1253 1335 struct acpi_video_device_attrib* attribute;
1254 1336
1255 if (!device || !video) 1337 if (!device || !video)
1256 return -EINVAL; 1338 return -EINVAL;
@@ -1271,20 +1353,30 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
1271 data->video = video; 1353 data->video = video;
1272 data->dev = device; 1354 data->dev = device;
1273 1355
1274 switch (device_id & 0xffff) { 1356 attribute = acpi_video_get_device_attr(video, device_id);
1275 case 0x0100: 1357
1276 data->flags.crt = 1; 1358 if((attribute != NULL) && attribute->device_id_scheme) {
1277 break; 1359 switch (attribute->display_type) {
1278 case 0x0400: 1360 case ACPI_VIDEO_DISPLAY_CRT:
1279 data->flags.lcd = 1; 1361 data->flags.crt = 1;
1280 break; 1362 break;
1281 case 0x0200: 1363 case ACPI_VIDEO_DISPLAY_TV:
1282 data->flags.tvout = 1; 1364 data->flags.tvout = 1;
1283 break; 1365 break;
1284 default: 1366 case ACPI_VIDEO_DISPLAY_DVI:
1367 data->flags.dvi = 1;
1368 break;
1369 case ACPI_VIDEO_DISPLAY_LCD:
1370 data->flags.lcd = 1;
1371 break;
1372 default:
1373 data->flags.unknown = 1;
1374 break;
1375 }
1376 if(attribute->bios_can_detect)
1377 data->flags.bios = 1;
1378 } else
1285 data->flags.unknown = 1; 1379 data->flags.unknown = 1;
1286 break;
1287 }
1288 1380
1289 acpi_video_device_bind(video, data); 1381 acpi_video_device_bind(video, data);
1290 acpi_video_device_find_cap(data); 1382 acpi_video_device_find_cap(data);
@@ -1588,7 +1680,10 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device)
1588 status = acpi_remove_notify_handler(device->dev->handle, 1680 status = acpi_remove_notify_handler(device->dev->handle,
1589 ACPI_DEVICE_NOTIFY, 1681 ACPI_DEVICE_NOTIFY,
1590 acpi_video_device_notify); 1682 acpi_video_device_notify);
1591 1683 if (device->backlight){
1684 backlight_device_unregister(device->backlight);
1685 kfree(device->data);
1686 }
1592 return 0; 1687 return 0;
1593} 1688}
1594 1689