From: Linus Torvalds Date: Thu, 28 Oct 2010 16:35:11 +0000 (-0700) Subject: Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab... X-Git-Tag: v2.6.37-rc1~64 X-Git-Url: https://bbs.cooldavid.org/git/?a=commitdiff_plain;h=0851668fdd97e526b2a41f794b785c204dd3d3e0;hp=-c;p=net-next-2.6.git Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6 * 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (505 commits) [media] af9015: Fix max I2C message size when used with tda18271 [media] IR: initialize ir_raw_event in few more drivers [media] Guard a divide in v4l1 compat layer [media] imon: fix nomouse modprobe option [media] imon: remove redundant change_protocol call [media] imon: fix my egregious brown paper bag w/rdev/idev split [media] cafe_ccic: Configure ov7670 correctly [media] ov7670: allow configuration of image size, clock speed, and I/O method [media] af9015: support for DigitalNow TinyTwin v3 [1f4d:9016] [media] af9015: map DigitalNow TinyTwin v2 remote [media] DigitalNow TinyTwin remote controller [media] af9015: RC fixes and improvements videodev2.h.xml: Update to reflect the latest changes at videodev2.h [media] v4l: document new Bayer and monochrome pixel formats [media] DocBook/v4l: Add missing formats used on gspca cpia1 and sn9c2028 [media] firedtv: add parameter to fake ca_system_ids in CA_INFO [media] tm6000: fix a macro coding style issue tm6000: Remove some ugly debug code [media] Nova-S-Plus audio line input [media] [RFC,1/1] V4L2: Use new CAP bits in existing RDS capable drivers ... --- 0851668fdd97e526b2a41f794b785c204dd3d3e0 diff --combined Documentation/devices.txt index 170cc1e7e13,76b1d2f22b6..eccffe71522 --- a/Documentation/devices.txt +++ b/Documentation/devices.txt @@@ -239,7 -239,6 +239,7 @@@ Your cooperation is appreciated 0 = /dev/tty Current TTY device 1 = /dev/console System console 2 = /dev/ptmx PTY master multiplex + 3 = /dev/ttyprintk User messages via printk TTY device 64 = /dev/cua0 Callout device for ttyS0 ... 255 = /dev/cua191 Callout device for ttyS191 @@@ -1496,9 -1495,6 +1496,6 @@@ 64 = /dev/radio0 Radio device ... 127 = /dev/radio63 Radio device - 192 = /dev/vtx0 Teletext device - ... - 223 = /dev/vtx31 Teletext device 224 = /dev/vbi0 Vertical blank interrupt ... 255 = /dev/vbi31 Vertical blank interrupt @@@ -2520,12 -2516,6 +2517,12 @@@ 8 = /dev/mmcblk1 Second SD/MMC card ... + The start of next SD/MMC card can be configured with + CONFIG_MMC_BLOCK_MINORS, or overridden at boot/modprobe + time using the mmcblk.perdev_minors option. That would + bump the offset between each card to be the configured + value instead of the default 8. + 179 char CCube DVXChip-based PCI products 0 = /dev/dvxirq0 First DVX device 1 = /dev/dvxirq1 Second DVX device @@@ -2560,10 -2550,7 +2557,10 @@@ 175 = /dev/usb/legousbtower15 16th USB Legotower device 176 = /dev/usb/usbtmc1 First USB TMC device ... - 192 = /dev/usb/usbtmc16 16th USB TMC device + 191 = /dev/usb/usbtmc16 16th USB TMC device + 192 = /dev/usb/yurex1 First USB Yurex device + ... + 209 = /dev/usb/yurex16 16th USB Yurex device 240 = /dev/usb/dabusb0 First daubusb device ... 243 = /dev/usb/dabusb3 Fourth dabusb device diff --combined Documentation/feature-removal-schedule.txt index f3da8c0a3af,d87ee1760e3..d8f36f984fa --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@@ -98,7 -98,7 +98,7 @@@ Who: Pavel Machek + + --------------------------- + What: sys_sysctl When: September 2010 Option: CONFIG_SYSCTL_SYSCALL @@@ -386,6 -401,34 +401,6 @@@ Who: Tejun Heo - ----------------------------- - What: Support for lcd_switch and display_get in asus-laptop driver When: March 2010 Why: These two features use non-standard interfaces. There are the @@@ -470,29 -513,6 +485,6 @@@ When: April 201 Why: Superseded by xt_CT Who: Netfilter developer team - --------------------------- - - What: video4linux /dev/vtx teletext API support - When: 2.6.35 - Files: drivers/media/video/saa5246a.c drivers/media/video/saa5249.c - include/linux/videotext.h - Why: The vtx device nodes have been superseded by vbi device nodes - for many years. No applications exist that use the vtx support. - Of the two i2c drivers that actually support this API the saa5249 - has been impossible to use for a year now and no known hardware - that supports this device exists. The saa5246a is theoretically - supported by the old mxb boards, but it never actually worked. - - In summary: there is no hardware that can use this API and there - are no applications actually implementing this API. - - The vtx support still reserves minors 192-223 and we would really - like to reuse those for upcoming new functionality. In the unlikely - event that new hardware appears that wants to use the functionality - provided by the vtx API, then that functionality should be build - around the sliced VBI API instead. - Who: Hans Verkuil - ---------------------------- What: IRQF_DISABLED @@@ -502,6 -522,16 +494,6 @@@ Who: Thomas Gleixner - ----------------------------- - What: The acpi_sleep=s4_nonvs command line option When: 2.6.37 Files: arch/x86/kernel/acpi/sleep.c @@@ -526,39 -556,3 +518,39 @@@ Who: FUJITA Tomonori + +---------------------------- + +What: iwlwifi disable_hw_scan module parameters +When: 2.6.40 +Why: Hareware scan is the prefer method for iwlwifi devices for + scanning operation. Remove software scan support for all the + iwlwifi devices. + +Who: Wey-Yi Guy + +---------------------------- + +What: access to nfsd auth cache through sys_nfsservctl or '.' files + in the 'nfsd' filesystem. +When: 2.6.40 +Why: This is a legacy interface which have been replaced by a more + dynamic cache. Continuing to maintain this interface is an + unnecessary burden. +Who: NeilBrown + +---------------------------- diff --combined arch/arm/mach-mx3/mach-pcm037.c index 86e86c1300d,b3288979833..2ff3f661a48 --- a/arch/arm/mach-mx3/mach-pcm037.c +++ b/arch/arm/mach-mx3/mach-pcm037.c @@@ -311,7 -311,6 +311,6 @@@ static struct soc_camera_link iclink_mt .bus_id = 0, /* Must match with the camera ID */ .board_info = &pcm037_i2c_camera[1], .i2c_adapter_id = 2, - .module_name = "mt9v022", }; static struct soc_camera_link iclink_mt9t031 = { @@@ -319,7 -318,6 +318,6 @@@ .power = pcm037_camera_power, .board_info = &pcm037_i2c_camera[0], .i2c_adapter_id = 2, - .module_name = "mt9t031", }; static struct i2c_board_info pcm037_i2c_devices[] = { @@@ -680,6 -678,8 +678,6 @@@ struct sys_timer pcm037_timer = MACHINE_START(PCM037, "Phytec Phycore pcm037") /* Maintainer: Pengutronix */ - .phys_io = MX31_AIPS1_BASE_ADDR, - .io_pg_offst = (MX31_AIPS1_BASE_ADDR_VIRT >> 18) & 0xfffc, .boot_params = MX3x_PHYS_OFFSET + 0x100, .map_io = mx31_map_io, .init_irq = mx31_init_irq, diff --combined arch/arm/mach-pxa/em-x270.c index ab48bb81b57,0c95476c791..ed0dbfdb22e --- a/arch/arm/mach-pxa/em-x270.c +++ b/arch/arm/mach-pxa/em-x270.c @@@ -43,7 -43,7 +43,7 @@@ #include #include #include -#include +#include #include #include #include @@@ -1015,7 -1015,6 +1015,6 @@@ static struct soc_camera_link iclink = .power = em_x270_sensor_power, .board_info = &em_x270_i2c_cam_info[0], .i2c_adapter_id = 0, - .module_name = "mt9m111", }; static struct platform_device em_x270_camera = { @@@ -1301,6 -1300,8 +1300,6 @@@ static void __init em_x270_init(void MACHINE_START(EM_X270, "Compulab EM-X270") .boot_params = 0xa0000100, - .phys_io = 0x40000000, - .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .map_io = pxa_map_io, .init_irq = pxa27x_init_irq, .timer = &pxa_timer, @@@ -1309,6 -1310,8 +1308,6 @@@ MACHINE_EN MACHINE_START(EXEDA, "Compulab eXeda") .boot_params = 0xa0000100, - .phys_io = 0x40000000, - .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .map_io = pxa_map_io, .init_irq = pxa27x_init_irq, .timer = &pxa_timer, diff --combined arch/arm/mach-pxa/ezx.c index 80a9352d43f,70dfe0867ef..142c711f4cd --- a/arch/arm/mach-pxa/ezx.c +++ b/arch/arm/mach-pxa/ezx.c @@@ -32,14 -32,12 +32,14 @@@ #include #include #include -#include +#include #include #include "devices.h" #include "generic.h" +#define EZX_NR_IRQS (IRQ_BOARD_START + 24) + #define GPIO12_A780_FLIP_LID 12 #define GPIO15_A1200_FLIP_LID 15 #define GPIO15_A910_FLIP_LID 15 @@@ -755,7 -753,6 +755,6 @@@ static struct soc_camera_link a780_icli .flags = SOCAM_SENSOR_INVERT_PCLK, .i2c_adapter_id = 0, .board_info = &a780_camera_i2c_board_info, - .module_name = "mt9m111", .power = a780_camera_power, .reset = a780_camera_reset, }; @@@ -798,9 -795,10 +797,9 @@@ static void __init a780_init(void } MACHINE_START(EZX_A780, "Motorola EZX A780") - .phys_io = 0x40000000, - .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .boot_params = 0xa0000100, .map_io = pxa_map_io, + .nr_irqs = EZX_NR_IRQS, .init_irq = pxa27x_init_irq, .timer = &pxa_timer, .init_machine = a780_init, @@@ -863,9 -861,10 +862,9 @@@ static void __init e680_init(void } MACHINE_START(EZX_E680, "Motorola EZX E680") - .phys_io = 0x40000000, - .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .boot_params = 0xa0000100, .map_io = pxa_map_io, + .nr_irqs = EZX_NR_IRQS, .init_irq = pxa27x_init_irq, .timer = &pxa_timer, .init_machine = e680_init, @@@ -928,9 -927,10 +927,9 @@@ static void __init a1200_init(void } MACHINE_START(EZX_A1200, "Motorola EZX A1200") - .phys_io = 0x40000000, - .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .boot_params = 0xa0000100, .map_io = pxa_map_io, + .nr_irqs = EZX_NR_IRQS, .init_irq = pxa27x_init_irq, .timer = &pxa_timer, .init_machine = a1200_init, @@@ -1024,7 -1024,6 +1023,6 @@@ static struct soc_camera_link a910_icli .bus_id = 0, .i2c_adapter_id = 0, .board_info = &a910_camera_i2c_board_info, - .module_name = "mt9m111", .power = a910_camera_power, .reset = a910_camera_reset, }; @@@ -1119,9 -1118,10 +1117,9 @@@ static void __init a910_init(void } MACHINE_START(EZX_A910, "Motorola EZX A910") - .phys_io = 0x40000000, - .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .boot_params = 0xa0000100, .map_io = pxa_map_io, + .nr_irqs = EZX_NR_IRQS, .init_irq = pxa27x_init_irq, .timer = &pxa_timer, .init_machine = a910_init, @@@ -1184,9 -1184,10 +1182,9 @@@ static void __init e6_init(void } MACHINE_START(EZX_E6, "Motorola EZX E6") - .phys_io = 0x40000000, - .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .boot_params = 0xa0000100, .map_io = pxa_map_io, + .nr_irqs = EZX_NR_IRQS, .init_irq = pxa27x_init_irq, .timer = &pxa_timer, .init_machine = e6_init, @@@ -1223,9 -1224,10 +1221,9 @@@ static void __init e2_init(void } MACHINE_START(EZX_E2, "Motorola EZX E2") - .phys_io = 0x40000000, - .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .boot_params = 0xa0000100, .map_io = pxa_map_io, + .nr_irqs = EZX_NR_IRQS, .init_irq = pxa27x_init_irq, .timer = &pxa_timer, .init_machine = e2_init, diff --combined arch/arm/mach-pxa/mioa701.c index 0c31fabfc7f,83734c8b4b5..f5fb915e131 --- a/arch/arm/mach-pxa/mioa701.c +++ b/arch/arm/mach-pxa/mioa701.c @@@ -45,7 -45,7 +45,7 @@@ #include #include -#include +#include #include #include #include @@@ -711,7 -711,6 +711,6 @@@ static struct soc_camera_link iclink = .bus_id = 0, /* Match id in pxa27x_device_camera in device.c */ .board_info = &mioa701_i2c_devices[0], .i2c_adapter_id = 0, - .module_name = "mt9m111", }; struct i2c_pxa_platform_data i2c_pdata = { @@@ -819,6 -818,8 +818,6 @@@ static void mioa701_machine_exit(void } MACHINE_START(MIOA701, "MIO A701") - .phys_io = 0x40000000, - .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .boot_params = 0xa0000100, .map_io = &pxa_map_io, .init_irq = &pxa27x_init_irq, diff --combined arch/sh/boards/mach-ecovec24/setup.c index 71a3368ab1f,ae0b1382284..ddc7e4e4d2a --- a/arch/sh/boards/mach-ecovec24/setup.c +++ b/arch/sh/boards/mach-ecovec24/setup.c @@@ -620,7 -620,6 +620,6 @@@ static struct soc_camera_link tw9910_li .bus_id = 1, .power = tw9910_power, .board_info = &i2c_camera[0], - .module_name = "tw9910", .priv = &tw9910_info, }; @@@ -644,7 -643,6 +643,6 @@@ static struct soc_camera_link mt9t112_l .power = mt9t112_power1, .bus_id = 0, .board_info = &i2c_camera[1], - .module_name = "mt9t112", .priv = &mt9t112_info1, }; @@@ -667,7 -665,6 +665,6 @@@ static struct soc_camera_link mt9t112_l .power = mt9t112_power2, .bus_id = 1, .board_info = &i2c_camera[2], - .module_name = "mt9t112", .priv = &mt9t112_info2, }; @@@ -793,7 -790,6 +790,6 @@@ static struct sh_vou_pdata sh_vou_pdat .flags = SH_VOU_HSYNC_LOW | SH_VOU_VSYNC_LOW, .board_info = &ak8813, .i2c_adap = 0, - .module_name = "ak881x", }; static struct resource sh_vou_resources[] = { @@@ -1248,14 -1244,14 +1244,14 @@@ static int __init arch_setup(void /* set SPU2 clock to 83.4 MHz */ clk = clk_get(NULL, "spu_clk"); - if (clk) { + if (!IS_ERR(clk)) { clk_set_rate(clk, clk_round_rate(clk, 83333333)); clk_put(clk); } /* change parent of FSI B */ clk = clk_get(NULL, "fsib_clk"); - if (clk) { + if (!IS_ERR(clk)) { clk_register(&fsimckb_clk); clk_set_parent(clk, &fsimckb_clk); clk_set_rate(clk, 11000); @@@ -1273,7 -1269,7 +1269,7 @@@ /* set VPU clock to 166 MHz */ clk = clk_get(NULL, "vpu_clk"); - if (clk) { + if (!IS_ERR(clk)) { clk_set_rate(clk, clk_round_rate(clk, 166000000)); clk_put(clk); } diff --combined drivers/media/IR/imon.c index faed5a332c7,f782a9d72ce..bc118066bc3 --- a/drivers/media/IR/imon.c +++ b/drivers/media/IR/imon.c @@@ -1,7 -1,7 +1,7 @@@ /* * imon.c: input and display driver for SoundGraph iMON IR/VFD/LCD * - * Copyright(C) 2009 Jarod Wilson + * Copyright(C) 2010 Jarod Wilson * Portions based on the original lirc_imon driver, * Copyright(C) 2004 Venky Raju(dev@venky.ws) * @@@ -26,6 -26,8 +26,8 @@@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + #define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__ + #include #include #include @@@ -44,7 -46,7 +46,7 @@@ #define MOD_AUTHOR "Jarod Wilson " #define MOD_DESC "Driver for SoundGraph iMON MultiMedia IR/Display" #define MOD_NAME "imon" - #define MOD_VERSION "0.9.1" + #define MOD_VERSION "0.9.2" #define DISPLAY_MINOR_BASE 144 #define DEVICE_NAME "lcd%d" @@@ -121,21 -123,26 +123,26 @@@ struct imon_context u16 vendor; /* usb vendor ID */ u16 product; /* usb product ID */ - struct input_dev *idev; /* input device for remote */ + struct input_dev *rdev; /* input device for remote */ + struct input_dev *idev; /* input device for panel & IR mouse */ struct input_dev *touch; /* input device for touchscreen */ + spinlock_t kc_lock; /* make sure we get keycodes right */ u32 kc; /* current input keycode */ u32 last_keycode; /* last reported input keycode */ + u32 rc_scancode; /* the computed remote scancode */ + u8 rc_toggle; /* the computed remote toggle bit */ u64 ir_type; /* iMON or MCE (RC6) IR protocol? */ - u8 mce_toggle_bit; /* last mce toggle bit */ bool release_code; /* some keys send a release code */ u8 display_type; /* store the display type */ bool pad_mouse; /* toggle kbd(0)/mouse(1) mode */ + char name_rdev[128]; /* rc input device name */ + char phys_rdev[64]; /* rc input device phys path */ + char name_idev[128]; /* input device name */ char phys_idev[64]; /* input device phys path */ - struct timer_list itimer; /* input device timer, need for rc6 */ char name_touch[128]; /* touch screen name */ char phys_touch[64]; /* touch screen phys path */ @@@ -151,8 -158,7 +158,8 @@@ static const struct file_operations vfd .owner = THIS_MODULE, .open = &display_open, .write = &vfd_write, - .release = &display_close + .release = &display_close, + .llseek = noop_llseek, }; /* lcd character device file operations */ @@@ -160,8 -166,7 +167,8 @@@ static const struct file_operations lcd .owner = THIS_MODULE, .open = &display_open, .write = &lcd_write, - .release = &display_close + .release = &display_close, + .llseek = noop_llseek, }; enum { @@@ -289,6 -294,9 +296,9 @@@ static const struct { 0x000100000000ffeell, KEY_VOLUMEUP }, { 0x010000000000ffeell, KEY_VOLUMEDOWN }, { 0x000000000100ffeell, KEY_MUTE }, + /* 0xffdc iMON MCE VFD */ + { 0x00010000ffffffeell, KEY_VOLUMEUP }, + { 0x01000000ffffffeell, KEY_VOLUMEDOWN }, /* iMON Knob values */ { 0x000100ffffffffeell, KEY_VOLUMEUP }, { 0x010000ffffffffeell, KEY_VOLUMEDOWN }, @@@ -307,7 -315,7 +317,7 @@@ MODULE_DEVICE_TABLE(usb, imon_usb_id_ta static bool debug; module_param(debug, bool, S_IRUGO | S_IWUSR); - MODULE_PARM_DESC(debug, "Debug messages: 0=no, 1=yes(default: no)"); + MODULE_PARM_DESC(debug, "Debug messages: 0=no, 1=yes (default: no)"); /* lcd, vfd, vga or none? should be auto-detected, but can be overridden... */ static int display_type; @@@ -365,15 -373,14 +375,14 @@@ static int display_open(struct inode *i subminor = iminor(inode); interface = usb_find_interface(&imon_driver, subminor); if (!interface) { - err("%s: could not find interface for minor %d", - __func__, subminor); + pr_err("could not find interface for minor %d\n", subminor); retval = -ENODEV; goto exit; } ictx = usb_get_intfdata(interface); if (!ictx) { - err("%s: no context found for minor %d", __func__, subminor); + pr_err("no context found for minor %d\n", subminor); retval = -ENODEV; goto exit; } @@@ -381,10 -388,10 +390,10 @@@ mutex_lock(&ictx->lock); if (!ictx->display_supported) { - err("%s: display not supported by device", __func__); + pr_err("display not supported by device\n"); retval = -ENODEV; } else if (ictx->display_isopen) { - err("%s: display port is already open", __func__); + pr_err("display port is already open\n"); retval = -EBUSY; } else { ictx->display_isopen = true; @@@ -411,17 -418,17 +420,17 @@@ static int display_close(struct inode * ictx = file->private_data; if (!ictx) { - err("%s: no context for device", __func__); + pr_err("no context for device\n"); return -ENODEV; } mutex_lock(&ictx->lock); if (!ictx->display_supported) { - err("%s: display not supported by device", __func__); + pr_err("display not supported by device\n"); retval = -ENODEV; } else if (!ictx->display_isopen) { - err("%s: display is not open", __func__); + pr_err("display is not open\n"); retval = -EIO; } else { ictx->display_isopen = false; @@@ -500,19 -507,19 +509,19 @@@ static int send_packet(struct imon_cont if (retval) { ictx->tx.busy = false; smp_rmb(); /* ensure later readers know we're not busy */ - err("%s: error submitting urb(%d)", __func__, retval); + pr_err("error submitting urb(%d)\n", retval); } else { /* Wait for transmission to complete (or abort) */ mutex_unlock(&ictx->lock); retval = wait_for_completion_interruptible( &ictx->tx.finished); if (retval) - err("%s: task interrupted", __func__); + pr_err("task interrupted\n"); mutex_lock(&ictx->lock); retval = ictx->tx.status; if (retval) - err("%s: packet tx failed (%d)", __func__, retval); + pr_err("packet tx failed (%d)\n", retval); } kfree(control_req); @@@ -544,12 -551,12 +553,12 @@@ static int send_associate_24g(struct im 0x00, 0x00, 0x00, 0x20 }; if (!ictx) { - err("%s: no context for device", __func__); + pr_err("no context for device\n"); return -ENODEV; } if (!ictx->dev_present_intf0) { - err("%s: no iMON device present", __func__); + pr_err("no iMON device present\n"); return -ENODEV; } @@@ -577,7 -584,7 +586,7 @@@ static int send_set_imon_clock(struct i int i; if (!ictx) { - err("%s: no context for device", __func__); + pr_err("no context for device\n"); return -ENODEV; } @@@ -638,8 -645,7 +647,7 @@@ memcpy(ictx->usb_tx_buf, clock_enable_pkt[i], 8); retval = send_packet(ictx); if (retval) { - err("%s: send_packet failed for packet %d", - __func__, i); + pr_err("send_packet failed for packet %d\n", i); break; } } @@@ -778,7 -784,7 +786,7 @@@ static struct attribute *imon_display_s NULL }; - static struct attribute_group imon_display_attribute_group = { + static struct attribute_group imon_display_attr_group = { .attrs = imon_display_sysfs_entries }; @@@ -787,7 -793,7 +795,7 @@@ static struct attribute *imon_rf_sysfs_ NULL }; - static struct attribute_group imon_rf_attribute_group = { + static struct attribute_group imon_rf_attr_group = { .attrs = imon_rf_sysfs_entries }; @@@ -815,20 -821,20 +823,20 @@@ static ssize_t vfd_write(struct file *f ictx = file->private_data; if (!ictx) { - err("%s: no context for device", __func__); + pr_err("no context for device\n"); return -ENODEV; } mutex_lock(&ictx->lock); if (!ictx->dev_present_intf0) { - err("%s: no iMON device present", __func__); + pr_err("no iMON device present\n"); retval = -ENODEV; goto exit; } if (n_bytes <= 0 || n_bytes > 32) { - err("%s: invalid payload size", __func__); + pr_err("invalid payload size\n"); retval = -EINVAL; goto exit; } @@@ -854,8 -860,7 +862,7 @@@ retval = send_packet(ictx); if (retval) { - err("%s: send packet failed for packet #%d", - __func__, seq/2); + pr_err("send packet failed for packet #%d\n", seq / 2); goto exit; } else { seq += 2; @@@ -869,8 -874,7 +876,7 @@@ ictx->usb_tx_buf[7] = (unsigned char) seq; retval = send_packet(ictx); if (retval) - err("%s: send packet failed for packet #%d", - __func__, seq / 2); + pr_err("send packet failed for packet #%d\n", seq / 2); exit: mutex_unlock(&ictx->lock); @@@ -899,21 -903,20 +905,20 @@@ static ssize_t lcd_write(struct file *f ictx = file->private_data; if (!ictx) { - err("%s: no context for device", __func__); + pr_err("no context for device\n"); return -ENODEV; } mutex_lock(&ictx->lock); if (!ictx->display_supported) { - err("%s: no iMON display present", __func__); + pr_err("no iMON display present\n"); retval = -ENODEV; goto exit; } if (n_bytes != 8) { - err("%s: invalid payload size: %d (expecting 8)", - __func__, (int) n_bytes); + pr_err("invalid payload size: %d (expected 8)\n", (int)n_bytes); retval = -EINVAL; goto exit; } @@@ -925,7 -928,7 +930,7 @@@ retval = send_packet(ictx); if (retval) { - err("%s: send packet failed!", __func__); + pr_err("send packet failed!\n"); goto exit; } else { dev_dbg(ictx->dev, "%s: write %d bytes to LCD\n", @@@ -957,17 -960,6 +962,6 @@@ static void usb_tx_callback(struct urb complete(&ictx->tx.finished); } - /** - * mce/rc6 keypresses have no distinct release code, use timer - */ - static void imon_mce_timeout(unsigned long data) - { - struct imon_context *ictx = (struct imon_context *)data; - - input_report_key(ictx->idev, ictx->last_keycode, 0); - input_sync(ictx->idev); - } - /** * report touchscreen input */ @@@ -1008,14 -1000,11 +1002,11 @@@ int imon_ir_change_protocol(void *priv dev_dbg(dev, "Configuring IR receiver for MCE protocol\n"); ir_proto_packet[0] = 0x01; pad_mouse = false; - init_timer(&ictx->itimer); - ictx->itimer.data = (unsigned long)ictx; - ictx->itimer.function = imon_mce_timeout; break; case IR_TYPE_UNKNOWN: case IR_TYPE_OTHER: dev_dbg(dev, "Configuring IR receiver for iMON protocol\n"); - if (pad_stabilize) + if (pad_stabilize && !nomouse) pad_mouse = true; else { dev_dbg(dev, "PAD stabilize functionality disabled\n"); @@@ -1027,7 -1016,7 +1018,7 @@@ default: dev_warn(dev, "Unsupported IR protocol specified, overriding " "to iMON IR protocol\n"); - if (pad_stabilize) + if (pad_stabilize && !nomouse) pad_mouse = true; else { dev_dbg(dev, "PAD stabilize functionality disabled\n"); @@@ -1149,20 -1138,21 +1140,21 @@@ static int stabilize(int a, int b, u16 return result; } - static u32 imon_remote_key_lookup(struct imon_context *ictx, u32 hw_code) + static u32 imon_remote_key_lookup(struct imon_context *ictx, u32 scancode) { - u32 scancode = be32_to_cpu(hw_code); u32 keycode; u32 release; bool is_release_code = false; /* Look for the initial press of a button */ - keycode = ir_g_keycode_from_table(ictx->idev, scancode); + keycode = ir_g_keycode_from_table(ictx->rdev, scancode); + ictx->rc_toggle = 0x0; + ictx->rc_scancode = scancode; /* Look for the release of a button */ if (keycode == KEY_RESERVED) { release = scancode & ~0x4000; - keycode = ir_g_keycode_from_table(ictx->idev, release); + keycode = ir_g_keycode_from_table(ictx->rdev, release); if (keycode != KEY_RESERVED) is_release_code = true; } @@@ -1172,9 -1162,8 +1164,8 @@@ return keycode; } - static u32 imon_mce_key_lookup(struct imon_context *ictx, u32 hw_code) + static u32 imon_mce_key_lookup(struct imon_context *ictx, u32 scancode) { - u32 scancode = be32_to_cpu(hw_code); u32 keycode; #define MCE_KEY_MASK 0x7000 @@@ -1188,18 -1177,21 +1179,21 @@@ * but we can't or them into all codes, as some keys are decoded in * a different way w/o the same use of the toggle bit... */ - if ((scancode >> 24) & 0x80) + if (scancode & 0x80000000) scancode = scancode | MCE_KEY_MASK | MCE_TOGGLE_BIT; - keycode = ir_g_keycode_from_table(ictx->idev, scancode); + ictx->rc_scancode = scancode; + keycode = ir_g_keycode_from_table(ictx->rdev, scancode); + + /* not used in mce mode, but make sure we know its false */ + ictx->release_code = false; return keycode; } - static u32 imon_panel_key_lookup(u64 hw_code) + static u32 imon_panel_key_lookup(u64 code) { int i; - u64 code = be64_to_cpu(hw_code); u32 keycode = KEY_RESERVED; for (i = 0; i < ARRAY_SIZE(imon_panel_key_table); i++) { @@@ -1219,6 -1211,9 +1213,9 @@@ static bool imon_mouse_event(struct imo u8 right_shift = 1; bool mouse_input = true; int dir = 0; + unsigned long flags; + + spin_lock_irqsave(&ictx->kc_lock, flags); /* newer iMON device PAD or mouse button */ if (ictx->product != 0xffdc && (buf[0] & 0x01) && len == 5) { @@@ -1250,6 -1245,8 +1247,8 @@@ } else mouse_input = false; + spin_unlock_irqrestore(&ictx->kc_lock, flags); + if (mouse_input) { dev_dbg(ictx->dev, "sending mouse data via input subsystem\n"); @@@ -1264,7 -1261,9 +1263,9 @@@ buf[1] >> right_shift & 0x1); } input_sync(ictx->idev); + spin_lock_irqsave(&ictx->kc_lock, flags); ictx->last_keycode = ictx->kc; + spin_unlock_irqrestore(&ictx->kc_lock, flags); } return mouse_input; @@@ -1286,8 -1285,8 +1287,8 @@@ static void imon_pad_to_keys(struct imo int dir = 0; char rel_x = 0x00, rel_y = 0x00; u16 timeout, threshold; - u64 temp_key; - u32 remote_key; + u32 scancode = KEY_RESERVED; + unsigned long flags; /* * The imon directional pad functions more like a touchpad. Bytes 3 & 4 @@@ -1311,26 -1310,36 +1312,36 @@@ dir = stabilize((int)rel_x, (int)rel_y, timeout, threshold); if (!dir) { + spin_lock_irqsave(&ictx->kc_lock, + flags); ictx->kc = KEY_UNKNOWN; + spin_unlock_irqrestore(&ictx->kc_lock, + flags); return; } buf[2] = dir & 0xFF; buf[3] = (dir >> 8) & 0xFF; - memcpy(&temp_key, buf, sizeof(temp_key)); - remote_key = (u32) (le64_to_cpu(temp_key) - & 0xffffffff); - ictx->kc = imon_remote_key_lookup(ictx, - remote_key); + scancode = be32_to_cpu(*((u32 *)buf)); } } else { + /* + * Hack alert: instead of using keycodes, we have + * to use hard-coded scancodes here... + */ if (abs(rel_y) > abs(rel_x)) { buf[2] = (rel_y > 0) ? 0x7F : 0x80; buf[3] = 0; - ictx->kc = (rel_y > 0) ? KEY_DOWN : KEY_UP; + if (rel_y > 0) + scancode = 0x01007f00; /* KEY_DOWN */ + else + scancode = 0x01008000; /* KEY_UP */ } else { buf[2] = 0; buf[3] = (rel_x > 0) ? 0x7F : 0x80; - ictx->kc = (rel_x > 0) ? KEY_RIGHT : KEY_LEFT; + if (rel_x > 0) + scancode = 0x0100007f; /* KEY_RIGHT */ + else + scancode = 0x01000080; /* KEY_LEFT */ } } @@@ -1367,34 -1376,56 +1378,56 @@@ dir = stabilize((int)rel_x, (int)rel_y, timeout, threshold); if (!dir) { + spin_lock_irqsave(&ictx->kc_lock, flags); ictx->kc = KEY_UNKNOWN; + spin_unlock_irqrestore(&ictx->kc_lock, flags); return; } buf[2] = dir & 0xFF; buf[3] = (dir >> 8) & 0xFF; - memcpy(&temp_key, buf, sizeof(temp_key)); - remote_key = (u32) (le64_to_cpu(temp_key) & 0xffffffff); - ictx->kc = imon_remote_key_lookup(ictx, remote_key); + scancode = be32_to_cpu(*((u32 *)buf)); } else { + /* + * Hack alert: instead of using keycodes, we have + * to use hard-coded scancodes here... + */ if (abs(rel_y) > abs(rel_x)) { buf[2] = (rel_y > 0) ? 0x7F : 0x80; buf[3] = 0; - ictx->kc = (rel_y > 0) ? KEY_DOWN : KEY_UP; + if (rel_y > 0) + scancode = 0x01007f00; /* KEY_DOWN */ + else + scancode = 0x01008000; /* KEY_UP */ } else { buf[2] = 0; buf[3] = (rel_x > 0) ? 0x7F : 0x80; - ictx->kc = (rel_x > 0) ? KEY_RIGHT : KEY_LEFT; + if (rel_x > 0) + scancode = 0x0100007f; /* KEY_RIGHT */ + else + scancode = 0x01000080; /* KEY_LEFT */ } } } + + if (scancode) { + spin_lock_irqsave(&ictx->kc_lock, flags); + ictx->kc = imon_remote_key_lookup(ictx, scancode); + spin_unlock_irqrestore(&ictx->kc_lock, flags); + } } + /** + * figure out if these is a press or a release. We don't actually + * care about repeats, as those will be auto-generated within the IR + * subsystem for repeating scancodes. + */ static int imon_parse_press_type(struct imon_context *ictx, unsigned char *buf, u8 ktype) { int press_type = 0; - int rep_delay = ictx->idev->rep[REP_DELAY]; - int rep_period = ictx->idev->rep[REP_PERIOD]; + unsigned long flags; + + spin_lock_irqsave(&ictx->kc_lock, flags); /* key release of 0x02XXXXXX key */ if (ictx->kc == KEY_RESERVED && buf[0] == 0x02 && buf[3] == 0x00) @@@ -1410,22 -1441,10 +1443,10 @@@ buf[2] == 0x81 && buf[3] == 0xb7) ictx->kc = ictx->last_keycode; - /* mce-specific button handling */ + /* mce-specific button handling, no keyup events */ else if (ktype == IMON_KEY_MCE) { - /* initial press */ - if (ictx->kc != ictx->last_keycode - || buf[2] != ictx->mce_toggle_bit) { - ictx->last_keycode = ictx->kc; - ictx->mce_toggle_bit = buf[2]; - press_type = 1; - mod_timer(&ictx->itimer, - jiffies + msecs_to_jiffies(rep_delay)); - /* repeat */ - } else { - press_type = 2; - mod_timer(&ictx->itimer, - jiffies + msecs_to_jiffies(rep_period)); - } + ictx->rc_toggle = buf[2]; + press_type = 1; /* incoherent or irrelevant data */ } else if (ictx->kc == KEY_RESERVED) @@@ -1439,6 -1458,8 +1460,8 @@@ else press_type = 1; + spin_unlock_irqrestore(&ictx->kc_lock, flags); + return press_type; } @@@ -1451,41 -1472,45 +1474,45 @@@ static void imon_incoming_packet(struc int len = urb->actual_length; unsigned char *buf = urb->transfer_buffer; struct device *dev = ictx->dev; + unsigned long flags; u32 kc; bool norelease = false; int i; - u64 temp_key; - u64 panel_key = 0; - u32 remote_key = 0; - struct input_dev *idev = NULL; + u64 scancode; + struct input_dev *rdev = NULL; + struct ir_input_dev *irdev = NULL; int press_type = 0; int msec; struct timeval t; static struct timeval prev_time = { 0, 0 }; - u8 ktype = IMON_KEY_IMON; + u8 ktype; - idev = ictx->idev; + rdev = ictx->rdev; + irdev = input_get_drvdata(rdev); /* filter out junk data on the older 0xffdc imon devices */ if ((buf[0] == 0xff) && (buf[1] == 0xff) && (buf[2] == 0xff)) return; /* Figure out what key was pressed */ - memcpy(&temp_key, buf, sizeof(temp_key)); if (len == 8 && buf[7] == 0xee) { + scancode = be64_to_cpu(*((u64 *)buf)); ktype = IMON_KEY_PANEL; - panel_key = le64_to_cpu(temp_key); - kc = imon_panel_key_lookup(panel_key); + kc = imon_panel_key_lookup(scancode); } else { - remote_key = (u32) (le64_to_cpu(temp_key) & 0xffffffff); + scancode = be32_to_cpu(*((u32 *)buf)); if (ictx->ir_type == IR_TYPE_RC6) { + ktype = IMON_KEY_IMON; if (buf[0] == 0x80) ktype = IMON_KEY_MCE; - kc = imon_mce_key_lookup(ictx, remote_key); - } else - kc = imon_remote_key_lookup(ictx, remote_key); + kc = imon_mce_key_lookup(ictx, scancode); + } else { + ktype = IMON_KEY_IMON; + kc = imon_remote_key_lookup(ictx, scancode); + } } + spin_lock_irqsave(&ictx->kc_lock, flags); /* keyboard/mouse mode toggle button */ if (kc == KEY_KEYBOARD && !ictx->release_code) { ictx->last_keycode = kc; @@@ -1493,6 -1518,7 +1520,7 @@@ ictx->pad_mouse = ~(ictx->pad_mouse) & 0x1; dev_dbg(dev, "toggling to %s mode\n", ictx->pad_mouse ? "mouse" : "keyboard"); + spin_unlock_irqrestore(&ictx->kc_lock, flags); return; } else { ictx->pad_mouse = 0; @@@ -1501,11 -1527,13 +1529,13 @@@ } ictx->kc = kc; + spin_unlock_irqrestore(&ictx->kc_lock, flags); /* send touchscreen events through input subsystem if touchpad data */ if (ictx->display_type == IMON_DISPLAY_TYPE_VGA && len == 8 && buf[7] == 0x86) { imon_touch_event(ictx, buf); + return; /* look for mouse events with pad in mouse mode */ } else if (ictx->pad_mouse) { @@@ -1533,36 -1561,55 +1563,55 @@@ if (press_type < 0) goto not_input_data; + spin_lock_irqsave(&ictx->kc_lock, flags); if (ictx->kc == KEY_UNKNOWN) goto unknown_key; + spin_unlock_irqrestore(&ictx->kc_lock, flags); + + if (ktype != IMON_KEY_PANEL) { + if (press_type == 0) + ir_keyup(irdev); + else { + ir_keydown(rdev, ictx->rc_scancode, ictx->rc_toggle); + spin_lock_irqsave(&ictx->kc_lock, flags); + ictx->last_keycode = ictx->kc; + spin_unlock_irqrestore(&ictx->kc_lock, flags); + } + return; + } - /* KEY_MUTE repeats from MCE and knob need to be suppressed */ - if ((ictx->kc == KEY_MUTE && ictx->kc == ictx->last_keycode) - && (buf[7] == 0xee || ktype == IMON_KEY_MCE)) { + /* Only panel type events left to process now */ + spin_lock_irqsave(&ictx->kc_lock, flags); + + /* KEY_MUTE repeats from knob need to be suppressed */ + if (ictx->kc == KEY_MUTE && ictx->kc == ictx->last_keycode) { do_gettimeofday(&t); msec = tv2int(&t, &prev_time); prev_time = t; - if (msec < idev->rep[REP_DELAY]) + if (msec < ictx->idev->rep[REP_DELAY]) { + spin_unlock_irqrestore(&ictx->kc_lock, flags); return; + } } + kc = ictx->kc; - input_report_key(idev, ictx->kc, press_type); - input_sync(idev); + spin_unlock_irqrestore(&ictx->kc_lock, flags); - /* panel keys and some remote keys don't generate a release */ - if (panel_key || norelease) { - input_report_key(idev, ictx->kc, 0); - input_sync(idev); - } + input_report_key(ictx->idev, kc, press_type); + input_sync(ictx->idev); - ictx->last_keycode = ictx->kc; + /* panel keys don't generate a release */ + input_report_key(ictx->idev, kc, 0); + input_sync(ictx->idev); + + ictx->last_keycode = kc; return; unknown_key: + spin_unlock_irqrestore(&ictx->kc_lock, flags); dev_info(dev, "%s: unknown keypress, code 0x%llx\n", __func__, - (panel_key ? be64_to_cpu(panel_key) : - be32_to_cpu(remote_key))); + (long long)scancode); return; not_input_data: @@@ -1653,31 -1700,205 +1702,205 @@@ static void usb_rx_callback_intf1(struc usb_submit_urb(ictx->rx_urb_intf1, GFP_ATOMIC); } + /* + * The 0x15c2:0xffdc device ID was used for umpteen different imon + * devices, and all of them constantly spew interrupts, even when there + * is no actual data to report. However, byte 6 of this buffer looks like + * its unique across device variants, so we're trying to key off that to + * figure out which display type (if any) and what IR protocol the device + * actually supports. These devices have their IR protocol hard-coded into + * their firmware, they can't be changed on the fly like the newer hardware. + */ + static void imon_get_ffdc_type(struct imon_context *ictx) + { + u8 ffdc_cfg_byte = ictx->usb_rx_buf[6]; + u8 detected_display_type = IMON_DISPLAY_TYPE_NONE; + u64 allowed_protos = IR_TYPE_OTHER; + + switch (ffdc_cfg_byte) { + /* iMON Knob, no display, iMON IR + vol knob */ + case 0x21: + dev_info(ictx->dev, "0xffdc iMON Knob, iMON IR"); + ictx->display_supported = false; + break; + /* iMON 2.4G LT (usb stick), no display, iMON RF */ + case 0x4e: + dev_info(ictx->dev, "0xffdc iMON 2.4G LT, iMON RF"); + ictx->display_supported = false; + ictx->rf_device = true; + break; + /* iMON VFD, no IR (does have vol knob tho) */ + case 0x35: + dev_info(ictx->dev, "0xffdc iMON VFD + knob, no IR"); + detected_display_type = IMON_DISPLAY_TYPE_VFD; + break; + /* iMON VFD, iMON IR */ + case 0x24: + case 0x85: + dev_info(ictx->dev, "0xffdc iMON VFD, iMON IR"); + detected_display_type = IMON_DISPLAY_TYPE_VFD; + break; + /* iMON VFD, MCE IR */ + case 0x9e: + dev_info(ictx->dev, "0xffdc iMON VFD, MCE IR"); + detected_display_type = IMON_DISPLAY_TYPE_VFD; + allowed_protos = IR_TYPE_RC6; + break; + /* iMON LCD, MCE IR */ + case 0x9f: + dev_info(ictx->dev, "0xffdc iMON LCD, MCE IR"); + detected_display_type = IMON_DISPLAY_TYPE_LCD; + allowed_protos = IR_TYPE_RC6; + break; + default: + dev_info(ictx->dev, "Unknown 0xffdc device, " + "defaulting to VFD and iMON IR"); + detected_display_type = IMON_DISPLAY_TYPE_VFD; + break; + } + + printk(KERN_CONT " (id 0x%02x)\n", ffdc_cfg_byte); + + ictx->display_type = detected_display_type; + ictx->props->allowed_protos = allowed_protos; + ictx->ir_type = allowed_protos; + } + + static void imon_set_display_type(struct imon_context *ictx) + { + u8 configured_display_type = IMON_DISPLAY_TYPE_VFD; + + /* + * Try to auto-detect the type of display if the user hasn't set + * it by hand via the display_type modparam. Default is VFD. + */ + + if (display_type == IMON_DISPLAY_TYPE_AUTO) { + switch (ictx->product) { + case 0xffdc: + /* set in imon_get_ffdc_type() */ + configured_display_type = ictx->display_type; + break; + case 0x0034: + case 0x0035: + configured_display_type = IMON_DISPLAY_TYPE_VGA; + break; + case 0x0038: + case 0x0039: + case 0x0045: + configured_display_type = IMON_DISPLAY_TYPE_LCD; + break; + case 0x003c: + case 0x0041: + case 0x0042: + case 0x0043: + configured_display_type = IMON_DISPLAY_TYPE_NONE; + ictx->display_supported = false; + break; + case 0x0036: + case 0x0044: + default: + configured_display_type = IMON_DISPLAY_TYPE_VFD; + break; + } + } else { + configured_display_type = display_type; + if (display_type == IMON_DISPLAY_TYPE_NONE) + ictx->display_supported = false; + else + ictx->display_supported = true; + dev_info(ictx->dev, "%s: overriding display type to %d via " + "modparam\n", __func__, display_type); + } + + ictx->display_type = configured_display_type; + } + + static struct input_dev *imon_init_rdev(struct imon_context *ictx) + { + struct input_dev *rdev; + struct ir_dev_props *props; + int ret; + char *ir_codes = NULL; + const unsigned char fp_packet[] = { 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x88 }; + + rdev = input_allocate_device(); + props = kzalloc(sizeof(*props), GFP_KERNEL); + if (!rdev || !props) { + dev_err(ictx->dev, "remote control dev allocation failed\n"); + goto out; + } + + snprintf(ictx->name_rdev, sizeof(ictx->name_rdev), + "iMON Remote (%04x:%04x)", ictx->vendor, ictx->product); + usb_make_path(ictx->usbdev_intf0, ictx->phys_rdev, + sizeof(ictx->phys_rdev)); + strlcat(ictx->phys_rdev, "/input0", sizeof(ictx->phys_rdev)); + + rdev->name = ictx->name_rdev; + rdev->phys = ictx->phys_rdev; + usb_to_input_id(ictx->usbdev_intf0, &rdev->id); + rdev->dev.parent = ictx->dev; + rdev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); + input_set_drvdata(rdev, ictx); + + props->priv = ictx; + props->driver_type = RC_DRIVER_SCANCODE; + props->allowed_protos = IR_TYPE_OTHER | IR_TYPE_RC6; /* iMON PAD or MCE */ + props->change_protocol = imon_ir_change_protocol; + ictx->props = props; + + /* Enable front-panel buttons and/or knobs */ + memcpy(ictx->usb_tx_buf, &fp_packet, sizeof(fp_packet)); + ret = send_packet(ictx); + /* Not fatal, but warn about it */ + if (ret) + dev_info(ictx->dev, "panel buttons/knobs setup failed\n"); + + if (ictx->product == 0xffdc) + imon_get_ffdc_type(ictx); + + imon_set_display_type(ictx); + + if (ictx->ir_type == IR_TYPE_RC6) + ir_codes = RC_MAP_IMON_MCE; + else + ir_codes = RC_MAP_IMON_PAD; + + ret = ir_input_register(rdev, ir_codes, props, MOD_NAME); + if (ret < 0) { + dev_err(ictx->dev, "remote input dev register failed\n"); + goto out; + } + + return rdev; + + out: + kfree(props); + input_free_device(rdev); + return NULL; + } + static struct input_dev *imon_init_idev(struct imon_context *ictx) { struct input_dev *idev; - struct ir_dev_props *props; int ret, i; idev = input_allocate_device(); if (!idev) { - dev_err(ictx->dev, "remote input dev allocation failed\n"); - goto idev_alloc_failed; - } - - props = kzalloc(sizeof(struct ir_dev_props), GFP_KERNEL); - if (!props) { - dev_err(ictx->dev, "remote ir dev props allocation failed\n"); - goto props_alloc_failed; + dev_err(ictx->dev, "input dev allocation failed\n"); + goto out; } snprintf(ictx->name_idev, sizeof(ictx->name_idev), - "iMON Remote (%04x:%04x)", ictx->vendor, ictx->product); + "iMON Panel, Knob and Mouse(%04x:%04x)", + ictx->vendor, ictx->product); idev->name = ictx->name_idev; usb_make_path(ictx->usbdev_intf0, ictx->phys_idev, sizeof(ictx->phys_idev)); - strlcat(ictx->phys_idev, "/input0", sizeof(ictx->phys_idev)); + strlcat(ictx->phys_idev, "/input1", sizeof(ictx->phys_idev)); idev->phys = ictx->phys_idev; idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) | BIT_MASK(EV_REL); @@@ -1693,30 -1914,20 +1916,20 @@@ __set_bit(kc, idev->keybit); } - props->priv = ictx; - props->driver_type = RC_DRIVER_SCANCODE; - /* IR_TYPE_OTHER maps to iMON PAD remote, IR_TYPE_RC6 to MCE remote */ - props->allowed_protos = IR_TYPE_OTHER | IR_TYPE_RC6; - props->change_protocol = imon_ir_change_protocol; - ictx->props = props; - usb_to_input_id(ictx->usbdev_intf0, &idev->id); idev->dev.parent = ictx->dev; + input_set_drvdata(idev, ictx); - ret = ir_input_register(idev, RC_MAP_IMON_PAD, props, MOD_NAME); + ret = input_register_device(idev); if (ret < 0) { - dev_err(ictx->dev, "remote input dev register failed\n"); - goto idev_register_failed; + dev_err(ictx->dev, "input dev register failed\n"); + goto out; } return idev; - idev_register_failed: - kfree(props); - props_alloc_failed: + out: input_free_device(idev); - idev_alloc_failed: - return NULL; } @@@ -1738,7 -1949,7 +1951,7 @@@ static struct input_dev *imon_init_touc usb_make_path(ictx->usbdev_intf1, ictx->phys_touch, sizeof(ictx->phys_touch)); - strlcat(ictx->phys_touch, "/input1", sizeof(ictx->phys_touch)); + strlcat(ictx->phys_touch, "/input2", sizeof(ictx->phys_touch)); touch->phys = ictx->phys_touch; touch->evbit[0] = @@@ -1850,7 -2061,7 +2063,7 @@@ static bool imon_find_endpoints(struct /* Input endpoint is mandatory */ if (!ir_ep_found) - err("%s: no valid input (IR) endpoint found.", __func__); + pr_err("no valid input (IR) endpoint found\n"); ictx->tx_control = tx_control; @@@ -1888,6 -2099,7 +2101,7 @@@ static struct imon_context *imon_init_i } mutex_init(&ictx->lock); + spin_lock_init(&ictx->kc_lock); mutex_lock(&ictx->lock); @@@ -1913,6 -2125,12 +2127,12 @@@ goto idev_setup_failed; } + ictx->rdev = imon_init_rdev(ictx); + if (!ictx->rdev) { + dev_err(dev, "%s: rc device setup failed\n", __func__); + goto rdev_setup_failed; + } + usb_fill_int_urb(ictx->rx_urb_intf0, ictx->usbdev_intf0, usb_rcvintpipe(ictx->usbdev_intf0, ictx->rx_endpoint_intf0->bEndpointAddress), @@@ -1922,15 -2140,16 +2142,16 @@@ ret = usb_submit_urb(ictx->rx_urb_intf0, GFP_KERNEL); if (ret) { - err("%s: usb_submit_urb failed for intf0 (%d)", - __func__, ret); + pr_err("usb_submit_urb failed for intf0 (%d)\n", ret); goto urb_submit_failed; } return ictx; urb_submit_failed: - ir_input_unregister(ictx->idev); + ir_input_unregister(ictx->rdev); + rdev_setup_failed: + input_unregister_device(ictx->idev); idev_setup_failed: find_endpoint_failed: mutex_unlock(&ictx->lock); @@@ -1954,7 -2173,7 +2175,7 @@@ static struct imon_context *imon_init_i rx_urb = usb_alloc_urb(0, GFP_KERNEL); if (!rx_urb) { - err("%s: usb_alloc_urb failed for IR urb", __func__); + pr_err("usb_alloc_urb failed for IR urb\n"); goto rx_urb_alloc_failed; } @@@ -1992,8 -2211,7 +2213,7 @@@ ret = usb_submit_urb(ictx->rx_urb_intf1, GFP_KERNEL); if (ret) { - err("%s: usb_submit_urb failed for intf1 (%d)", - __func__, ret); + pr_err("usb_submit_urb failed for intf1 (%d)\n", ret); goto urb_submit_failed; } @@@ -2012,116 -2230,6 +2232,6 @@@ rx_urb_alloc_failed return NULL; } - /* - * The 0x15c2:0xffdc device ID was used for umpteen different imon - * devices, and all of them constantly spew interrupts, even when there - * is no actual data to report. However, byte 6 of this buffer looks like - * its unique across device variants, so we're trying to key off that to - * figure out which display type (if any) and what IR protocol the device - * actually supports. These devices have their IR protocol hard-coded into - * their firmware, they can't be changed on the fly like the newer hardware. - */ - static void imon_get_ffdc_type(struct imon_context *ictx) - { - u8 ffdc_cfg_byte = ictx->usb_rx_buf[6]; - u8 detected_display_type = IMON_DISPLAY_TYPE_NONE; - u64 allowed_protos = IR_TYPE_OTHER; - - switch (ffdc_cfg_byte) { - /* iMON Knob, no display, iMON IR + vol knob */ - case 0x21: - dev_info(ictx->dev, "0xffdc iMON Knob, iMON IR"); - ictx->display_supported = false; - break; - /* iMON 2.4G LT (usb stick), no display, iMON RF */ - case 0x4e: - dev_info(ictx->dev, "0xffdc iMON 2.4G LT, iMON RF"); - ictx->display_supported = false; - ictx->rf_device = true; - break; - /* iMON VFD, no IR (does have vol knob tho) */ - case 0x35: - dev_info(ictx->dev, "0xffdc iMON VFD + knob, no IR"); - detected_display_type = IMON_DISPLAY_TYPE_VFD; - break; - /* iMON VFD, iMON IR */ - case 0x24: - case 0x85: - dev_info(ictx->dev, "0xffdc iMON VFD, iMON IR"); - detected_display_type = IMON_DISPLAY_TYPE_VFD; - break; - /* iMON LCD, MCE IR */ - case 0x9e: - case 0x9f: - dev_info(ictx->dev, "0xffdc iMON LCD, MCE IR"); - detected_display_type = IMON_DISPLAY_TYPE_LCD; - allowed_protos = IR_TYPE_RC6; - break; - default: - dev_info(ictx->dev, "Unknown 0xffdc device, " - "defaulting to VFD and iMON IR"); - detected_display_type = IMON_DISPLAY_TYPE_VFD; - break; - } - - printk(KERN_CONT " (id 0x%02x)\n", ffdc_cfg_byte); - - ictx->display_type = detected_display_type; - ictx->props->allowed_protos = allowed_protos; - ictx->ir_type = allowed_protos; - } - - static void imon_set_display_type(struct imon_context *ictx, - struct usb_interface *intf) - { - u8 configured_display_type = IMON_DISPLAY_TYPE_VFD; - - /* - * Try to auto-detect the type of display if the user hasn't set - * it by hand via the display_type modparam. Default is VFD. - */ - - if (display_type == IMON_DISPLAY_TYPE_AUTO) { - switch (ictx->product) { - case 0xffdc: - /* set in imon_get_ffdc_type() */ - configured_display_type = ictx->display_type; - break; - case 0x0034: - case 0x0035: - configured_display_type = IMON_DISPLAY_TYPE_VGA; - break; - case 0x0038: - case 0x0039: - case 0x0045: - configured_display_type = IMON_DISPLAY_TYPE_LCD; - break; - case 0x003c: - case 0x0041: - case 0x0042: - case 0x0043: - configured_display_type = IMON_DISPLAY_TYPE_NONE; - ictx->display_supported = false; - break; - case 0x0036: - case 0x0044: - default: - configured_display_type = IMON_DISPLAY_TYPE_VFD; - break; - } - } else { - configured_display_type = display_type; - if (display_type == IMON_DISPLAY_TYPE_NONE) - ictx->display_supported = false; - else - ictx->display_supported = true; - dev_info(ictx->dev, "%s: overriding display type to %d via " - "modparam\n", __func__, display_type); - } - - ictx->display_type = configured_display_type; - } - static void imon_init_display(struct imon_context *ictx, struct usb_interface *intf) { @@@ -2130,8 -2238,7 +2240,7 @@@ dev_dbg(ictx->dev, "Registering iMON display with sysfs\n"); /* set up sysfs entry for built-in clock */ - ret = sysfs_create_group(&intf->dev.kobj, - &imon_display_attribute_group); + ret = sysfs_create_group(&intf->dev.kobj, &imon_display_attr_group); if (ret) dev_err(ictx->dev, "Could not create display sysfs " "entries(%d)", ret); @@@ -2162,8 -2269,6 +2271,6 @@@ static int __devinit imon_probe(struct struct imon_context *ictx = NULL; struct imon_context *first_if_ctx = NULL; u16 vendor, product; - const unsigned char fp_packet[] = { 0x40, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x88 }; code_length = BUF_CHUNK_SIZE * 8; @@@ -2185,7 -2290,7 +2292,7 @@@ if (ifnum == 0) { ictx = imon_init_intf0(interface); if (!ictx) { - err("%s: failed to initialize context!\n", __func__); + pr_err("failed to initialize context!\n"); ret = -ENODEV; goto fail; } @@@ -2194,7 -2299,7 +2301,7 @@@ /* this is the secondary interface on the device */ ictx = imon_init_intf1(interface, first_if_ctx); if (!ictx) { - err("%s: failed to attach to context!\n", __func__); + pr_err("failed to attach to context!\n"); ret = -ENODEV; goto fail; } @@@ -2204,39 -2309,18 +2311,18 @@@ usb_set_intfdata(interface, ictx); if (ifnum == 0) { - /* Enable front-panel buttons and/or knobs */ - memcpy(ictx->usb_tx_buf, &fp_packet, sizeof(fp_packet)); - ret = send_packet(ictx); - /* Not fatal, but warn about it */ - if (ret) - dev_info(dev, "failed to enable panel buttons " - "and/or knobs\n"); - - if (product == 0xffdc) - imon_get_ffdc_type(ictx); - - imon_set_display_type(ictx, interface); - if (product == 0xffdc && ictx->rf_device) { sysfs_err = sysfs_create_group(&interface->dev.kobj, - &imon_rf_attribute_group); + &imon_rf_attr_group); if (sysfs_err) - err("%s: Could not create RF sysfs entries(%d)", - __func__, sysfs_err); + pr_err("Could not create RF sysfs entries(%d)\n", + sysfs_err); } if (ictx->display_supported) imon_init_display(ictx, interface); } - /* set IR protocol/remote type */ - ret = imon_ir_change_protocol(ictx, ictx->ir_type); - if (ret) { - dev_warn(dev, "%s: failed to set IR protocol, falling back " - "to standard iMON protocol mode\n", __func__); - ictx->ir_type = IR_TYPE_OTHER; - } - dev_info(dev, "iMON device (%04x:%04x, intf%d) on " "usb<%d:%d> initialized\n", vendor, product, ifnum, usbdev->bus->busnum, usbdev->devnum); @@@ -2275,10 -2359,8 +2361,8 @@@ static void __devexit imon_disconnect(s * sysfs_remove_group is safe to call even if sysfs_create_group * hasn't been called */ - sysfs_remove_group(&interface->dev.kobj, - &imon_display_attribute_group); - sysfs_remove_group(&interface->dev.kobj, - &imon_rf_attribute_group); + sysfs_remove_group(&interface->dev.kobj, &imon_display_attr_group); + sysfs_remove_group(&interface->dev.kobj, &imon_rf_attr_group); usb_set_intfdata(interface, NULL); @@@ -2291,7 -2373,8 +2375,8 @@@ if (ifnum == 0) { ictx->dev_present_intf0 = false; usb_kill_urb(ictx->rx_urb_intf0); - ir_input_unregister(ictx->idev); + input_unregister_device(ictx->idev); + ir_input_unregister(ictx->rdev); if (ictx->display_supported) { if (ictx->display_type == IMON_DISPLAY_TYPE_LCD) usb_deregister_dev(interface, &imon_lcd_class); @@@ -2311,11 -2394,8 +2396,8 @@@ mutex_unlock(&ictx->lock); if (!ictx->display_isopen) free_imon_context(ictx); - } else { - if (ictx->ir_type == IR_TYPE_RC6) - del_timer_sync(&ictx->itimer); + } else mutex_unlock(&ictx->lock); - } mutex_unlock(&driver_lock); @@@ -2372,7 -2452,7 +2454,7 @@@ static int __init imon_init(void rc = usb_register(&imon_driver); if (rc) { - err("%s: usb register failed(%d)", __func__, rc); + pr_err("usb register failed(%d)\n", rc); rc = -ENODEV; } diff --combined drivers/media/IR/ir-keytable.c index c06b4d50a3d,5f24cd6ed99..9186b45132e --- a/drivers/media/IR/ir-keytable.c +++ b/drivers/media/IR/ir-keytable.c @@@ -24,57 -24,15 +24,57 @@@ /* FIXME: IR_KEYPRESS_TIMEOUT should be protocol specific */ #define IR_KEYPRESS_TIMEOUT 250 +/** + * ir_create_table() - initializes a scancode table + * @rc_tab: the ir_scancode_table to initialize + * @name: name to assign to the table + * @ir_type: ir type to assign to the new table + * @size: initial size of the table + * @return: zero on success or a negative error code + * + * This routine will initialize the ir_scancode_table and will allocate + * memory to hold at least the specified number elements. + */ +static int ir_create_table(struct ir_scancode_table *rc_tab, + const char *name, u64 ir_type, size_t size) +{ + rc_tab->name = name; + rc_tab->ir_type = ir_type; + rc_tab->alloc = roundup_pow_of_two(size * sizeof(struct ir_scancode)); + rc_tab->size = rc_tab->alloc / sizeof(struct ir_scancode); + rc_tab->scan = kmalloc(rc_tab->alloc, GFP_KERNEL); + if (!rc_tab->scan) + return -ENOMEM; + + IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n", + rc_tab->size, rc_tab->alloc); + return 0; +} + +/** + * ir_free_table() - frees memory allocated by a scancode table + * @rc_tab: the table whose mappings need to be freed + * + * This routine will free memory alloctaed for key mappings used by given + * scancode table. + */ +static void ir_free_table(struct ir_scancode_table *rc_tab) +{ + rc_tab->size = 0; + kfree(rc_tab->scan); + rc_tab->scan = NULL; +} + /** * ir_resize_table() - resizes a scancode table if necessary * @rc_tab: the ir_scancode_table to resize + * @gfp_flags: gfp flags to use when allocating memory * @return: zero on success or a negative error code * * This routine will shrink the ir_scancode_table if it has lots of * unused entries and grow it if it is full. */ -static int ir_resize_table(struct ir_scancode_table *rc_tab) +static int ir_resize_table(struct ir_scancode_table *rc_tab, gfp_t gfp_flags) { unsigned int oldalloc = rc_tab->alloc; unsigned int newalloc = oldalloc; @@@ -99,7 -57,7 +99,7 @@@ if (newalloc == oldalloc) return 0; - newscan = kmalloc(newalloc, GFP_ATOMIC); + newscan = kmalloc(newalloc, gfp_flags); if (!newscan) { IR_dprintk(1, "Failed to kmalloc %u bytes\n", newalloc); return -ENOMEM; @@@ -114,78 -72,26 +114,78 @@@ } /** - * ir_do_setkeycode() - internal function to set a keycode in the - * scancode->keycode table + * ir_update_mapping() - set a keycode in the scancode->keycode table * @dev: the struct input_dev device descriptor - * @rc_tab: the struct ir_scancode_table to set the keycode in - * @scancode: the scancode for the ir command - * @keycode: the keycode for the ir command - * @resize: whether the keytable may be shrunk - * @return: -EINVAL if the keycode could not be inserted, otherwise zero. + * @rc_tab: scancode table to be adjusted + * @index: index of the mapping that needs to be updated + * @keycode: the desired keycode + * @return: previous keycode assigned to the mapping + * + * This routine is used to update scancode->keycopde mapping at given + * position. + */ +static unsigned int ir_update_mapping(struct input_dev *dev, + struct ir_scancode_table *rc_tab, + unsigned int index, + unsigned int new_keycode) +{ + int old_keycode = rc_tab->scan[index].keycode; + int i; + + /* Did the user wish to remove the mapping? */ + if (new_keycode == KEY_RESERVED || new_keycode == KEY_UNKNOWN) { + IR_dprintk(1, "#%d: Deleting scan 0x%04x\n", + index, rc_tab->scan[index].scancode); + rc_tab->len--; + memmove(&rc_tab->scan[index], &rc_tab->scan[index+ 1], + (rc_tab->len - index) * sizeof(struct ir_scancode)); + } else { + IR_dprintk(1, "#%d: %s scan 0x%04x with key 0x%04x\n", + index, + old_keycode == KEY_RESERVED ? "New" : "Replacing", + rc_tab->scan[index].scancode, new_keycode); + rc_tab->scan[index].keycode = new_keycode; + __set_bit(new_keycode, dev->keybit); + } + + if (old_keycode != KEY_RESERVED) { + /* A previous mapping was updated... */ + __clear_bit(old_keycode, dev->keybit); + /* ... but another scancode might use the same keycode */ + for (i = 0; i < rc_tab->len; i++) { + if (rc_tab->scan[i].keycode == old_keycode) { + __set_bit(old_keycode, dev->keybit); + break; + } + } + + /* Possibly shrink the keytable, failure is not a problem */ + ir_resize_table(rc_tab, GFP_ATOMIC); + } + + return old_keycode; +} + +/** + * ir_locate_scancode() - set a keycode in the scancode->keycode table + * @ir_dev: the struct ir_input_dev device descriptor + * @rc_tab: scancode table to be searched + * @scancode: the desired scancode + * @resize: controls whether we allowed to resize the table to + * accomodate not yet present scancodes + * @return: index of the mapping containing scancode in question + * or -1U in case of failure. * - * This routine is used internally to manipulate the scancode->keycode table. - * The caller has to hold @rc_tab->lock. + * This routine is used to locate given scancode in ir_scancode_table. + * If scancode is not yet present the routine will allocate a new slot + * for it. */ -static int ir_do_setkeycode(struct input_dev *dev, - struct ir_scancode_table *rc_tab, - unsigned scancode, unsigned keycode, - bool resize) +static unsigned int ir_establish_scancode(struct ir_input_dev *ir_dev, + struct ir_scancode_table *rc_tab, + unsigned int scancode, + bool resize) { unsigned int i; - int old_keycode = KEY_RESERVED; - struct ir_input_dev *ir_dev = input_get_drvdata(dev); /* * Unfortunately, some hardware-based IR decoders don't provide @@@ -194,34 -100,65 +194,34 @@@ * the provided IR with another one, it is needed to allow loading * IR tables from other remotes. So, */ - if (ir_dev->props && ir_dev->props->scanmask) { + if (ir_dev->props && ir_dev->props->scanmask) scancode &= ir_dev->props->scanmask; - } /* First check if we already have a mapping for this ir command */ for (i = 0; i < rc_tab->len; i++) { + if (rc_tab->scan[i].scancode == scancode) + return i; + /* Keytable is sorted from lowest to highest scancode */ - if (rc_tab->scan[i].scancode > scancode) + if (rc_tab->scan[i].scancode >= scancode) break; - else if (rc_tab->scan[i].scancode < scancode) - continue; - - old_keycode = rc_tab->scan[i].keycode; - rc_tab->scan[i].keycode = keycode; - - /* Did the user wish to remove the mapping? */ - if (keycode == KEY_RESERVED || keycode == KEY_UNKNOWN) { - IR_dprintk(1, "#%d: Deleting scan 0x%04x\n", - i, scancode); - rc_tab->len--; - memmove(&rc_tab->scan[i], &rc_tab->scan[i + 1], - (rc_tab->len - i) * sizeof(struct ir_scancode)); - } - - /* Possibly shrink the keytable, failure is not a problem */ - ir_resize_table(rc_tab); - break; } - if (old_keycode == KEY_RESERVED && keycode != KEY_RESERVED) { - /* No previous mapping found, we might need to grow the table */ - if (resize && ir_resize_table(rc_tab)) - return -ENOMEM; - - IR_dprintk(1, "#%d: New scan 0x%04x with key 0x%04x\n", - i, scancode, keycode); + /* No previous mapping found, we might need to grow the table */ + if (rc_tab->size == rc_tab->len) { + if (!resize || ir_resize_table(rc_tab, GFP_ATOMIC)) + return -1U; + } - /* i is the proper index to insert our new keycode */ + /* i is the proper index to insert our new keycode */ + if (i < rc_tab->len) memmove(&rc_tab->scan[i + 1], &rc_tab->scan[i], (rc_tab->len - i) * sizeof(struct ir_scancode)); - rc_tab->scan[i].scancode = scancode; - rc_tab->scan[i].keycode = keycode; - rc_tab->len++; - set_bit(keycode, dev->keybit); - } else { - IR_dprintk(1, "#%d: Replacing scan 0x%04x with key 0x%04x\n", - i, scancode, keycode); - /* A previous mapping was updated... */ - clear_bit(old_keycode, dev->keybit); - /* ...but another scancode might use the same keycode */ - for (i = 0; i < rc_tab->len; i++) { - if (rc_tab->scan[i].keycode == old_keycode) { - set_bit(old_keycode, dev->keybit); - break; - } - } - } + rc_tab->scan[i].scancode = scancode; + rc_tab->scan[i].keycode = KEY_RESERVED; + rc_tab->len++; - return 0; + return i; } /** @@@ -234,41 -171,17 +234,41 @@@ * This routine is used to handle evdev EVIOCSKEY ioctl. */ static int ir_setkeycode(struct input_dev *dev, - unsigned int scancode, unsigned int keycode) + const struct input_keymap_entry *ke, + unsigned int *old_keycode) { - int rc; - unsigned long flags; struct ir_input_dev *ir_dev = input_get_drvdata(dev); struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; + unsigned int index; + unsigned int scancode; + int retval; + unsigned long flags; spin_lock_irqsave(&rc_tab->lock, flags); - rc = ir_do_setkeycode(dev, rc_tab, scancode, keycode, true); + + if (ke->flags & INPUT_KEYMAP_BY_INDEX) { + index = ke->index; + if (index >= rc_tab->len) { + retval = -EINVAL; + goto out; + } + } else { + retval = input_scancode_to_scalar(ke, &scancode); + if (retval) + goto out; + + index = ir_establish_scancode(ir_dev, rc_tab, scancode, true); + if (index >= rc_tab->len) { + retval = -ENOMEM; + goto out; + } + } + + *old_keycode = ir_update_mapping(dev, rc_tab, index, ke->keycode); + +out: spin_unlock_irqrestore(&rc_tab->lock, flags); - return rc; + return retval; } /** @@@ -276,72 -189,31 +276,72 @@@ * @dev: the struct input_dev device descriptor * @to: the struct ir_scancode_table to copy entries to * @from: the struct ir_scancode_table to copy entries from - * @return: -EINVAL if all keycodes could not be inserted, otherwise zero. + * @return: -ENOMEM if all keycodes could not be inserted, otherwise zero. * * This routine is used to handle table initialization. */ -static int ir_setkeytable(struct input_dev *dev, - struct ir_scancode_table *to, +static int ir_setkeytable(struct ir_input_dev *ir_dev, const struct ir_scancode_table *from) { - struct ir_input_dev *ir_dev = input_get_drvdata(dev); struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; - unsigned long flags; - unsigned int i; - int rc = 0; + unsigned int i, index; + int rc; + + rc = ir_create_table(&ir_dev->rc_tab, + from->name, from->ir_type, from->size); + if (rc) + return rc; + + IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n", + rc_tab->size, rc_tab->alloc); - spin_lock_irqsave(&rc_tab->lock, flags); for (i = 0; i < from->size; i++) { - rc = ir_do_setkeycode(dev, to, from->scan[i].scancode, - from->scan[i].keycode, false); - if (rc) + index = ir_establish_scancode(ir_dev, rc_tab, + from->scan[i].scancode, false); + if (index >= rc_tab->len) { + rc = -ENOMEM; break; + } + + ir_update_mapping(ir_dev->input_dev, rc_tab, index, + from->scan[i].keycode); } - spin_unlock_irqrestore(&rc_tab->lock, flags); + + if (rc) + ir_free_table(rc_tab); + return rc; } +/** + * ir_lookup_by_scancode() - locate mapping by scancode + * @rc_tab: the &struct ir_scancode_table to search + * @scancode: scancode to look for in the table + * @return: index in the table, -1U if not found + * + * This routine performs binary search in RC keykeymap table for + * given scancode. + */ +static unsigned int ir_lookup_by_scancode(const struct ir_scancode_table *rc_tab, + unsigned int scancode) +{ + unsigned int start = 0; + unsigned int end = rc_tab->len - 1; + unsigned int mid; + + while (start <= end) { + mid = (start + end) / 2; + if (rc_tab->scan[mid].scancode < scancode) + start = mid + 1; + else if (rc_tab->scan[mid].scancode > scancode) + end = mid - 1; + else + return mid; + } + + return -1U; +} + /** * ir_getkeycode() - get a keycode from the scancode->keycode table * @dev: the struct input_dev device descriptor @@@ -352,46 -224,36 +352,46 @@@ * This routine is used to handle evdev EVIOCGKEY ioctl. */ static int ir_getkeycode(struct input_dev *dev, - unsigned int scancode, unsigned int *keycode) + struct input_keymap_entry *ke) { - int start, end, mid; - unsigned long flags; - int key = KEY_RESERVED; struct ir_input_dev *ir_dev = input_get_drvdata(dev); struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; + struct ir_scancode *entry; + unsigned long flags; + unsigned int index; + unsigned int scancode; + int retval; spin_lock_irqsave(&rc_tab->lock, flags); - start = 0; - end = rc_tab->len - 1; - while (start <= end) { - mid = (start + end) / 2; - if (rc_tab->scan[mid].scancode < scancode) - start = mid + 1; - else if (rc_tab->scan[mid].scancode > scancode) - end = mid - 1; - else { - key = rc_tab->scan[mid].keycode; - break; - } + + if (ke->flags & INPUT_KEYMAP_BY_INDEX) { + index = ke->index; + } else { + retval = input_scancode_to_scalar(ke, &scancode); + if (retval) + goto out; + + index = ir_lookup_by_scancode(rc_tab, scancode); + } + + if (index >= rc_tab->len) { + if (!(ke->flags & INPUT_KEYMAP_BY_INDEX)) + IR_dprintk(1, "unknown key for scancode 0x%04x\n", + scancode); + retval = -EINVAL; + goto out; } - spin_unlock_irqrestore(&rc_tab->lock, flags); - if (key == KEY_RESERVED) - IR_dprintk(1, "unknown key for scancode 0x%04x\n", - scancode); + entry = &rc_tab->scan[index]; - *keycode = key; - return 0; + ke->index = index; + ke->keycode = entry->keycode; + ke->len = sizeof(entry->scancode); + memcpy(ke->scancode, &entry->scancode, sizeof(entry->scancode)); + +out: + spin_unlock_irqrestore(&rc_tab->lock, flags); + return retval; } /** @@@ -406,24 -268,12 +406,24 @@@ */ u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode) { - int keycode; + struct ir_input_dev *ir_dev = input_get_drvdata(dev); + struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; + unsigned int keycode; + unsigned int index; + unsigned long flags; + + spin_lock_irqsave(&rc_tab->lock, flags); + + index = ir_lookup_by_scancode(rc_tab, scancode); + keycode = index < rc_tab->len ? + rc_tab->scan[index].keycode : KEY_RESERVED; + + spin_unlock_irqrestore(&rc_tab->lock, flags); - ir_getkeycode(dev, scancode, &keycode); if (keycode != KEY_RESERVED) IR_dprintk(1, "%s: scancode 0x%04x keycode 0x%02x\n", dev->name, scancode, keycode); + return keycode; } EXPORT_SYMBOL_GPL(ir_g_keycode_from_table); @@@ -435,7 -285,7 +435,7 @@@ * This routine is used to signal that a key has been released on the * remote control. It reports a keyup input event via input_report_key(). */ - static void ir_keyup(struct ir_input_dev *ir) + void ir_keyup(struct ir_input_dev *ir) { if (!ir->keypressed) return; @@@ -445,6 -295,7 +445,7 @@@ input_sync(ir->input_dev); ir->keypressed = false; } + EXPORT_SYMBOL_GPL(ir_keyup); /** * ir_timer_keyup() - generates a keyup event after a timeout @@@ -603,8 -454,8 +604,8 @@@ int __ir_input_register(struct input_de goto out_dev; } - input_dev->getkeycode = ir_getkeycode; - input_dev->setkeycode = ir_setkeycode; + input_dev->getkeycode_new = ir_getkeycode; + input_dev->setkeycode_new = ir_setkeycode; input_set_drvdata(input_dev, ir_dev); ir_dev->input_dev = input_dev; @@@ -612,6 -463,12 +613,6 @@@ spin_lock_init(&ir_dev->keylock); setup_timer(&ir_dev->timer_keyup, ir_timer_keyup, (unsigned long)ir_dev); - ir_dev->rc_tab.name = rc_tab->name; - ir_dev->rc_tab.ir_type = rc_tab->ir_type; - ir_dev->rc_tab.alloc = roundup_pow_of_two(rc_tab->size * - sizeof(struct ir_scancode)); - ir_dev->rc_tab.scan = kmalloc(ir_dev->rc_tab.alloc, GFP_KERNEL); - ir_dev->rc_tab.size = ir_dev->rc_tab.alloc / sizeof(struct ir_scancode); if (props) { ir_dev->props = props; if (props->open) @@@ -620,14 -477,23 +621,14 @@@ input_dev->close = ir_close; } - if (!ir_dev->rc_tab.scan) { - rc = -ENOMEM; - goto out_name; - } - - IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n", - ir_dev->rc_tab.size, ir_dev->rc_tab.alloc); - set_bit(EV_KEY, input_dev->evbit); set_bit(EV_REP, input_dev->evbit); set_bit(EV_MSC, input_dev->evbit); set_bit(MSC_SCAN, input_dev->mscbit); - if (ir_setkeytable(input_dev, &ir_dev->rc_tab, rc_tab)) { - rc = -ENOMEM; - goto out_table; - } + rc = ir_setkeytable(ir_dev, rc_tab); + if (rc) + goto out_name; rc = ir_register_class(input_dev); if (rc < 0) @@@ -640,6 -506,10 +641,10 @@@ goto out_event; } + rc = ir_register_input(input_dev); + if (rc < 0) + goto out_event; + IR_dprintk(1, "Registered input device on %s for %s remote%s.\n", driver_name, rc_tab->name, (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_IR_RAW) ? @@@ -657,7 -527,7 +662,7 @@@ out_event: ir_unregister_class(input_dev); out_table: - kfree(ir_dev->rc_tab.scan); + ir_free_table(&ir_dev->rc_tab); out_name: kfree(ir_dev->driver_name); out_dev: @@@ -675,6 -545,7 +680,6 @@@ EXPORT_SYMBOL_GPL(__ir_input_register) void ir_input_unregister(struct input_dev *input_dev) { struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - struct ir_scancode_table *rc_tab; if (!ir_dev) return; @@@ -686,7 -557,10 +691,7 @@@ if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW) ir_raw_event_unregister(input_dev); - rc_tab = &ir_dev->rc_tab; - rc_tab->size = 0; - kfree(rc_tab->scan); - rc_tab->scan = NULL; + ir_free_table(&ir_dev->rc_tab); ir_unregister_class(input_dev); diff --combined drivers/media/IR/ir-lirc-codec.c index 1983cd3f399,1d9c6b0fd0e..9fc0db9d344 --- a/drivers/media/IR/ir-lirc-codec.c +++ b/drivers/media/IR/ir-lirc-codec.c @@@ -32,6 -32,7 +32,7 @@@ static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev) { struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + struct lirc_codec *lirc = &ir_dev->raw->lirc; int sample; if (!(ir_dev->raw->enabled_protocols & IR_TYPE_LIRC)) @@@ -40,21 -41,57 +41,57 @@@ if (!ir_dev->raw->lirc.drv || !ir_dev->raw->lirc.drv->rbuf) return -EINVAL; - if (IS_RESET(ev)) + /* Packet start */ + if (ev.reset) return 0; - IR_dprintk(2, "LIRC data transfer started (%uus %s)\n", - TO_US(ev.duration), TO_STR(ev.pulse)); + /* Carrier reports */ + if (ev.carrier_report) { + sample = LIRC_FREQUENCY(ev.carrier); - sample = ev.duration / 1000; - if (ev.pulse) - sample |= PULSE_BIT; + /* Packet end */ + } else if (ev.timeout) { + + if (lirc->gap) + return 0; + + lirc->gap_start = ktime_get(); + lirc->gap = true; + lirc->gap_duration = ev.duration; + + if (!lirc->send_timeout_reports) + return 0; + + sample = LIRC_TIMEOUT(ev.duration / 1000); + + /* Normal sample */ + } else { + + if (lirc->gap) { + int gap_sample; + + lirc->gap_duration += ktime_to_ns(ktime_sub(ktime_get(), + lirc->gap_start)); + + /* Convert to ms and cap by LIRC_VALUE_MASK */ + do_div(lirc->gap_duration, 1000); + lirc->gap_duration = min(lirc->gap_duration, + (u64)LIRC_VALUE_MASK); + + gap_sample = LIRC_SPACE(lirc->gap_duration); + lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf, + (unsigned char *) &gap_sample); + lirc->gap = false; + } + + sample = ev.pulse ? LIRC_PULSE(ev.duration / 1000) : + LIRC_SPACE(ev.duration / 1000); + } lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf, (unsigned char *) &sample); wake_up(&ir_dev->raw->lirc.drv->rbuf->wait_poll); - return 0; } @@@ -102,7 -139,7 +139,7 @@@ static long ir_lirc_ioctl(struct file * struct ir_input_dev *ir_dev; int ret = 0; void *drv_data; - unsigned long val = 0; + __u32 val = 0, tmp; lirc = lirc_get_pdata(filep); if (!lirc) @@@ -115,7 -152,7 +152,7 @@@ drv_data = ir_dev->props->priv; if (_IOC_DIR(cmd) & _IOC_WRITE) { - ret = get_user(val, (unsigned long *)arg); + ret = get_user(val, (__u32 *)arg); if (ret) return ret; } @@@ -130,22 -167,20 +167,20 @@@ case LIRC_SET_SEND_MODE: if (val != (LIRC_MODE_PULSE & LIRC_CAN_SEND_MASK)) return -EINVAL; - break; + return 0; /* TX settings */ case LIRC_SET_TRANSMITTER_MASK: - if (ir_dev->props->s_tx_mask) - ret = ir_dev->props->s_tx_mask(drv_data, (u32)val); - else + if (!ir_dev->props->s_tx_mask) return -EINVAL; - break; + + return ir_dev->props->s_tx_mask(drv_data, val); case LIRC_SET_SEND_CARRIER: - if (ir_dev->props->s_tx_carrier) - ir_dev->props->s_tx_carrier(drv_data, (u32)val); - else + if (!ir_dev->props->s_tx_carrier) return -EINVAL; - break; + + return ir_dev->props->s_tx_carrier(drv_data, val); case LIRC_SET_SEND_DUTY_CYCLE: if (!ir_dev->props->s_tx_duty_cycle) @@@ -154,39 -189,42 +189,42 @@@ if (val <= 0 || val >= 100) return -EINVAL; - ir_dev->props->s_tx_duty_cycle(ir_dev->props->priv, val); - break; + return ir_dev->props->s_tx_duty_cycle(drv_data, val); /* RX settings */ case LIRC_SET_REC_CARRIER: - if (ir_dev->props->s_rx_carrier_range) - ret = ir_dev->props->s_rx_carrier_range( - ir_dev->props->priv, - ir_dev->raw->lirc.carrier_low, val); - else + if (!ir_dev->props->s_rx_carrier_range) return -ENOSYS; - if (!ret) - ir_dev->raw->lirc.carrier_low = 0; - break; + if (val <= 0) + return -EINVAL; + + return ir_dev->props->s_rx_carrier_range(drv_data, + ir_dev->raw->lirc.carrier_low, val); case LIRC_SET_REC_CARRIER_RANGE: - if (val >= 0) - ir_dev->raw->lirc.carrier_low = val; - break; + if (val <= 0) + return -EINVAL; + ir_dev->raw->lirc.carrier_low = val; + return 0; case LIRC_GET_REC_RESOLUTION: val = ir_dev->props->rx_resolution; break; case LIRC_SET_WIDEBAND_RECEIVER: - if (ir_dev->props->s_learning_mode) - return ir_dev->props->s_learning_mode( - ir_dev->props->priv, !!val); - else + if (!ir_dev->props->s_learning_mode) return -ENOSYS; + return ir_dev->props->s_learning_mode(drv_data, !!val); + + case LIRC_SET_MEASURE_CARRIER_MODE: + if (!ir_dev->props->s_carrier_report) + return -ENOSYS; + + return ir_dev->props->s_carrier_report(drv_data, !!val); + /* Generic timeout support */ case LIRC_GET_MIN_TIMEOUT: if (!ir_dev->props->max_timeout) @@@ -201,10 -239,20 +239,20 @@@ break; case LIRC_SET_REC_TIMEOUT: - if (val < ir_dev->props->min_timeout || - val > ir_dev->props->max_timeout) - return -EINVAL; - ir_dev->props->timeout = val * 1000; + if (!ir_dev->props->max_timeout) + return -ENOSYS; + + tmp = val * 1000; + + if (tmp < ir_dev->props->min_timeout || + tmp > ir_dev->props->max_timeout) + return -EINVAL; + + ir_dev->props->timeout = tmp; + break; + + case LIRC_SET_REC_TIMEOUT_REPORTS: + lirc->send_timeout_reports = !!val; break; default: @@@ -212,7 -260,7 +260,7 @@@ } if (_IOC_DIR(cmd) & _IOC_READ) - ret = put_user(val, (unsigned long *)arg); + ret = put_user(val, (__u32 *)arg); return ret; } @@@ -231,11 -279,13 +279,14 @@@ static struct file_operations lirc_fop .owner = THIS_MODULE, .write = ir_lirc_transmit_ir, .unlocked_ioctl = ir_lirc_ioctl, + #ifdef CONFIG_COMPAT + .compat_ioctl = ir_lirc_ioctl, + #endif .read = lirc_dev_fop_read, .poll = lirc_dev_fop_poll, .open = lirc_dev_fop_open, .release = lirc_dev_fop_close, + .llseek = no_llseek, }; static int ir_lirc_register(struct input_dev *input_dev) @@@ -278,6 -328,10 +329,10 @@@ if (ir_dev->props->s_learning_mode) features |= LIRC_CAN_USE_WIDEBAND_RECEIVER; + if (ir_dev->props->s_carrier_report) + features |= LIRC_CAN_MEASURE_CARRIER; + + if (ir_dev->props->max_timeout) features |= LIRC_CAN_SET_REC_TIMEOUT; diff --combined drivers/media/IR/lirc_dev.c index 202581808bd,3ef15625fa8..8418b14ee4d --- a/drivers/media/IR/lirc_dev.c +++ b/drivers/media/IR/lirc_dev.c @@@ -27,6 -27,7 +27,6 @@@ #include #include #include -#include #include #include #include @@@ -57,13 -58,12 +57,12 @@@ struct irctl struct task_struct *task; long jiffies_to_wait; - - struct cdev cdev; }; static DEFINE_MUTEX(lirc_dev_lock); static struct irctl *irctls[MAX_IRCTL_DEVICES]; + static struct cdev cdevs[MAX_IRCTL_DEVICES]; /* Only used for sysfs but defined to void otherwise */ static struct class *lirc_class; @@@ -71,15 -71,13 +70,13 @@@ /* helper function * initializes the irctl structure */ - static void init_irctl(struct irctl *ir) + static void lirc_irctl_init(struct irctl *ir) { - dev_dbg(ir->d.dev, LOGHEAD "initializing irctl\n", - ir->d.name, ir->d.minor); mutex_init(&ir->irctl_lock); ir->d.minor = NOPLUG; } - static void cleanup(struct irctl *ir) + static void lirc_irctl_cleanup(struct irctl *ir) { dev_dbg(ir->d.dev, LOGHEAD "cleaning up\n", ir->d.name, ir->d.minor); @@@ -96,7 -94,7 +93,7 @@@ * reads key codes from driver and puts them into buffer * returns 0 on success */ - static int add_to_buf(struct irctl *ir) + static int lirc_add_to_buf(struct irctl *ir) { if (ir->d.add_to_buf) { int res = -ENODATA; @@@ -139,7 -137,7 +136,7 @@@ static int lirc_thread(void *irctl } if (kthread_should_stop()) break; - if (!add_to_buf(ir)) + if (!lirc_add_to_buf(ir)) wake_up_interruptible(&ir->buf->wait_poll); } else { set_current_state(TASK_INTERRUPTIBLE); @@@ -154,34 -152,37 +151,38 @@@ } - static struct file_operations fops = { + static struct file_operations lirc_dev_fops = { .owner = THIS_MODULE, .read = lirc_dev_fop_read, .write = lirc_dev_fop_write, .poll = lirc_dev_fop_poll, .unlocked_ioctl = lirc_dev_fop_ioctl, + #ifdef CONFIG_COMPAT + .compat_ioctl = lirc_dev_fop_ioctl, + #endif .open = lirc_dev_fop_open, .release = lirc_dev_fop_close, + .llseek = noop_llseek, }; static int lirc_cdev_add(struct irctl *ir) { int retval; struct lirc_driver *d = &ir->d; + struct cdev *cdev = &cdevs[d->minor]; if (d->fops) { - cdev_init(&ir->cdev, d->fops); - ir->cdev.owner = d->owner; + cdev_init(cdev, d->fops); + cdev->owner = d->owner; } else { - cdev_init(&ir->cdev, &fops); - ir->cdev.owner = THIS_MODULE; + cdev_init(cdev, &lirc_dev_fops); + cdev->owner = THIS_MODULE; } - kobject_set_name(&ir->cdev.kobj, "lirc%d", d->minor); + kobject_set_name(&cdev->kobj, "lirc%d", d->minor); - retval = cdev_add(&ir->cdev, MKDEV(MAJOR(lirc_base_dev), d->minor), 1); + retval = cdev_add(cdev, MKDEV(MAJOR(lirc_base_dev), d->minor), 1); if (retval) - kobject_put(&ir->cdev.kobj); + kobject_put(&cdev->kobj); return retval; } @@@ -202,6 -203,12 +203,12 @@@ int lirc_register_driver(struct lirc_dr goto out; } + if (!d->dev) { + printk(KERN_ERR "%s: dev pointer not filled in!\n", __func__); + err = -EINVAL; + goto out; + } + if (MAX_IRCTL_DEVICES <= d->minor) { dev_err(d->dev, "lirc_dev: lirc_register_driver: " "\"minor\" must be between 0 and %d (%d)!\n", @@@ -277,7 -284,7 +284,7 @@@ err = -ENOMEM; goto out_lock; } - init_irctl(ir); + lirc_irctl_init(ir); irctls[minor] = ir; d->minor = minor; @@@ -316,7 -323,6 +323,6 @@@ d->features = LIRC_CAN_REC_LIRCCODE; ir->d = *d; - ir->d.minor = minor; device_create(lirc_class, ir->d.dev, MKDEV(MAJOR(lirc_base_dev), ir->d.minor), NULL, @@@ -357,21 -363,28 +363,28 @@@ EXPORT_SYMBOL(lirc_register_driver) int lirc_unregister_driver(int minor) { struct irctl *ir; + struct cdev *cdev; if (minor < 0 || minor >= MAX_IRCTL_DEVICES) { - printk(KERN_ERR "lirc_dev: lirc_unregister_driver: " - "\"minor (%d)\" must be between 0 and %d!\n", - minor, MAX_IRCTL_DEVICES-1); + printk(KERN_ERR "lirc_dev: %s: minor (%d) must be between " + "0 and %d!\n", __func__, minor, MAX_IRCTL_DEVICES-1); return -EBADRQC; } ir = irctls[minor]; + if (!ir) { + printk(KERN_ERR "lirc_dev: %s: failed to get irctl struct " + "for minor %d!\n", __func__, minor); + return -ENOENT; + } + + cdev = &cdevs[minor]; mutex_lock(&lirc_dev_lock); if (ir->d.minor != minor) { - printk(KERN_ERR "lirc_dev: lirc_unregister_driver: " - "minor (%d) device not registered!", minor); + printk(KERN_ERR "lirc_dev: %s: minor (%d) device not " + "registered!\n", __func__, minor); mutex_unlock(&lirc_dev_lock); return -ENOENT; } @@@ -390,12 -403,11 +403,11 @@@ wake_up_interruptible(&ir->buf->wait_poll); mutex_lock(&ir->irctl_lock); ir->d.set_use_dec(ir->d.data); - module_put(ir->d.owner); + module_put(cdev->owner); mutex_unlock(&ir->irctl_lock); - cdev_del(&ir->cdev); } else { - cleanup(ir); - cdev_del(&ir->cdev); + lirc_irctl_cleanup(ir); + cdev_del(cdev); kfree(ir); irctls[minor] = NULL; } @@@ -409,6 -421,7 +421,7 @@@ EXPORT_SYMBOL(lirc_unregister_driver) int lirc_dev_fop_open(struct inode *inode, struct file *file) { struct irctl *ir; + struct cdev *cdev; int retval = 0; if (iminor(inode) >= MAX_IRCTL_DEVICES) { @@@ -425,7 -438,6 +438,6 @@@ retval = -ENODEV; goto error; } - file->private_data = ir; dev_dbg(ir->d.dev, LOGHEAD "open called\n", ir->d.name, ir->d.minor); @@@ -439,13 -451,14 +451,14 @@@ goto error; } - if (try_module_get(ir->d.owner)) { - ++ir->open; + cdev = &cdevs[iminor(inode)]; + if (try_module_get(cdev->owner)) { + ir->open++; retval = ir->d.set_use_inc(ir->d.data); if (retval) { - module_put(ir->d.owner); - --ir->open; + module_put(cdev->owner); + ir->open--; } else { lirc_buffer_clear(ir->buf); } @@@ -460,8 -473,6 +473,8 @@@ error mutex_unlock(&lirc_dev_lock); + nonseekable_open(inode, file); + return retval; } EXPORT_SYMBOL(lirc_dev_fop_open); @@@ -469,17 -480,24 +482,24 @@@ int lirc_dev_fop_close(struct inode *inode, struct file *file) { struct irctl *ir = irctls[iminor(inode)]; + struct cdev *cdev = &cdevs[iminor(inode)]; + + if (!ir) { + printk(KERN_ERR "%s: called with invalid irctl\n", __func__); + return -EINVAL; + } dev_dbg(ir->d.dev, LOGHEAD "close called\n", ir->d.name, ir->d.minor); WARN_ON(mutex_lock_killable(&lirc_dev_lock)); - --ir->open; + ir->open--; if (ir->attached) { ir->d.set_use_dec(ir->d.data); - module_put(ir->d.owner); + module_put(cdev->owner); } else { - cleanup(ir); + lirc_irctl_cleanup(ir); + cdev_del(cdev); irctls[ir->d.minor] = NULL; kfree(ir); } @@@ -495,6 -513,11 +515,11 @@@ unsigned int lirc_dev_fop_poll(struct f struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)]; unsigned int ret; + if (!ir) { + printk(KERN_ERR "%s: called with invalid irctl\n", __func__); + return POLLERR; + } + dev_dbg(ir->d.dev, LOGHEAD "poll called\n", ir->d.name, ir->d.minor); if (!ir->attached) { @@@ -521,9 -544,14 +546,14 @@@ EXPORT_SYMBOL(lirc_dev_fop_poll) long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - unsigned long mode; + __u32 mode; int result = 0; - struct irctl *ir = file->private_data; + struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)]; + + if (!ir) { + printk(KERN_ERR "lirc_dev: %s: no irctl found!\n", __func__); + return -ENODEV; + } dev_dbg(ir->d.dev, LOGHEAD "ioctl called (0x%x)\n", ir->d.name, ir->d.minor, cmd); @@@ -538,7 -566,7 +568,7 @@@ switch (cmd) { case LIRC_GET_FEATURES: - result = put_user(ir->d.features, (unsigned long *)arg); + result = put_user(ir->d.features, (__u32 *)arg); break; case LIRC_GET_REC_MODE: if (!(ir->d.features & LIRC_CAN_REC_MASK)) { @@@ -548,7 -576,7 +578,7 @@@ result = put_user(LIRC_REC2MODE (ir->d.features & LIRC_CAN_REC_MASK), - (unsigned long *)arg); + (__u32 *)arg); break; case LIRC_SET_REC_MODE: if (!(ir->d.features & LIRC_CAN_REC_MASK)) { @@@ -556,7 -584,7 +586,7 @@@ break; } - result = get_user(mode, (unsigned long *)arg); + result = get_user(mode, (__u32 *)arg); if (!result && !(LIRC_MODE2REC(mode) & ir->d.features)) result = -EINVAL; /* @@@ -565,7 -593,7 +595,7 @@@ */ break; case LIRC_GET_LENGTH: - result = put_user(ir->d.code_length, (unsigned long *)arg); + result = put_user(ir->d.code_length, (__u32 *)arg); break; case LIRC_GET_MIN_TIMEOUT: if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) || @@@ -574,7 -602,7 +604,7 @@@ break; } - result = put_user(ir->d.min_timeout, (unsigned long *)arg); + result = put_user(ir->d.min_timeout, (__u32 *)arg); break; case LIRC_GET_MAX_TIMEOUT: if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) || @@@ -583,7 -611,7 +613,7 @@@ break; } - result = put_user(ir->d.max_timeout, (unsigned long *)arg); + result = put_user(ir->d.max_timeout, (__u32 *)arg); break; default: result = -EINVAL; @@@ -604,12 -632,21 +634,21 @@@ ssize_t lirc_dev_fop_read(struct file * loff_t *ppos) { struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)]; - unsigned char buf[ir->chunk_size]; + unsigned char *buf; int ret = 0, written = 0; DECLARE_WAITQUEUE(wait, current); + if (!ir) { + printk(KERN_ERR "%s: called with invalid irctl\n", __func__); + return -ENODEV; + } + dev_dbg(ir->d.dev, LOGHEAD "read called\n", ir->d.name, ir->d.minor); + buf = kzalloc(ir->chunk_size, GFP_KERNEL); + if (!buf) + return -ENOMEM; + if (mutex_lock_interruptible(&ir->irctl_lock)) return -ERESTARTSYS; if (!ir->attached) { @@@ -681,6 -718,7 +720,7 @@@ mutex_unlock(&ir->irctl_lock); out_unlocked: + kfree(buf); dev_dbg(ir->d.dev, LOGHEAD "read result = %s (%d)\n", ir->d.name, ir->d.minor, ret ? "-EFAULT" : "OK", ret); @@@ -709,6 -747,11 +749,11 @@@ ssize_t lirc_dev_fop_write(struct file { struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)]; + if (!ir) { + printk(KERN_ERR "%s: called with invalid irctl\n", __func__); + return -ENODEV; + } + dev_dbg(ir->d.dev, LOGHEAD "write called\n", ir->d.name, ir->d.minor); if (!ir->attached) diff --combined drivers/media/dvb/dvb-core/dvb_frontend.c index 970c9b8882d,083ed151e9c..1589d5a5cb4 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@@ -702,7 -702,7 +702,7 @@@ static void dvb_frontend_stop(struct dv kthread_stop(fepriv->thread); - init_MUTEX (&fepriv->sem); + sema_init(&fepriv->sem, 1); fepriv->state = FESTATE_IDLE; /* paranoia check in case a signal arrived */ @@@ -2034,8 -2034,7 +2034,8 @@@ static const struct file_operations dvb .unlocked_ioctl = dvb_generic_ioctl, .poll = dvb_frontend_poll, .open = dvb_frontend_open, - .release = dvb_frontend_release + .release = dvb_frontend_release, + .llseek = noop_llseek, }; int dvb_register_frontend(struct dvb_adapter* dvb, @@@ -2062,7 -2061,7 +2062,7 @@@ } fepriv = fe->frontend_priv; - init_MUTEX (&fepriv->sem); + sema_init(&fepriv->sem, 1); init_waitqueue_head (&fepriv->wait_queue); init_waitqueue_head (&fepriv->events.wait_queue); mutex_init(&fepriv->events.mtx); diff --combined drivers/media/dvb/ttpci/av7110.c index a12b88f53ed,c453cd0a745..fc0a60f8a1e --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/dvb/ttpci/av7110.c @@@ -26,7 -26,7 +26,7 @@@ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html * * - * the project's page is at http://www.linuxtv.org/dvb/ + * the project's page is at http://www.linuxtv.org/ */ @@@ -730,7 -730,6 +730,7 @@@ static const struct file_operations dvb .unlocked_ioctl = dvb_generic_ioctl, .open = dvb_generic_open, .release = dvb_generic_release, + .llseek = noop_llseek, }; static struct dvb_device dvbdev_osd = { @@@ -2291,7 -2290,12 +2291,7 @@@ static int frontend_init(struct av7110 /* Budgetpatch note: * Original hardware design by Roberto Deza: * There is a DVB_Wiki at - * http://212.227.36.83/linuxtv/wiki/index.php/Main_Page - * where is described this 'DVB TT Budget Patch', on Card Modding: - * http://212.227.36.83/linuxtv/wiki/index.php/DVB_TT_Budget_Patch - * On the short description there is also a link to a external file, - * with more details: - * http://perso.wanadoo.es/jesussolano/Ttf_tsc1.zip + * http://www.linuxtv.org/ * * New software triggering design by Emard that works on * original Roberto Deza's hardware: @@@ -2472,7 -2476,6 +2472,6 @@@ static int __devinit av7110_attach(stru get recognized before the main driver is fully loaded */ saa7146_write(dev, GPIO_CTRL, 0x500000); - av7110->i2c_adap.class = I2C_CLASS_TV_DIGITAL; strlcpy(av7110->i2c_adap.name, pci_ext->ext_priv, sizeof(av7110->i2c_adap.name)); saa7146_i2c_adapter_prepare(dev, &av7110->i2c_adap, SAA7146_I2C_BUS_BIT_RATE_120); /* 275 kHz */ @@@ -2886,7 -2889,7 +2885,7 @@@ MODULE_DEVICE_TABLE(pci, pci_tbl) static struct saa7146_extension av7110_extension_driver = { - .name = "dvb", + .name = "av7110", .flags = SAA7146_USE_I2C_IRQ, .module = THIS_MODULE, diff --combined drivers/media/dvb/ttpci/av7110_av.c index 244d5d51f5f,4a31cf67463..952b33dbac4 --- a/drivers/media/dvb/ttpci/av7110_av.c +++ b/drivers/media/dvb/ttpci/av7110_av.c @@@ -25,7 -25,7 +25,7 @@@ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html * * - * the project's page is at http://www.linuxtv.org/dvb/ + * the project's page is at http://www.linuxtv.org/ */ #include @@@ -245,8 -245,11 +245,11 @@@ int av7110_pes_play(void *dest, struct return -1; } while (1) { - if ((len = dvb_ringbuffer_avail(buf)) < 6) + len = dvb_ringbuffer_avail(buf); + if (len < 6) { + wake_up(&buf->queue); return -1; + } sync = DVB_RINGBUFFER_PEEK(buf, 0) << 24; sync |= DVB_RINGBUFFER_PEEK(buf, 1) << 16; sync |= DVB_RINGBUFFER_PEEK(buf, 2) << 8; @@@ -1521,7 -1524,6 +1524,7 @@@ static const struct file_operations dvb .open = dvb_video_open, .release = dvb_video_release, .poll = dvb_video_poll, + .llseek = noop_llseek, }; static struct dvb_device dvbdev_video = { @@@ -1540,7 -1542,6 +1543,7 @@@ static const struct file_operations dvb .open = dvb_audio_open, .release = dvb_audio_release, .poll = dvb_audio_poll, + .llseek = noop_llseek, }; static struct dvb_device dvbdev_audio = { diff --combined drivers/media/dvb/ttpci/budget-core.c index 05466131531,847f6601d84..37666d4edab --- a/drivers/media/dvb/ttpci/budget-core.c +++ b/drivers/media/dvb/ttpci/budget-core.c @@@ -31,7 -31,7 +31,7 @@@ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html * * - * the project's page is at http://www.linuxtv.org/dvb/ + * the project's page is at http://www.linuxtv.org/ */ @@@ -495,8 -495,6 +495,6 @@@ int ttpci_budget_init(struct budget *bu if (bi->type != BUDGET_FS_ACTIVY) saa7146_write(dev, GPIO_CTRL, 0x500000); /* GPIO 3 = 1 */ - budget->i2c_adap.class = I2C_CLASS_TV_DIGITAL; - strlcpy(budget->i2c_adap.name, budget->card->name, sizeof(budget->i2c_adap.name)); saa7146_i2c_adapter_prepare(dev, &budget->i2c_adap, SAA7146_I2C_BUS_BIT_RATE_120); diff --combined drivers/media/video/Kconfig index d000522cb0f,0efbb29a1a0..ac16e815e27 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@@ -539,7 -539,7 +539,7 @@@ config VIDEO_VI config VIDEO_VIVI tristate "Virtual Video Driver" depends on VIDEO_DEV && VIDEO_V4L2 && !SPARC32 && !SPARC64 - depends on (FRAMEBUFFER_CONSOLE || STI_CONSOLE) && FONTS + depends on FRAMEBUFFER_CONSOLE || STI_CONSOLE select FONT_8x16 select VIDEOBUF_VMALLOC default n @@@ -599,68 -599,8 +599,8 @@@ config VIDEO_W996 Check out for more information. - config VIDEO_CPIA - tristate "CPiA Video For Linux (DEPRECATED)" - depends on VIDEO_V4L1 - default n - ---help--- - This driver is DEPRECATED please use the gspca cpia1 module - instead. Note that you need atleast version 0.6.4 of libv4l for - the cpia1 gspca module. - - This is the video4linux driver for cameras based on Vision's CPiA - (Colour Processor Interface ASIC), such as the Creative Labs Video - Blaster Webcam II. If you have one of these cameras, say Y here - and select parallel port and/or USB lowlevel support below, - otherwise say N. This will not work with the Creative Webcam III. - - Please read for more - information. - - This driver is also available as a module (cpia). - - config VIDEO_CPIA_PP - tristate "CPiA Parallel Port Lowlevel Support" - depends on PARPORT_1284 && VIDEO_CPIA && PARPORT - help - This is the lowlevel parallel port support for cameras based on - Vision's CPiA (Colour Processor Interface ASIC), such as the - Creative Webcam II. If you have the parallel port version of one - of these cameras, say Y here, otherwise say N. It is also available - as a module (cpia_pp). - - config VIDEO_CPIA_USB - tristate "CPiA USB Lowlevel Support" - depends on VIDEO_CPIA && USB - help - This is the lowlevel USB support for cameras based on Vision's CPiA - (Colour Processor Interface ASIC), such as the Creative Webcam II. - If you have the USB version of one of these cameras, say Y here, - otherwise say N. This will not work with the Creative Webcam III. - It is also available as a module (cpia_usb). - source "drivers/media/video/cpia2/Kconfig" - config VIDEO_SAA5246A - tristate "SAA5246A, SAA5281 Teletext processor" - depends on I2C && VIDEO_V4L2 - help - Support for I2C bus based teletext using the SAA5246A or SAA5281 - chip. Useful only if you live in Europe. - - To compile this driver as a module, choose M here: the - module will be called saa5246a. - - config VIDEO_SAA5249 - tristate "SAA5249 Teletext processor" - depends on I2C && VIDEO_V4L2 - help - Support for I2C bus based teletext using the SAA5249 chip. At the - moment this is only useful on some European WinTV cards. - - To compile this driver as a module, choose M here: the - module will be called saa5249. - config VIDEO_VINO tristate "SGI Vino Video For Linux (EXPERIMENTAL)" depends on I2C && SGI_IP22 && EXPERIMENTAL && VIDEO_V4L2 @@@ -669,14 -609,6 +609,6 @@@ Say Y here to build in support for the Vino video input system found on SGI Indy machines. - config VIDEO_STRADIS - tristate "Stradis 4:2:2 MPEG-2 video driver (EXPERIMENTAL)" - depends on EXPERIMENTAL && PCI && VIDEO_V4L1 && VIRT_TO_BUS - help - Say Y here to enable support for the Stradis 4:2:2 MPEG-2 video - driver for PCI. There is a product page at - . - source "drivers/media/video/zoran/Kconfig" config VIDEO_MEYE @@@ -774,6 -706,22 +706,22 @@@ config VIDEO_CAFE_CCI CMOS camera controller. This is the controller found on first- generation OLPC systems. + config VIDEO_SR030PC30 + tristate "SR030PC30 VGA camera sensor support" + depends on I2C && VIDEO_V4L2 + ---help--- + This driver supports SR030PC30 VGA camera from Siliconfile + + config VIDEO_VIA_CAMERA + tristate "VIAFB camera controller support" + depends on FB_VIA + select VIDEOBUF_DMA_SG + select VIDEO_OV7670 + help + Driver support for the integrated camera controller in VIA + Chrome9 chipsets. Currently only tested on OLPC xo-1.5 systems + with ov7670 sensors. + config SOC_CAMERA tristate "SoC camera support" depends on VIDEO_V4L2 && HAS_DMA && I2C @@@ -783,6 -731,12 +731,12 @@@ over a bus like PCI or USB. For example some i2c camera connected directly to the data bus of an SoC. + config SOC_CAMERA_IMX074 + tristate "imx074 support" + depends on SOC_CAMERA && I2C + help + This driver supports IMX074 cameras from Sony + config SOC_CAMERA_MT9M001 tristate "mt9m001 support" depends on SOC_CAMERA && I2C @@@ -835,6 -789,12 +789,12 @@@ config SOC_CAMERA_PLATFOR help This is a generic SoC camera platform driver, useful for testing + config SOC_CAMERA_OV6650 + tristate "ov6650 sensor support" + depends on SOC_CAMERA && I2C + ---help--- + This is a V4L2 SoC camera driver for the OmniVision OV6650 sensor + config SOC_CAMERA_OV772X tristate "ov772x camera support" depends on SOC_CAMERA && I2C @@@ -890,6 -850,14 +850,14 @@@ config VIDEO_SH_MOBILE_CE ---help--- This is a v4l2 driver for the SuperH Mobile CEU Interface + config VIDEO_OMAP1 + tristate "OMAP1 Camera Interface driver" + depends on VIDEO_DEV && ARCH_OMAP1 && SOC_CAMERA + select VIDEOBUF_DMA_CONTIG + select VIDEOBUF_DMA_SG + ---help--- + This is a v4l2 driver for the TI OMAP1 camera interface + config VIDEO_OMAP2 tristate "OMAP2 Camera Capture Interface driver" depends on VIDEO_DEV && ARCH_OMAP2 @@@ -978,7 -946,7 +946,7 @@@ config USB_STKWEBCA Supported devices are typically found in some Asus laptops, with USB id 174f:a311 and 05e1:0501. Other Syntek cameras may be supported by the stk11xx driver, from which this is - derived, see http://stk11xx.sourceforge.net + derived, see To compile this driver as a module, choose M here: the module will be called stkwebcam. diff --combined drivers/media/video/cafe_ccic.c index 9536f1a40dd,7c849eaf851..2934770dacc --- a/drivers/media/video/cafe_ccic.c +++ b/drivers/media/video/cafe_ccic.c @@@ -4,7 -4,7 +4,7 @@@ * sensor. * * The data sheet for this device can be found at: - * http://www.marvell.com/products/pcconn/88ALP01.jsp + * http://www.marvell.com/products/pc_connectivity/88alp01/ * * Copyright 2006 One Laptop Per Child Association, Inc. * Copyright 2006-7 Jonathan Corbet @@@ -25,6 -25,7 +25,7 @@@ #include #include #include + #include #include #include #include @@@ -46,6 -47,7 +47,7 @@@ #include #include + #include "ov7670.h" #include "cafe_ccic-regs.h" #define CAFE_VERSION 0x000002 @@@ -180,6 -182,7 +182,7 @@@ struct cafe_camer /* Current operating parameters */ u32 sensor_type; /* Currently ov7670 only */ struct v4l2_pix_format pix_format; + enum v4l2_mbus_pixelcode mbus_code; /* Locks */ struct mutex s_mutex; /* Access to this structure */ @@@ -207,6 -210,49 +210,49 @@@ static inline struct cafe_camera *to_ca return container_of(dev, struct cafe_camera, v4l2_dev); } + static struct cafe_format_struct { + __u8 *desc; + __u32 pixelformat; + int bpp; /* Bytes per pixel */ + enum v4l2_mbus_pixelcode mbus_code; + } cafe_formats[] = { + { + .desc = "YUYV 4:2:2", + .pixelformat = V4L2_PIX_FMT_YUYV, + .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8, + .bpp = 2, + }, + { + .desc = "RGB 444", + .pixelformat = V4L2_PIX_FMT_RGB444, + .mbus_code = V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE, + .bpp = 2, + }, + { + .desc = "RGB 565", + .pixelformat = V4L2_PIX_FMT_RGB565, + .mbus_code = V4L2_MBUS_FMT_RGB565_2X8_LE, + .bpp = 2, + }, + { + .desc = "Raw RGB Bayer", + .pixelformat = V4L2_PIX_FMT_SBGGR8, + .mbus_code = V4L2_MBUS_FMT_SBGGR8_1X8, + .bpp = 1 + }, + }; + #define N_CAFE_FMTS ARRAY_SIZE(cafe_formats) + + static struct cafe_format_struct *cafe_find_format(u32 pixelformat) + { + unsigned i; + + for (i = 0; i < N_CAFE_FMTS; i++) + if (cafe_formats[i].pixelformat == pixelformat) + return cafe_formats + i; + /* Not found? Then return the first format. */ + return cafe_formats; + } /* * Start over with DMA buffers - dev_lock needed. @@@ -319,7 -365,6 +365,6 @@@ static int cafe_smbus_write_data(struc { unsigned int rval; unsigned long flags; - DEFINE_WAIT(the_wait); spin_lock_irqsave(&cam->dev_lock, flags); rval = TWSIC0_EN | ((addr << TWSIC0_SID_SHIFT) & TWSIC0_SID); @@@ -334,28 -379,27 +379,27 @@@ cafe_reg_write(cam, REG_TWSIC1, rval); spin_unlock_irqrestore(&cam->dev_lock, flags); + /* Unfortunately, reading TWSIC1 too soon after sending a command + * causes the device to die. + * Use a busy-wait because we often send a large quantity of small + * commands at-once; using msleep() would cause a lot of context + * switches which take longer than 2ms, resulting in a noticable + * boot-time and capture-start delays. + */ + mdelay(2); + /* - * Time to wait for the write to complete. THIS IS A RACY - * WAY TO DO IT, but the sad fact is that reading the TWSIC1 - * register too quickly after starting the operation sends - * the device into a place that may be kinder and better, but - * which is absolutely useless for controlling the sensor. In - * practice we have plenty of time to get into our sleep state - * before the interrupt hits, and the worst case is that we - * time out and then see that things completed, so this seems - * the best way for now. + * Another sad fact is that sometimes, commands silently complete but + * cafe_smbus_write_done() never becomes aware of this. + * This happens at random and appears to possible occur with any + * command. + * We don't understand why this is. We work around this issue + * with the timeout in the wait below, assuming that all commands + * complete within the timeout. */ - do { - prepare_to_wait(&cam->smbus_wait, &the_wait, - TASK_UNINTERRUPTIBLE); - schedule_timeout(1); /* even 1 jiffy is too long */ - finish_wait(&cam->smbus_wait, &the_wait); - } while (!cafe_smbus_write_done(cam)); - - #ifdef IF_THE_CAFE_HARDWARE_WORKED_RIGHT wait_event_timeout(cam->smbus_wait, cafe_smbus_write_done(cam), CAFE_SMBUS_TIMEOUT); - #endif + spin_lock_irqsave(&cam->dev_lock, flags); rval = cafe_reg_read(cam, REG_TWSIC1); spin_unlock_irqrestore(&cam->dev_lock, flags); @@@ -812,15 -856,15 +856,15 @@@ static int cafe_cam_set_flip(struct caf static int cafe_cam_configure(struct cafe_camera *cam) { - struct v4l2_format fmt; + struct v4l2_mbus_framefmt mbus_fmt; int ret; if (cam->state != S_IDLE) return -EINVAL; - fmt.fmt.pix = cam->pix_format; + v4l2_fill_mbus_format(&mbus_fmt, &cam->pix_format, cam->mbus_code); ret = sensor_call(cam, core, init, 0); if (ret == 0) - ret = sensor_call(cam, video, s_fmt, &fmt); + ret = sensor_call(cam, video, s_mbus_fmt, &mbus_fmt); /* * OV7670 does weird things if flip is set *before* format... */ @@@ -1481,7 -1525,7 +1525,7 @@@ static int cafe_vidioc_querycap(struct /* * The default format we use until somebody says otherwise. */ - static struct v4l2_pix_format cafe_def_pix_format = { + static const struct v4l2_pix_format cafe_def_pix_format = { .width = VGA_WIDTH, .height = VGA_HEIGHT, .pixelformat = V4L2_PIX_FMT_YUYV, @@@ -1490,28 -1534,38 +1534,38 @@@ .sizeimage = VGA_WIDTH*VGA_HEIGHT*2, }; + static const enum v4l2_mbus_pixelcode cafe_def_mbus_code = + V4L2_MBUS_FMT_YUYV8_2X8; + static int cafe_vidioc_enum_fmt_vid_cap(struct file *filp, void *priv, struct v4l2_fmtdesc *fmt) { - struct cafe_camera *cam = priv; - int ret; - - mutex_lock(&cam->s_mutex); - ret = sensor_call(cam, video, enum_fmt, fmt); - mutex_unlock(&cam->s_mutex); - return ret; + if (fmt->index >= N_CAFE_FMTS) + return -EINVAL; + strlcpy(fmt->description, cafe_formats[fmt->index].desc, + sizeof(fmt->description)); + fmt->pixelformat = cafe_formats[fmt->index].pixelformat; + return 0; } - static int cafe_vidioc_try_fmt_vid_cap(struct file *filp, void *priv, struct v4l2_format *fmt) { struct cafe_camera *cam = priv; + struct cafe_format_struct *f; + struct v4l2_pix_format *pix = &fmt->fmt.pix; + struct v4l2_mbus_framefmt mbus_fmt; int ret; + f = cafe_find_format(pix->pixelformat); + pix->pixelformat = f->pixelformat; + v4l2_fill_mbus_format(&mbus_fmt, pix, f->mbus_code); mutex_lock(&cam->s_mutex); - ret = sensor_call(cam, video, try_fmt, fmt); + ret = sensor_call(cam, video, try_mbus_fmt, &mbus_fmt); mutex_unlock(&cam->s_mutex); + v4l2_fill_pix_format(pix, &mbus_fmt); + pix->bytesperline = pix->width * f->bpp; + pix->sizeimage = pix->height * pix->bytesperline; return ret; } @@@ -1519,6 -1573,7 +1573,7 @@@ static int cafe_vidioc_s_fmt_vid_cap(st struct v4l2_format *fmt) { struct cafe_camera *cam = priv; + struct cafe_format_struct *f; int ret; /* @@@ -1527,6 -1582,9 +1582,9 @@@ */ if (cam->state != S_IDLE || cam->n_sbufs > 0) return -EBUSY; + + f = cafe_find_format(fmt->fmt.pix.pixelformat); + /* * See if the formatting works in principle. */ @@@ -1539,6 -1597,8 +1597,8 @@@ */ mutex_lock(&cam->s_mutex); cam->pix_format = fmt->fmt.pix; + cam->mbus_code = f->mbus_code; + /* * Make sure we have appropriate DMA buffers. */ @@@ -1652,6 -1712,30 +1712,30 @@@ static int cafe_vidioc_g_chip_ident(str return sensor_call(cam, core, g_chip_ident, chip); } + static int cafe_vidioc_enum_framesizes(struct file *filp, void *priv, + struct v4l2_frmsizeenum *sizes) + { + struct cafe_camera *cam = priv; + int ret; + + mutex_lock(&cam->s_mutex); + ret = sensor_call(cam, video, enum_framesizes, sizes); + mutex_unlock(&cam->s_mutex); + return ret; + } + + static int cafe_vidioc_enum_frameintervals(struct file *filp, void *priv, + struct v4l2_frmivalenum *interval) + { + struct cafe_camera *cam = priv; + int ret; + + mutex_lock(&cam->s_mutex); + ret = sensor_call(cam, video, enum_frameintervals, interval); + mutex_unlock(&cam->s_mutex); + return ret; + } + #ifdef CONFIG_VIDEO_ADV_DEBUG static int cafe_vidioc_g_register(struct file *file, void *priv, struct v4l2_dbg_register *reg) @@@ -1715,6 -1799,8 +1799,8 @@@ static const struct v4l2_ioctl_ops cafe .vidioc_s_ctrl = cafe_vidioc_s_ctrl, .vidioc_g_parm = cafe_vidioc_g_parm, .vidioc_s_parm = cafe_vidioc_s_parm, + .vidioc_enum_framesizes = cafe_vidioc_enum_framesizes, + .vidioc_enum_frameintervals = cafe_vidioc_enum_frameintervals, .vidioc_g_chip_ident = cafe_vidioc_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .vidioc_g_register = cafe_vidioc_g_register, @@@ -1890,11 -1976,33 +1976,33 @@@ static irqreturn_t cafe_irq(int irq, vo * PCI interface stuff. */ + static const struct dmi_system_id olpc_xo1_dmi[] = { + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "OLPC"), + DMI_MATCH(DMI_PRODUCT_NAME, "XO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "1"), + }, + }, + { } + }; + static int cafe_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { int ret; struct cafe_camera *cam; + struct ov7670_config sensor_cfg = { + /* This controller only does SMBUS */ + .use_smbus = true, + + /* + * Exclude QCIF mode, because it only captures a tiny portion + * of the sensor FOV + */ + .min_width = 320, + .min_height = 240, + }; /* * Start putting together one of our big camera structures. @@@ -1915,6 -2023,7 +2023,7 @@@ init_waitqueue_head(&cam->iowait); cam->pdev = pdev; cam->pix_format = cafe_def_pix_format; + cam->mbus_code = cafe_def_mbus_code; INIT_LIST_HEAD(&cam->dev_list); INIT_LIST_HEAD(&cam->sb_avail); INIT_LIST_HEAD(&cam->sb_full); @@@ -1951,13 -2060,18 +2060,18 @@@ if (ret) goto out_freeirq; + /* Apply XO-1 clock speed */ + if (dmi_check_system(olpc_xo1_dmi)) + sensor_cfg.clock_speed = 45; + cam->sensor_addr = 0x42; cam->sensor = v4l2_i2c_new_subdev(&cam->v4l2_dev, &cam->i2c_adapter, - "ov7670", "ov7670", cam->sensor_addr, NULL); + NULL, "ov7670", cam->sensor_addr, NULL); if (cam->sensor == NULL) { ret = -ENODEV; goto out_smbus; } + ret = cafe_cam_init(cam); if (ret) goto out_smbus; diff --combined drivers/media/video/cx23885/cx23885-417.c index 53a67824071,6628e07a809..a6cc12f8736 --- a/drivers/media/video/cx23885/cx23885-417.c +++ b/drivers/media/video/cx23885/cx23885-417.c @@@ -7,7 -7,7 +7,7 @@@ * (c) 2008 Steven Toth * - CX23885/7/8 support * - * Includes parts from the ivtv driver( http://ivtv.sourceforge.net/), + * Includes parts from the ivtv driver * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@@ -1591,7 -1591,7 +1591,7 @@@ static int mpeg_open(struct file *file V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED, sizeof(struct cx23885_buffer), - fh); + fh, NULL); unlock_kernel(); return 0; diff --combined drivers/media/video/cx88/cx88-blackbird.c index 660b2a927fe,ac885f49313..417d1d5c73c --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@@ -9,7 -9,7 +9,7 @@@ * (c) 2005-2006 Mauro Carvalho Chehab * - video_ioctl2 conversion * - * Includes parts from the ivtv driver( http://ivtv.sourceforge.net/), + * Includes parts from the ivtv driver * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@@ -1057,7 -1057,7 +1057,7 @@@ static int mpeg_open(struct file *file dprintk( 1, "%s\n", __func__); - lock_kernel(); + mutex_lock(&dev->core->lock); /* Make sure we can acquire the hardware */ drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD); @@@ -1065,7 -1065,7 +1065,7 @@@ err = drv->request_acquire(drv); if(err != 0) { dprintk(1,"%s: Unable to acquire hardware, %d\n", __func__, err); - unlock_kernel(); + mutex_unlock(&dev->core->lock);; return err; } } @@@ -1073,7 -1073,7 +1073,7 @@@ if (!atomic_read(&dev->core->mpeg_users) && blackbird_initialize_codec(dev) < 0) { if (drv) drv->request_release(drv); - unlock_kernel(); + mutex_unlock(&dev->core->lock); return -EINVAL; } dprintk(1, "open dev=%s\n", video_device_node_name(vdev)); @@@ -1083,7 -1083,7 +1083,7 @@@ if (NULL == fh) { if (drv) drv->request_release(drv); - unlock_kernel(); + mutex_unlock(&dev->core->lock); return -ENOMEM; } file->private_data = fh; @@@ -1094,15 -1094,14 +1094,14 @@@ V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED, sizeof(struct cx88_buffer), - fh); + fh, NULL); /* FIXME: locking against other video device */ cx88_set_scale(dev->core, dev->width, dev->height, fh->mpegq.field); - unlock_kernel(); atomic_inc(&dev->core->mpeg_users); - + mutex_unlock(&dev->core->lock); return 0; } @@@ -1120,8 -1119,11 +1119,11 @@@ static int mpeg_release(struct file *fi videobuf_stop(&fh->mpegq); videobuf_mmap_free(&fh->mpegq); + + mutex_lock(&dev->core->lock); file->private_data = NULL; kfree(fh); + mutex_unlock(&dev->core->lock); /* Make sure we release the hardware */ drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD); diff --combined drivers/media/video/mxb.c index b1dbcf1d2bc,4c9c1bb688c..94ba698d0ad --- a/drivers/media/video/mxb.c +++ b/drivers/media/video/mxb.c @@@ -3,7 -3,7 +3,7 @@@ Copyright (C) 1998-2006 Michael Hunold - Visit http://www.mihu.de/linux/saa7146/mxb/ + Visit http://www.themm.net/~mihu/linux/saa7146/mxb.html for further details about this card. This program is free software; you can redistribute it and/or modify @@@ -32,7 -32,6 +32,6 @@@ #include "tea6415c.h" #include "tea6420.h" - #define I2C_SAA5246A 0x11 #define I2C_SAA7111A 0x24 #define I2C_TDA9840 0x42 #define I2C_TEA6415C 0x43 @@@ -186,21 -185,17 +185,17 @@@ static int mxb_probe(struct saa7146_de } mxb->saa7111a = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter, - "saa7115", "saa7111", I2C_SAA7111A, NULL); + NULL, "saa7111", I2C_SAA7111A, NULL); mxb->tea6420_1 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter, - "tea6420", "tea6420", I2C_TEA6420_1, NULL); + NULL, "tea6420", I2C_TEA6420_1, NULL); mxb->tea6420_2 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter, - "tea6420", "tea6420", I2C_TEA6420_2, NULL); + NULL, "tea6420", I2C_TEA6420_2, NULL); mxb->tea6415c = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter, - "tea6415c", "tea6415c", I2C_TEA6415C, NULL); + NULL, "tea6415c", I2C_TEA6415C, NULL); mxb->tda9840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter, - "tda9840", "tda9840", I2C_TDA9840, NULL); + NULL, "tda9840", I2C_TDA9840, NULL); mxb->tuner = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter, - "tuner", "tuner", I2C_TUNER, NULL); - if (v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter, - "saa5246a", "saa5246a", I2C_SAA5246A, NULL)) { - printk(KERN_INFO "mxb: found teletext decoder\n"); - } + NULL, "tuner", I2C_TUNER, NULL); /* check if all devices are present */ if (!mxb->tea6420_1 || !mxb->tea6420_2 || !mxb->tea6415c || diff --combined drivers/media/video/zoran/zoran_driver.c index 3c471a4e3e4,c155ddfb133..401082b853f --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c @@@ -1177,7 -1177,7 +1177,7 @@@ static int setup_window(struct zoran_f if (height > BUZ_MAX_HEIGHT) height = BUZ_MAX_HEIGHT; - /* Check for vaild parameters */ + /* Check for invalid parameters */ if (width < BUZ_MIN_WIDTH || height < BUZ_MIN_HEIGHT || width > BUZ_MAX_WIDTH || height > BUZ_MAX_HEIGHT) { dprintk(1, @@@ -3322,7 -3322,7 +3322,7 @@@ zoran_mmap (struct file *file mmap_unlock_and_return: mutex_unlock(&zr->resource_lock); - return 0; + return res; } static const struct v4l2_ioctl_ops zoran_ioctl_ops = { diff --combined drivers/staging/Kconfig index 8e03e760023,078525ca19d..2ea91e04925 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@@ -51,6 -51,10 +51,10 @@@ source "drivers/staging/cx25821/Kconfig source "drivers/staging/tm6000/Kconfig" + source "drivers/staging/cpia/Kconfig" + + source "drivers/staging/stradis/Kconfig" + source "drivers/staging/usbip/Kconfig" source "drivers/staging/winbond/Kconfig" @@@ -139,6 -143,8 +143,6 @@@ source "drivers/staging/adis16255/Kconf source "drivers/staging/xgifb/Kconfig" -source "drivers/staging/mrst-touchscreen/Kconfig" - source "drivers/staging/msm/Kconfig" source "drivers/staging/lirc/Kconfig" diff --combined drivers/staging/Makefile index 0e7d7559d37,057adca4d04..c359fbb0e04 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@@ -8,6 -8,8 +8,8 @@@ obj-$(CONFIG_SLICOSS) += slicoss obj-$(CONFIG_VIDEO_GO7007) += go7007/ obj-$(CONFIG_VIDEO_CX25821) += cx25821/ obj-$(CONFIG_VIDEO_TM6000) += tm6000/ + obj-$(CONFIG_VIDEO_CPIA) += cpia/ + obj-$(CONFIG_VIDEO_STRADIS) += stradis/ obj-$(CONFIG_LIRC_STAGING) += lirc/ obj-$(CONFIG_USB_IP_COMMON) += usbip/ obj-$(CONFIG_W35UND) += winbond/ @@@ -51,6 -53,7 +53,6 @@@ obj-$(CONFIG_CXT1E1) += cxt1e1 obj-$(CONFIG_TI_ST) += ti-st/ obj-$(CONFIG_ADIS16255) += adis16255/ obj-$(CONFIG_FB_XGI) += xgifb/ -obj-$(CONFIG_TOUCHSCREEN_MRSTOUCH) += mrst-touchscreen/ obj-$(CONFIG_MSM_STAGING) += msm/ obj-$(CONFIG_EASYCAP) += easycap/ obj-$(CONFIG_SOLO6X10) += solo6x10/ diff --combined drivers/staging/cx25821/Kconfig index 813cb355ac0,a766d0bed4f..1d73334d2a4 --- a/drivers/staging/cx25821/Kconfig +++ b/drivers/staging/cx25821/Kconfig @@@ -1,11 -1,10 +1,11 @@@ config VIDEO_CX25821 tristate "Conexant cx25821 support" depends on DVB_CORE && VIDEO_DEV && PCI && I2C && INPUT + depends on BKL # please fix select I2C_ALGOBIT select VIDEO_BTCX select VIDEO_TVEEPROM - select VIDEO_IR + depends on VIDEO_IR select VIDEOBUF_DVB select VIDEOBUF_DMA_SG select VIDEO_CX25840 diff --combined drivers/staging/go7007/Kconfig index 75fa4680552,b816a6045d0..3aecd30f0d1 --- a/drivers/staging/go7007/Kconfig +++ b/drivers/staging/go7007/Kconfig @@@ -1,10 -1,9 +1,10 @@@ config VIDEO_GO7007 tristate "WIS GO7007 MPEG encoder support" depends on VIDEO_DEV && PCI && I2C && INPUT + depends on BKL # please fix depends on SND select VIDEOBUF_DMA_SG - select VIDEO_IR + depends on VIDEO_IR select VIDEO_TUNER select VIDEO_TVEEPROM select SND_PCM diff --combined drivers/staging/lirc/lirc_it87.c index 543c5c3bf90,20f02bc6236..929ae579546 --- a/drivers/staging/lirc/lirc_it87.c +++ b/drivers/staging/lirc/lirc_it87.c @@@ -239,8 -239,7 +239,7 @@@ static ssize_t lirc_write(struct file * static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) { int retval = 0; - unsigned long value = 0; - unsigned int ivalue; + __u32 value = 0; unsigned long hw_flags; if (cmd == LIRC_GET_FEATURES) @@@ -256,24 -255,24 +255,24 @@@ case LIRC_GET_FEATURES: case LIRC_GET_SEND_MODE: case LIRC_GET_REC_MODE: - retval = put_user(value, (unsigned long *) arg); + retval = put_user(value, (__u32 *) arg); break; case LIRC_SET_SEND_MODE: case LIRC_SET_REC_MODE: - retval = get_user(value, (unsigned long *) arg); + retval = get_user(value, (__u32 *) arg); break; case LIRC_SET_SEND_CARRIER: - retval = get_user(ivalue, (unsigned int *) arg); + retval = get_user(value, (__u32 *) arg); if (retval) return retval; - ivalue /= 1000; - if (ivalue > IT87_CIR_FREQ_MAX || - ivalue < IT87_CIR_FREQ_MIN) + value /= 1000; + if (value > IT87_CIR_FREQ_MAX || + value < IT87_CIR_FREQ_MIN) return -EINVAL; - it87_freq = ivalue; + it87_freq = value; spin_lock_irqsave(&hardware_lock, hw_flags); outb(((inb(io + IT87_CIR_TCR2) & IT87_CIR_TCR2_TXMPW) | @@@ -340,9 -339,11 +339,12 @@@ static const struct file_operations lir .write = lirc_write, .poll = lirc_poll, .unlocked_ioctl = lirc_ioctl, + #ifdef CONFIG_COMPAT + .compat_ioctl = lirc_ioctl, + #endif .open = lirc_open, .release = lirc_close, + .llseek = noop_llseek, }; static int set_use_inc(void *data) @@@ -964,10 -965,11 +966,11 @@@ static void __exit lirc_it87_exit(void printk(KERN_INFO LIRC_DRIVER_NAME ": Uninstalled.\n"); } - /* SECTION: PNP for ITE8704/18 */ + /* SECTION: PNP for ITE8704/13/18 */ static const struct pnp_device_id pnp_dev_table[] = { {"ITE8704", 0}, + {"ITE8713", 0}, {} }; diff --combined drivers/staging/lirc/lirc_serial.c index 8da38249261,05a9bf3980a..971844bbee2 --- a/drivers/staging/lirc/lirc_serial.c +++ b/drivers/staging/lirc/lirc_serial.c @@@ -372,7 -372,7 +372,7 @@@ static unsigned long conv_us_to_clocks static int init_timing_params(unsigned int new_duty_cycle, unsigned int new_freq) { - unsigned long long loops_per_sec, work; + __u64 loops_per_sec, work; duty_cycle = new_duty_cycle; freq = new_freq; @@@ -987,8 -987,7 +987,7 @@@ static ssize_t lirc_write(struct file * static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) { int result; - unsigned long value; - unsigned int ivalue; + __u32 value; switch (cmd) { case LIRC_GET_SEND_MODE: @@@ -997,7 -996,7 +996,7 @@@ result = put_user(LIRC_SEND2MODE (hardware[type].features&LIRC_CAN_SEND_MASK), - (unsigned long *) arg); + (__u32 *) arg); if (result) return result; break; @@@ -1006,7 -1005,7 +1005,7 @@@ if (!(hardware[type].features&LIRC_CAN_SEND_MASK)) return -ENOIOCTLCMD; - result = get_user(value, (unsigned long *) arg); + result = get_user(value, (__u32 *) arg); if (result) return result; /* only LIRC_MODE_PULSE supported */ @@@ -1023,12 -1022,12 +1022,12 @@@ if (!(hardware[type].features&LIRC_CAN_SET_SEND_DUTY_CYCLE)) return -ENOIOCTLCMD; - result = get_user(ivalue, (unsigned int *) arg); + result = get_user(value, (__u32 *) arg); if (result) return result; - if (ivalue <= 0 || ivalue > 100) + if (value <= 0 || value > 100) return -EINVAL; - return init_timing_params(ivalue, freq); + return init_timing_params(value, freq); break; case LIRC_SET_SEND_CARRIER: @@@ -1036,12 -1035,12 +1035,12 @@@ if (!(hardware[type].features&LIRC_CAN_SET_SEND_CARRIER)) return -ENOIOCTLCMD; - result = get_user(ivalue, (unsigned int *) arg); + result = get_user(value, (__u32 *) arg); if (result) return result; - if (ivalue > 500000 || ivalue < 20000) + if (value > 500000 || value < 20000) return -EINVAL; - return init_timing_params(duty_cycle, ivalue); + return init_timing_params(duty_cycle, value); break; default: @@@ -1054,11 -1053,13 +1053,14 @@@ static const struct file_operations lir .owner = THIS_MODULE, .write = lirc_write, .unlocked_ioctl = lirc_ioctl, + #ifdef CONFIG_COMPAT + .compat_ioctl = lirc_ioctl, + #endif .read = lirc_dev_fop_read, .poll = lirc_dev_fop_poll, .open = lirc_dev_fop_open, .release = lirc_dev_fop_close, + .llseek = no_llseek, }; static struct lirc_driver driver = { diff --combined drivers/staging/lirc/lirc_sir.c index 2478871bd95,c4cb3aa842d..c553ab62623 --- a/drivers/staging/lirc/lirc_sir.c +++ b/drivers/staging/lirc/lirc_sir.c @@@ -336,9 -336,8 +336,8 @@@ static ssize_t lirc_write(struct file * static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) { int retval = 0; - unsigned long value = 0; + __u32 value = 0; #ifdef LIRC_ON_SA1100 - unsigned int ivalue; if (cmd == LIRC_GET_FEATURES) value = LIRC_CAN_SEND_PULSE | @@@ -362,22 -361,22 +361,22 @@@ case LIRC_GET_FEATURES: case LIRC_GET_SEND_MODE: case LIRC_GET_REC_MODE: - retval = put_user(value, (unsigned long *) arg); + retval = put_user(value, (__u32 *) arg); break; case LIRC_SET_SEND_MODE: case LIRC_SET_REC_MODE: - retval = get_user(value, (unsigned long *) arg); + retval = get_user(value, (__u32 *) arg); break; #ifdef LIRC_ON_SA1100 case LIRC_SET_SEND_DUTY_CYCLE: - retval = get_user(ivalue, (unsigned int *) arg); + retval = get_user(value, (__u32 *) arg); if (retval) return retval; - if (ivalue <= 0 || ivalue > 100) + if (value <= 0 || value > 100) return -EINVAL; - /* (ivalue/100)*(1000000/freq) */ - duty_cycle = ivalue; + /* (value/100)*(1000000/freq) */ + duty_cycle = value; pulse_width = (unsigned long) duty_cycle*10000/freq; space_width = (unsigned long) 1000000L/freq-pulse_width; if (pulse_width >= LIRC_ON_SA1100_TRANSMITTER_LATENCY) @@@ -386,12 -385,12 +385,12 @@@ space_width -= LIRC_ON_SA1100_TRANSMITTER_LATENCY; break; case LIRC_SET_SEND_CARRIER: - retval = get_user(ivalue, (unsigned int *) arg); + retval = get_user(value, (__u32 *) arg); if (retval) return retval; - if (ivalue > 500000 || ivalue < 20000) + if (value > 500000 || value < 20000) return -EINVAL; - freq = ivalue; + freq = value; pulse_width = (unsigned long) duty_cycle*10000/freq; space_width = (unsigned long) 1000000L/freq-pulse_width; if (pulse_width >= LIRC_ON_SA1100_TRANSMITTER_LATENCY) @@@ -457,9 -456,11 +456,12 @@@ static const struct file_operations lir .write = lirc_write, .poll = lirc_poll, .unlocked_ioctl = lirc_ioctl, + #ifdef CONFIG_COMPAT + .compat_ioctl = lirc_ioctl, + #endif .open = lirc_dev_fop_open, .release = lirc_dev_fop_close, + .llseek = no_llseek, }; static int set_use_inc(void *data) diff --combined drivers/video/via/accel.c index 3c969cdef0a,04bec058569..4b67b8e6030 --- a/drivers/video/via/accel.c +++ b/drivers/video/via/accel.c @@@ -283,12 -283,11 +283,12 @@@ static int hw_bitblt_2(void __iomem *en writel(tmp, engine + 0x1C); } - if (op != VIA_BITBLT_COLOR) + if (op == VIA_BITBLT_FILL) { + writel(fg_color, engine + 0x58); + } else if (op == VIA_BITBLT_MONO) { writel(fg_color, engine + 0x4C); - - if (op == VIA_BITBLT_MONO) writel(bg_color, engine + 0x50); + } if (op == VIA_BITBLT_FILL) ge_cmd |= fill_rop << 24 | 0x00002000 | 0x00000001; @@@ -315,11 -314,13 +315,11 @@@ return 0; } -int viafb_init_engine(struct fb_info *info) +int viafb_setup_engine(struct fb_info *info) { struct viafb_par *viapar = info->par; void __iomem *engine; - int highest_reg, i; - u32 vq_start_addr, vq_end_addr, vq_start_low, vq_end_low, vq_high, - vq_len, chip_name = viapar->shared->chip_info.gfx_chip_name; + u32 chip_name = viapar->shared->chip_info.gfx_chip_name; engine = viapar->shared->vdev->engine_mmio; if (!engine) { @@@ -328,6 -329,18 +328,6 @@@ return -ENOMEM; } - /* Initialize registers to reset the 2D engine */ - switch (viapar->shared->chip_info.twod_engine) { - case VIA_2D_ENG_M1: - highest_reg = 0x5c; - break; - default: - highest_reg = 0x40; - break; - } - for (i = 0; i <= highest_reg; i += 4) - writel(0x0, engine + i); - switch (chip_name) { case UNICHROME_CLE266: case UNICHROME_K400: @@@ -343,7 -356,6 +343,7 @@@ break; case UNICHROME_VX800: case UNICHROME_VX855: + case UNICHROME_VX900: viapar->shared->hw_bitblt = hw_bitblt_2; break; default: @@@ -358,7 -370,7 +358,7 @@@ viapar->shared->vq_vram_addr = viapar->fbmem_free; viapar->fbmem_used += VQ_SIZE; - #if defined(CONFIG_FB_VIA_CAMERA) || defined(CONFIG_FB_VIA_CAMERA_MODULE) + #if defined(CONFIG_VIDEO_VIA_CAMERA) || defined(CONFIG_VIDEO_VIA_CAMERA_MODULE) /* * Set aside a chunk of framebuffer memory for the camera * driver. Someday this driver probably needs a proper allocator @@@ -374,36 -386,12 +374,36 @@@ viapar->shared->vdev->camera_fbmem_offset = viapar->fbmem_free; #endif + viafb_reset_engine(viapar); + return 0; +} + +void viafb_reset_engine(struct viafb_par *viapar) +{ + void __iomem *engine = viapar->shared->vdev->engine_mmio; + int highest_reg, i; + u32 vq_start_addr, vq_end_addr, vq_start_low, vq_end_low, vq_high, + vq_len, chip_name = viapar->shared->chip_info.gfx_chip_name; + + /* Initialize registers to reset the 2D engine */ + switch (viapar->shared->chip_info.twod_engine) { + case VIA_2D_ENG_M1: + highest_reg = 0x5c; + break; + default: + highest_reg = 0x40; + break; + } + for (i = 0; i <= highest_reg; i += 4) + writel(0x0, engine + i); + /* Init AGP and VQ regs */ switch (chip_name) { case UNICHROME_K8M890: case UNICHROME_P4M900: case UNICHROME_VX800: case UNICHROME_VX855: + case UNICHROME_VX900: writel(0x00100000, engine + VIA_REG_CR_TRANSET); writel(0x680A0000, engine + VIA_REG_CR_TRANSPACE); writel(0x02000000, engine + VIA_REG_CR_TRANSPACE); @@@ -440,7 -428,6 +440,7 @@@ case UNICHROME_P4M900: case UNICHROME_VX800: case UNICHROME_VX855: + case UNICHROME_VX900: vq_start_low |= 0x20000000; vq_end_low |= 0x20000000; vq_high |= 0x20000000; @@@ -486,7 -473,7 +486,7 @@@ writel(0x0, engine + VIA_REG_CURSOR_ORG); writel(0x0, engine + VIA_REG_CURSOR_BG); writel(0x0, engine + VIA_REG_CURSOR_FG); - return 0; + return; } void viafb_show_hw_cursor(struct fb_info *info, int Status) diff --combined drivers/video/via/via-core.c index 31e30338e89,27d7260d4f5..a3aa9170950 --- a/drivers/video/via/via-core.c +++ b/drivers/video/via/via-core.c @@@ -20,7 -20,7 +20,7 @@@ * The default port config. */ static struct via_port_cfg adap_configs[] = { - [VIA_PORT_26] = { VIA_PORT_I2C, VIA_MODE_OFF, VIASR, 0x26 }, + [VIA_PORT_26] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x26 }, [VIA_PORT_31] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x31 }, [VIA_PORT_25] = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x25 }, [VIA_PORT_2C] = { VIA_PORT_GPIO, VIA_MODE_I2C, VIASR, 0x2c }, @@@ -94,6 -94,13 +94,13 @@@ void viafb_irq_disable(u32 mask EXPORT_SYMBOL_GPL(viafb_irq_disable); /* ---------------------------------------------------------------------- */ + /* + * Currently, the camera driver is the only user of the DMA code, so we + * only compile it in if the camera driver is being built. Chances are, + * most viafb systems will not need to have this extra code for a while. + * As soon as another user comes long, the ifdef can be removed. + */ + #if defined(CONFIG_VIDEO_VIA_CAMERA) || defined(CONFIG_VIDEO_VIA_CAMERA_MODULE) /* * Access to the DMA engine. This currently provides what the camera * driver needs (i.e. outgoing only) but is easily expandable if need @@@ -322,7 -329,7 +329,7 @@@ int viafb_dma_copy_out_sg(unsigned int return 0; } EXPORT_SYMBOL_GPL(viafb_dma_copy_out_sg); - + #endif /* CONFIG_VIDEO_VIA_CAMERA */ /* ---------------------------------------------------------------------- */ /* @@@ -333,7 -340,7 +340,7 @@@ static u16 via_function3[] = { CLE266_FUNCTION3, KM400_FUNCTION3, CN400_FUNCTION3, CN700_FUNCTION3, CX700_FUNCTION3, KM800_FUNCTION3, KM890_FUNCTION3, P4M890_FUNCTION3, - P4M900_FUNCTION3, VX800_FUNCTION3, VX855_FUNCTION3, + P4M900_FUNCTION3, VX800_FUNCTION3, VX855_FUNCTION3, VX900_FUNCTION3, }; /* Get the BIOS-configured framebuffer size from PCI configuration space @@@ -370,7 -377,6 +377,7 @@@ static int viafb_get_fb_size_from_pci(i case P4M900_FUNCTION3: case VX800_FUNCTION3: case VX855_FUNCTION3: + case VX900_FUNCTION3: /*case CN750_FUNCTION3: */ offset = 0xA0; break; @@@ -475,10 -481,7 +482,10 @@@ static int __devinit via_pci_setup_mmio * Eventually we want to move away from mapping this * entire region. */ - vdev->fbmem_start = pci_resource_start(vdev->pdev, 0); + if (vdev->chip_type == UNICHROME_VX900) + vdev->fbmem_start = pci_resource_start(vdev->pdev, 2); + else + vdev->fbmem_start = pci_resource_start(vdev->pdev, 0); ret = vdev->fbmem_len = viafb_get_fb_size_from_pci(vdev->chip_type); if (ret < 0) goto out_unmap; @@@ -511,7 -514,12 +518,12 @@@ static struct viafb_subdev_info }, { .name = "viafb-i2c", - } + }, + #if defined(CONFIG_VIDEO_VIA_CAMERA) || defined(CONFIG_VIDEO_VIA_CAMERA_MODULE) + { + .name = "viafb-camera", + }, + #endif }; #define N_SUBDEVS ARRAY_SIZE(viafb_subdevs) @@@ -639,8 -647,6 +651,8 @@@ static struct pci_device_id via_pci_tab .driver_data = UNICHROME_VX800 }, { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX855_DID), .driver_data = UNICHROME_VX855 }, + { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX900_DID), + .driver_data = UNICHROME_VX900 }, { } }; MODULE_DEVICE_TABLE(pci, via_pci_table); @@@ -650,10 -656,6 +662,10 @@@ static struct pci_driver via_driver = .id_table = via_pci_table, .probe = via_pci_probe, .remove = __devexit_p(via_pci_remove), +#ifdef CONFIG_PM + .suspend = viafb_suspend, + .resume = viafb_resume, +#endif }; static int __init via_core_init(void) diff --combined include/linux/Kbuild index 831c4634162,38a9f502bae..05a59f0ce37 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@@ -301,7 -301,6 +301,7 @@@ header-y += quota. header-y += radeonfb.h header-y += random.h header-y += raw.h +header-y += rds.h header-y += reboot.h header-y += reiserfs_fs.h header-y += reiserfs_xattr.h @@@ -372,7 -371,6 +372,6 @@@ header-y += veth. header-y += vhost.h header-y += videodev.h header-y += videodev2.h - header-y += videotext.h header-y += virtio_9p.h header-y += virtio_balloon.h header-y += virtio_blk.h diff --combined include/media/rc-map.h index 9b201ec8dc7,25883cfc311..e0f17edf38e --- a/include/media/rc-map.h +++ b/include/media/rc-map.h @@@ -17,12 -17,13 +17,13 @@@ #define IR_TYPE_RC6 (1 << 2) /* Philips RC6 protocol */ #define IR_TYPE_JVC (1 << 3) /* JVC protocol */ #define IR_TYPE_SONY (1 << 4) /* Sony12/15/20 protocol */ + #define IR_TYPE_RC5_SZ (1 << 5) /* RC5 variant used by Streamzap */ #define IR_TYPE_LIRC (1 << 30) /* Pass raw IR to lirc userspace */ #define IR_TYPE_OTHER (1u << 31) #define IR_TYPE_ALL (IR_TYPE_RC5 | IR_TYPE_NEC | IR_TYPE_RC6 | \ IR_TYPE_JVC | IR_TYPE_SONY | IR_TYPE_LIRC | \ - IR_TYPE_OTHER) + IR_TYPE_RC5_SZ | IR_TYPE_OTHER) struct ir_scancode { u32 scancode; @@@ -35,7 -36,7 +36,7 @@@ struct ir_scancode_table unsigned int len; /* Used number of entries */ unsigned int alloc; /* Size of *scan in bytes */ u64 ir_type; - char *name; + const char *name; spinlock_t lock; }; @@@ -54,6 -55,8 +55,8 @@@ void rc_map_init(void) /* Names of the several keytables defined in-kernel */ #define RC_MAP_ADSTECH_DVB_T_PCI "rc-adstech-dvb-t-pci" + #define RC_MAP_ALINK_DTU_M "rc-alink-dtu-m" + #define RC_MAP_ANYSEE "rc-anysee" #define RC_MAP_APAC_VIEWCOMP "rc-apac-viewcomp" #define RC_MAP_ASUS_PC39 "rc-asus-pc39" #define RC_MAP_ATI_TV_WONDER_HD_600 "rc-ati-tv-wonder-hd-600" @@@ -62,8 -65,10 +65,10 @@@ #define RC_MAP_AVERMEDIA_DVBT "rc-avermedia-dvbt" #define RC_MAP_AVERMEDIA_M135A "rc-avermedia-m135a" #define RC_MAP_AVERMEDIA_M733A_RM_K6 "rc-avermedia-m733a-rm-k6" + #define RC_MAP_AVERMEDIA_RM_KS "rc-avermedia-rm-ks" #define RC_MAP_AVERMEDIA "rc-avermedia" #define RC_MAP_AVERTV_303 "rc-avertv-303" + #define RC_MAP_AZUREWAVE_AD_TU700 "rc-azurewave-ad-tu700" #define RC_MAP_BEHOLD_COLUMBUS "rc-behold-columbus" #define RC_MAP_BEHOLD "rc-behold" #define RC_MAP_BUDGET_CI_OLD "rc-budget-ci-old" @@@ -71,6 -76,8 +76,8 @@@ #define RC_MAP_CINERGY "rc-cinergy" #define RC_MAP_DIB0700_NEC_TABLE "rc-dib0700-nec" #define RC_MAP_DIB0700_RC5_TABLE "rc-dib0700-rc5" + #define RC_MAP_DIGITALNOW_TINYTWIN "rc-digitalnow-tinytwin" + #define RC_MAP_DIGITTRADE "rc-digittrade" #define RC_MAP_DM1105_NEC "rc-dm1105-nec" #define RC_MAP_DNTV_LIVE_DVBT_PRO "rc-dntv-live-dvbt-pro" #define RC_MAP_DNTV_LIVE_DVB_T "rc-dntv-live-dvb-t" @@@ -94,8 -101,12 +101,12 @@@ #define RC_MAP_KAIOMY "rc-kaiomy" #define RC_MAP_KWORLD_315U "rc-kworld-315u" #define RC_MAP_KWORLD_PLUS_TV_ANALOG "rc-kworld-plus-tv-analog" + #define RC_MAP_LEADTEK_Y04G0051 "rc-leadtek-y04g0051" #define RC_MAP_LIRC "rc-lirc" + #define RC_MAP_LME2510 "rc-lme2510" #define RC_MAP_MANLI "rc-manli" + #define RC_MAP_MSI_DIGIVOX_II "rc-msi-digivox-ii" + #define RC_MAP_MSI_DIGIVOX_III "rc-msi-digivox-iii" #define RC_MAP_MSI_TVANYWHERE_PLUS "rc-msi-tvanywhere-plus" #define RC_MAP_MSI_TVANYWHERE "rc-msi-tvanywhere" #define RC_MAP_NEBULA "rc-nebula" @@@ -114,14 -125,18 +125,18 @@@ #define RC_MAP_PURPLETV "rc-purpletv" #define RC_MAP_PV951 "rc-pv951" #define RC_MAP_RC5_HAUPPAUGE_NEW "rc-rc5-hauppauge-new" - #define RC_MAP_RC5_STREAMZAP "rc-rc5-streamzap" #define RC_MAP_RC5_TV "rc-rc5-tv" #define RC_MAP_RC6_MCE "rc-rc6-mce" #define RC_MAP_REAL_AUDIO_220_32_KEYS "rc-real-audio-220-32-keys" + #define RC_MAP_STREAMZAP "rc-streamzap" #define RC_MAP_TBS_NEC "rc-tbs-nec" #define RC_MAP_TERRATEC_CINERGY_XS "rc-terratec-cinergy-xs" + #define RC_MAP_TERRATEC_SLIM "rc-terratec-slim" #define RC_MAP_TEVII_NEC "rc-tevii-nec" + #define RC_MAP_TOTAL_MEDIA_IN_HAND "rc-total-media-in-hand" + #define RC_MAP_TREKSTOR "rc-trekstor" #define RC_MAP_TT_1500 "rc-tt-1500" + #define RC_MAP_TWINHAN_VP1027_DVBS "rc-twinhan1027" #define RC_MAP_VIDEOMATE_S350 "rc-videomate-s350" #define RC_MAP_VIDEOMATE_TV_PVR "rc-videomate-tv-pvr" #define RC_MAP_WINFAST "rc-winfast"