diff options
Diffstat (limited to 'drivers/acpi/video.c')
-rw-r--r-- | drivers/acpi/video.c | 101 |
1 files changed, 92 insertions, 9 deletions
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index ac63be4e8197..3c9bb85a6a93 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 { |
@@ -1764,6 +1766,9 @@ static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data) | |||
1764 | { | 1766 | { |
1765 | struct acpi_video_bus *video = data; | 1767 | struct acpi_video_bus *video = data; |
1766 | struct acpi_device *device = NULL; | 1768 | struct acpi_device *device = NULL; |
1769 | struct input_dev *input; | ||
1770 | int keycode; | ||
1771 | |||
1767 | 1772 | ||
1768 | printk("video bus notify\n"); | 1773 | printk("video bus notify\n"); |
1769 | 1774 | ||
@@ -1771,11 +1776,13 @@ static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data) | |||
1771 | return; | 1776 | return; |
1772 | 1777 | ||
1773 | device = video->device; | 1778 | device = video->device; |
1779 | input = video->input; | ||
1774 | 1780 | ||
1775 | switch (event) { | 1781 | switch (event) { |
1776 | case ACPI_VIDEO_NOTIFY_SWITCH: /* User requested a switch, | 1782 | case ACPI_VIDEO_NOTIFY_SWITCH: /* User requested a switch, |
1777 | * most likely via hotkey. */ | 1783 | * most likely via hotkey. */ |
1778 | acpi_bus_generate_event(device, event, 0); | 1784 | acpi_bus_generate_proc_event(device, event, 0); |
1785 | keycode = KEY_SWITCHVIDEOMODE; | ||
1779 | break; | 1786 | break; |
1780 | 1787 | ||
1781 | case ACPI_VIDEO_NOTIFY_PROBE: /* User plugged in or removed a video | 1788 | case ACPI_VIDEO_NOTIFY_PROBE: /* User plugged in or removed a video |
@@ -1783,22 +1790,38 @@ static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data) | |||
1783 | acpi_video_device_enumerate(video); | 1790 | acpi_video_device_enumerate(video); |
1784 | acpi_video_device_rebind(video); | 1791 | acpi_video_device_rebind(video); |
1785 | acpi_video_switch_output(video, event); | 1792 | acpi_video_switch_output(video, event); |
1786 | acpi_bus_generate_event(device, event, 0); | 1793 | acpi_bus_generate_proc_event(device, event, 0); |
1794 | keycode = KEY_SWITCHVIDEOMODE; | ||
1787 | break; | 1795 | break; |
1788 | 1796 | ||
1789 | case ACPI_VIDEO_NOTIFY_CYCLE: /* Cycle Display output hotkey pressed. */ | 1797 | case ACPI_VIDEO_NOTIFY_CYCLE: /* Cycle Display output hotkey pressed. */ |
1798 | acpi_video_switch_output(video, event); | ||
1799 | acpi_bus_generate_proc_event(device, event, 0); | ||
1800 | keycode = KEY_SWITCHVIDEOMODE; | ||
1801 | break; | ||
1790 | case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT: /* Next Display output hotkey pressed. */ | 1802 | case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT: /* Next Display output hotkey pressed. */ |
1803 | acpi_video_switch_output(video, event); | ||
1804 | acpi_bus_generate_proc_event(device, event, 0); | ||
1805 | keycode = KEY_VIDEO_NEXT; | ||
1806 | break; | ||
1791 | case ACPI_VIDEO_NOTIFY_PREV_OUTPUT: /* previous Display output hotkey pressed. */ | 1807 | case ACPI_VIDEO_NOTIFY_PREV_OUTPUT: /* previous Display output hotkey pressed. */ |
1792 | acpi_video_switch_output(video, event); | 1808 | acpi_video_switch_output(video, event); |
1793 | acpi_bus_generate_event(device, event, 0); | 1809 | acpi_bus_generate_proc_event(device, event, 0); |
1810 | keycode = KEY_VIDEO_PREV; | ||
1794 | break; | 1811 | break; |
1795 | 1812 | ||
1796 | default: | 1813 | default: |
1814 | keycode = KEY_UNKNOWN; | ||
1797 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 1815 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
1798 | "Unsupported event [0x%x]\n", event)); | 1816 | "Unsupported event [0x%x]\n", event)); |
1799 | break; | 1817 | break; |
1800 | } | 1818 | } |
1801 | 1819 | ||
1820 | input_report_key(input, keycode, 1); | ||
1821 | input_sync(input); | ||
1822 | input_report_key(input, keycode, 0); | ||
1823 | input_sync(input); | ||
1824 | |||
1802 | return; | 1825 | return; |
1803 | } | 1826 | } |
1804 | 1827 | ||
@@ -1806,30 +1829,55 @@ static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data) | |||
1806 | { | 1829 | { |
1807 | struct acpi_video_device *video_device = data; | 1830 | struct acpi_video_device *video_device = data; |
1808 | struct acpi_device *device = NULL; | 1831 | struct acpi_device *device = NULL; |
1832 | struct acpi_video_bus *bus; | ||
1833 | struct input_dev *input; | ||
1834 | int keycode; | ||
1809 | 1835 | ||
1810 | if (!video_device) | 1836 | if (!video_device) |
1811 | return; | 1837 | return; |
1812 | 1838 | ||
1813 | device = video_device->dev; | 1839 | device = video_device->dev; |
1840 | bus = video_device->video; | ||
1841 | input = bus->input; | ||
1814 | 1842 | ||
1815 | switch (event) { | 1843 | 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 */ | 1844 | case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS: /* Cycle brightness */ |
1845 | acpi_video_switch_brightness(video_device, event); | ||
1846 | acpi_bus_generate_proc_event(device, event, 0); | ||
1847 | keycode = KEY_BRIGHTNESS_CYCLE; | ||
1848 | break; | ||
1821 | case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS: /* Increase brightness */ | 1849 | case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS: /* Increase brightness */ |
1850 | acpi_video_switch_brightness(video_device, event); | ||
1851 | acpi_bus_generate_proc_event(device, event, 0); | ||
1852 | keycode = KEY_BRIGHTNESSUP; | ||
1853 | break; | ||
1822 | case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS: /* Decrease brightness */ | 1854 | case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS: /* Decrease brightness */ |
1855 | acpi_video_switch_brightness(video_device, event); | ||
1856 | acpi_bus_generate_proc_event(device, event, 0); | ||
1857 | keycode = KEY_BRIGHTNESSDOWN; | ||
1858 | break; | ||
1823 | case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS: /* zero brightnesss */ | 1859 | case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS: /* zero brightnesss */ |
1860 | acpi_video_switch_brightness(video_device, event); | ||
1861 | acpi_bus_generate_proc_event(device, event, 0); | ||
1862 | keycode = KEY_BRIGHTNESS_ZERO; | ||
1863 | break; | ||
1824 | case ACPI_VIDEO_NOTIFY_DISPLAY_OFF: /* display device off */ | 1864 | case ACPI_VIDEO_NOTIFY_DISPLAY_OFF: /* display device off */ |
1825 | acpi_video_switch_brightness(video_device, event); | 1865 | acpi_video_switch_brightness(video_device, event); |
1826 | acpi_bus_generate_event(device, event, 0); | 1866 | acpi_bus_generate_proc_event(device, event, 0); |
1867 | keycode = KEY_DISPLAY_OFF; | ||
1827 | break; | 1868 | break; |
1828 | default: | 1869 | default: |
1870 | keycode = KEY_UNKNOWN; | ||
1829 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 1871 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
1830 | "Unsupported event [0x%x]\n", event)); | 1872 | "Unsupported event [0x%x]\n", event)); |
1831 | break; | 1873 | break; |
1832 | } | 1874 | } |
1875 | |||
1876 | input_report_key(input, keycode, 1); | ||
1877 | input_sync(input); | ||
1878 | input_report_key(input, keycode, 0); | ||
1879 | input_sync(input); | ||
1880 | |||
1833 | return; | 1881 | return; |
1834 | } | 1882 | } |
1835 | 1883 | ||
@@ -1839,6 +1887,7 @@ static int acpi_video_bus_add(struct acpi_device *device) | |||
1839 | int result = 0; | 1887 | int result = 0; |
1840 | acpi_status status = 0; | 1888 | acpi_status status = 0; |
1841 | struct acpi_video_bus *video = NULL; | 1889 | struct acpi_video_bus *video = NULL; |
1890 | struct input_dev *input; | ||
1842 | 1891 | ||
1843 | 1892 | ||
1844 | if (!device) | 1893 | if (!device) |
@@ -1889,6 +1938,39 @@ static int acpi_video_bus_add(struct acpi_device *device) | |||
1889 | goto end; | 1938 | goto end; |
1890 | } | 1939 | } |
1891 | 1940 | ||
1941 | |||
1942 | video->input = input = input_allocate_device(); | ||
1943 | |||
1944 | snprintf(video->phys, sizeof(video->phys), | ||
1945 | "%s/video/input0", acpi_device_hid(video->device)); | ||
1946 | |||
1947 | input->name = acpi_device_name(video->device); | ||
1948 | input->phys = video->phys; | ||
1949 | input->id.bustype = BUS_HOST; | ||
1950 | input->id.product = 0x06; | ||
1951 | input->evbit[0] = BIT(EV_KEY); | ||
1952 | set_bit(KEY_SWITCHVIDEOMODE, input->keybit); | ||
1953 | set_bit(KEY_VIDEO_NEXT, input->keybit); | ||
1954 | set_bit(KEY_VIDEO_PREV, input->keybit); | ||
1955 | set_bit(KEY_BRIGHTNESS_CYCLE, input->keybit); | ||
1956 | set_bit(KEY_BRIGHTNESSUP, input->keybit); | ||
1957 | set_bit(KEY_BRIGHTNESSDOWN, input->keybit); | ||
1958 | set_bit(KEY_BRIGHTNESS_ZERO, input->keybit); | ||
1959 | set_bit(KEY_DISPLAY_OFF, input->keybit); | ||
1960 | set_bit(KEY_UNKNOWN, input->keybit); | ||
1961 | result = input_register_device(input); | ||
1962 | if (result) { | ||
1963 | acpi_remove_notify_handler(video->device->handle, | ||
1964 | ACPI_DEVICE_NOTIFY, | ||
1965 | acpi_video_bus_notify); | ||
1966 | acpi_video_bus_stop_devices(video); | ||
1967 | acpi_video_bus_put_devices(video); | ||
1968 | kfree(video->attached_array); | ||
1969 | acpi_video_bus_remove_fs(device); | ||
1970 | goto end; | ||
1971 | } | ||
1972 | |||
1973 | |||
1892 | printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s rom: %s post: %s)\n", | 1974 | printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s rom: %s post: %s)\n", |
1893 | ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device), | 1975 | ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device), |
1894 | video->flags.multihead ? "yes" : "no", | 1976 | video->flags.multihead ? "yes" : "no", |
@@ -1922,6 +2004,7 @@ static int acpi_video_bus_remove(struct acpi_device *device, int type) | |||
1922 | acpi_video_bus_put_devices(video); | 2004 | acpi_video_bus_put_devices(video); |
1923 | acpi_video_bus_remove_fs(device); | 2005 | acpi_video_bus_remove_fs(device); |
1924 | 2006 | ||
2007 | input_unregister_device(video->input); | ||
1925 | kfree(video->attached_array); | 2008 | kfree(video->attached_array); |
1926 | kfree(video); | 2009 | kfree(video); |
1927 | 2010 | ||