diff options
Diffstat (limited to 'drivers/acpi/video.c')
-rw-r--r-- | drivers/acpi/video.c | 199 |
1 files changed, 103 insertions, 96 deletions
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 43b228314a86..f7eb12e55602 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 |
@@ -743,21 +741,19 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) | |||
743 | if (IS_ERR(device->cdev)) | 741 | if (IS_ERR(device->cdev)) |
744 | return; | 742 | return; |
745 | 743 | ||
746 | if (device->cdev) { | 744 | printk(KERN_INFO PREFIX |
747 | printk(KERN_INFO PREFIX | 745 | "%s is registered as cooling_device%d\n", |
748 | "%s is registered as cooling_device%d\n", | 746 | device->dev->dev.bus_id, device->cdev->id); |
749 | device->dev->dev.bus_id, device->cdev->id); | 747 | result = sysfs_create_link(&device->dev->dev.kobj, |
750 | result = sysfs_create_link(&device->dev->dev.kobj, | 748 | &device->cdev->device.kobj, |
751 | &device->cdev->device.kobj, | 749 | "thermal_cooling"); |
752 | "thermal_cooling"); | 750 | if (result) |
753 | if (result) | 751 | printk(KERN_ERR PREFIX "Create sysfs link\n"); |
754 | printk(KERN_ERR PREFIX "Create sysfs link\n"); | 752 | result = sysfs_create_link(&device->cdev->device.kobj, |
755 | result = sysfs_create_link(&device->cdev->device.kobj, | 753 | &device->dev->dev.kobj, "device"); |
756 | &device->dev->dev.kobj, | 754 | if (result) |
757 | "device"); | 755 | printk(KERN_ERR PREFIX "Create sysfs link\n"); |
758 | if (result) | 756 | |
759 | printk(KERN_ERR PREFIX "Create sysfs link\n"); | ||
760 | } | ||
761 | } | 757 | } |
762 | if (device->cap._DCS && device->cap._DSS){ | 758 | if (device->cap._DCS && device->cap._DSS){ |
763 | static int count = 0; | 759 | static int count = 0; |
@@ -1059,30 +1055,25 @@ acpi_video_device_EDID_open_fs(struct inode *inode, struct file *file) | |||
1059 | 1055 | ||
1060 | static int acpi_video_device_add_fs(struct acpi_device *device) | 1056 | static int acpi_video_device_add_fs(struct acpi_device *device) |
1061 | { | 1057 | { |
1062 | struct proc_dir_entry *entry = NULL; | 1058 | struct proc_dir_entry *entry, *device_dir; |
1063 | struct acpi_video_device *vid_dev; | 1059 | struct acpi_video_device *vid_dev; |
1064 | 1060 | ||
1065 | |||
1066 | if (!device) | ||
1067 | return -ENODEV; | ||
1068 | |||
1069 | vid_dev = acpi_driver_data(device); | 1061 | vid_dev = acpi_driver_data(device); |
1070 | if (!vid_dev) | 1062 | if (!vid_dev) |
1071 | return -ENODEV; | 1063 | return -ENODEV; |
1072 | 1064 | ||
1073 | if (!acpi_device_dir(device)) { | 1065 | device_dir = proc_mkdir(acpi_device_bid(device), |
1074 | acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), | 1066 | vid_dev->video->dir); |
1075 | vid_dev->video->dir); | 1067 | if (!device_dir) |
1076 | if (!acpi_device_dir(device)) | 1068 | return -ENOMEM; |
1077 | return -ENODEV; | 1069 | |
1078 | acpi_device_dir(device)->owner = THIS_MODULE; | 1070 | device_dir->owner = THIS_MODULE; |
1079 | } | ||
1080 | 1071 | ||
1081 | /* 'info' [R] */ | 1072 | /* 'info' [R] */ |
1082 | entry = proc_create_data("info", S_IRUGO, acpi_device_dir(device), | 1073 | entry = proc_create_data("info", S_IRUGO, acpi_device_dir(device), |
1083 | &acpi_video_device_info_fops, acpi_driver_data(device)); | 1074 | &acpi_video_device_info_fops, acpi_driver_data(device)); |
1084 | if (!entry) | 1075 | if (!entry) |
1085 | return -ENODEV; | 1076 | goto err_remove_dir; |
1086 | 1077 | ||
1087 | /* 'state' [R/W] */ | 1078 | /* 'state' [R/W] */ |
1088 | acpi_video_device_state_fops.write = acpi_video_device_write_state; | 1079 | acpi_video_device_state_fops.write = acpi_video_device_write_state; |
@@ -1091,7 +1082,7 @@ static int acpi_video_device_add_fs(struct acpi_device *device) | |||
1091 | &acpi_video_device_state_fops, | 1082 | &acpi_video_device_state_fops, |
1092 | acpi_driver_data(device)); | 1083 | acpi_driver_data(device)); |
1093 | if (!entry) | 1084 | if (!entry) |
1094 | return -ENODEV; | 1085 | goto err_remove_info; |
1095 | 1086 | ||
1096 | /* 'brightness' [R/W] */ | 1087 | /* 'brightness' [R/W] */ |
1097 | acpi_video_device_brightness_fops.write = | 1088 | acpi_video_device_brightness_fops.write = |
@@ -1101,30 +1092,43 @@ static int acpi_video_device_add_fs(struct acpi_device *device) | |||
1101 | &acpi_video_device_brightness_fops, | 1092 | &acpi_video_device_brightness_fops, |
1102 | acpi_driver_data(device)); | 1093 | acpi_driver_data(device)); |
1103 | if (!entry) | 1094 | if (!entry) |
1104 | return -ENODEV; | 1095 | goto err_remove_state; |
1105 | 1096 | ||
1106 | /* 'EDID' [R] */ | 1097 | /* 'EDID' [R] */ |
1107 | entry = proc_create_data("EDID", S_IRUGO, acpi_device_dir(device), | 1098 | entry = proc_create_data("EDID", S_IRUGO, acpi_device_dir(device), |
1108 | &acpi_video_device_EDID_fops, | 1099 | &acpi_video_device_EDID_fops, |
1109 | acpi_driver_data(device)); | 1100 | acpi_driver_data(device)); |
1110 | if (!entry) | 1101 | if (!entry) |
1111 | return -ENODEV; | 1102 | goto err_remove_brightness; |
1103 | |||
1112 | return 0; | 1104 | return 0; |
1105 | |||
1106 | err_remove_brightness: | ||
1107 | remove_proc_entry("brightness", device_dir); | ||
1108 | err_remove_state: | ||
1109 | remove_proc_entry("state", device_dir); | ||
1110 | err_remove_info: | ||
1111 | remove_proc_entry("info", device_dir); | ||
1112 | err_remove_dir: | ||
1113 | remove_proc_entry(acpi_device_bid(device), vid_dev->video->dir); | ||
1114 | return -ENOMEM; | ||
1113 | } | 1115 | } |
1114 | 1116 | ||
1115 | static int acpi_video_device_remove_fs(struct acpi_device *device) | 1117 | static int acpi_video_device_remove_fs(struct acpi_device *device) |
1116 | { | 1118 | { |
1117 | struct acpi_video_device *vid_dev; | 1119 | struct acpi_video_device *vid_dev; |
1120 | struct proc_dir_entry *device_dir; | ||
1118 | 1121 | ||
1119 | vid_dev = acpi_driver_data(device); | 1122 | vid_dev = acpi_driver_data(device); |
1120 | if (!vid_dev || !vid_dev->video || !vid_dev->video->dir) | 1123 | if (!vid_dev || !vid_dev->video || !vid_dev->video->dir) |
1121 | return -ENODEV; | 1124 | return -ENODEV; |
1122 | 1125 | ||
1123 | if (acpi_device_dir(device)) { | 1126 | device_dir = acpi_device_dir(device); |
1124 | remove_proc_entry("info", acpi_device_dir(device)); | 1127 | if (device_dir) { |
1125 | remove_proc_entry("state", acpi_device_dir(device)); | 1128 | remove_proc_entry("info", device_dir); |
1126 | remove_proc_entry("brightness", acpi_device_dir(device)); | 1129 | remove_proc_entry("state", device_dir); |
1127 | remove_proc_entry("EDID", acpi_device_dir(device)); | 1130 | remove_proc_entry("brightness", device_dir); |
1131 | remove_proc_entry("EDID", device_dir); | ||
1128 | remove_proc_entry(acpi_device_bid(device), vid_dev->video->dir); | 1132 | remove_proc_entry(acpi_device_bid(device), vid_dev->video->dir); |
1129 | acpi_device_dir(device) = NULL; | 1133 | acpi_device_dir(device) = NULL; |
1130 | } | 1134 | } |
@@ -1331,76 +1335,81 @@ acpi_video_bus_write_DOS(struct file *file, | |||
1331 | 1335 | ||
1332 | static int acpi_video_bus_add_fs(struct acpi_device *device) | 1336 | static int acpi_video_bus_add_fs(struct acpi_device *device) |
1333 | { | 1337 | { |
1334 | struct proc_dir_entry *entry = NULL; | 1338 | struct acpi_video_bus *video = acpi_driver_data(device); |
1335 | struct acpi_video_bus *video; | 1339 | struct proc_dir_entry *device_dir; |
1340 | struct proc_dir_entry *entry; | ||
1336 | 1341 | ||
1342 | device_dir = proc_mkdir(acpi_device_bid(device), acpi_video_dir); | ||
1343 | if (!device_dir) | ||
1344 | return -ENOMEM; | ||
1337 | 1345 | ||
1338 | video = acpi_driver_data(device); | 1346 | device_dir->owner = THIS_MODULE; |
1339 | |||
1340 | if (!acpi_device_dir(device)) { | ||
1341 | acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), | ||
1342 | acpi_video_dir); | ||
1343 | if (!acpi_device_dir(device)) | ||
1344 | return -ENODEV; | ||
1345 | video->dir = acpi_device_dir(device); | ||
1346 | acpi_device_dir(device)->owner = THIS_MODULE; | ||
1347 | } | ||
1348 | 1347 | ||
1349 | /* 'info' [R] */ | 1348 | /* 'info' [R] */ |
1350 | entry = proc_create_data("info", S_IRUGO, acpi_device_dir(device), | 1349 | entry = proc_create_data("info", S_IRUGO, acpi_device_dir(device), |
1351 | &acpi_video_bus_info_fops, | 1350 | &acpi_video_bus_info_fops, |
1352 | acpi_driver_data(device)); | 1351 | acpi_driver_data(device)); |
1353 | if (!entry) | 1352 | if (!entry) |
1354 | return -ENODEV; | 1353 | goto err_remove_dir; |
1355 | 1354 | ||
1356 | /* 'ROM' [R] */ | 1355 | /* 'ROM' [R] */ |
1357 | entry = proc_create_data("ROM", S_IRUGO, acpi_device_dir(device), | 1356 | entry = proc_create_data("ROM", S_IRUGO, acpi_device_dir(device), |
1358 | &acpi_video_bus_ROM_fops, | 1357 | &acpi_video_bus_ROM_fops, |
1359 | acpi_driver_data(device)); | 1358 | acpi_driver_data(device)); |
1360 | if (!entry) | 1359 | if (!entry) |
1361 | return -ENODEV; | 1360 | goto err_remove_info; |
1362 | 1361 | ||
1363 | /* 'POST_info' [R] */ | 1362 | /* 'POST_info' [R] */ |
1364 | entry = proc_create_data("POST_info", S_IRUGO, acpi_device_dir(device), | 1363 | entry = proc_create_data("POST_info", S_IRUGO, acpi_device_dir(device), |
1365 | &acpi_video_bus_POST_info_fops, | 1364 | &acpi_video_bus_POST_info_fops, |
1366 | acpi_driver_data(device)); | 1365 | acpi_driver_data(device)); |
1367 | if (!entry) | 1366 | if (!entry) |
1368 | return -ENODEV; | 1367 | goto err_remove_rom; |
1369 | 1368 | ||
1370 | /* 'POST' [R/W] */ | 1369 | /* 'POST' [R/W] */ |
1371 | acpi_video_bus_POST_fops.write = acpi_video_bus_write_POST; | 1370 | acpi_video_bus_POST_fops.write = acpi_video_bus_write_POST; |
1372 | entry = proc_create_data("POST", S_IFREG | S_IRUGO | S_IRUSR, | 1371 | entry = proc_create_data("POST", S_IFREG | S_IRUGO | S_IWUSR, |
1373 | acpi_device_dir(device), | 1372 | acpi_device_dir(device), |
1374 | &acpi_video_bus_POST_fops, | 1373 | &acpi_video_bus_POST_fops, |
1375 | acpi_driver_data(device)); | 1374 | acpi_driver_data(device)); |
1376 | if (!entry) | 1375 | if (!entry) |
1377 | return -ENODEV; | 1376 | goto err_remove_post_info; |
1378 | 1377 | ||
1379 | /* 'DOS' [R/W] */ | 1378 | /* 'DOS' [R/W] */ |
1380 | acpi_video_bus_DOS_fops.write = acpi_video_bus_write_DOS; | 1379 | acpi_video_bus_DOS_fops.write = acpi_video_bus_write_DOS; |
1381 | entry = proc_create_data("DOS", S_IFREG | S_IRUGO | S_IRUSR, | 1380 | entry = proc_create_data("DOS", S_IFREG | S_IRUGO | S_IWUSR, |
1382 | acpi_device_dir(device), | 1381 | acpi_device_dir(device), |
1383 | &acpi_video_bus_DOS_fops, | 1382 | &acpi_video_bus_DOS_fops, |
1384 | acpi_driver_data(device)); | 1383 | acpi_driver_data(device)); |
1385 | if (!entry) | 1384 | if (!entry) |
1386 | return -ENODEV; | 1385 | goto err_remove_post; |
1387 | 1386 | ||
1387 | video->dir = acpi_device_dir(device) = device_dir; | ||
1388 | return 0; | 1388 | return 0; |
1389 | |||
1390 | err_remove_post: | ||
1391 | remove_proc_entry("POST", device_dir); | ||
1392 | err_remove_post_info: | ||
1393 | remove_proc_entry("POST_info", device_dir); | ||
1394 | err_remove_rom: | ||
1395 | remove_proc_entry("ROM", device_dir); | ||
1396 | err_remove_info: | ||
1397 | remove_proc_entry("info", device_dir); | ||
1398 | err_remove_dir: | ||
1399 | remove_proc_entry(acpi_device_bid(device), acpi_video_dir); | ||
1400 | return -ENOMEM; | ||
1389 | } | 1401 | } |
1390 | 1402 | ||
1391 | static int acpi_video_bus_remove_fs(struct acpi_device *device) | 1403 | static int acpi_video_bus_remove_fs(struct acpi_device *device) |
1392 | { | 1404 | { |
1393 | struct acpi_video_bus *video; | 1405 | struct proc_dir_entry *device_dir = acpi_device_dir(device); |
1394 | |||
1395 | 1406 | ||
1396 | video = acpi_driver_data(device); | 1407 | if (device_dir) { |
1397 | 1408 | remove_proc_entry("info", device_dir); | |
1398 | if (acpi_device_dir(device)) { | 1409 | remove_proc_entry("ROM", device_dir); |
1399 | remove_proc_entry("info", acpi_device_dir(device)); | 1410 | remove_proc_entry("POST_info", device_dir); |
1400 | remove_proc_entry("ROM", acpi_device_dir(device)); | 1411 | remove_proc_entry("POST", device_dir); |
1401 | remove_proc_entry("POST_info", acpi_device_dir(device)); | 1412 | remove_proc_entry("DOS", device_dir); |
1402 | remove_proc_entry("POST", acpi_device_dir(device)); | ||
1403 | remove_proc_entry("DOS", acpi_device_dir(device)); | ||
1404 | remove_proc_entry(acpi_device_bid(device), acpi_video_dir); | 1413 | remove_proc_entry(acpi_device_bid(device), acpi_video_dir); |
1405 | acpi_device_dir(device) = NULL; | 1414 | acpi_device_dir(device) = NULL; |
1406 | } | 1415 | } |
@@ -1416,11 +1425,15 @@ static int acpi_video_bus_remove_fs(struct acpi_device *device) | |||
1416 | static struct acpi_video_device_attrib* | 1425 | static struct acpi_video_device_attrib* |
1417 | acpi_video_get_device_attr(struct acpi_video_bus *video, unsigned long device_id) | 1426 | acpi_video_get_device_attr(struct acpi_video_bus *video, unsigned long device_id) |
1418 | { | 1427 | { |
1419 | int count; | 1428 | struct acpi_video_enumerated_device *ids; |
1429 | int i; | ||
1430 | |||
1431 | for (i = 0; i < video->attached_count; i++) { | ||
1432 | ids = &video->attached_array[i]; | ||
1433 | if ((ids->value.int_val & 0xffff) == device_id) | ||
1434 | return &ids->value.attrib; | ||
1435 | } | ||
1420 | 1436 | ||
1421 | for(count = 0; count < video->attached_count; count++) | ||
1422 | if((video->attached_array[count].value.int_val & 0xffff) == device_id) | ||
1423 | return &(video->attached_array[count].value.attrib); | ||
1424 | return NULL; | 1437 | return NULL; |
1425 | } | 1438 | } |
1426 | 1439 | ||
@@ -1547,20 +1560,16 @@ static void | |||
1547 | acpi_video_device_bind(struct acpi_video_bus *video, | 1560 | acpi_video_device_bind(struct acpi_video_bus *video, |
1548 | struct acpi_video_device *device) | 1561 | struct acpi_video_device *device) |
1549 | { | 1562 | { |
1563 | struct acpi_video_enumerated_device *ids; | ||
1550 | int i; | 1564 | int i; |
1551 | 1565 | ||
1552 | #define IDS_VAL(i) video->attached_array[i].value.int_val | 1566 | for (i = 0; i < video->attached_count; i++) { |
1553 | #define IDS_BIND(i) video->attached_array[i].bind_info | 1567 | ids = &video->attached_array[i]; |
1554 | 1568 | if (device->device_id == (ids->value.int_val & 0xffff)) { | |
1555 | for (i = 0; IDS_VAL(i) != ACPI_VIDEO_HEAD_INVALID && | 1569 | ids->bind_info = device; |
1556 | i < video->attached_count; i++) { | ||
1557 | if (device->device_id == (IDS_VAL(i) & 0xffff)) { | ||
1558 | IDS_BIND(i) = device; | ||
1559 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "device_bind %d\n", i)); | 1570 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "device_bind %d\n", i)); |
1560 | } | 1571 | } |
1561 | } | 1572 | } |
1562 | #undef IDS_VAL | ||
1563 | #undef IDS_BIND | ||
1564 | } | 1573 | } |
1565 | 1574 | ||
1566 | /* | 1575 | /* |
@@ -1579,7 +1588,7 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video) | |||
1579 | int status; | 1588 | int status; |
1580 | int count; | 1589 | int count; |
1581 | int i; | 1590 | int i; |
1582 | struct acpi_video_enumerated_device *active_device_list; | 1591 | struct acpi_video_enumerated_device *active_list; |
1583 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 1592 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
1584 | union acpi_object *dod = NULL; | 1593 | union acpi_object *dod = NULL; |
1585 | union acpi_object *obj; | 1594 | union acpi_object *obj; |
@@ -1600,13 +1609,10 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video) | |||
1600 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d video heads in _DOD\n", | 1609 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d video heads in _DOD\n", |
1601 | dod->package.count)); | 1610 | dod->package.count)); |
1602 | 1611 | ||
1603 | active_device_list = kmalloc((1 + | 1612 | active_list = kcalloc(1 + dod->package.count, |
1604 | dod->package.count) * | 1613 | sizeof(struct acpi_video_enumerated_device), |
1605 | sizeof(struct | 1614 | GFP_KERNEL); |
1606 | acpi_video_enumerated_device), | 1615 | if (!active_list) { |
1607 | GFP_KERNEL); | ||
1608 | |||
1609 | if (!active_device_list) { | ||
1610 | status = -ENOMEM; | 1616 | status = -ENOMEM; |
1611 | goto out; | 1617 | goto out; |
1612 | } | 1618 | } |
@@ -1616,23 +1622,24 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video) | |||
1616 | obj = &dod->package.elements[i]; | 1622 | obj = &dod->package.elements[i]; |
1617 | 1623 | ||
1618 | if (obj->type != ACPI_TYPE_INTEGER) { | 1624 | if (obj->type != ACPI_TYPE_INTEGER) { |
1619 | printk(KERN_ERR PREFIX "Invalid _DOD data\n"); | 1625 | printk(KERN_ERR PREFIX |
1620 | active_device_list[i].value.int_val = | 1626 | "Invalid _DOD data in element %d\n", i); |
1621 | ACPI_VIDEO_HEAD_INVALID; | 1627 | continue; |
1622 | } | 1628 | } |
1623 | active_device_list[i].value.int_val = obj->integer.value; | 1629 | |
1624 | active_device_list[i].bind_info = NULL; | 1630 | active_list[count].value.int_val = obj->integer.value; |
1631 | active_list[count].bind_info = NULL; | ||
1625 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "dod element[%d] = %d\n", i, | 1632 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "dod element[%d] = %d\n", i, |
1626 | (int)obj->integer.value)); | 1633 | (int)obj->integer.value)); |
1627 | count++; | 1634 | count++; |
1628 | } | 1635 | } |
1629 | active_device_list[count].value.int_val = ACPI_VIDEO_HEAD_END; | ||
1630 | 1636 | ||
1631 | kfree(video->attached_array); | 1637 | kfree(video->attached_array); |
1632 | 1638 | ||
1633 | video->attached_array = active_device_list; | 1639 | video->attached_array = active_list; |
1634 | video->attached_count = count; | 1640 | video->attached_count = count; |
1635 | out: | 1641 | |
1642 | out: | ||
1636 | kfree(buffer.pointer); | 1643 | kfree(buffer.pointer); |
1637 | return status; | 1644 | return status; |
1638 | } | 1645 | } |