diff options
Diffstat (limited to 'drivers/acpi/video.c')
-rw-r--r-- | drivers/acpi/video.c | 112 |
1 files changed, 101 insertions, 11 deletions
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index d98701941981..d05891f16282 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c | |||
@@ -31,7 +31,7 @@ | |||
31 | #include <linux/list.h> | 31 | #include <linux/list.h> |
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 | #include <linux/input.h> | |
35 | #include <linux/backlight.h> | 35 | #include <linux/backlight.h> |
36 | #include <linux/video_output.h> | 36 | #include <linux/video_output.h> |
37 | #include <asm/uaccess.h> | 37 | #include <asm/uaccess.h> |
@@ -138,6 +138,8 @@ struct acpi_video_bus { | |||
138 | struct semaphore sem; | 138 | struct semaphore sem; |
139 | struct list_head video_device_list; | 139 | struct list_head video_device_list; |
140 | struct proc_dir_entry *dir; | 140 | struct proc_dir_entry *dir; |
141 | struct input_dev *input; | ||
142 | char phys[32]; /* for input device */ | ||
141 | }; | 143 | }; |
142 | 144 | ||
143 | struct acpi_video_device_flags { | 145 | struct acpi_video_device_flags { |
@@ -415,7 +417,6 @@ acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level) | |||
415 | arg0.integer.value = level; | 417 | arg0.integer.value = level; |
416 | status = acpi_evaluate_object(device->dev->handle, "_BCM", &args, NULL); | 418 | status = acpi_evaluate_object(device->dev->handle, "_BCM", &args, NULL); |
417 | 419 | ||
418 | printk(KERN_DEBUG "set_level status: %x\n", status); | ||
419 | return status; | 420 | return status; |
420 | } | 421 | } |
421 | 422 | ||
@@ -1752,7 +1753,7 @@ static int acpi_video_bus_put_devices(struct acpi_video_bus *video) | |||
1752 | 1753 | ||
1753 | static int acpi_video_bus_start_devices(struct acpi_video_bus *video) | 1754 | static int acpi_video_bus_start_devices(struct acpi_video_bus *video) |
1754 | { | 1755 | { |
1755 | return acpi_video_bus_DOS(video, 1, 0); | 1756 | return acpi_video_bus_DOS(video, 0, 0); |
1756 | } | 1757 | } |
1757 | 1758 | ||
1758 | static int acpi_video_bus_stop_devices(struct acpi_video_bus *video) | 1759 | static int acpi_video_bus_stop_devices(struct acpi_video_bus *video) |
@@ -1764,6 +1765,9 @@ static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data) | |||
1764 | { | 1765 | { |
1765 | struct acpi_video_bus *video = data; | 1766 | struct acpi_video_bus *video = data; |
1766 | struct acpi_device *device = NULL; | 1767 | struct acpi_device *device = NULL; |
1768 | struct input_dev *input; | ||
1769 | int keycode; | ||
1770 | |||
1767 | 1771 | ||
1768 | printk("video bus notify\n"); | 1772 | printk("video bus notify\n"); |
1769 | 1773 | ||
@@ -1771,11 +1775,13 @@ static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data) | |||
1771 | return; | 1775 | return; |
1772 | 1776 | ||
1773 | device = video->device; | 1777 | device = video->device; |
1778 | input = video->input; | ||
1774 | 1779 | ||
1775 | switch (event) { | 1780 | switch (event) { |
1776 | case ACPI_VIDEO_NOTIFY_SWITCH: /* User requested a switch, | 1781 | case ACPI_VIDEO_NOTIFY_SWITCH: /* User requested a switch, |
1777 | * most likely via hotkey. */ | 1782 | * most likely via hotkey. */ |
1778 | acpi_bus_generate_event(device, event, 0); | 1783 | acpi_bus_generate_proc_event(device, event, 0); |
1784 | keycode = KEY_SWITCHVIDEOMODE; | ||
1779 | break; | 1785 | break; |
1780 | 1786 | ||
1781 | case ACPI_VIDEO_NOTIFY_PROBE: /* User plugged in or removed a video | 1787 | case ACPI_VIDEO_NOTIFY_PROBE: /* User plugged in or removed a video |
@@ -1783,22 +1789,38 @@ static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data) | |||
1783 | acpi_video_device_enumerate(video); | 1789 | acpi_video_device_enumerate(video); |
1784 | acpi_video_device_rebind(video); | 1790 | acpi_video_device_rebind(video); |
1785 | acpi_video_switch_output(video, event); | 1791 | acpi_video_switch_output(video, event); |
1786 | acpi_bus_generate_event(device, event, 0); | 1792 | acpi_bus_generate_proc_event(device, event, 0); |
1793 | keycode = KEY_SWITCHVIDEOMODE; | ||
1787 | break; | 1794 | break; |
1788 | 1795 | ||
1789 | case ACPI_VIDEO_NOTIFY_CYCLE: /* Cycle Display output hotkey pressed. */ | 1796 | case ACPI_VIDEO_NOTIFY_CYCLE: /* Cycle Display output hotkey pressed. */ |
1797 | acpi_video_switch_output(video, event); | ||
1798 | acpi_bus_generate_proc_event(device, event, 0); | ||
1799 | keycode = KEY_SWITCHVIDEOMODE; | ||
1800 | break; | ||
1790 | case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT: /* Next Display output hotkey pressed. */ | 1801 | case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT: /* Next Display output hotkey pressed. */ |
1802 | acpi_video_switch_output(video, event); | ||
1803 | acpi_bus_generate_proc_event(device, event, 0); | ||
1804 | keycode = KEY_VIDEO_NEXT; | ||
1805 | break; | ||
1791 | case ACPI_VIDEO_NOTIFY_PREV_OUTPUT: /* previous Display output hotkey pressed. */ | 1806 | case ACPI_VIDEO_NOTIFY_PREV_OUTPUT: /* previous Display output hotkey pressed. */ |
1792 | acpi_video_switch_output(video, event); | 1807 | acpi_video_switch_output(video, event); |
1793 | acpi_bus_generate_event(device, event, 0); | 1808 | acpi_bus_generate_proc_event(device, event, 0); |
1809 | keycode = KEY_VIDEO_PREV; | ||
1794 | break; | 1810 | break; |
1795 | 1811 | ||
1796 | default: | 1812 | default: |
1813 | keycode = KEY_UNKNOWN; | ||
1797 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 1814 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
1798 | "Unsupported event [0x%x]\n", event)); | 1815 | "Unsupported event [0x%x]\n", event)); |
1799 | break; | 1816 | break; |
1800 | } | 1817 | } |
1801 | 1818 | ||
1819 | input_report_key(input, keycode, 1); | ||
1820 | input_sync(input); | ||
1821 | input_report_key(input, keycode, 0); | ||
1822 | input_sync(input); | ||
1823 | |||
1802 | return; | 1824 | return; |
1803 | } | 1825 | } |
1804 | 1826 | ||
@@ -1806,38 +1828,65 @@ static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data) | |||
1806 | { | 1828 | { |
1807 | struct acpi_video_device *video_device = data; | 1829 | struct acpi_video_device *video_device = data; |
1808 | struct acpi_device *device = NULL; | 1830 | struct acpi_device *device = NULL; |
1831 | struct acpi_video_bus *bus; | ||
1832 | struct input_dev *input; | ||
1833 | int keycode; | ||
1809 | 1834 | ||
1810 | if (!video_device) | 1835 | if (!video_device) |
1811 | return; | 1836 | return; |
1812 | 1837 | ||
1813 | device = video_device->dev; | 1838 | device = video_device->dev; |
1839 | bus = video_device->video; | ||
1840 | input = bus->input; | ||
1814 | 1841 | ||
1815 | switch (event) { | 1842 | switch (event) { |
1816 | case ACPI_VIDEO_NOTIFY_SWITCH: /* change in status (cycle output device) */ | ||
1817 | case ACPI_VIDEO_NOTIFY_PROBE: /* change in status (output device status) */ | ||
1818 | acpi_bus_generate_event(device, event, 0); | ||
1819 | break; | ||
1820 | case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS: /* Cycle brightness */ | 1843 | case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS: /* Cycle brightness */ |
1844 | acpi_video_switch_brightness(video_device, event); | ||
1845 | acpi_bus_generate_proc_event(device, event, 0); | ||
1846 | keycode = KEY_BRIGHTNESS_CYCLE; | ||
1847 | break; | ||
1821 | case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS: /* Increase brightness */ | 1848 | case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS: /* Increase brightness */ |
1849 | acpi_video_switch_brightness(video_device, event); | ||
1850 | acpi_bus_generate_proc_event(device, event, 0); | ||
1851 | keycode = KEY_BRIGHTNESSUP; | ||
1852 | break; | ||
1822 | case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS: /* Decrease brightness */ | 1853 | case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS: /* Decrease brightness */ |
1854 | acpi_video_switch_brightness(video_device, event); | ||
1855 | acpi_bus_generate_proc_event(device, event, 0); | ||
1856 | keycode = KEY_BRIGHTNESSDOWN; | ||
1857 | break; | ||
1823 | case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS: /* zero brightnesss */ | 1858 | case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS: /* zero brightnesss */ |
1859 | acpi_video_switch_brightness(video_device, event); | ||
1860 | acpi_bus_generate_proc_event(device, event, 0); | ||
1861 | keycode = KEY_BRIGHTNESS_ZERO; | ||
1862 | break; | ||
1824 | case ACPI_VIDEO_NOTIFY_DISPLAY_OFF: /* display device off */ | 1863 | case ACPI_VIDEO_NOTIFY_DISPLAY_OFF: /* display device off */ |
1825 | acpi_video_switch_brightness(video_device, event); | 1864 | acpi_video_switch_brightness(video_device, event); |
1826 | acpi_bus_generate_event(device, event, 0); | 1865 | acpi_bus_generate_proc_event(device, event, 0); |
1866 | keycode = KEY_DISPLAY_OFF; | ||
1827 | break; | 1867 | break; |
1828 | default: | 1868 | default: |
1869 | keycode = KEY_UNKNOWN; | ||
1829 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 1870 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
1830 | "Unsupported event [0x%x]\n", event)); | 1871 | "Unsupported event [0x%x]\n", event)); |
1831 | break; | 1872 | break; |
1832 | } | 1873 | } |
1874 | |||
1875 | input_report_key(input, keycode, 1); | ||
1876 | input_sync(input); | ||
1877 | input_report_key(input, keycode, 0); | ||
1878 | input_sync(input); | ||
1879 | |||
1833 | return; | 1880 | return; |
1834 | } | 1881 | } |
1835 | 1882 | ||
1883 | static int instance; | ||
1836 | static int acpi_video_bus_add(struct acpi_device *device) | 1884 | static int acpi_video_bus_add(struct acpi_device *device) |
1837 | { | 1885 | { |
1838 | int result = 0; | 1886 | int result = 0; |
1839 | acpi_status status = 0; | 1887 | acpi_status status = 0; |
1840 | struct acpi_video_bus *video = NULL; | 1888 | struct acpi_video_bus *video = NULL; |
1889 | struct input_dev *input; | ||
1841 | 1890 | ||
1842 | 1891 | ||
1843 | if (!device) | 1892 | if (!device) |
@@ -1847,6 +1896,13 @@ static int acpi_video_bus_add(struct acpi_device *device) | |||
1847 | if (!video) | 1896 | if (!video) |
1848 | return -ENOMEM; | 1897 | return -ENOMEM; |
1849 | 1898 | ||
1899 | /* a hack to fix the duplicate name "VID" problem on T61 */ | ||
1900 | if (!strcmp(device->pnp.bus_id, "VID")) { | ||
1901 | if (instance) | ||
1902 | device->pnp.bus_id[3] = '0' + instance; | ||
1903 | instance ++; | ||
1904 | } | ||
1905 | |||
1850 | video->device = device; | 1906 | video->device = device; |
1851 | strcpy(acpi_device_name(device), ACPI_VIDEO_BUS_NAME); | 1907 | strcpy(acpi_device_name(device), ACPI_VIDEO_BUS_NAME); |
1852 | strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS); | 1908 | strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS); |
@@ -1881,6 +1937,39 @@ static int acpi_video_bus_add(struct acpi_device *device) | |||
1881 | goto end; | 1937 | goto end; |
1882 | } | 1938 | } |
1883 | 1939 | ||
1940 | |||
1941 | video->input = input = input_allocate_device(); | ||
1942 | |||
1943 | snprintf(video->phys, sizeof(video->phys), | ||
1944 | "%s/video/input0", acpi_device_hid(video->device)); | ||
1945 | |||
1946 | input->name = acpi_device_name(video->device); | ||
1947 | input->phys = video->phys; | ||
1948 | input->id.bustype = BUS_HOST; | ||
1949 | input->id.product = 0x06; | ||
1950 | input->evbit[0] = BIT(EV_KEY); | ||
1951 | set_bit(KEY_SWITCHVIDEOMODE, input->keybit); | ||
1952 | set_bit(KEY_VIDEO_NEXT, input->keybit); | ||
1953 | set_bit(KEY_VIDEO_PREV, input->keybit); | ||
1954 | set_bit(KEY_BRIGHTNESS_CYCLE, input->keybit); | ||
1955 | set_bit(KEY_BRIGHTNESSUP, input->keybit); | ||
1956 | set_bit(KEY_BRIGHTNESSDOWN, input->keybit); | ||
1957 | set_bit(KEY_BRIGHTNESS_ZERO, input->keybit); | ||
1958 | set_bit(KEY_DISPLAY_OFF, input->keybit); | ||
1959 | set_bit(KEY_UNKNOWN, input->keybit); | ||
1960 | result = input_register_device(input); | ||
1961 | if (result) { | ||
1962 | acpi_remove_notify_handler(video->device->handle, | ||
1963 | ACPI_DEVICE_NOTIFY, | ||
1964 | acpi_video_bus_notify); | ||
1965 | acpi_video_bus_stop_devices(video); | ||
1966 | acpi_video_bus_put_devices(video); | ||
1967 | kfree(video->attached_array); | ||
1968 | acpi_video_bus_remove_fs(device); | ||
1969 | goto end; | ||
1970 | } | ||
1971 | |||
1972 | |||
1884 | printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s rom: %s post: %s)\n", | 1973 | printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s rom: %s post: %s)\n", |
1885 | ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device), | 1974 | ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device), |
1886 | video->flags.multihead ? "yes" : "no", | 1975 | video->flags.multihead ? "yes" : "no", |
@@ -1914,6 +2003,7 @@ static int acpi_video_bus_remove(struct acpi_device *device, int type) | |||
1914 | acpi_video_bus_put_devices(video); | 2003 | acpi_video_bus_put_devices(video); |
1915 | acpi_video_bus_remove_fs(device); | 2004 | acpi_video_bus_remove_fs(device); |
1916 | 2005 | ||
2006 | input_unregister_device(video->input); | ||
1917 | kfree(video->attached_array); | 2007 | kfree(video->attached_array); |
1918 | kfree(video); | 2008 | kfree(video); |
1919 | 2009 | ||