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.c905
1 files changed, 35 insertions, 870 deletions
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index 67dec0c675aa..db39e9e607d8 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -30,12 +30,9 @@
30#include <linux/types.h> 30#include <linux/types.h>
31#include <linux/list.h> 31#include <linux/list.h>
32#include <linux/mutex.h> 32#include <linux/mutex.h>
33#include <linux/proc_fs.h>
34#include <linux/seq_file.h>
35#include <linux/input.h> 33#include <linux/input.h>
36#include <linux/backlight.h> 34#include <linux/backlight.h>
37#include <linux/thermal.h> 35#include <linux/thermal.h>
38#include <linux/video_output.h>
39#include <linux/sort.h> 36#include <linux/sort.h>
40#include <linux/pci.h> 37#include <linux/pci.h>
41#include <linux/pci_ids.h> 38#include <linux/pci_ids.h>
@@ -83,6 +80,13 @@ module_param(brightness_switch_enabled, bool, 0644);
83static int allow_duplicates; 80static int allow_duplicates;
84module_param(allow_duplicates, bool, 0644); 81module_param(allow_duplicates, bool, 0644);
85 82
83/*
84 * Some BIOSes claim they use minimum backlight at boot,
85 * and this may bring dimming screen after boot
86 */
87static int use_bios_initial_backlight = 1;
88module_param(use_bios_initial_backlight, bool, 0644);
89
86static int register_count = 0; 90static int register_count = 0;
87static int acpi_video_bus_add(struct acpi_device *device); 91static int acpi_video_bus_add(struct acpi_device *device);
88static int acpi_video_bus_remove(struct acpi_device *device, int type); 92static int acpi_video_bus_remove(struct acpi_device *device, int type);
@@ -152,9 +156,6 @@ struct acpi_video_bus {
152 struct acpi_video_bus_flags flags; 156 struct acpi_video_bus_flags flags;
153 struct list_head video_device_list; 157 struct list_head video_device_list;
154 struct mutex device_list_lock; /* protects video_device_list */ 158 struct mutex device_list_lock; /* protects video_device_list */
155#ifdef CONFIG_ACPI_PROCFS
156 struct proc_dir_entry *dir;
157#endif
158 struct input_dev *input; 159 struct input_dev *input;
159 char phys[32]; /* for input device */ 160 char phys[32]; /* for input device */
160 struct notifier_block pm_nb; 161 struct notifier_block pm_nb;
@@ -177,9 +178,6 @@ struct acpi_video_device_cap {
177 u8 _BQC:1; /* Get current brightness level */ 178 u8 _BQC:1; /* Get current brightness level */
178 u8 _BCQ:1; /* Some buggy BIOS uses _BCQ instead of _BQC */ 179 u8 _BCQ:1; /* Some buggy BIOS uses _BCQ instead of _BQC */
179 u8 _DDC:1; /*Return the EDID for this device */ 180 u8 _DDC:1; /*Return the EDID for this device */
180 u8 _DCS:1; /*Return status of output device */
181 u8 _DGS:1; /*Query graphics state */
182 u8 _DSS:1; /*Device state set */
183}; 181};
184 182
185struct acpi_video_brightness_flags { 183struct acpi_video_brightness_flags {
@@ -207,110 +205,7 @@ struct acpi_video_device {
207 struct acpi_video_device_brightness *brightness; 205 struct acpi_video_device_brightness *brightness;
208 struct backlight_device *backlight; 206 struct backlight_device *backlight;
209 struct thermal_cooling_device *cooling_dev; 207 struct thermal_cooling_device *cooling_dev;
210 struct output_device *output_dev;
211};
212
213#ifdef CONFIG_ACPI_PROCFS
214/* bus */
215static int acpi_video_bus_info_open_fs(struct inode *inode, struct file *file);
216static const struct file_operations acpi_video_bus_info_fops = {
217 .owner = THIS_MODULE,
218 .open = acpi_video_bus_info_open_fs,
219 .read = seq_read,
220 .llseek = seq_lseek,
221 .release = single_release,
222};
223
224static int acpi_video_bus_ROM_open_fs(struct inode *inode, struct file *file);
225static const struct file_operations acpi_video_bus_ROM_fops = {
226 .owner = THIS_MODULE,
227 .open = acpi_video_bus_ROM_open_fs,
228 .read = seq_read,
229 .llseek = seq_lseek,
230 .release = single_release,
231};
232
233static int acpi_video_bus_POST_info_open_fs(struct inode *inode,
234 struct file *file);
235static const struct file_operations acpi_video_bus_POST_info_fops = {
236 .owner = THIS_MODULE,
237 .open = acpi_video_bus_POST_info_open_fs,
238 .read = seq_read,
239 .llseek = seq_lseek,
240 .release = single_release,
241};
242
243static int acpi_video_bus_POST_open_fs(struct inode *inode, struct file *file);
244static ssize_t acpi_video_bus_write_POST(struct file *file,
245 const char __user *buffer, size_t count, loff_t *data);
246static const struct file_operations acpi_video_bus_POST_fops = {
247 .owner = THIS_MODULE,
248 .open = acpi_video_bus_POST_open_fs,
249 .read = seq_read,
250 .write = acpi_video_bus_write_POST,
251 .llseek = seq_lseek,
252 .release = single_release,
253};
254
255static int acpi_video_bus_DOS_open_fs(struct inode *inode, struct file *file);
256static ssize_t acpi_video_bus_write_DOS(struct file *file,
257 const char __user *buffer, size_t count, loff_t *data);
258static const struct file_operations acpi_video_bus_DOS_fops = {
259 .owner = THIS_MODULE,
260 .open = acpi_video_bus_DOS_open_fs,
261 .read = seq_read,
262 .write = acpi_video_bus_write_DOS,
263 .llseek = seq_lseek,
264 .release = single_release,
265};
266
267/* device */
268static int acpi_video_device_info_open_fs(struct inode *inode,
269 struct file *file);
270static const struct file_operations acpi_video_device_info_fops = {
271 .owner = THIS_MODULE,
272 .open = acpi_video_device_info_open_fs,
273 .read = seq_read,
274 .llseek = seq_lseek,
275 .release = single_release,
276};
277
278static int acpi_video_device_state_open_fs(struct inode *inode,
279 struct file *file);
280static ssize_t acpi_video_device_write_state(struct file *file,
281 const char __user *buffer, size_t count, loff_t *data);
282static const struct file_operations acpi_video_device_state_fops = {
283 .owner = THIS_MODULE,
284 .open = acpi_video_device_state_open_fs,
285 .read = seq_read,
286 .write = acpi_video_device_write_state,
287 .llseek = seq_lseek,
288 .release = single_release,
289};
290
291static int acpi_video_device_brightness_open_fs(struct inode *inode,
292 struct file *file);
293static ssize_t acpi_video_device_write_brightness(struct file *file,
294 const char __user *buffer, size_t count, loff_t *data);
295static const struct file_operations acpi_video_device_brightness_fops = {
296 .owner = THIS_MODULE,
297 .open = acpi_video_device_brightness_open_fs,
298 .read = seq_read,
299 .write = acpi_video_device_write_brightness,
300 .llseek = seq_lseek,
301 .release = single_release,
302};
303
304static int acpi_video_device_EDID_open_fs(struct inode *inode,
305 struct file *file);
306static const struct file_operations acpi_video_device_EDID_fops = {
307 .owner = THIS_MODULE,
308 .open = acpi_video_device_EDID_open_fs,
309 .read = seq_read,
310 .llseek = seq_lseek,
311 .release = single_release,
312}; 208};
313#endif /* CONFIG_ACPI_PROCFS */
314 209
315static const char device_decode[][30] = { 210static const char device_decode[][30] = {
316 "motherboard VGA device", 211 "motherboard VGA device",
@@ -333,10 +228,6 @@ static int acpi_video_get_next_level(struct acpi_video_device *device,
333 u32 level_current, u32 event); 228 u32 level_current, u32 event);
334static int acpi_video_switch_brightness(struct acpi_video_device *device, 229static int acpi_video_switch_brightness(struct acpi_video_device *device,
335 int event); 230 int event);
336static int acpi_video_device_get_state(struct acpi_video_device *device,
337 unsigned long long *state);
338static int acpi_video_output_get(struct output_device *od);
339static int acpi_video_device_set_state(struct acpi_video_device *device, int state);
340 231
341/*backlight device sysfs support*/ 232/*backlight device sysfs support*/
342static int acpi_video_get_brightness(struct backlight_device *bd) 233static int acpi_video_get_brightness(struct backlight_device *bd)
@@ -367,35 +258,11 @@ static int acpi_video_set_brightness(struct backlight_device *bd)
367 vd->brightness->levels[request_level]); 258 vd->brightness->levels[request_level]);
368} 259}
369 260
370static struct backlight_ops acpi_backlight_ops = { 261static const struct backlight_ops acpi_backlight_ops = {
371 .get_brightness = acpi_video_get_brightness, 262 .get_brightness = acpi_video_get_brightness,
372 .update_status = acpi_video_set_brightness, 263 .update_status = acpi_video_set_brightness,
373}; 264};
374 265
375/*video output device sysfs support*/
376static int acpi_video_output_get(struct output_device *od)
377{
378 unsigned long long state;
379 struct acpi_video_device *vd =
380 (struct acpi_video_device *)dev_get_drvdata(&od->dev);
381 acpi_video_device_get_state(vd, &state);
382 return (int)state;
383}
384
385static int acpi_video_output_set(struct output_device *od)
386{
387 unsigned long state = od->request_state;
388 struct acpi_video_device *vd=
389 (struct acpi_video_device *)dev_get_drvdata(&od->dev);
390 return acpi_video_device_set_state(vd, state);
391}
392
393static struct output_properties acpi_output_properties = {
394 .set_state = acpi_video_output_set,
395 .get_status = acpi_video_output_get,
396};
397
398
399/* thermal cooling device callbacks */ 266/* thermal cooling device callbacks */
400static int video_get_max_state(struct thermal_cooling_device *cooling_dev, unsigned 267static int video_get_max_state(struct thermal_cooling_device *cooling_dev, unsigned
401 long *state) 268 long *state)
@@ -451,34 +318,6 @@ static struct thermal_cooling_device_ops video_cooling_ops = {
451 Video Management 318 Video Management
452 -------------------------------------------------------------------------- */ 319 -------------------------------------------------------------------------- */
453 320
454/* device */
455
456static int
457acpi_video_device_get_state(struct acpi_video_device *device,
458 unsigned long long *state)
459{
460 int status;
461
462 status = acpi_evaluate_integer(device->dev->handle, "_DCS", NULL, state);
463
464 return status;
465}
466
467static int
468acpi_video_device_set_state(struct acpi_video_device *device, int state)
469{
470 int status;
471 union acpi_object arg0 = { ACPI_TYPE_INTEGER };
472 struct acpi_object_list args = { 1, &arg0 };
473 unsigned long long ret;
474
475
476 arg0.integer.value = state;
477 status = acpi_evaluate_integer(device->dev->handle, "_DSS", &args, &ret);
478
479 return status;
480}
481
482static int 321static int
483acpi_video_device_lcd_query_levels(struct acpi_video_device *device, 322acpi_video_device_lcd_query_levels(struct acpi_video_device *device,
484 union acpi_object **levels) 323 union acpi_object **levels)
@@ -873,9 +712,11 @@ acpi_video_init_brightness(struct acpi_video_device *device)
873 * when invoked for the first time, i.e. level_old is invalid. 712 * when invoked for the first time, i.e. level_old is invalid.
874 * set the backlight to max_level in this case 713 * set the backlight to max_level in this case
875 */ 714 */
876 for (i = 2; i < br->count; i++) 715 if (use_bios_initial_backlight) {
877 if (level_old == br->levels[i]) 716 for (i = 2; i < br->count; i++)
878 level = level_old; 717 if (level_old == br->levels[i])
718 level = level_old;
719 }
879 goto set_level; 720 goto set_level;
880 } 721 }
881 722
@@ -938,18 +779,12 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
938 if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DDC", &h_dummy1))) { 779 if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DDC", &h_dummy1))) {
939 device->cap._DDC = 1; 780 device->cap._DDC = 1;
940 } 781 }
941 if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DCS", &h_dummy1))) {
942 device->cap._DCS = 1;
943 }
944 if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DGS", &h_dummy1))) {
945 device->cap._DGS = 1;
946 }
947 if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DSS", &h_dummy1))) {
948 device->cap._DSS = 1;
949 }
950 782
951 if (acpi_video_backlight_support()) { 783 if (acpi_video_backlight_support()) {
952 struct backlight_properties props; 784 struct backlight_properties props;
785 struct pci_dev *pdev;
786 acpi_handle acpi_parent;
787 struct device *parent = NULL;
953 int result; 788 int result;
954 static int count = 0; 789 static int count = 0;
955 char *name; 790 char *name;
@@ -962,9 +797,20 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
962 return; 797 return;
963 count++; 798 count++;
964 799
800 acpi_get_parent(device->dev->handle, &acpi_parent);
801
802 pdev = acpi_get_pci_dev(acpi_parent);
803 if (pdev) {
804 parent = &pdev->dev;
805 pci_dev_put(pdev);
806 }
807
965 memset(&props, 0, sizeof(struct backlight_properties)); 808 memset(&props, 0, sizeof(struct backlight_properties));
809 props.type = BACKLIGHT_FIRMWARE;
966 props.max_brightness = device->brightness->count - 3; 810 props.max_brightness = device->brightness->count - 3;
967 device->backlight = backlight_device_register(name, NULL, device, 811 device->backlight = backlight_device_register(name,
812 parent,
813 device,
968 &acpi_backlight_ops, 814 &acpi_backlight_ops,
969 &props); 815 &props);
970 kfree(name); 816 kfree(name);
@@ -978,11 +824,6 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
978 device->backlight->props.brightness = 824 device->backlight->props.brightness =
979 acpi_video_get_brightness(device->backlight); 825 acpi_video_get_brightness(device->backlight);
980 826
981 result = sysfs_create_link(&device->backlight->dev.kobj,
982 &device->dev->dev.kobj, "device");
983 if (result)
984 printk(KERN_ERR PREFIX "Create sysfs link\n");
985
986 device->cooling_dev = thermal_cooling_device_register("LCD", 827 device->cooling_dev = thermal_cooling_device_register("LCD",
987 device->dev, &video_cooling_ops); 828 device->dev, &video_cooling_ops);
988 if (IS_ERR(device->cooling_dev)) { 829 if (IS_ERR(device->cooling_dev)) {
@@ -1011,21 +852,6 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
1011 printk(KERN_ERR PREFIX "Create sysfs link\n"); 852 printk(KERN_ERR PREFIX "Create sysfs link\n");
1012 853
1013 } 854 }
1014
1015 if (acpi_video_display_switch_support()) {
1016
1017 if (device->cap._DCS && device->cap._DSS) {
1018 static int count;
1019 char *name;
1020 name = kasprintf(GFP_KERNEL, "acpi_video%d", count);
1021 if (!name)
1022 return;
1023 count++;
1024 device->output_dev = video_output_register(name,
1025 NULL, device, &acpi_output_properties);
1026 kfree(name);
1027 }
1028 }
1029} 855}
1030 856
1031/* 857/*
@@ -1111,646 +937,6 @@ static int acpi_video_bus_check(struct acpi_video_bus *video)
1111} 937}
1112 938
1113/* -------------------------------------------------------------------------- 939/* --------------------------------------------------------------------------
1114 FS Interface (/proc)
1115 -------------------------------------------------------------------------- */
1116#ifdef CONFIG_ACPI_PROCFS
1117
1118static struct proc_dir_entry *acpi_video_dir;
1119
1120/* video devices */
1121
1122static int acpi_video_device_info_seq_show(struct seq_file *seq, void *offset)
1123{
1124 struct acpi_video_device *dev = seq->private;
1125
1126
1127 if (!dev)
1128 goto end;
1129
1130 seq_printf(seq, "device_id: 0x%04x\n", (u32) dev->device_id);
1131 seq_printf(seq, "type: ");
1132 if (dev->flags.crt)
1133 seq_printf(seq, "CRT\n");
1134 else if (dev->flags.lcd)
1135 seq_printf(seq, "LCD\n");
1136 else if (dev->flags.tvout)
1137 seq_printf(seq, "TVOUT\n");
1138 else if (dev->flags.dvi)
1139 seq_printf(seq, "DVI\n");
1140 else
1141 seq_printf(seq, "UNKNOWN\n");
1142
1143 seq_printf(seq, "known by bios: %s\n", dev->flags.bios ? "yes" : "no");
1144
1145 end:
1146 return 0;
1147}
1148
1149static int
1150acpi_video_device_info_open_fs(struct inode *inode, struct file *file)
1151{
1152 return single_open(file, acpi_video_device_info_seq_show,
1153 PDE(inode)->data);
1154}
1155
1156static int
1157acpi_video_device_query(struct acpi_video_device *device,
1158 unsigned long long *state)
1159{
1160 int status;
1161
1162 status = acpi_evaluate_integer(device->dev->handle, "_DGS",
1163 NULL, state);
1164
1165 return status;
1166}
1167
1168static int acpi_video_device_state_seq_show(struct seq_file *seq, void *offset)
1169{
1170 int status;
1171 struct acpi_video_device *dev = seq->private;
1172 unsigned long long state;
1173
1174
1175 if (!dev)
1176 goto end;
1177
1178 status = acpi_video_device_get_state(dev, &state);
1179 seq_printf(seq, "state: ");
1180 if (ACPI_SUCCESS(status))
1181 seq_printf(seq, "0x%02llx\n", state);
1182 else
1183 seq_printf(seq, "<not supported>\n");
1184
1185 status = acpi_video_device_query(dev, &state);
1186 seq_printf(seq, "query: ");
1187 if (ACPI_SUCCESS(status))
1188 seq_printf(seq, "0x%02llx\n", state);
1189 else
1190 seq_printf(seq, "<not supported>\n");
1191
1192 end:
1193 return 0;
1194}
1195
1196static int
1197acpi_video_device_state_open_fs(struct inode *inode, struct file *file)
1198{
1199 return single_open(file, acpi_video_device_state_seq_show,
1200 PDE(inode)->data);
1201}
1202
1203static ssize_t
1204acpi_video_device_write_state(struct file *file,
1205 const char __user * buffer,
1206 size_t count, loff_t * data)
1207{
1208 int status;
1209 struct seq_file *m = file->private_data;
1210 struct acpi_video_device *dev = m->private;
1211 char str[12] = { 0 };
1212 u32 state = 0;
1213
1214
1215 if (!dev || count >= sizeof(str))
1216 return -EINVAL;
1217
1218 if (copy_from_user(str, buffer, count))
1219 return -EFAULT;
1220
1221 str[count] = 0;
1222 state = simple_strtoul(str, NULL, 0);
1223 state &= ((1ul << 31) | (1ul << 30) | (1ul << 0));
1224
1225 status = acpi_video_device_set_state(dev, state);
1226
1227 if (status)
1228 return -EFAULT;
1229
1230 return count;
1231}
1232
1233static int
1234acpi_video_device_brightness_seq_show(struct seq_file *seq, void *offset)
1235{
1236 struct acpi_video_device *dev = seq->private;
1237 int i;
1238
1239
1240 if (!dev || !dev->brightness) {
1241 seq_printf(seq, "<not supported>\n");
1242 return 0;
1243 }
1244
1245 seq_printf(seq, "levels: ");
1246 for (i = 2; i < dev->brightness->count; i++)
1247 seq_printf(seq, " %d", dev->brightness->levels[i]);
1248 seq_printf(seq, "\ncurrent: %d\n", dev->brightness->curr);
1249
1250 return 0;
1251}
1252
1253static int
1254acpi_video_device_brightness_open_fs(struct inode *inode, struct file *file)
1255{
1256 return single_open(file, acpi_video_device_brightness_seq_show,
1257 PDE(inode)->data);
1258}
1259
1260static ssize_t
1261acpi_video_device_write_brightness(struct file *file,
1262 const char __user * buffer,
1263 size_t count, loff_t * data)
1264{
1265 struct seq_file *m = file->private_data;
1266 struct acpi_video_device *dev = m->private;
1267 char str[5] = { 0 };
1268 unsigned int level = 0;
1269 int i;
1270
1271
1272 if (!dev || !dev->brightness || count >= sizeof(str))
1273 return -EINVAL;
1274
1275 if (copy_from_user(str, buffer, count))
1276 return -EFAULT;
1277
1278 str[count] = 0;
1279 level = simple_strtoul(str, NULL, 0);
1280
1281 if (level > 100)
1282 return -EFAULT;
1283
1284 /* validate through the list of available levels */
1285 for (i = 2; i < dev->brightness->count; i++)
1286 if (level == dev->brightness->levels[i]) {
1287 if (!acpi_video_device_lcd_set_level(dev, level))
1288 return count;
1289 break;
1290 }
1291
1292 return -EINVAL;
1293}
1294
1295static int acpi_video_device_EDID_seq_show(struct seq_file *seq, void *offset)
1296{
1297 struct acpi_video_device *dev = seq->private;
1298 int status;
1299 int i;
1300 union acpi_object *edid = NULL;
1301
1302
1303 if (!dev)
1304 goto out;
1305
1306 status = acpi_video_device_EDID(dev, &edid, 128);
1307 if (ACPI_FAILURE(status)) {
1308 status = acpi_video_device_EDID(dev, &edid, 256);
1309 }
1310
1311 if (ACPI_FAILURE(status)) {
1312 goto out;
1313 }
1314
1315 if (edid && edid->type == ACPI_TYPE_BUFFER) {
1316 for (i = 0; i < edid->buffer.length; i++)
1317 seq_putc(seq, edid->buffer.pointer[i]);
1318 }
1319
1320 out:
1321 if (!edid)
1322 seq_printf(seq, "<not supported>\n");
1323 else
1324 kfree(edid);
1325
1326 return 0;
1327}
1328
1329static int
1330acpi_video_device_EDID_open_fs(struct inode *inode, struct file *file)
1331{
1332 return single_open(file, acpi_video_device_EDID_seq_show,
1333 PDE(inode)->data);
1334}
1335
1336static int acpi_video_device_add_fs(struct acpi_device *device)
1337{
1338 struct proc_dir_entry *entry, *device_dir;
1339 struct acpi_video_device *vid_dev;
1340
1341 vid_dev = acpi_driver_data(device);
1342 if (!vid_dev)
1343 return -ENODEV;
1344
1345 device_dir = proc_mkdir(acpi_device_bid(device),
1346 vid_dev->video->dir);
1347 if (!device_dir)
1348 return -ENOMEM;
1349
1350 /* 'info' [R] */
1351 entry = proc_create_data("info", S_IRUGO, device_dir,
1352 &acpi_video_device_info_fops, acpi_driver_data(device));
1353 if (!entry)
1354 goto err_remove_dir;
1355
1356 /* 'state' [R/W] */
1357 entry = proc_create_data("state", S_IFREG | S_IRUGO | S_IWUSR,
1358 device_dir,
1359 &acpi_video_device_state_fops,
1360 acpi_driver_data(device));
1361 if (!entry)
1362 goto err_remove_info;
1363
1364 /* 'brightness' [R/W] */
1365 entry = proc_create_data("brightness", S_IFREG | S_IRUGO | S_IWUSR,
1366 device_dir,
1367 &acpi_video_device_brightness_fops,
1368 acpi_driver_data(device));
1369 if (!entry)
1370 goto err_remove_state;
1371
1372 /* 'EDID' [R] */
1373 entry = proc_create_data("EDID", S_IRUGO, device_dir,
1374 &acpi_video_device_EDID_fops,
1375 acpi_driver_data(device));
1376 if (!entry)
1377 goto err_remove_brightness;
1378
1379 acpi_device_dir(device) = device_dir;
1380
1381 return 0;
1382
1383 err_remove_brightness:
1384 remove_proc_entry("brightness", device_dir);
1385 err_remove_state:
1386 remove_proc_entry("state", device_dir);
1387 err_remove_info:
1388 remove_proc_entry("info", device_dir);
1389 err_remove_dir:
1390 remove_proc_entry(acpi_device_bid(device), vid_dev->video->dir);
1391 return -ENOMEM;
1392}
1393
1394static int acpi_video_device_remove_fs(struct acpi_device *device)
1395{
1396 struct acpi_video_device *vid_dev;
1397 struct proc_dir_entry *device_dir;
1398
1399 vid_dev = acpi_driver_data(device);
1400 if (!vid_dev || !vid_dev->video || !vid_dev->video->dir)
1401 return -ENODEV;
1402
1403 device_dir = acpi_device_dir(device);
1404 if (device_dir) {
1405 remove_proc_entry("info", device_dir);
1406 remove_proc_entry("state", device_dir);
1407 remove_proc_entry("brightness", device_dir);
1408 remove_proc_entry("EDID", device_dir);
1409 remove_proc_entry(acpi_device_bid(device), vid_dev->video->dir);
1410 acpi_device_dir(device) = NULL;
1411 }
1412
1413 return 0;
1414}
1415
1416/* video bus */
1417static int acpi_video_bus_info_seq_show(struct seq_file *seq, void *offset)
1418{
1419 struct acpi_video_bus *video = seq->private;
1420
1421
1422 if (!video)
1423 goto end;
1424
1425 seq_printf(seq, "Switching heads: %s\n",
1426 video->flags.multihead ? "yes" : "no");
1427 seq_printf(seq, "Video ROM: %s\n",
1428 video->flags.rom ? "yes" : "no");
1429 seq_printf(seq, "Device to be POSTed on boot: %s\n",
1430 video->flags.post ? "yes" : "no");
1431
1432 end:
1433 return 0;
1434}
1435
1436static int acpi_video_bus_info_open_fs(struct inode *inode, struct file *file)
1437{
1438 return single_open(file, acpi_video_bus_info_seq_show,
1439 PDE(inode)->data);
1440}
1441
1442static int acpi_video_bus_ROM_seq_show(struct seq_file *seq, void *offset)
1443{
1444 struct acpi_video_bus *video = seq->private;
1445
1446
1447 if (!video)
1448 goto end;
1449
1450 printk(KERN_INFO PREFIX "Please implement %s\n", __func__);
1451 seq_printf(seq, "<TODO>\n");
1452
1453 end:
1454 return 0;
1455}
1456
1457static int acpi_video_bus_ROM_open_fs(struct inode *inode, struct file *file)
1458{
1459 return single_open(file, acpi_video_bus_ROM_seq_show, PDE(inode)->data);
1460}
1461
1462static int
1463acpi_video_bus_POST_options(struct acpi_video_bus *video,
1464 unsigned long long *options)
1465{
1466 int status;
1467
1468 status = acpi_evaluate_integer(video->device->handle, "_VPO",
1469 NULL, options);
1470 *options &= 3;
1471
1472 return status;
1473}
1474
1475static int acpi_video_bus_POST_info_seq_show(struct seq_file *seq, void *offset)
1476{
1477 struct acpi_video_bus *video = seq->private;
1478 unsigned long long options;
1479 int status;
1480
1481
1482 if (!video)
1483 goto end;
1484
1485 status = acpi_video_bus_POST_options(video, &options);
1486 if (ACPI_SUCCESS(status)) {
1487 if (!(options & 1)) {
1488 printk(KERN_WARNING PREFIX
1489 "The motherboard VGA device is not listed as a possible POST device.\n");
1490 printk(KERN_WARNING PREFIX
1491 "This indicates a BIOS bug. Please contact the manufacturer.\n");
1492 }
1493 printk(KERN_WARNING "%llx\n", options);
1494 seq_printf(seq, "can POST: <integrated video>");
1495 if (options & 2)
1496 seq_printf(seq, " <PCI video>");
1497 if (options & 4)
1498 seq_printf(seq, " <AGP video>");
1499 seq_putc(seq, '\n');
1500 } else
1501 seq_printf(seq, "<not supported>\n");
1502 end:
1503 return 0;
1504}
1505
1506static int
1507acpi_video_bus_POST_info_open_fs(struct inode *inode, struct file *file)
1508{
1509 return single_open(file, acpi_video_bus_POST_info_seq_show,
1510 PDE(inode)->data);
1511}
1512
1513static int
1514acpi_video_bus_get_POST(struct acpi_video_bus *video, unsigned long long *id)
1515{
1516 int status;
1517
1518 status = acpi_evaluate_integer(video->device->handle, "_GPD", NULL, id);
1519
1520 return status;
1521}
1522
1523static int acpi_video_bus_POST_seq_show(struct seq_file *seq, void *offset)
1524{
1525 struct acpi_video_bus *video = seq->private;
1526 int status;
1527 unsigned long long id;
1528
1529
1530 if (!video)
1531 goto end;
1532
1533 status = acpi_video_bus_get_POST(video, &id);
1534 if (!ACPI_SUCCESS(status)) {
1535 seq_printf(seq, "<not supported>\n");
1536 goto end;
1537 }
1538 seq_printf(seq, "device POSTed is <%s>\n", device_decode[id & 3]);
1539
1540 end:
1541 return 0;
1542}
1543
1544static int acpi_video_bus_DOS_seq_show(struct seq_file *seq, void *offset)
1545{
1546 struct acpi_video_bus *video = seq->private;
1547
1548
1549 seq_printf(seq, "DOS setting: <%d>\n", video->dos_setting);
1550
1551 return 0;
1552}
1553
1554static int acpi_video_bus_POST_open_fs(struct inode *inode, struct file *file)
1555{
1556 return single_open(file, acpi_video_bus_POST_seq_show,
1557 PDE(inode)->data);
1558}
1559
1560static int acpi_video_bus_DOS_open_fs(struct inode *inode, struct file *file)
1561{
1562 return single_open(file, acpi_video_bus_DOS_seq_show, PDE(inode)->data);
1563}
1564
1565static int
1566acpi_video_bus_set_POST(struct acpi_video_bus *video, unsigned long option)
1567{
1568 int status;
1569 unsigned long long tmp;
1570 union acpi_object arg0 = { ACPI_TYPE_INTEGER };
1571 struct acpi_object_list args = { 1, &arg0 };
1572
1573
1574 arg0.integer.value = option;
1575
1576 status = acpi_evaluate_integer(video->device->handle, "_SPD",
1577 &args, &tmp);
1578 if (ACPI_SUCCESS(status))
1579 status = tmp ? (-EINVAL) : (AE_OK);
1580
1581 return status;
1582}
1583
1584static ssize_t
1585acpi_video_bus_write_POST(struct file *file,
1586 const char __user * buffer,
1587 size_t count, loff_t * data)
1588{
1589 int status;
1590 struct seq_file *m = file->private_data;
1591 struct acpi_video_bus *video = m->private;
1592 char str[12] = { 0 };
1593 unsigned long long opt, options;
1594
1595
1596 if (!video || count >= sizeof(str))
1597 return -EINVAL;
1598
1599 status = acpi_video_bus_POST_options(video, &options);
1600 if (!ACPI_SUCCESS(status))
1601 return -EINVAL;
1602
1603 if (copy_from_user(str, buffer, count))
1604 return -EFAULT;
1605
1606 str[count] = 0;
1607 opt = strtoul(str, NULL, 0);
1608 if (opt > 3)
1609 return -EFAULT;
1610
1611 /* just in case an OEM 'forgot' the motherboard... */
1612 options |= 1;
1613
1614 if (options & (1ul << opt)) {
1615 status = acpi_video_bus_set_POST(video, opt);
1616 if (!ACPI_SUCCESS(status))
1617 return -EFAULT;
1618
1619 }
1620
1621 return count;
1622}
1623
1624static ssize_t
1625acpi_video_bus_write_DOS(struct file *file,
1626 const char __user * buffer,
1627 size_t count, loff_t * data)
1628{
1629 int status;
1630 struct seq_file *m = file->private_data;
1631 struct acpi_video_bus *video = m->private;
1632 char str[12] = { 0 };
1633 unsigned long opt;
1634
1635
1636 if (!video || count >= sizeof(str))
1637 return -EINVAL;
1638
1639 if (copy_from_user(str, buffer, count))
1640 return -EFAULT;
1641
1642 str[count] = 0;
1643 opt = strtoul(str, NULL, 0);
1644 if (opt > 7)
1645 return -EFAULT;
1646
1647 status = acpi_video_bus_DOS(video, opt & 0x3, (opt & 0x4) >> 2);
1648
1649 if (!ACPI_SUCCESS(status))
1650 return -EFAULT;
1651
1652 return count;
1653}
1654
1655static int acpi_video_bus_add_fs(struct acpi_device *device)
1656{
1657 struct acpi_video_bus *video = acpi_driver_data(device);
1658 struct proc_dir_entry *device_dir;
1659 struct proc_dir_entry *entry;
1660
1661 device_dir = proc_mkdir(acpi_device_bid(device), acpi_video_dir);
1662 if (!device_dir)
1663 return -ENOMEM;
1664
1665 /* 'info' [R] */
1666 entry = proc_create_data("info", S_IRUGO, device_dir,
1667 &acpi_video_bus_info_fops,
1668 acpi_driver_data(device));
1669 if (!entry)
1670 goto err_remove_dir;
1671
1672 /* 'ROM' [R] */
1673 entry = proc_create_data("ROM", S_IRUGO, device_dir,
1674 &acpi_video_bus_ROM_fops,
1675 acpi_driver_data(device));
1676 if (!entry)
1677 goto err_remove_info;
1678
1679 /* 'POST_info' [R] */
1680 entry = proc_create_data("POST_info", S_IRUGO, device_dir,
1681 &acpi_video_bus_POST_info_fops,
1682 acpi_driver_data(device));
1683 if (!entry)
1684 goto err_remove_rom;
1685
1686 /* 'POST' [R/W] */
1687 entry = proc_create_data("POST", S_IFREG | S_IRUGO | S_IWUSR,
1688 device_dir,
1689 &acpi_video_bus_POST_fops,
1690 acpi_driver_data(device));
1691 if (!entry)
1692 goto err_remove_post_info;
1693
1694 /* 'DOS' [R/W] */
1695 entry = proc_create_data("DOS", S_IFREG | S_IRUGO | S_IWUSR,
1696 device_dir,
1697 &acpi_video_bus_DOS_fops,
1698 acpi_driver_data(device));
1699 if (!entry)
1700 goto err_remove_post;
1701
1702 video->dir = acpi_device_dir(device) = device_dir;
1703 return 0;
1704
1705 err_remove_post:
1706 remove_proc_entry("POST", device_dir);
1707 err_remove_post_info:
1708 remove_proc_entry("POST_info", device_dir);
1709 err_remove_rom:
1710 remove_proc_entry("ROM", device_dir);
1711 err_remove_info:
1712 remove_proc_entry("info", device_dir);
1713 err_remove_dir:
1714 remove_proc_entry(acpi_device_bid(device), acpi_video_dir);
1715 return -ENOMEM;
1716}
1717
1718static int acpi_video_bus_remove_fs(struct acpi_device *device)
1719{
1720 struct proc_dir_entry *device_dir = acpi_device_dir(device);
1721
1722 if (device_dir) {
1723 remove_proc_entry("info", device_dir);
1724 remove_proc_entry("ROM", device_dir);
1725 remove_proc_entry("POST_info", device_dir);
1726 remove_proc_entry("POST", device_dir);
1727 remove_proc_entry("DOS", device_dir);
1728 remove_proc_entry(acpi_device_bid(device), acpi_video_dir);
1729 acpi_device_dir(device) = NULL;
1730 }
1731
1732 return 0;
1733}
1734#else
1735static inline int acpi_video_device_add_fs(struct acpi_device *device)
1736{
1737 return 0;
1738}
1739static inline int acpi_video_device_remove_fs(struct acpi_device *device)
1740{
1741 return 0;
1742}
1743static inline int acpi_video_bus_add_fs(struct acpi_device *device)
1744{
1745 return 0;
1746}
1747static inline int acpi_video_bus_remove_fs(struct acpi_device *device)
1748{
1749 return 0;
1750}
1751#endif /* CONFIG_ACPI_PROCFS */
1752
1753/* --------------------------------------------------------------------------
1754 Driver Interface 940 Driver Interface
1755 -------------------------------------------------------------------------- */ 941 -------------------------------------------------------------------------- */
1756 942
@@ -1877,8 +1063,6 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
1877 list_add_tail(&data->entry, &video->video_device_list); 1063 list_add_tail(&data->entry, &video->video_device_list);
1878 mutex_unlock(&video->device_list_lock); 1064 mutex_unlock(&video->device_list_lock);
1879 1065
1880 acpi_video_device_add_fs(device);
1881
1882 return 0; 1066 return 0;
1883 } 1067 }
1884 1068
@@ -2109,6 +1293,9 @@ int acpi_video_get_edid(struct acpi_device *device, int type, int device_id,
2109 if (!video_device) 1293 if (!video_device)
2110 continue; 1294 continue;
2111 1295
1296 if (!video_device->cap._DDC)
1297 continue;
1298
2112 if (type) { 1299 if (type) {
2113 switch (type) { 1300 switch (type) {
2114 case ACPI_VIDEO_DISPLAY_CRT: 1301 case ACPI_VIDEO_DISPLAY_CRT:
@@ -2167,7 +1354,7 @@ acpi_video_bus_get_devices(struct acpi_video_bus *video,
2167 status = acpi_video_bus_get_one_device(dev, video); 1354 status = acpi_video_bus_get_one_device(dev, video);
2168 if (ACPI_FAILURE(status)) { 1355 if (ACPI_FAILURE(status)) {
2169 printk(KERN_WARNING PREFIX 1356 printk(KERN_WARNING PREFIX
2170 "Cant attach device\n"); 1357 "Can't attach device\n");
2171 continue; 1358 continue;
2172 } 1359 }
2173 } 1360 }
@@ -2181,17 +1368,14 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device)
2181 if (!device || !device->video) 1368 if (!device || !device->video)
2182 return -ENOENT; 1369 return -ENOENT;
2183 1370
2184 acpi_video_device_remove_fs(device->dev);
2185
2186 status = acpi_remove_notify_handler(device->dev->handle, 1371 status = acpi_remove_notify_handler(device->dev->handle,
2187 ACPI_DEVICE_NOTIFY, 1372 ACPI_DEVICE_NOTIFY,
2188 acpi_video_device_notify); 1373 acpi_video_device_notify);
2189 if (ACPI_FAILURE(status)) { 1374 if (ACPI_FAILURE(status)) {
2190 printk(KERN_WARNING PREFIX 1375 printk(KERN_WARNING PREFIX
2191 "Cant remove video notify handler\n"); 1376 "Can't remove video notify handler\n");
2192 } 1377 }
2193 if (device->backlight) { 1378 if (device->backlight) {
2194 sysfs_remove_link(&device->backlight->dev.kobj, "device");
2195 backlight_device_unregister(device->backlight); 1379 backlight_device_unregister(device->backlight);
2196 device->backlight = NULL; 1380 device->backlight = NULL;
2197 } 1381 }
@@ -2203,7 +1387,6 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device)
2203 thermal_cooling_device_unregister(device->cooling_dev); 1387 thermal_cooling_device_unregister(device->cooling_dev);
2204 device->cooling_dev = NULL; 1388 device->cooling_dev = NULL;
2205 } 1389 }
2206 video_output_unregister(device->output_dev);
2207 1390
2208 return 0; 1391 return 0;
2209} 1392}
@@ -2338,7 +1521,7 @@ static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data)
2338 acpi_bus_generate_proc_event(device, event, 0); 1521 acpi_bus_generate_proc_event(device, event, 0);
2339 keycode = KEY_BRIGHTNESSDOWN; 1522 keycode = KEY_BRIGHTNESSDOWN;
2340 break; 1523 break;
2341 case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS: /* zero brightnesss */ 1524 case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS: /* zero brightness */
2342 if (brightness_switch_enabled) 1525 if (brightness_switch_enabled)
2343 acpi_video_switch_brightness(video_device, event); 1526 acpi_video_switch_brightness(video_device, event);
2344 acpi_bus_generate_proc_event(device, event, 0); 1527 acpi_bus_generate_proc_event(device, event, 0);
@@ -2466,10 +1649,6 @@ static int acpi_video_bus_add(struct acpi_device *device)
2466 if (error) 1649 if (error)
2467 goto err_free_video; 1650 goto err_free_video;
2468 1651
2469 error = acpi_video_bus_add_fs(device);
2470 if (error)
2471 goto err_free_video;
2472
2473 mutex_init(&video->device_list_lock); 1652 mutex_init(&video->device_list_lock);
2474 INIT_LIST_HEAD(&video->video_device_list); 1653 INIT_LIST_HEAD(&video->video_device_list);
2475 1654
@@ -2522,7 +1701,6 @@ static int acpi_video_bus_add(struct acpi_device *device)
2522 acpi_video_bus_stop_devices(video); 1701 acpi_video_bus_stop_devices(video);
2523 acpi_video_bus_put_devices(video); 1702 acpi_video_bus_put_devices(video);
2524 kfree(video->attached_array); 1703 kfree(video->attached_array);
2525 acpi_video_bus_remove_fs(device);
2526 err_free_video: 1704 err_free_video:
2527 kfree(video); 1705 kfree(video);
2528 device->driver_data = NULL; 1706 device->driver_data = NULL;
@@ -2544,7 +1722,6 @@ static int acpi_video_bus_remove(struct acpi_device *device, int type)
2544 1722
2545 acpi_video_bus_stop_devices(video); 1723 acpi_video_bus_stop_devices(video);
2546 acpi_video_bus_put_devices(video); 1724 acpi_video_bus_put_devices(video);
2547 acpi_video_bus_remove_fs(device);
2548 1725
2549 input_unregister_device(video->input); 1726 input_unregister_device(video->input);
2550 kfree(video->attached_array); 1727 kfree(video->attached_array);
@@ -2584,17 +1761,9 @@ int acpi_video_register(void)
2584 return 0; 1761 return 0;
2585 } 1762 }
2586 1763
2587#ifdef CONFIG_ACPI_PROCFS
2588 acpi_video_dir = proc_mkdir(ACPI_VIDEO_CLASS, acpi_root_dir);
2589 if (!acpi_video_dir)
2590 return -ENODEV;
2591#endif
2592
2593 result = acpi_bus_register_driver(&acpi_video_bus); 1764 result = acpi_bus_register_driver(&acpi_video_bus);
2594 if (result < 0) { 1765 if (result < 0)
2595 remove_proc_entry(ACPI_VIDEO_CLASS, acpi_root_dir);
2596 return -ENODEV; 1766 return -ENODEV;
2597 }
2598 1767
2599 /* 1768 /*
2600 * When the acpi_video_bus is loaded successfully, increase 1769 * When the acpi_video_bus is loaded successfully, increase
@@ -2617,10 +1786,6 @@ void acpi_video_unregister(void)
2617 } 1786 }
2618 acpi_bus_unregister_driver(&acpi_video_bus); 1787 acpi_bus_unregister_driver(&acpi_video_bus);
2619 1788
2620#ifdef CONFIG_ACPI_PROCFS
2621 remove_proc_entry(ACPI_VIDEO_CLASS, acpi_root_dir);
2622#endif
2623
2624 register_count = 0; 1789 register_count = 0;
2625 1790
2626 return; 1791 return;