diff options
| author | Len Brown <len.brown@intel.com> | 2007-11-20 01:20:57 -0500 |
|---|---|---|
| committer | Len Brown <len.brown@intel.com> | 2007-11-20 01:20:57 -0500 |
| commit | d89a9bda14204547f966ed1510a269a44c0b7f5d (patch) | |
| tree | a096081fcc05ea6b9ed44778e3b86b5db9738b83 | |
| parent | d12dbbfe948c89156ad1b0fe7c808ba4d6f00bc2 (diff) | |
| parent | c88c5786d3df51ccfa4e2d111fc9c8fc0f5b2797 (diff) | |
Pull video-2.6.24 into release branch
| -rw-r--r-- | drivers/acpi/video.c | 155 |
1 files changed, 75 insertions, 80 deletions
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index bac956b30c57..44a0d9ba9bd6 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #include <linux/init.h> | 29 | #include <linux/init.h> |
| 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/proc_fs.h> | 33 | #include <linux/proc_fs.h> |
| 33 | #include <linux/seq_file.h> | 34 | #include <linux/seq_file.h> |
| 34 | #include <linux/input.h> | 35 | #include <linux/input.h> |
| @@ -135,8 +136,8 @@ struct acpi_video_bus { | |||
| 135 | u8 attached_count; | 136 | u8 attached_count; |
| 136 | struct acpi_video_bus_cap cap; | 137 | struct acpi_video_bus_cap cap; |
| 137 | struct acpi_video_bus_flags flags; | 138 | struct acpi_video_bus_flags flags; |
| 138 | struct semaphore sem; | ||
| 139 | struct list_head video_device_list; | 139 | struct list_head video_device_list; |
| 140 | struct mutex device_list_lock; /* protects video_device_list */ | ||
| 140 | struct proc_dir_entry *dir; | 141 | struct proc_dir_entry *dir; |
| 141 | struct input_dev *input; | 142 | struct input_dev *input; |
| 142 | char phys[32]; /* for input device */ | 143 | char phys[32]; /* for input device */ |
| @@ -896,7 +897,7 @@ acpi_video_device_write_brightness(struct file *file, | |||
| 896 | { | 897 | { |
| 897 | struct seq_file *m = file->private_data; | 898 | struct seq_file *m = file->private_data; |
| 898 | struct acpi_video_device *dev = m->private; | 899 | struct acpi_video_device *dev = m->private; |
| 899 | char str[4] = { 0 }; | 900 | char str[5] = { 0 }; |
| 900 | unsigned int level = 0; | 901 | unsigned int level = 0; |
| 901 | int i; | 902 | int i; |
| 902 | 903 | ||
| @@ -1436,9 +1437,9 @@ acpi_video_bus_get_one_device(struct acpi_device *device, | |||
| 1436 | return -ENODEV; | 1437 | return -ENODEV; |
| 1437 | } | 1438 | } |
| 1438 | 1439 | ||
| 1439 | down(&video->sem); | 1440 | mutex_lock(&video->device_list_lock); |
| 1440 | list_add_tail(&data->entry, &video->video_device_list); | 1441 | list_add_tail(&data->entry, &video->video_device_list); |
| 1441 | up(&video->sem); | 1442 | mutex_unlock(&video->device_list_lock); |
| 1442 | 1443 | ||
| 1443 | acpi_video_device_add_fs(device); | 1444 | acpi_video_device_add_fs(device); |
| 1444 | 1445 | ||
| @@ -1462,12 +1463,14 @@ acpi_video_bus_get_one_device(struct acpi_device *device, | |||
| 1462 | 1463 | ||
| 1463 | static void acpi_video_device_rebind(struct acpi_video_bus *video) | 1464 | static void acpi_video_device_rebind(struct acpi_video_bus *video) |
| 1464 | { | 1465 | { |
| 1465 | struct list_head *node, *next; | 1466 | struct acpi_video_device *dev; |
| 1466 | list_for_each_safe(node, next, &video->video_device_list) { | 1467 | |
| 1467 | struct acpi_video_device *dev = | 1468 | mutex_lock(&video->device_list_lock); |
| 1468 | container_of(node, struct acpi_video_device, entry); | 1469 | |
| 1470 | list_for_each_entry(dev, &video->video_device_list, entry) | ||
| 1469 | acpi_video_device_bind(video, dev); | 1471 | acpi_video_device_bind(video, dev); |
| 1470 | } | 1472 | |
| 1473 | mutex_unlock(&video->device_list_lock); | ||
| 1471 | } | 1474 | } |
| 1472 | 1475 | ||
| 1473 | /* | 1476 | /* |
| @@ -1592,30 +1595,33 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video) | |||
| 1592 | 1595 | ||
| 1593 | static int acpi_video_switch_output(struct acpi_video_bus *video, int event) | 1596 | static int acpi_video_switch_output(struct acpi_video_bus *video, int event) |
| 1594 | { | 1597 | { |
| 1595 | struct list_head *node, *next; | 1598 | struct list_head *node; |
| 1596 | struct acpi_video_device *dev = NULL; | 1599 | struct acpi_video_device *dev = NULL; |
| 1597 | struct acpi_video_device *dev_next = NULL; | 1600 | struct acpi_video_device *dev_next = NULL; |
| 1598 | struct acpi_video_device *dev_prev = NULL; | 1601 | struct acpi_video_device *dev_prev = NULL; |
| 1599 | unsigned long state; | 1602 | unsigned long state; |
| 1600 | int status = 0; | 1603 | int status = 0; |
| 1601 | 1604 | ||
| 1605 | mutex_lock(&video->device_list_lock); | ||
| 1602 | 1606 | ||
| 1603 | list_for_each_safe(node, next, &video->video_device_list) { | 1607 | list_for_each(node, &video->video_device_list) { |
| 1604 | dev = container_of(node, struct acpi_video_device, entry); | 1608 | dev = container_of(node, struct acpi_video_device, entry); |
| 1605 | status = acpi_video_device_get_state(dev, &state); | 1609 | status = acpi_video_device_get_state(dev, &state); |
| 1606 | if (state & 0x2) { | 1610 | if (state & 0x2) { |
| 1607 | dev_next = | 1611 | dev_next = container_of(node->next, |
| 1608 | container_of(node->next, struct acpi_video_device, | 1612 | struct acpi_video_device, entry); |
| 1609 | entry); | 1613 | dev_prev = container_of(node->prev, |
| 1610 | dev_prev = | 1614 | struct acpi_video_device, entry); |
| 1611 | container_of(node->prev, struct acpi_video_device, | ||
| 1612 | entry); | ||
| 1613 | goto out; | 1615 | goto out; |
| 1614 | } | 1616 | } |
| 1615 | } | 1617 | } |
| 1618 | |||
| 1616 | dev_next = container_of(node->next, struct acpi_video_device, entry); | 1619 | dev_next = container_of(node->next, struct acpi_video_device, entry); |
| 1617 | dev_prev = container_of(node->prev, struct acpi_video_device, entry); | 1620 | dev_prev = container_of(node->prev, struct acpi_video_device, entry); |
| 1618 | out: | 1621 | |
| 1622 | out: | ||
| 1623 | mutex_unlock(&video->device_list_lock); | ||
| 1624 | |||
| 1619 | switch (event) { | 1625 | switch (event) { |
| 1620 | case ACPI_VIDEO_NOTIFY_CYCLE: | 1626 | case ACPI_VIDEO_NOTIFY_CYCLE: |
| 1621 | case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT: | 1627 | case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT: |
| @@ -1691,24 +1697,17 @@ acpi_video_bus_get_devices(struct acpi_video_bus *video, | |||
| 1691 | struct acpi_device *device) | 1697 | struct acpi_device *device) |
| 1692 | { | 1698 | { |
| 1693 | int status = 0; | 1699 | int status = 0; |
| 1694 | struct list_head *node, *next; | 1700 | struct acpi_device *dev; |
| 1695 | |||
| 1696 | 1701 | ||
| 1697 | acpi_video_device_enumerate(video); | 1702 | acpi_video_device_enumerate(video); |
| 1698 | 1703 | ||
| 1699 | list_for_each_safe(node, next, &device->children) { | 1704 | list_for_each_entry(dev, &device->children, node) { |
| 1700 | struct acpi_device *dev = | ||
| 1701 | list_entry(node, struct acpi_device, node); | ||
| 1702 | |||
| 1703 | if (!dev) | ||
| 1704 | continue; | ||
| 1705 | 1705 | ||
| 1706 | status = acpi_video_bus_get_one_device(dev, video); | 1706 | status = acpi_video_bus_get_one_device(dev, video); |
| 1707 | if (ACPI_FAILURE(status)) { | 1707 | if (ACPI_FAILURE(status)) { |
| 1708 | ACPI_EXCEPTION((AE_INFO, status, "Cant attach device")); | 1708 | ACPI_EXCEPTION((AE_INFO, status, "Cant attach device")); |
| 1709 | continue; | 1709 | continue; |
| 1710 | } | 1710 | } |
| 1711 | |||
| 1712 | } | 1711 | } |
| 1713 | return status; | 1712 | return status; |
| 1714 | } | 1713 | } |
| @@ -1724,9 +1723,6 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device) | |||
| 1724 | 1723 | ||
| 1725 | video = device->video; | 1724 | video = device->video; |
| 1726 | 1725 | ||
| 1727 | down(&video->sem); | ||
| 1728 | list_del(&device->entry); | ||
| 1729 | up(&video->sem); | ||
| 1730 | acpi_video_device_remove_fs(device->dev); | 1726 | acpi_video_device_remove_fs(device->dev); |
| 1731 | 1727 | ||
| 1732 | status = acpi_remove_notify_handler(device->dev->handle, | 1728 | status = acpi_remove_notify_handler(device->dev->handle, |
| @@ -1734,32 +1730,34 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device) | |||
| 1734 | acpi_video_device_notify); | 1730 | acpi_video_device_notify); |
| 1735 | backlight_device_unregister(device->backlight); | 1731 | backlight_device_unregister(device->backlight); |
| 1736 | video_output_unregister(device->output_dev); | 1732 | video_output_unregister(device->output_dev); |
| 1733 | |||
| 1737 | return 0; | 1734 | return 0; |
| 1738 | } | 1735 | } |
| 1739 | 1736 | ||
| 1740 | static int acpi_video_bus_put_devices(struct acpi_video_bus *video) | 1737 | static int acpi_video_bus_put_devices(struct acpi_video_bus *video) |
| 1741 | { | 1738 | { |
| 1742 | int status; | 1739 | int status; |
| 1743 | struct list_head *node, *next; | 1740 | struct acpi_video_device *dev, *next; |
| 1744 | 1741 | ||
| 1742 | mutex_lock(&video->device_list_lock); | ||
| 1745 | 1743 | ||
| 1746 | list_for_each_safe(node, next, &video->video_device_list) { | 1744 | list_for_each_entry_safe(dev, next, &video->video_device_list, entry) { |
| 1747 | struct acpi_video_device *data = | ||
| 1748 | list_entry(node, struct acpi_video_device, entry); | ||
| 1749 | if (!data) | ||
| 1750 | continue; | ||
| 1751 | 1745 | ||
| 1752 | status = acpi_video_bus_put_one_device(data); | 1746 | status = acpi_video_bus_put_one_device(dev); |
| 1753 | if (ACPI_FAILURE(status)) | 1747 | if (ACPI_FAILURE(status)) |
| 1754 | printk(KERN_WARNING PREFIX | 1748 | printk(KERN_WARNING PREFIX |
| 1755 | "hhuuhhuu bug in acpi video driver.\n"); | 1749 | "hhuuhhuu bug in acpi video driver.\n"); |
| 1756 | 1750 | ||
| 1757 | if (data->brightness) | 1751 | if (dev->brightness) { |
| 1758 | kfree(data->brightness->levels); | 1752 | kfree(dev->brightness->levels); |
| 1759 | kfree(data->brightness); | 1753 | kfree(dev->brightness); |
| 1760 | kfree(data); | 1754 | } |
| 1755 | list_del(&dev->entry); | ||
| 1756 | kfree(dev); | ||
| 1761 | } | 1757 | } |
| 1762 | 1758 | ||
| 1759 | mutex_unlock(&video->device_list_lock); | ||
| 1760 | |||
| 1763 | return 0; | 1761 | return 0; |
| 1764 | } | 1762 | } |
| 1765 | 1763 | ||
| @@ -1782,9 +1780,6 @@ static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data) | |||
| 1782 | struct input_dev *input; | 1780 | struct input_dev *input; |
| 1783 | int keycode; | 1781 | int keycode; |
| 1784 | 1782 | ||
| 1785 | |||
| 1786 | printk("video bus notify\n"); | ||
| 1787 | |||
| 1788 | if (!video) | 1783 | if (!video) |
| 1789 | return; | 1784 | return; |
| 1790 | 1785 | ||
| @@ -1897,14 +1892,10 @@ static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data) | |||
| 1897 | static int instance; | 1892 | static int instance; |
| 1898 | static int acpi_video_bus_add(struct acpi_device *device) | 1893 | static int acpi_video_bus_add(struct acpi_device *device) |
| 1899 | { | 1894 | { |
| 1900 | int result = 0; | 1895 | acpi_status status; |
| 1901 | acpi_status status = 0; | 1896 | struct acpi_video_bus *video; |
| 1902 | struct acpi_video_bus *video = NULL; | ||
| 1903 | struct input_dev *input; | 1897 | struct input_dev *input; |
| 1904 | 1898 | int error; | |
| 1905 | |||
| 1906 | if (!device) | ||
| 1907 | return -EINVAL; | ||
| 1908 | 1899 | ||
| 1909 | video = kzalloc(sizeof(struct acpi_video_bus), GFP_KERNEL); | 1900 | video = kzalloc(sizeof(struct acpi_video_bus), GFP_KERNEL); |
| 1910 | if (!video) | 1901 | if (!video) |
| @@ -1923,15 +1914,15 @@ static int acpi_video_bus_add(struct acpi_device *device) | |||
| 1923 | acpi_driver_data(device) = video; | 1914 | acpi_driver_data(device) = video; |
| 1924 | 1915 | ||
| 1925 | acpi_video_bus_find_cap(video); | 1916 | acpi_video_bus_find_cap(video); |
| 1926 | result = acpi_video_bus_check(video); | 1917 | error = acpi_video_bus_check(video); |
| 1927 | if (result) | 1918 | if (error) |
| 1928 | goto end; | 1919 | goto err_free_video; |
| 1929 | 1920 | ||
| 1930 | result = acpi_video_bus_add_fs(device); | 1921 | error = acpi_video_bus_add_fs(device); |
| 1931 | if (result) | 1922 | if (error) |
| 1932 | goto end; | 1923 | goto err_free_video; |
| 1933 | 1924 | ||
| 1934 | init_MUTEX(&video->sem); | 1925 | mutex_init(&video->device_list_lock); |
| 1935 | INIT_LIST_HEAD(&video->video_device_list); | 1926 | INIT_LIST_HEAD(&video->video_device_list); |
| 1936 | 1927 | ||
| 1937 | acpi_video_bus_get_devices(video, device); | 1928 | acpi_video_bus_get_devices(video, device); |
| @@ -1943,16 +1934,15 @@ static int acpi_video_bus_add(struct acpi_device *device) | |||
| 1943 | if (ACPI_FAILURE(status)) { | 1934 | if (ACPI_FAILURE(status)) { |
| 1944 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | 1935 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, |
| 1945 | "Error installing notify handler\n")); | 1936 | "Error installing notify handler\n")); |
| 1946 | acpi_video_bus_stop_devices(video); | 1937 | error = -ENODEV; |
| 1947 | acpi_video_bus_put_devices(video); | 1938 | goto err_stop_video; |
| 1948 | kfree(video->attached_array); | ||
| 1949 | acpi_video_bus_remove_fs(device); | ||
| 1950 | result = -ENODEV; | ||
| 1951 | goto end; | ||
| 1952 | } | 1939 | } |
| 1953 | 1940 | ||
| 1954 | |||
| 1955 | video->input = input = input_allocate_device(); | 1941 | video->input = input = input_allocate_device(); |
| 1942 | if (!input) { | ||
| 1943 | error = -ENOMEM; | ||
| 1944 | goto err_uninstall_notify; | ||
| 1945 | } | ||
| 1956 | 1946 | ||
| 1957 | snprintf(video->phys, sizeof(video->phys), | 1947 | snprintf(video->phys, sizeof(video->phys), |
| 1958 | "%s/video/input0", acpi_device_hid(video->device)); | 1948 | "%s/video/input0", acpi_device_hid(video->device)); |
| @@ -1961,6 +1951,7 @@ static int acpi_video_bus_add(struct acpi_device *device) | |||
| 1961 | input->phys = video->phys; | 1951 | input->phys = video->phys; |
| 1962 | input->id.bustype = BUS_HOST; | 1952 | input->id.bustype = BUS_HOST; |
| 1963 | input->id.product = 0x06; | 1953 | input->id.product = 0x06; |
| 1954 | input->dev.parent = &device->dev; | ||
| 1964 | input->evbit[0] = BIT(EV_KEY); | 1955 | input->evbit[0] = BIT(EV_KEY); |
| 1965 | set_bit(KEY_SWITCHVIDEOMODE, input->keybit); | 1956 | set_bit(KEY_SWITCHVIDEOMODE, input->keybit); |
| 1966 | set_bit(KEY_VIDEO_NEXT, input->keybit); | 1957 | set_bit(KEY_VIDEO_NEXT, input->keybit); |
| @@ -1971,18 +1962,10 @@ static int acpi_video_bus_add(struct acpi_device *device) | |||
| 1971 | set_bit(KEY_BRIGHTNESS_ZERO, input->keybit); | 1962 | set_bit(KEY_BRIGHTNESS_ZERO, input->keybit); |
| 1972 | set_bit(KEY_DISPLAY_OFF, input->keybit); | 1963 | set_bit(KEY_DISPLAY_OFF, input->keybit); |
| 1973 | set_bit(KEY_UNKNOWN, input->keybit); | 1964 | set_bit(KEY_UNKNOWN, input->keybit); |
| 1974 | result = input_register_device(input); | ||
| 1975 | if (result) { | ||
| 1976 | acpi_remove_notify_handler(video->device->handle, | ||
| 1977 | ACPI_DEVICE_NOTIFY, | ||
| 1978 | acpi_video_bus_notify); | ||
| 1979 | acpi_video_bus_stop_devices(video); | ||
| 1980 | acpi_video_bus_put_devices(video); | ||
| 1981 | kfree(video->attached_array); | ||
| 1982 | acpi_video_bus_remove_fs(device); | ||
| 1983 | goto end; | ||
| 1984 | } | ||
| 1985 | 1965 | ||
| 1966 | error = input_register_device(input); | ||
| 1967 | if (error) | ||
| 1968 | goto err_free_input_dev; | ||
| 1986 | 1969 | ||
| 1987 | printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s rom: %s post: %s)\n", | 1970 | printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s rom: %s post: %s)\n", |
| 1988 | ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device), | 1971 | ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device), |
| @@ -1990,11 +1973,23 @@ static int acpi_video_bus_add(struct acpi_device *device) | |||
| 1990 | video->flags.rom ? "yes" : "no", | 1973 | video->flags.rom ? "yes" : "no", |
| 1991 | video->flags.post ? "yes" : "no"); | 1974 | video->flags.post ? "yes" : "no"); |
| 1992 | 1975 | ||
| 1993 | end: | 1976 | return 0; |
| 1994 | if (result) | 1977 | |
| 1995 | kfree(video); | 1978 | err_free_input_dev: |
| 1979 | input_free_device(input); | ||
| 1980 | err_uninstall_notify: | ||
| 1981 | acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, | ||
| 1982 | acpi_video_bus_notify); | ||
| 1983 | err_stop_video: | ||
| 1984 | acpi_video_bus_stop_devices(video); | ||
| 1985 | acpi_video_bus_put_devices(video); | ||
| 1986 | kfree(video->attached_array); | ||
| 1987 | acpi_video_bus_remove_fs(device); | ||
| 1988 | err_free_video: | ||
| 1989 | kfree(video); | ||
| 1990 | acpi_driver_data(device) = NULL; | ||
| 1996 | 1991 | ||
| 1997 | return result; | 1992 | return error; |
| 1998 | } | 1993 | } |
| 1999 | 1994 | ||
| 2000 | static int acpi_video_bus_remove(struct acpi_device *device, int type) | 1995 | static int acpi_video_bus_remove(struct acpi_device *device, int type) |
