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.c288
1 files changed, 142 insertions, 146 deletions
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index 55c095619379..33c502e56026 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -57,8 +57,6 @@
57#define ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS 0x88 57#define ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS 0x88
58#define ACPI_VIDEO_NOTIFY_DISPLAY_OFF 0x89 58#define ACPI_VIDEO_NOTIFY_DISPLAY_OFF 0x89
59 59
60#define ACPI_VIDEO_HEAD_INVALID (~0u - 1)
61#define ACPI_VIDEO_HEAD_END (~0u)
62#define MAX_NAME_LEN 20 60#define MAX_NAME_LEN 20
63 61
64#define ACPI_VIDEO_DISPLAY_CRT 1 62#define ACPI_VIDEO_DISPLAY_CRT 1
@@ -1048,87 +1046,90 @@ acpi_video_device_EDID_open_fs(struct inode *inode, struct file *file)
1048 1046
1049static int acpi_video_device_add_fs(struct acpi_device *device) 1047static int acpi_video_device_add_fs(struct acpi_device *device)
1050{ 1048{
1051 struct proc_dir_entry *entry = NULL; 1049 struct proc_dir_entry *entry, *device_dir;
1052 struct acpi_video_device *vid_dev; 1050 struct acpi_video_device *vid_dev;
1053 1051
1054
1055 if (!device)
1056 return -ENODEV;
1057
1058 vid_dev = acpi_driver_data(device); 1052 vid_dev = acpi_driver_data(device);
1059 if (!vid_dev) 1053 if (!vid_dev)
1060 return -ENODEV; 1054 return -ENODEV;
1061 1055
1062 if (!acpi_device_dir(device)) { 1056 device_dir = proc_mkdir(acpi_device_bid(device),
1063 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), 1057 vid_dev->video->dir);
1064 vid_dev->video->dir); 1058 if (!device_dir)
1065 if (!acpi_device_dir(device)) 1059 return -ENOMEM;
1066 return -ENODEV; 1060
1067 acpi_device_dir(device)->owner = THIS_MODULE; 1061 device_dir->owner = THIS_MODULE;
1068 }
1069 1062
1070 /* 'info' [R] */ 1063 /* 'info' [R] */
1071 entry = create_proc_entry("info", S_IRUGO, acpi_device_dir(device)); 1064 entry = create_proc_entry("info", S_IRUGO, device_dir);
1072 if (!entry) 1065 if (!entry)
1073 return -ENODEV; 1066 goto err_remove_dir;
1074 else { 1067
1075 entry->proc_fops = &acpi_video_device_info_fops; 1068 entry->proc_fops = &acpi_video_device_info_fops;
1076 entry->data = acpi_driver_data(device); 1069 entry->data = acpi_driver_data(device);
1077 entry->owner = THIS_MODULE; 1070 entry->owner = THIS_MODULE;
1078 }
1079 1071
1080 /* 'state' [R/W] */ 1072 /* 'state' [R/W] */
1081 entry = 1073 entry = create_proc_entry("state", S_IFREG | S_IRUGO | S_IWUSR,
1082 create_proc_entry("state", S_IFREG | S_IRUGO | S_IWUSR, 1074 device_dir);
1083 acpi_device_dir(device));
1084 if (!entry) 1075 if (!entry)
1085 return -ENODEV; 1076 goto err_remove_info;
1086 else { 1077
1087 acpi_video_device_state_fops.write = acpi_video_device_write_state; 1078 acpi_video_device_state_fops.write = acpi_video_device_write_state;
1088 entry->proc_fops = &acpi_video_device_state_fops; 1079 entry->proc_fops = &acpi_video_device_state_fops;
1089 entry->data = acpi_driver_data(device); 1080 entry->data = acpi_driver_data(device);
1090 entry->owner = THIS_MODULE; 1081 entry->owner = THIS_MODULE;
1091 }
1092 1082
1093 /* 'brightness' [R/W] */ 1083 /* 'brightness' [R/W] */
1094 entry = 1084 entry = create_proc_entry("brightness", S_IFREG | S_IRUGO | S_IWUSR,
1095 create_proc_entry("brightness", S_IFREG | S_IRUGO | S_IWUSR, 1085 device_dir);
1096 acpi_device_dir(device));
1097 if (!entry) 1086 if (!entry)
1098 return -ENODEV; 1087 goto err_remove_state;
1099 else { 1088
1100 acpi_video_device_brightness_fops.write = acpi_video_device_write_brightness; 1089 acpi_video_device_brightness_fops.write =
1101 entry->proc_fops = &acpi_video_device_brightness_fops; 1090 acpi_video_device_write_brightness;
1102 entry->data = acpi_driver_data(device); 1091 entry->proc_fops = &acpi_video_device_brightness_fops;
1103 entry->owner = THIS_MODULE; 1092 entry->data = acpi_driver_data(device);
1104 } 1093 entry->owner = THIS_MODULE;
1105 1094
1106 /* 'EDID' [R] */ 1095 /* 'EDID' [R] */
1107 entry = create_proc_entry("EDID", S_IRUGO, acpi_device_dir(device)); 1096 entry = create_proc_entry("EDID", S_IRUGO, device_dir);
1108 if (!entry) 1097 if (!entry)
1109 return -ENODEV; 1098 goto err_remove_brightness;
1110 else { 1099
1111 entry->proc_fops = &acpi_video_device_EDID_fops; 1100 entry->proc_fops = &acpi_video_device_EDID_fops;
1112 entry->data = acpi_driver_data(device); 1101 entry->data = acpi_driver_data(device);
1113 entry->owner = THIS_MODULE; 1102 entry->owner = THIS_MODULE;
1114 }
1115 1103
1104 acpi_device_dir(device) = device_dir;
1116 return 0; 1105 return 0;
1106
1107 err_remove_brightness:
1108 remove_proc_entry("brightness", device_dir);
1109 err_remove_state:
1110 remove_proc_entry("state", device_dir);
1111 err_remove_info:
1112 remove_proc_entry("info", device_dir);
1113 err_remove_dir:
1114 remove_proc_entry(acpi_device_bid(device), vid_dev->video->dir);
1115 return -ENOMEM;
1117} 1116}
1118 1117
1119static int acpi_video_device_remove_fs(struct acpi_device *device) 1118static int acpi_video_device_remove_fs(struct acpi_device *device)
1120{ 1119{
1121 struct acpi_video_device *vid_dev; 1120 struct acpi_video_device *vid_dev;
1121 struct proc_dir_entry *device_dir;
1122 1122
1123 vid_dev = acpi_driver_data(device); 1123 vid_dev = acpi_driver_data(device);
1124 if (!vid_dev || !vid_dev->video || !vid_dev->video->dir) 1124 if (!vid_dev || !vid_dev->video || !vid_dev->video->dir)
1125 return -ENODEV; 1125 return -ENODEV;
1126 1126
1127 if (acpi_device_dir(device)) { 1127 device_dir = acpi_device_dir(device);
1128 remove_proc_entry("info", acpi_device_dir(device)); 1128 if (device_dir) {
1129 remove_proc_entry("state", acpi_device_dir(device)); 1129 remove_proc_entry("info", device_dir);
1130 remove_proc_entry("brightness", acpi_device_dir(device)); 1130 remove_proc_entry("state", device_dir);
1131 remove_proc_entry("EDID", acpi_device_dir(device)); 1131 remove_proc_entry("brightness", device_dir);
1132 remove_proc_entry("EDID", device_dir);
1132 remove_proc_entry(acpi_device_bid(device), vid_dev->video->dir); 1133 remove_proc_entry(acpi_device_bid(device), vid_dev->video->dir);
1133 acpi_device_dir(device) = NULL; 1134 acpi_device_dir(device) = NULL;
1134 } 1135 }
@@ -1335,94 +1336,91 @@ acpi_video_bus_write_DOS(struct file *file,
1335 1336
1336static int acpi_video_bus_add_fs(struct acpi_device *device) 1337static int acpi_video_bus_add_fs(struct acpi_device *device)
1337{ 1338{
1338 struct proc_dir_entry *entry = NULL; 1339 struct acpi_video_bus *video = acpi_driver_data(device);
1339 struct acpi_video_bus *video; 1340 struct proc_dir_entry *device_dir;
1341 struct proc_dir_entry *entry;
1340 1342
1343 device_dir = proc_mkdir(acpi_device_bid(device), acpi_video_dir);
1344 if (!device_dir)
1345 return -ENOMEM;
1341 1346
1342 video = acpi_driver_data(device); 1347 device_dir->owner = THIS_MODULE;
1343
1344 if (!acpi_device_dir(device)) {
1345 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
1346 acpi_video_dir);
1347 if (!acpi_device_dir(device))
1348 return -ENODEV;
1349 video->dir = acpi_device_dir(device);
1350 acpi_device_dir(device)->owner = THIS_MODULE;
1351 }
1352 1348
1353 /* 'info' [R] */ 1349 /* 'info' [R] */
1354 entry = create_proc_entry("info", S_IRUGO, acpi_device_dir(device)); 1350 entry = create_proc_entry("info", S_IRUGO, device_dir);
1355 if (!entry) 1351 if (!entry)
1356 return -ENODEV; 1352 goto err_remove_dir;
1357 else { 1353
1358 entry->proc_fops = &acpi_video_bus_info_fops; 1354 entry->proc_fops = &acpi_video_bus_info_fops;
1359 entry->data = acpi_driver_data(device); 1355 entry->data = acpi_driver_data(device);
1360 entry->owner = THIS_MODULE; 1356 entry->owner = THIS_MODULE;
1361 }
1362 1357
1363 /* 'ROM' [R] */ 1358 /* 'ROM' [R] */
1364 entry = create_proc_entry("ROM", S_IRUGO, acpi_device_dir(device)); 1359 entry = create_proc_entry("ROM", S_IRUGO, device_dir);
1365 if (!entry) 1360 if (!entry)
1366 return -ENODEV; 1361 goto err_remove_info;
1367 else { 1362
1368 entry->proc_fops = &acpi_video_bus_ROM_fops; 1363 entry->proc_fops = &acpi_video_bus_ROM_fops;
1369 entry->data = acpi_driver_data(device); 1364 entry->data = acpi_driver_data(device);
1370 entry->owner = THIS_MODULE; 1365 entry->owner = THIS_MODULE;
1371 }
1372 1366
1373 /* 'POST_info' [R] */ 1367 /* 'POST_info' [R] */
1374 entry = 1368 entry = create_proc_entry("POST_info", S_IRUGO, device_dir);
1375 create_proc_entry("POST_info", S_IRUGO, acpi_device_dir(device));
1376 if (!entry) 1369 if (!entry)
1377 return -ENODEV; 1370 goto err_remove_rom;
1378 else { 1371
1379 entry->proc_fops = &acpi_video_bus_POST_info_fops; 1372 entry->proc_fops = &acpi_video_bus_POST_info_fops;
1380 entry->data = acpi_driver_data(device); 1373 entry->data = acpi_driver_data(device);
1381 entry->owner = THIS_MODULE; 1374 entry->owner = THIS_MODULE;
1382 }
1383 1375
1384 /* 'POST' [R/W] */ 1376 /* 'POST' [R/W] */
1385 entry = 1377 entry = create_proc_entry("POST", S_IFREG | S_IRUGO | S_IWUSR,
1386 create_proc_entry("POST", S_IFREG | S_IRUGO | S_IRUSR, 1378 device_dir);
1387 acpi_device_dir(device));
1388 if (!entry) 1379 if (!entry)
1389 return -ENODEV; 1380 goto err_remove_post_info;
1390 else { 1381
1391 acpi_video_bus_POST_fops.write = acpi_video_bus_write_POST; 1382 acpi_video_bus_POST_fops.write = acpi_video_bus_write_POST;
1392 entry->proc_fops = &acpi_video_bus_POST_fops; 1383 entry->proc_fops = &acpi_video_bus_POST_fops;
1393 entry->data = acpi_driver_data(device); 1384 entry->data = acpi_driver_data(device);
1394 entry->owner = THIS_MODULE; 1385 entry->owner = THIS_MODULE;
1395 }
1396 1386
1397 /* 'DOS' [R/W] */ 1387 /* 'DOS' [R/W] */
1398 entry = 1388 entry = create_proc_entry("DOS", S_IFREG | S_IRUGO | S_IWUSR,
1399 create_proc_entry("DOS", S_IFREG | S_IRUGO | S_IRUSR, 1389 device_dir);
1400 acpi_device_dir(device));
1401 if (!entry) 1390 if (!entry)
1402 return -ENODEV; 1391 goto err_remove_post;
1403 else { 1392
1404 acpi_video_bus_DOS_fops.write = acpi_video_bus_write_DOS; 1393 acpi_video_bus_DOS_fops.write = acpi_video_bus_write_DOS;
1405 entry->proc_fops = &acpi_video_bus_DOS_fops; 1394 entry->proc_fops = &acpi_video_bus_DOS_fops;
1406 entry->data = acpi_driver_data(device); 1395 entry->data = acpi_driver_data(device);
1407 entry->owner = THIS_MODULE; 1396 entry->owner = THIS_MODULE;
1408 }
1409 1397
1398 video->dir = acpi_device_dir(device) = device_dir;
1410 return 0; 1399 return 0;
1400
1401 err_remove_post:
1402 remove_proc_entry("POST", device_dir);
1403 err_remove_post_info:
1404 remove_proc_entry("POST_info", device_dir);
1405 err_remove_rom:
1406 remove_proc_entry("ROM", device_dir);
1407 err_remove_info:
1408 remove_proc_entry("info", device_dir);
1409 err_remove_dir:
1410 remove_proc_entry(acpi_device_bid(device), acpi_video_dir);
1411 return -ENOMEM;
1411} 1412}
1412 1413
1413static int acpi_video_bus_remove_fs(struct acpi_device *device) 1414static int acpi_video_bus_remove_fs(struct acpi_device *device)
1414{ 1415{
1415 struct acpi_video_bus *video; 1416 struct proc_dir_entry *device_dir = acpi_device_dir(device);
1416
1417
1418 video = acpi_driver_data(device);
1419 1417
1420 if (acpi_device_dir(device)) { 1418 if (device_dir) {
1421 remove_proc_entry("info", acpi_device_dir(device)); 1419 remove_proc_entry("info", device_dir);
1422 remove_proc_entry("ROM", acpi_device_dir(device)); 1420 remove_proc_entry("ROM", device_dir);
1423 remove_proc_entry("POST_info", acpi_device_dir(device)); 1421 remove_proc_entry("POST_info", device_dir);
1424 remove_proc_entry("POST", acpi_device_dir(device)); 1422 remove_proc_entry("POST", device_dir);
1425 remove_proc_entry("DOS", acpi_device_dir(device)); 1423 remove_proc_entry("DOS", device_dir);
1426 remove_proc_entry(acpi_device_bid(device), acpi_video_dir); 1424 remove_proc_entry(acpi_device_bid(device), acpi_video_dir);
1427 acpi_device_dir(device) = NULL; 1425 acpi_device_dir(device) = NULL;
1428 } 1426 }
@@ -1438,11 +1436,15 @@ static int acpi_video_bus_remove_fs(struct acpi_device *device)
1438static struct acpi_video_device_attrib* 1436static struct acpi_video_device_attrib*
1439acpi_video_get_device_attr(struct acpi_video_bus *video, unsigned long device_id) 1437acpi_video_get_device_attr(struct acpi_video_bus *video, unsigned long device_id)
1440{ 1438{
1441 int count; 1439 struct acpi_video_enumerated_device *ids;
1440 int i;
1441
1442 for (i = 0; i < video->attached_count; i++) {
1443 ids = &video->attached_array[i];
1444 if ((ids->value.int_val & 0xffff) == device_id)
1445 return &ids->value.attrib;
1446 }
1442 1447
1443 for(count = 0; count < video->attached_count; count++)
1444 if((video->attached_array[count].value.int_val & 0xffff) == device_id)
1445 return &(video->attached_array[count].value.attrib);
1446 return NULL; 1448 return NULL;
1447} 1449}
1448 1450
@@ -1569,20 +1571,16 @@ static void
1569acpi_video_device_bind(struct acpi_video_bus *video, 1571acpi_video_device_bind(struct acpi_video_bus *video,
1570 struct acpi_video_device *device) 1572 struct acpi_video_device *device)
1571{ 1573{
1574 struct acpi_video_enumerated_device *ids;
1572 int i; 1575 int i;
1573 1576
1574#define IDS_VAL(i) video->attached_array[i].value.int_val 1577 for (i = 0; i < video->attached_count; i++) {
1575#define IDS_BIND(i) video->attached_array[i].bind_info 1578 ids = &video->attached_array[i];
1576 1579 if (device->device_id == (ids->value.int_val & 0xffff)) {
1577 for (i = 0; IDS_VAL(i) != ACPI_VIDEO_HEAD_INVALID && 1580 ids->bind_info = device;
1578 i < video->attached_count; i++) {
1579 if (device->device_id == (IDS_VAL(i) & 0xffff)) {
1580 IDS_BIND(i) = device;
1581 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "device_bind %d\n", i)); 1581 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "device_bind %d\n", i));
1582 } 1582 }
1583 } 1583 }
1584#undef IDS_VAL
1585#undef IDS_BIND
1586} 1584}
1587 1585
1588/* 1586/*
@@ -1601,7 +1599,7 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video)
1601 int status; 1599 int status;
1602 int count; 1600 int count;
1603 int i; 1601 int i;
1604 struct acpi_video_enumerated_device *active_device_list; 1602 struct acpi_video_enumerated_device *active_list;
1605 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 1603 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
1606 union acpi_object *dod = NULL; 1604 union acpi_object *dod = NULL;
1607 union acpi_object *obj; 1605 union acpi_object *obj;
@@ -1622,13 +1620,10 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video)
1622 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d video heads in _DOD\n", 1620 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d video heads in _DOD\n",
1623 dod->package.count)); 1621 dod->package.count));
1624 1622
1625 active_device_list = kmalloc((1 + 1623 active_list = kcalloc(1 + dod->package.count,
1626 dod->package.count) * 1624 sizeof(struct acpi_video_enumerated_device),
1627 sizeof(struct 1625 GFP_KERNEL);
1628 acpi_video_enumerated_device), 1626 if (!active_list) {
1629 GFP_KERNEL);
1630
1631 if (!active_device_list) {
1632 status = -ENOMEM; 1627 status = -ENOMEM;
1633 goto out; 1628 goto out;
1634 } 1629 }
@@ -1638,23 +1633,24 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video)
1638 obj = &dod->package.elements[i]; 1633 obj = &dod->package.elements[i];
1639 1634
1640 if (obj->type != ACPI_TYPE_INTEGER) { 1635 if (obj->type != ACPI_TYPE_INTEGER) {
1641 printk(KERN_ERR PREFIX "Invalid _DOD data\n"); 1636 printk(KERN_ERR PREFIX
1642 active_device_list[i].value.int_val = 1637 "Invalid _DOD data in element %d\n", i);
1643 ACPI_VIDEO_HEAD_INVALID; 1638 continue;
1644 } 1639 }
1645 active_device_list[i].value.int_val = obj->integer.value; 1640
1646 active_device_list[i].bind_info = NULL; 1641 active_list[count].value.int_val = obj->integer.value;
1642 active_list[count].bind_info = NULL;
1647 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "dod element[%d] = %d\n", i, 1643 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "dod element[%d] = %d\n", i,
1648 (int)obj->integer.value)); 1644 (int)obj->integer.value));
1649 count++; 1645 count++;
1650 } 1646 }
1651 active_device_list[count].value.int_val = ACPI_VIDEO_HEAD_END;
1652 1647
1653 kfree(video->attached_array); 1648 kfree(video->attached_array);
1654 1649
1655 video->attached_array = active_device_list; 1650 video->attached_array = active_list;
1656 video->attached_count = count; 1651 video->attached_count = count;
1657 out: 1652
1653 out:
1658 kfree(buffer.pointer); 1654 kfree(buffer.pointer);
1659 return status; 1655 return status;
1660} 1656}