From 2132deff694765bc2e6c7ac84c6b30dab0775256 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 10 Mar 2010 07:57:03 -0300 Subject: V4L/DVB: omap24xxcam: potential buffer overflow The previous loop goes until last == VIDEO_MAX_FRAME, so this could potentially go one past the end of the loop. Signed-off-by: Dan Carpenter Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/omap24xxcam.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/omap24xxcam.c b/drivers/media/video/omap24xxcam.c index b189fe63394..ce76d952e16 100644 --- a/drivers/media/video/omap24xxcam.c +++ b/drivers/media/video/omap24xxcam.c @@ -1405,7 +1405,7 @@ static int omap24xxcam_mmap_buffers(struct file *file, } size = 0; - for (i = first; i <= last; i++) { + for (i = first; i <= last && i < VIDEO_MAX_FRAME; i++) { struct videobuf_dmabuf *dma = videobuf_to_dma(vbq->bufs[i]); for (j = 0; j < dma->sglen; j++) { -- cgit v1.2.3-70-g09d2 From b704e82a54591d69816b45f4324caf143f1a6fc8 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Sat, 13 Mar 2010 10:58:39 -0300 Subject: V4L/DVB: V4L - Makfile:Removed duplicate entry of davinci Signed-off-by: Vaibhav Hiremath Signed-off-by: Muralidharan Karicheri Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Makefile | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index b88b6174a33..c51c386559f 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -160,8 +160,6 @@ obj-$(CONFIG_VIDEO_MX3) += mx3_camera.o obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o -obj-$(CONFIG_ARCH_DAVINCI) += davinci/ - obj-$(CONFIG_VIDEO_AU0828) += au0828/ obj-$(CONFIG_USB_VIDEO_CLASS) += uvc/ -- cgit v1.2.3-70-g09d2 From ab51bec1f852f6b858a26e745b32a79cd1a67eec Mon Sep 17 00:00:00 2001 From: Murali Karicheri Date: Mon, 1 Mar 2010 19:54:02 -0300 Subject: V4L/DVB: V4L: vpfe_capture - free ccdc_lock when memory allocation fails This patch fixes a bug in vpfe_probe() that doesn't call mutex_unlock() if memory allocation for ccdc_cfg fails. See also the smatch warning report from Dan Carpenter that shows this as an issue. Signed-off-by: Murali Karicheri Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/davinci/vpfe_capture.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/davinci/vpfe_capture.c b/drivers/media/video/davinci/vpfe_capture.c index 7cf042f9b37..55128644b5d 100644 --- a/drivers/media/video/davinci/vpfe_capture.c +++ b/drivers/media/video/davinci/vpfe_capture.c @@ -1830,7 +1830,7 @@ static __init int vpfe_probe(struct platform_device *pdev) if (NULL == ccdc_cfg) { v4l2_err(pdev->dev.driver, "Memory allocation failed for ccdc_cfg\n"); - goto probe_free_dev_mem; + goto probe_free_lock; } strncpy(ccdc_cfg->name, vpfe_cfg->ccdc, 32); @@ -1982,8 +1982,9 @@ probe_out_video_release: probe_out_release_irq: free_irq(vpfe_dev->ccdc_irq0, vpfe_dev); probe_free_ccdc_cfg_mem: - mutex_unlock(&ccdc_lock); kfree(ccdc_cfg); +probe_free_lock: + mutex_unlock(&ccdc_lock); probe_free_dev_mem: kfree(vpfe_dev); return ret; -- cgit v1.2.3-70-g09d2 From a76b9f49ba58d081e373080ff75130673140d3f1 Mon Sep 17 00:00:00 2001 From: Yong Zhang Date: Fri, 5 Feb 2010 10:52:39 -0300 Subject: V4L/DVB: gspca - sn9c20x: Correct onstack wait_queue_head declaration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use DECLARE_WAIT_QUEUE_HEAD_ONSTACK to make lockdep happy Signed-off-by: Yong Zhang Signed-off-by: Jean-François Moine CC: Brian Johnson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sn9c20x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c index 38a6e15e096..3dee3e5844b 100644 --- a/drivers/media/video/gspca/sn9c20x.c +++ b/drivers/media/video/gspca/sn9c20x.c @@ -1427,7 +1427,7 @@ static int input_kthread(void *data) struct gspca_dev *gspca_dev = (struct gspca_dev *)data; struct sd *sd = (struct sd *) gspca_dev; - DECLARE_WAIT_QUEUE_HEAD(wait); + DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wait); set_freezable(); for (;;) { if (kthread_should_stop()) -- cgit v1.2.3-70-g09d2 From 55e0b489a39bb635a44f769d620e44c70d9c065b Mon Sep 17 00:00:00 2001 From: Erik Andrén Date: Mon, 8 Mar 2010 17:16:00 -0300 Subject: V4L/DVB: gspca - stv06xx: Remove the 046d:08da from the stv06xx driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 046d:08da usb id shouldn't be associated with the stv06xx driver as they're not compatible with each other. This fixes a bug where Quickcam Messenger cams fail to use its proper driver (gspca-zc3xx), rendering the camera inoperable. Signed-off-by: Erik Andrén Tested-by: Gabriel Craciunescu Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/stv06xx/stv06xx.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.c b/drivers/media/video/gspca/stv06xx/stv06xx.c index af73da34c83..14f179a1948 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx.c +++ b/drivers/media/video/gspca/stv06xx/stv06xx.c @@ -524,8 +524,6 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x046D, 0x08F5), .driver_info = BRIDGE_ST6422 }, /* QuickCam Messenger (new) */ {USB_DEVICE(0x046D, 0x08F6), .driver_info = BRIDGE_ST6422 }, - /* QuickCam Messenger (new) */ - {USB_DEVICE(0x046D, 0x08DA), .driver_info = BRIDGE_ST6422 }, {} }; MODULE_DEVICE_TABLE(usb, device_table); -- cgit v1.2.3-70-g09d2 From f8f73d01a31488ec8e923b2148043579d43d0378 Mon Sep 17 00:00:00 2001 From: John Ellson Date: Wed, 17 Mar 2010 10:22:58 -0300 Subject: V4L/DVB: gspca: make usb id 0461:0815 get handled by the right driver The 0461:0815 camera is spca561 based not spca508 Signed-off-by: John Ellson Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/spca508.c | 1 - drivers/media/video/gspca/spca561.c | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/spca508.c b/drivers/media/video/gspca/spca508.c index 15b2eef8a3f..edf0fe15750 100644 --- a/drivers/media/video/gspca/spca508.c +++ b/drivers/media/video/gspca/spca508.c @@ -1513,7 +1513,6 @@ static const struct sd_desc sd_desc = { static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x0130, 0x0130), .driver_info = HamaUSBSightcam}, {USB_DEVICE(0x041e, 0x4018), .driver_info = CreativeVista}, - {USB_DEVICE(0x0461, 0x0815), .driver_info = MicroInnovationIC200}, {USB_DEVICE(0x0733, 0x0110), .driver_info = ViewQuestVQ110}, {USB_DEVICE(0x0af9, 0x0010), .driver_info = HamaUSBSightcam}, {USB_DEVICE(0x0af9, 0x0011), .driver_info = HamaUSBSightcam2}, diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index dc7f2b0fbc7..b9c80e2103b 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c @@ -1053,6 +1053,7 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x041e, 0x401a), .driver_info = Rev072A}, {USB_DEVICE(0x041e, 0x403b), .driver_info = Rev012A}, {USB_DEVICE(0x0458, 0x7004), .driver_info = Rev072A}, + {USB_DEVICE(0x0461, 0x0815), .driver_info = Rev072A}, {USB_DEVICE(0x046d, 0x0928), .driver_info = Rev012A}, {USB_DEVICE(0x046d, 0x0929), .driver_info = Rev012A}, {USB_DEVICE(0x046d, 0x092a), .driver_info = Rev012A}, -- cgit v1.2.3-70-g09d2 From 6a4f0623a4ebe46c743d213db808067553953913 Mon Sep 17 00:00:00 2001 From: Muralidharan Karicheri Date: Thu, 18 Mar 2010 11:44:12 -0300 Subject: V4L/DVB: V4L - vpfe capture - fix for kernel crash As part of upstream merge, set_params() function was removed from isif.c. This requires removal of BUG_ON() and check for set_params ptr in vpfe_capture.c. Without this kernel crash dump is seen while bootup on DM365 Also made following changes:- 1) converted error messages to debug messages since it is not right to flood the console with error messages for user mistakes. 2) returns -EINVAL if ioctl is not supported Signed-off-by: Muralidharan Karicheri Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/davinci/vpfe_capture.c | 33 ++++++++++++++++++------------ 1 file changed, 20 insertions(+), 13 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/davinci/vpfe_capture.c b/drivers/media/video/davinci/vpfe_capture.c index 55128644b5d..398dbe71cb8 100644 --- a/drivers/media/video/davinci/vpfe_capture.c +++ b/drivers/media/video/davinci/vpfe_capture.c @@ -223,7 +223,6 @@ int vpfe_register_ccdc_device(struct ccdc_hw_device *dev) BUG_ON(!dev->hw_ops.get_frame_format); BUG_ON(!dev->hw_ops.get_pixel_format); BUG_ON(!dev->hw_ops.set_pixel_format); - BUG_ON(!dev->hw_ops.set_params); BUG_ON(!dev->hw_ops.set_image_window); BUG_ON(!dev->hw_ops.get_image_window); BUG_ON(!dev->hw_ops.get_line_length); @@ -1689,11 +1688,12 @@ static long vpfe_param_handler(struct file *file, void *priv, struct vpfe_device *vpfe_dev = video_drvdata(file); int ret = 0; - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_param_handler\n"); + v4l2_dbg(2, debug, &vpfe_dev->v4l2_dev, "vpfe_param_handler\n"); if (vpfe_dev->started) { /* only allowed if streaming is not started */ - v4l2_err(&vpfe_dev->v4l2_dev, "device already started\n"); + v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, + "device already started\n"); return -EBUSY; } @@ -1705,16 +1705,23 @@ static long vpfe_param_handler(struct file *file, void *priv, case VPFE_CMD_S_CCDC_RAW_PARAMS: v4l2_warn(&vpfe_dev->v4l2_dev, "VPFE_CMD_S_CCDC_RAW_PARAMS: experimental ioctl\n"); - ret = ccdc_dev->hw_ops.set_params(param); - if (ret) { - v4l2_err(&vpfe_dev->v4l2_dev, - "Error in setting parameters in CCDC\n"); - goto unlock_out; - } - if (vpfe_get_ccdc_image_format(vpfe_dev, &vpfe_dev->fmt) < 0) { - v4l2_err(&vpfe_dev->v4l2_dev, - "Invalid image format at CCDC\n"); - goto unlock_out; + if (ccdc_dev->hw_ops.set_params) { + ret = ccdc_dev->hw_ops.set_params(param); + if (ret) { + v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, + "Error setting parameters in CCDC\n"); + goto unlock_out; + } + if (vpfe_get_ccdc_image_format(vpfe_dev, + &vpfe_dev->fmt) < 0) { + v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, + "Invalid image format at CCDC\n"); + goto unlock_out; + } + } else { + ret = -EINVAL; + v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, + "VPFE_CMD_S_CCDC_RAW_PARAMS not supported\n"); } break; default: -- cgit v1.2.3-70-g09d2 From d2f2d6d0a11e892263ea511e46af449113fd2081 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 22 Mar 2010 03:14:22 -0300 Subject: V4L/DVB: v4l: fix config dependencies: mxb and saa7191 are V4L2 drivers, not V4L1 v4l: fix config dependencies: mxb and saa7191 are V4L2 drivers, not V4L1 Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index f8fc8654693..9644cf760aa 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -361,7 +361,7 @@ config VIDEO_SAA717X config VIDEO_SAA7191 tristate "Philips SAA7191 video decoder" - depends on VIDEO_V4L1 && I2C + depends on VIDEO_V4L2 && I2C ---help--- Support for the Philips SAA7191 video decoder. @@ -756,7 +756,7 @@ source "drivers/media/video/saa7134/Kconfig" config VIDEO_MXB tristate "Siemens-Nixdorf 'Multimedia eXtension Board'" - depends on PCI && VIDEO_V4L1 && I2C + depends on PCI && VIDEO_V4L2 && I2C select VIDEO_SAA7146_VV select VIDEO_TUNER select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO -- cgit v1.2.3-70-g09d2 From 03b1930efd3c2320b1dcba76c8af15f7e454919d Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 24 Mar 2010 19:09:55 -0300 Subject: V4L/DVB: saa7146: fix regression of the av7110/budget-av driver An earlier regression fix for the mxb driver (V4L/DVB: saa7146_vv: fix regression where v4l2_device was registered too late) caused a new regression in the av7110 driver. Reverted the old fix and fixed the problem in the mxb driver instead. Tested on mxb and budget-av cards. The real problem is that the saa7146 framework has separate probe() and attach() driver callbacks which should be rolled into one. This is now done for the mxb driver, but others should do the same. Lack of hardware makes this hard to do, though. I hope to get hold of some hexium cards and then I can try to improve the framework to prevent this from happening again. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/saa7146_fops.c | 11 +++++------ drivers/media/video/hexium_gemini.c | 3 --- drivers/media/video/hexium_orion.c | 4 ---- drivers/media/video/mxb.c | 17 ++++++++--------- include/media/saa7146_vv.h | 1 - 5 files changed, 13 insertions(+), 23 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c index fd8e1f45be3..7364b9642d0 100644 --- a/drivers/media/common/saa7146_fops.c +++ b/drivers/media/common/saa7146_fops.c @@ -423,15 +423,14 @@ static void vv_callback(struct saa7146_dev *dev, unsigned long status) } } -int saa7146_vv_devinit(struct saa7146_dev *dev) -{ - return v4l2_device_register(&dev->pci->dev, &dev->v4l2_dev); -} -EXPORT_SYMBOL_GPL(saa7146_vv_devinit); - int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv) { struct saa7146_vv *vv; + int err; + + err = v4l2_device_register(&dev->pci->dev, &dev->v4l2_dev); + if (err) + return err; vv = kzalloc(sizeof(struct saa7146_vv), GFP_KERNEL); if (vv == NULL) { diff --git a/drivers/media/video/hexium_gemini.c b/drivers/media/video/hexium_gemini.c index e620a3a92f2..ad2c232baa6 100644 --- a/drivers/media/video/hexium_gemini.c +++ b/drivers/media/video/hexium_gemini.c @@ -356,9 +356,6 @@ static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_d DEB_EE((".\n")); - ret = saa7146_vv_devinit(dev); - if (ret) - return ret; hexium = kzalloc(sizeof(struct hexium), GFP_KERNEL); if (NULL == hexium) { printk("hexium_gemini: not enough kernel memory in hexium_attach().\n"); diff --git a/drivers/media/video/hexium_orion.c b/drivers/media/video/hexium_orion.c index fe596a1c12a..938a1f8f880 100644 --- a/drivers/media/video/hexium_orion.c +++ b/drivers/media/video/hexium_orion.c @@ -216,10 +216,6 @@ static int hexium_probe(struct saa7146_dev *dev) return -EFAULT; } - err = saa7146_vv_devinit(dev); - if (err) - return err; - hexium = kzalloc(sizeof(struct hexium), GFP_KERNEL); if (NULL == hexium) { printk("hexium_orion: hexium_probe: not enough kernel memory.\n"); diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c index 9f01f14e4aa..ef0c8178f25 100644 --- a/drivers/media/video/mxb.c +++ b/drivers/media/video/mxb.c @@ -169,11 +169,7 @@ static struct saa7146_extension extension; static int mxb_probe(struct saa7146_dev *dev) { struct mxb *mxb = NULL; - int err; - err = saa7146_vv_devinit(dev); - if (err) - return err; mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL); if (mxb == NULL) { DEB_D(("not enough kernel memory.\n")); @@ -699,14 +695,17 @@ static struct saa7146_ext_vv vv_data; /* this function only gets called when the probing was successful */ static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info) { - struct mxb *mxb = (struct mxb *)dev->ext_priv; + struct mxb *mxb; DEB_EE(("dev:%p\n", dev)); - /* checking for i2c-devices can be omitted here, because we - already did this in "mxb_vl42_probe" */ - saa7146_vv_init(dev, &vv_data); + if (mxb_probe(dev)) { + saa7146_vv_release(dev); + return -1; + } + mxb = (struct mxb *)dev->ext_priv; + vv_data.ops.vidioc_queryctrl = vidioc_queryctrl; vv_data.ops.vidioc_g_ctrl = vidioc_g_ctrl; vv_data.ops.vidioc_s_ctrl = vidioc_s_ctrl; @@ -726,6 +725,7 @@ static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data vv_data.ops.vidioc_default = vidioc_default; if (saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) { ERR(("cannot register capture v4l2 device. skipping.\n")); + saa7146_vv_release(dev); return -1; } @@ -846,7 +846,6 @@ static struct saa7146_extension extension = { .pci_tbl = &pci_tbl[0], .module = THIS_MODULE, - .probe = mxb_probe, .attach = mxb_attach, .detach = mxb_detach, diff --git a/include/media/saa7146_vv.h b/include/media/saa7146_vv.h index b9da1f5591e..4aeff96ff7d 100644 --- a/include/media/saa7146_vv.h +++ b/include/media/saa7146_vv.h @@ -188,7 +188,6 @@ void saa7146_buffer_timeout(unsigned long data); void saa7146_dma_free(struct saa7146_dev* dev,struct videobuf_queue *q, struct saa7146_buf *buf); -int saa7146_vv_devinit(struct saa7146_dev *dev); int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv); int saa7146_vv_release(struct saa7146_dev* dev); -- cgit v1.2.3-70-g09d2 From b7d41d6d580743b1fed1b9560d948c9ef58564bd Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Sat, 27 Mar 2010 18:42:13 -0300 Subject: V4L/DVB: mx1-camera: compile fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes a regression of 7d58289 (mx1: prefix SOC specific defines with MX1_ and deprecate old names) Signed-off-by: Uwe Kleine-König Acked-by: Sascha Hauer Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- arch/arm/plat-mxc/include/mach/dma-mx1-mx2.h | 8 +++++++- drivers/media/video/mx1_camera.c | 8 +++----- 2 files changed, 10 insertions(+), 6 deletions(-) (limited to 'drivers/media/video') diff --git a/arch/arm/plat-mxc/include/mach/dma-mx1-mx2.h b/arch/arm/plat-mxc/include/mach/dma-mx1-mx2.h index 07be8ad7ec3..7c4870bd5a2 100644 --- a/arch/arm/plat-mxc/include/mach/dma-mx1-mx2.h +++ b/arch/arm/plat-mxc/include/mach/dma-mx1-mx2.h @@ -31,7 +31,13 @@ #define DMA_MODE_WRITE 1 #define DMA_MODE_MASK 1 -#define DMA_BASE IO_ADDRESS(DMA_BASE_ADDR) +#define MX1_DMA_REG(offset) MX1_IO_ADDRESS(MX1_DMA_BASE_ADDR + (offset)) + +/* DMA Interrupt Mask Register */ +#define MX1_DMA_DIMR MX1_DMA_REG(0x08) + +/* Channel Control Register */ +#define MX1_DMA_CCR(x) MX1_DMA_REG(0x8c + ((x) << 6)) #define IMX_DMA_MEMSIZE_32 (0 << 4) #define IMX_DMA_MEMSIZE_8 (1 << 4) diff --git a/drivers/media/video/mx1_camera.c b/drivers/media/video/mx1_camera.c index 3c8ebfcb742..34a66019190 100644 --- a/drivers/media/video/mx1_camera.c +++ b/drivers/media/video/mx1_camera.c @@ -49,8 +49,6 @@ /* * CSI registers */ -#define DMA_CCR(x) (0x8c + ((x) << 6)) /* Control Registers */ -#define DMA_DIMR 0x08 /* Interrupt mask Register */ #define CSICR1 0x00 /* CSI Control Register 1 */ #define CSISR 0x08 /* CSI Status Register */ #define CSIRXR 0x10 /* CSI RxFIFO Register */ @@ -784,7 +782,7 @@ static int __init mx1_camera_probe(struct platform_device *pdev) pcdev); imx_dma_config_channel(pcdev->dma_chan, IMX_DMA_TYPE_FIFO, - IMX_DMA_MEMSIZE_32, DMA_REQ_CSI_R, 0); + IMX_DMA_MEMSIZE_32, MX1_DMA_REQ_CSI_R, 0); /* burst length : 16 words = 64 bytes */ imx_dma_config_burstlen(pcdev->dma_chan, 0); @@ -798,8 +796,8 @@ static int __init mx1_camera_probe(struct platform_device *pdev) set_fiq_handler(&mx1_camera_sof_fiq_start, &mx1_camera_sof_fiq_end - &mx1_camera_sof_fiq_start); - regs.ARM_r8 = DMA_BASE + DMA_DIMR; - regs.ARM_r9 = DMA_BASE + DMA_CCR(pcdev->dma_chan); + regs.ARM_r8 = (long)MX1_DMA_DIMR; + regs.ARM_r9 = (long)MX1_DMA_CCR(pcdev->dma_chan); regs.ARM_r10 = (long)pcdev->base + CSICR1; regs.ARM_fp = (long)pcdev->base + CSISR; regs.ARM_sp = 1 << pcdev->dma_chan; -- cgit v1.2.3-70-g09d2 From 981cbef2c30ee82d6011bb2ef50461f6a074de71 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 7 Apr 2010 06:41:14 -0300 Subject: V4L/DVB: video: testing unsigned for less than 0 soc_mbus_bytes_per_line() returns -EINVAL on error but we store it in an unsigned int so the test for less than zero doesn't work. I think it always returns "small" positive values so we can just cast it to int here. Signed-off-by: Dan Carpenter Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/sh_mobile_ceu_camera.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index 6e16b397932..1ad980f8e77 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c @@ -1633,7 +1633,7 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, height = pix->height; pix->bytesperline = soc_mbus_bytes_per_line(width, xlate->host_fmt); - if (pix->bytesperline < 0) + if ((int)pix->bytesperline < 0) return pix->bytesperline; pix->sizeimage = height * pix->bytesperline; -- cgit v1.2.3-70-g09d2 From a47f6be45670465d45a3d27f7ff71986bd35d6c4 Mon Sep 17 00:00:00 2001 From: Stefan Herbrechtsmeier Date: Tue, 20 Apr 2010 03:51:29 -0300 Subject: V4L/DVB: pxa_camera: move fifo reset direct before dma start Move the fifo reset from pxa_camera_start_capture to pxa_camera_irq direct before the dma start after an end of frame interrupt to prevent images from shifting because of old data at the begin of the frame. Signed-off-by: Stefan Herbrechtsmeier Acked-by: Robert Jarzmik Tested-by: Antonio Ospite Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pxa_camera.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index 5ecc30daef2..04bf5c11308 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c @@ -609,12 +609,9 @@ static void pxa_dma_add_tail_buf(struct pxa_camera_dev *pcdev, */ static void pxa_camera_start_capture(struct pxa_camera_dev *pcdev) { - unsigned long cicr0, cifr; + unsigned long cicr0; dev_dbg(pcdev->soc_host.v4l2_dev.dev, "%s\n", __func__); - /* Reset the FIFOs */ - cifr = __raw_readl(pcdev->base + CIFR) | CIFR_RESET_F; - __raw_writel(cifr, pcdev->base + CIFR); /* Enable End-Of-Frame Interrupt */ cicr0 = __raw_readl(pcdev->base + CICR0) | CICR0_ENB; cicr0 &= ~CICR0_EOFM; @@ -935,7 +932,7 @@ static void pxa_camera_deactivate(struct pxa_camera_dev *pcdev) static irqreturn_t pxa_camera_irq(int irq, void *data) { struct pxa_camera_dev *pcdev = data; - unsigned long status, cicr0; + unsigned long status, cifr, cicr0; struct pxa_buffer *buf; struct videobuf_buffer *vb; @@ -949,6 +946,10 @@ static irqreturn_t pxa_camera_irq(int irq, void *data) __raw_writel(status, pcdev->base + CISR); if (status & CISR_EOF) { + /* Reset the FIFOs */ + cifr = __raw_readl(pcdev->base + CIFR) | CIFR_RESET_F; + __raw_writel(cifr, pcdev->base + CIFR); + pcdev->active = list_first_entry(&pcdev->capture, struct pxa_buffer, vb.queue); vb = &pcdev->active->vb; -- cgit v1.2.3-70-g09d2 From e26b31449142a18512b57dbea515af234992ba7c Mon Sep 17 00:00:00 2001 From: Márton Németh Date: Wed, 24 Feb 2010 17:13:29 -0300 Subject: V4L/DVB: The first two parameters of soc_camera_limit_side() are usually pointers to struct v4l2_rect elements. They are signed, so adjust the prototype accordingly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This will remove the following sparse warning (see "make C=1"): * incorrect type in argument 1 (different signedness) expected unsigned int *start got signed int * as well as a couple more signedness mismatches. Signed-off-by: Márton Németh Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/mt9v022.c | 2 +- drivers/media/video/mx3_camera.c | 4 ++-- drivers/media/video/rj54n1cb0c.c | 18 +++++++++--------- drivers/media/video/sh_mobile_ceu_camera.c | 8 ++++---- include/media/soc_camera.h | 4 ++-- 5 files changed, 18 insertions(+), 18 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c index 1a34d2993e9..e5bae4c9393 100644 --- a/drivers/media/video/mt9v022.c +++ b/drivers/media/video/mt9v022.c @@ -325,7 +325,7 @@ static int mt9v022_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) if (ret < 0) return ret; - dev_dbg(&client->dev, "Frame %ux%u pixel\n", rect.width, rect.height); + dev_dbg(&client->dev, "Frame %dx%d pixel\n", rect.width, rect.height); mt9v022->rect = rect; diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c index bd297f567dc..d477e305800 100644 --- a/drivers/media/video/mx3_camera.c +++ b/drivers/media/video/mx3_camera.c @@ -796,7 +796,7 @@ static int acquire_dma_channel(struct mx3_camera_dev *mx3_cam) * FIXME: learn to use stride != width, then we can keep stride properly aligned * and support arbitrary (even) widths. */ -static inline void stride_align(__s32 *width) +static inline void stride_align(__u32 *width) { if (((*width + 7) & ~7) < 4096) *width = (*width + 7) & ~7; @@ -844,7 +844,7 @@ static int mx3_camera_set_crop(struct soc_camera_device *icd, * So far only direct camera-to-memory is supported */ if (channel_change_requested(icd, rect)) { - int ret = acquire_dma_channel(mx3_cam); + ret = acquire_dma_channel(mx3_cam); if (ret < 0) return ret; } diff --git a/drivers/media/video/rj54n1cb0c.c b/drivers/media/video/rj54n1cb0c.c index 9277194cd82..bbd9c11e2c5 100644 --- a/drivers/media/video/rj54n1cb0c.c +++ b/drivers/media/video/rj54n1cb0c.c @@ -555,15 +555,15 @@ static int rj54n1_commit(struct i2c_client *client) return ret; } -static int rj54n1_sensor_scale(struct v4l2_subdev *sd, u32 *in_w, u32 *in_h, - u32 *out_w, u32 *out_h); +static int rj54n1_sensor_scale(struct v4l2_subdev *sd, s32 *in_w, s32 *in_h, + s32 *out_w, s32 *out_h); static int rj54n1_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) { struct i2c_client *client = sd->priv; struct rj54n1 *rj54n1 = to_rj54n1(client); struct v4l2_rect *rect = &a->c; - unsigned int dummy = 0, output_w, output_h, + int dummy = 0, output_w, output_h, input_w = rect->width, input_h = rect->height; int ret; @@ -577,7 +577,7 @@ static int rj54n1_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) output_w = (input_w * 1024 + rj54n1->resize / 2) / rj54n1->resize; output_h = (input_h * 1024 + rj54n1->resize / 2) / rj54n1->resize; - dev_dbg(&client->dev, "Scaling for %ux%u : %u = %ux%u\n", + dev_dbg(&client->dev, "Scaling for %dx%d : %u = %dx%d\n", input_w, input_h, rj54n1->resize, output_w, output_h); ret = rj54n1_sensor_scale(sd, &input_w, &input_h, &output_w, &output_h); @@ -638,8 +638,8 @@ static int rj54n1_g_fmt(struct v4l2_subdev *sd, * the output one, updates the window sizes and returns an error or the resize * coefficient on success. Note: we only use the "Fixed Scaling" on this camera. */ -static int rj54n1_sensor_scale(struct v4l2_subdev *sd, u32 *in_w, u32 *in_h, - u32 *out_w, u32 *out_h) +static int rj54n1_sensor_scale(struct v4l2_subdev *sd, s32 *in_w, s32 *in_h, + s32 *out_w, s32 *out_h) { struct i2c_client *client = sd->priv; struct rj54n1 *rj54n1 = to_rj54n1(client); @@ -749,7 +749,7 @@ static int rj54n1_sensor_scale(struct v4l2_subdev *sd, u32 *in_w, u32 *in_h, * improve the image quality or stability for larger frames (see comment * above), but I didn't check the framerate. */ - skip = min(resize / 1024, (unsigned)15); + skip = min(resize / 1024, 15U); inc_sel = 1 << skip; @@ -819,7 +819,7 @@ static int rj54n1_sensor_scale(struct v4l2_subdev *sd, u32 *in_w, u32 *in_h, *out_w = output_w; *out_h = output_h; - dev_dbg(&client->dev, "Scaled for %ux%u : %u = %ux%u, skip %u\n", + dev_dbg(&client->dev, "Scaled for %dx%d : %u = %ux%u, skip %u\n", *in_w, *in_h, resize, output_w, output_h, skip); return resize; @@ -1017,7 +1017,7 @@ static int rj54n1_s_fmt(struct v4l2_subdev *sd, struct i2c_client *client = sd->priv; struct rj54n1 *rj54n1 = to_rj54n1(client); const struct rj54n1_datafmt *fmt; - unsigned int output_w, output_h, max_w, max_h, + int output_w, output_h, max_w, max_h, input_w = rj54n1->rect.width, input_h = rj54n1->rect.height; int ret; diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index 1ad980f8e77..7a229ebe692 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c @@ -1041,13 +1041,13 @@ static int client_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *crop, */ if (!memcmp(rect, cam_rect, sizeof(*rect))) { /* Even if camera S_CROP failed, but camera rectangle matches */ - dev_dbg(dev, "Camera S_CROP successful for %ux%u@%u:%u\n", + dev_dbg(dev, "Camera S_CROP successful for %dx%d@%d:%d\n", rect->width, rect->height, rect->left, rect->top); return 0; } /* Try to fix cropping, that camera hasn't managed to set */ - dev_geo(dev, "Fix camera S_CROP for %ux%u@%u:%u to %ux%u@%u:%u\n", + dev_geo(dev, "Fix camera S_CROP for %dx%d@%d:%d to %dx%d@%d:%d\n", cam_rect->width, cam_rect->height, cam_rect->left, cam_rect->top, rect->width, rect->height, rect->left, rect->top); @@ -1103,7 +1103,7 @@ static int client_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *crop, v4l2_subdev_call(sd, video, s_crop, cam_crop); ret = client_g_rect(sd, cam_rect); - dev_geo(dev, "Camera S_CROP %d for %ux%u@%u:%u\n", ret, + dev_geo(dev, "Camera S_CROP %d for %dx%d@%d:%d\n", ret, cam_rect->width, cam_rect->height, cam_rect->left, cam_rect->top); } @@ -1117,7 +1117,7 @@ static int client_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *crop, *cam_rect = cap.bounds; v4l2_subdev_call(sd, video, s_crop, cam_crop); ret = client_g_rect(sd, cam_rect); - dev_geo(dev, "Camera S_CROP %d for max %ux%u@%u:%u\n", ret, + dev_geo(dev, "Camera S_CROP %d for max %dx%d@%d:%d\n", ret, cam_rect->width, cam_rect->height, cam_rect->left, cam_rect->top); } diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h index 9d69f01b6fa..5a173652cf4 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h @@ -266,8 +266,8 @@ static inline unsigned long soc_camera_bus_param_compatible( common_flags; } -static inline void soc_camera_limit_side(unsigned int *start, - unsigned int *length, unsigned int start_min, +static inline void soc_camera_limit_side(int *start, int *length, + unsigned int start_min, unsigned int length_min, unsigned int length_max) { if (*length < length_min) -- cgit v1.2.3-70-g09d2 From 4f9fb5ed020324d6c151db34460df572b0fdc491 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 18 May 2010 00:46:09 -0300 Subject: V4L/DVB: soc-camera: add runtime pm support for subdevices To save power soc-camera powers subdevices down, when they are not in use, if this is supported by the platform. However, the V4L standard dictates, that video nodes shall preserve configuration between uses. This requires runtime power management, which is implemented by this patch. It allows subdevice drivers to specify their runtime power-management methods, by assigning a type to the video device. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/soc_camera.c | 18 +++++++++++++++++- include/media/soc_camera.h | 8 ++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index a24174ddec4..0c65031f3d8 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -388,6 +389,11 @@ static int soc_camera_open(struct file *file) goto eiciadd; } + pm_runtime_enable(&icd->vdev->dev); + ret = pm_runtime_resume(&icd->vdev->dev); + if (ret < 0 && ret != -ENOSYS) + goto eresume; + /* * Try to configure with default parameters. Notice: this is the * very first open, so, we cannot race against other calls, @@ -409,10 +415,12 @@ static int soc_camera_open(struct file *file) return 0; /* - * First five errors are entered with the .video_lock held + * First four errors are entered with the .video_lock held * and use_count == 1 */ esfmt: + pm_runtime_disable(&icd->vdev->dev); +eresume: ici->ops->remove(icd); eiciadd: if (icl->power) @@ -437,7 +445,11 @@ static int soc_camera_close(struct file *file) if (!icd->use_count) { struct soc_camera_link *icl = to_soc_camera_link(icd); + pm_runtime_suspend(&icd->vdev->dev); + pm_runtime_disable(&icd->vdev->dev); + ici->ops->remove(icd); + if (icl->power) icl->power(icd->pdev, 0); } @@ -1319,6 +1331,7 @@ static int video_dev_create(struct soc_camera_device *icd) */ static int soc_camera_video_start(struct soc_camera_device *icd) { + struct device_type *type = icd->vdev->dev.type; int ret; if (!icd->dev.parent) @@ -1335,6 +1348,9 @@ static int soc_camera_video_start(struct soc_camera_device *icd) return ret; } + /* Restore device type, possibly set by the subdevice driver */ + icd->vdev->dev.type = type; + return 0; } diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h index 5a173652cf4..c9a5bbfa6ab 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h @@ -284,4 +284,12 @@ static inline void soc_camera_limit_side(int *start, int *length, extern unsigned long soc_camera_apply_sensor_flags(struct soc_camera_link *icl, unsigned long flags); +/* This is only temporary here - until v4l2-subdev begins to link to video_device */ +#include +static inline struct video_device *soc_camera_i2c_to_vdev(struct i2c_client *client) +{ + struct soc_camera_device *icd = client->dev.platform_data; + return icd->vdev; +} + #endif -- cgit v1.2.3-70-g09d2 From 535653b1c22c29d4e8f554928efc87fe138f917d Mon Sep 17 00:00:00 2001 From: Valentin Longchamp Date: Tue, 9 Feb 2010 07:59:12 -0300 Subject: V4L/DVB: mt9t031: use runtime pm support to restore ADDRESS_MODE registers If the platform hooks are provided, soc_camera powers off the device on close and powers it on on open. This resets the ADDRESS_MODE registers which then can be different to the value the driver has computed for them. This patch setups runtime pm usage for mt9t031 and uses the resume function to write the ADDRESS_MODE registers in order to fix the above described problem. Signed-off-by: Valentin Longchamp Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/mt9t031.c | 66 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 62 insertions(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/mt9t031.c b/drivers/media/video/mt9t031.c index a9061bff79b..78b4e091d2d 100644 --- a/drivers/media/video/mt9t031.c +++ b/drivers/media/video/mt9t031.c @@ -8,14 +8,16 @@ * published by the Free Software Foundation. */ -#include -#include +#include #include #include +#include +#include +#include -#include -#include #include +#include +#include /* * mt9t031 i2c address 0x5d @@ -680,6 +682,59 @@ static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) return 0; } +/* + * Power Management: + * This function does nothing for now but must be present for pm to work + */ +static int mt9t031_runtime_suspend(struct device *dev) +{ + return 0; +} + +/* + * Power Management: + * COLUMN_ADDRESS_MODE and ROW_ADDRESS_MODE are not rewritten if unchanged + * they are however changed at reset if the platform hook is present + * thus we rewrite them with the values stored by the driver + */ +static int mt9t031_runtime_resume(struct device *dev) +{ + struct video_device *vdev = to_video_device(dev); + struct soc_camera_device *icd = container_of(vdev->parent, + struct soc_camera_device, dev); + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + struct i2c_client *client = sd->priv; + struct mt9t031 *mt9t031 = to_mt9t031(client); + + int ret; + u16 xbin, ybin; + + xbin = min(mt9t031->xskip, (u16)3); + ybin = min(mt9t031->yskip, (u16)3); + + ret = reg_write(client, MT9T031_COLUMN_ADDRESS_MODE, + ((xbin - 1) << 4) | (mt9t031->xskip - 1)); + if (ret < 0) + return ret; + + ret = reg_write(client, MT9T031_ROW_ADDRESS_MODE, + ((ybin - 1) << 4) | (mt9t031->yskip - 1)); + if (ret < 0) + return ret; + + return 0; +} + +static struct dev_pm_ops mt9t031_dev_pm_ops = { + .runtime_suspend = mt9t031_runtime_suspend, + .runtime_resume = mt9t031_runtime_resume, +}; + +static struct device_type mt9t031_dev_type = { + .name = "MT9T031", + .pm = &mt9t031_dev_pm_ops, +}; + /* * Interface active, can use i2c. If it fails, it can indeed mean, that * this wasn't our capture interface, so, we wait for the right one @@ -687,6 +742,7 @@ static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) static int mt9t031_video_probe(struct i2c_client *client) { struct mt9t031 *mt9t031 = to_mt9t031(client); + struct video_device *vdev = soc_camera_i2c_to_vdev(client); s32 data; int ret; @@ -712,6 +768,8 @@ static int mt9t031_video_probe(struct i2c_client *client) ret = mt9t031_idle(client); if (ret < 0) dev_err(&client->dev, "Failed to initialise the camera\n"); + else + vdev->dev.type = &mt9t031_dev_type; /* mt9t031_idle() has reset the chip to default. */ mt9t031->exposure = 255; -- cgit v1.2.3-70-g09d2 From d044189dfea1e8329d63cb4e18815a7e92d2e049 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Wed, 24 Feb 2010 13:23:36 -0300 Subject: V4L/DVB: cx88: increase BUFFER_TIMEOUT to 2 seconds When temporarily there is no video signal, sometimes it takes more than 0.5 secs for the cx88 chip to generate a single frame. If a dma timeout occurs during recording, it confuses the recording application (at least mencoder) and the recording stops. Since there is already an #if 0 for 2 seconds buffer timeout in the code at the -hg development tree, re-enabling that seemed the most simple solution. Signed-off-by: Marton Balint Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 48b6c04fb49..b5f054d124f 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -290,7 +290,7 @@ struct cx88_subid { #define RESOURCE_VIDEO 2 #define RESOURCE_VBI 4 -#define BUFFER_TIMEOUT msecs_to_jiffies(500) /* 0.5 seconds */ +#define BUFFER_TIMEOUT msecs_to_jiffies(2000) /* buffer for one video frame */ struct cx88_buffer { -- cgit v1.2.3-70-g09d2 From 6c9eaa82da53676db830572f5a41aa9ffea133a1 Mon Sep 17 00:00:00 2001 From: Márton Németh Date: Sun, 28 Feb 2010 11:19:47 -0300 Subject: V4L/DVB: tlg2300: cleanups when power management is not configured MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When power management is not configured (CONFIG_PM) then some code is no longer necessary. This patch will remove the following compiler warnings: * pd-dvb.c: In function 'poseidon_fe_release': * pd-dvb.c:101: warning: unused variable 'pd' * pd-video.c:14: warning: 'pm_video_suspend' declared 'static' but never defined * pd-video.c:15: warning: 'pm_video_resume' declared 'static' but never defined Signed-off-by: Márton Németh Acked-by: Huang Shijie Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tlg2300/pd-dvb.c | 6 ++++-- drivers/media/video/tlg2300/pd-video.c | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/tlg2300/pd-dvb.c b/drivers/media/video/tlg2300/pd-dvb.c index ebd9cb5bec7..edd78f8b1ba 100644 --- a/drivers/media/video/tlg2300/pd-dvb.c +++ b/drivers/media/video/tlg2300/pd-dvb.c @@ -97,15 +97,17 @@ open_out: return ret; } +#ifdef CONFIG_PM static void poseidon_fe_release(struct dvb_frontend *fe) { struct poseidon *pd = fe->demodulator_priv; -#ifdef CONFIG_PM pd->pm_suspend = NULL; pd->pm_resume = NULL; -#endif } +#else +#define poseidon_fe_release NULL +#endif static s32 poseidon_fe_sleep(struct dvb_frontend *fe) { diff --git a/drivers/media/video/tlg2300/pd-video.c b/drivers/media/video/tlg2300/pd-video.c index cf8f18c007e..ed5cb1818ad 100644 --- a/drivers/media/video/tlg2300/pd-video.c +++ b/drivers/media/video/tlg2300/pd-video.c @@ -12,8 +12,10 @@ #include "pd-common.h" #include "vendorcmds.h" +#ifdef CONFIG_PM static int pm_video_suspend(struct poseidon *pd); static int pm_video_resume(struct poseidon *pd); +#endif static void iso_bubble_handler(struct work_struct *w); int usb_transfer_mode; -- cgit v1.2.3-70-g09d2 From 278a58cf2ab6e690fa79ca7e0d466a0cb453296f Mon Sep 17 00:00:00 2001 From: Márton Németh Date: Mon, 1 Mar 2010 03:31:02 -0300 Subject: V4L/DVB: tlg2300: make local variables and functions static MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the local variables and functions static. Some of them are not exported by their symbol name but used trough other means. For example a pointer of the operation structure is passed through a function call. This will remove the following sparse warnings (see "make C=1"): * pd-video.c:20:5: warning: symbol 'usb_transfer_mode' was not declared. Should it be static? * pd-video.c:621:5: warning: symbol 'fire_all_urb' was not declared. Should it be static? * pd-video.c:881:5: warning: symbol 'vidioc_s_std' was not declared. Should it be static? * pd-video.c:1024:5: warning: symbol 'vidioc_g_audio' was not declared. Should it be static? * pd-video.c:1033:5: warning: symbol 'vidioc_s_audio' was not declared. Should it be static? * pd-video.c:1193:5: warning: symbol 'usb_transfer_stop' was not declared. Should it be static? * pd-video.c:1522:14: warning: symbol 'pd_video_poll' was not declared. Should it be static? * pd-video.c:1528:9: warning: symbol 'pd_video_read' was not declared. Should it be static? * pd-radio.c:164:5: warning: symbol 'tlg_fm_vidioc_g_tuner' was not declared. Should it be static? * pd-radio.c:206:5: warning: symbol 'fm_get_freq' was not declared. Should it be static? * pd-radio.c:249:5: warning: symbol 'fm_set_freq' was not declared. Should it be static? * pd-radio.c:261:5: warning: symbol 'tlg_fm_vidioc_g_ctrl' was not declared. Should it be static? * pd-radio.c:267:5: warning: symbol 'tlg_fm_vidioc_g_exts_ctrl' was not declared. Should it be static? * pd-radio.c:288:5: warning: symbol 'tlg_fm_vidioc_s_exts_ctrl' was not declared. Should it be static? * pd-radio.c:315:5: warning: symbol 'tlg_fm_vidioc_s_ctrl' was not declared. Should it be static? * pd-radio.c:321:5: warning: symbol 'tlg_fm_vidioc_queryctrl' was not declared. Should it be static? * pd-radio.c:340:5: warning: symbol 'tlg_fm_vidioc_querymenu' was not declared. Should it be static? * pd-main.c:58:12: warning: symbol 'firmware_name' was not declared. Should it be static? * pd-main.c:59:19: warning: symbol 'poseidon_driver' was not declared. Should it be static? Signed-off-by: Márton Németh Acked-by: Huang Shijie Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tlg2300/pd-main.c | 6 +++--- drivers/media/video/tlg2300/pd-radio.c | 21 ++++++++++++--------- drivers/media/video/tlg2300/pd-video.c | 16 ++++++++-------- 3 files changed, 23 insertions(+), 20 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/tlg2300/pd-main.c b/drivers/media/video/tlg2300/pd-main.c index 2cf0ebf9f28..832b7c7b13d 100644 --- a/drivers/media/video/tlg2300/pd-main.c +++ b/drivers/media/video/tlg2300/pd-main.c @@ -55,8 +55,8 @@ int debug_mode; module_param(debug_mode, int, 0644); MODULE_PARM_DESC(debug_mode, "0 = disable, 1 = enable, 2 = verbose"); -const char *firmware_name = "tlg2300_firmware.bin"; -struct usb_driver poseidon_driver; +static const char *firmware_name = "tlg2300_firmware.bin"; +static struct usb_driver poseidon_driver; static LIST_HEAD(pd_device_list); /* @@ -501,7 +501,7 @@ static void poseidon_disconnect(struct usb_interface *interface) kref_put(&pd->kref, poseidon_delete); } -struct usb_driver poseidon_driver = { +static struct usb_driver poseidon_driver = { .name = "poseidon", .probe = poseidon_probe, .disconnect = poseidon_disconnect, diff --git a/drivers/media/video/tlg2300/pd-radio.c b/drivers/media/video/tlg2300/pd-radio.c index 755766b1515..fae84c2a0c3 100644 --- a/drivers/media/video/tlg2300/pd-radio.c +++ b/drivers/media/video/tlg2300/pd-radio.c @@ -161,7 +161,8 @@ static const struct v4l2_file_operations poseidon_fm_fops = { .ioctl = video_ioctl2, }; -int tlg_fm_vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *vt) +static int tlg_fm_vidioc_g_tuner(struct file *file, void *priv, + struct v4l2_tuner *vt) { struct tuner_fm_sig_stat_s fm_stat = {}; int ret, status, count = 5; @@ -203,7 +204,8 @@ int tlg_fm_vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *vt) return 0; } -int fm_get_freq(struct file *file, void *priv, struct v4l2_frequency *argp) +static int fm_get_freq(struct file *file, void *priv, + struct v4l2_frequency *argp) { struct poseidon *p = file->private_data; @@ -246,7 +248,8 @@ error: return ret; } -int fm_set_freq(struct file *file, void *priv, struct v4l2_frequency *argp) +static int fm_set_freq(struct file *file, void *priv, + struct v4l2_frequency *argp) { struct poseidon *p = file->private_data; @@ -258,13 +261,13 @@ int fm_set_freq(struct file *file, void *priv, struct v4l2_frequency *argp) return set_frequency(p, argp->frequency); } -int tlg_fm_vidioc_g_ctrl(struct file *file, void *priv, +static int tlg_fm_vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *arg) { return 0; } -int tlg_fm_vidioc_g_exts_ctrl(struct file *file, void *fh, +static int tlg_fm_vidioc_g_exts_ctrl(struct file *file, void *fh, struct v4l2_ext_controls *ctrls) { struct poseidon *p = file->private_data; @@ -285,7 +288,7 @@ int tlg_fm_vidioc_g_exts_ctrl(struct file *file, void *fh, return 0; } -int tlg_fm_vidioc_s_exts_ctrl(struct file *file, void *fh, +static int tlg_fm_vidioc_s_exts_ctrl(struct file *file, void *fh, struct v4l2_ext_controls *ctrls) { int i; @@ -312,13 +315,13 @@ int tlg_fm_vidioc_s_exts_ctrl(struct file *file, void *fh, return 0; } -int tlg_fm_vidioc_s_ctrl(struct file *file, void *priv, +static int tlg_fm_vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { return 0; } -int tlg_fm_vidioc_queryctrl(struct file *file, void *priv, +static int tlg_fm_vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *ctrl) { if (!(ctrl->id & V4L2_CTRL_FLAG_NEXT_CTRL)) @@ -337,7 +340,7 @@ int tlg_fm_vidioc_queryctrl(struct file *file, void *priv, return -EINVAL; } -int tlg_fm_vidioc_querymenu(struct file *file, void *fh, +static int tlg_fm_vidioc_querymenu(struct file *file, void *fh, struct v4l2_querymenu *qmenu) { return v4l2_ctrl_query_menu(qmenu, NULL, NULL); diff --git a/drivers/media/video/tlg2300/pd-video.c b/drivers/media/video/tlg2300/pd-video.c index ed5cb1818ad..c750fd115ec 100644 --- a/drivers/media/video/tlg2300/pd-video.c +++ b/drivers/media/video/tlg2300/pd-video.c @@ -18,7 +18,7 @@ static int pm_video_resume(struct poseidon *pd); #endif static void iso_bubble_handler(struct work_struct *w); -int usb_transfer_mode; +static int usb_transfer_mode; module_param(usb_transfer_mode, int, 0644); MODULE_PARM_DESC(usb_transfer_mode, "0 = Bulk, 1 = Isochronous"); @@ -619,7 +619,7 @@ static int pd_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, return 0; } -int fire_all_urb(struct video_data *video) +static int fire_all_urb(struct video_data *video) { int i, ret; @@ -879,7 +879,7 @@ out: return ret; } -int vidioc_s_std(struct file *file, void *fh, v4l2_std_id *norm) +static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id *norm) { struct front_face *front = fh; logs(front); @@ -1022,7 +1022,7 @@ static int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *a) return 0; } -int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a) +static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a) { a->index = 0; a->capability = V4L2_AUDCAP_STEREO; @@ -1031,7 +1031,7 @@ int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a) return 0; } -int vidioc_s_audio(struct file *file, void *fh, struct v4l2_audio *a) +static int vidioc_s_audio(struct file *file, void *fh, struct v4l2_audio *a) { return (0 == a->index) ? 0 : -EINVAL; } @@ -1191,7 +1191,7 @@ static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b) } /* Just stop the URBs, do not free the URBs */ -int usb_transfer_stop(struct video_data *video) +static int usb_transfer_stop(struct video_data *video) { if (video->is_streaming) { int i; @@ -1520,13 +1520,13 @@ static int pd_video_mmap(struct file *file, struct vm_area_struct *vma) return videobuf_mmap_mapper(&front->q, vma); } -unsigned int pd_video_poll(struct file *file, poll_table *table) +static unsigned int pd_video_poll(struct file *file, poll_table *table) { struct front_face *front = file->private_data; return videobuf_poll_stream(file, &front->q, table); } -ssize_t pd_video_read(struct file *file, char __user *buffer, +static ssize_t pd_video_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) { struct front_face *front = file->private_data; -- cgit v1.2.3-70-g09d2 From 52897d86b1f0c8639e4b132b6b4ab1973694650f Mon Sep 17 00:00:00 2001 From: Erik Andrén Date: Sun, 7 Mar 2010 05:13:49 -0300 Subject: V4L/DVB: gspca - pac207: Let all pac207 ctrls have a coherent naming MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Erik Andrén Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/pac207.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/pac207.c b/drivers/media/video/gspca/pac207.c index 0c87c3490b1..a40f8893310 100644 --- a/drivers/media/video/gspca/pac207.c +++ b/drivers/media/video/gspca/pac207.c @@ -99,7 +99,7 @@ static const struct ctrl sd_ctrls[] = { { .id = V4L2_CID_EXPOSURE, .type = V4L2_CTRL_TYPE_INTEGER, - .name = "exposure", + .name = "Exposure", .minimum = PAC207_EXPOSURE_MIN, .maximum = PAC207_EXPOSURE_MAX, .step = 1, @@ -130,7 +130,7 @@ static const struct ctrl sd_ctrls[] = { { .id = V4L2_CID_GAIN, .type = V4L2_CTRL_TYPE_INTEGER, - .name = "gain", + .name = "Gain", .minimum = PAC207_GAIN_MIN, .maximum = PAC207_GAIN_MAX, .step = 1, -- cgit v1.2.3-70-g09d2 From 24f222e77ad62e41b1a882c77feeb8268c80b909 Mon Sep 17 00:00:00 2001 From: Jean-François Moine Date: Sun, 7 Mar 2010 05:58:55 -0300 Subject: V4L/DVB: gspca - t613: Check the result of kmalloc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/t613.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c index 668a7536af9..8c7dadef821 100644 --- a/drivers/media/video/gspca/t613.c +++ b/drivers/media/video/gspca/t613.c @@ -523,6 +523,10 @@ static void reg_w_buf(struct gspca_dev *gspca_dev, u8 *tmpbuf; tmpbuf = kmalloc(len, GFP_KERNEL); + if (!tmpbuf) { + err("Out of memory"); + return; + } memcpy(tmpbuf, buffer, len); usb_control_msg(gspca_dev->dev, usb_sndctrlpipe(gspca_dev->dev, 0), @@ -542,10 +546,15 @@ static void reg_w_ixbuf(struct gspca_dev *gspca_dev, int i; u8 *p, *tmpbuf; - if (len * 2 <= USB_BUF_SZ) + if (len * 2 <= USB_BUF_SZ) { p = tmpbuf = gspca_dev->usb_buf; - else + } else { p = tmpbuf = kmalloc(len * 2, GFP_KERNEL); + if (!tmpbuf) { + err("Out of memory"); + return; + } + } i = len; while (--i >= 0) { *p++ = reg++; -- cgit v1.2.3-70-g09d2 From e10f73194d63321d020433fa1287e619d4107b79 Mon Sep 17 00:00:00 2001 From: German Galkin Date: Sun, 7 Mar 2010 06:19:02 -0300 Subject: V4L/DVB: gspca - sn9c20x: Fix exposure control for HV7131R sensor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the range of exposure values (0-0x1770) distribute evenly through HV7131R's exposure control bytes. Signed-off-by: German Galkin Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sn9c20x.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c index 3dee3e5844b..04bf80ddfbb 100644 --- a/drivers/media/video/gspca/sn9c20x.c +++ b/drivers/media/video/gspca/sn9c20x.c @@ -1655,9 +1655,9 @@ static int set_exposure(struct gspca_dev *gspca_dev) case SENSOR_HV7131R: exp[0] |= (4 << 4); exp[2] = 0x25; - exp[3] = ((sd->exposure * 0xffffff) / 0xffff) >> 16; - exp[4] = ((sd->exposure * 0xffffff) / 0xffff) >> 8; - exp[5] = ((sd->exposure * 0xffffff) / 0xffff) & 0xff; + exp[3] = (sd->exposure >> 5) & 0xff; + exp[4] = (sd->exposure << 3) & 0xff; + exp[5] = 0; break; default: return 0; -- cgit v1.2.3-70-g09d2 From 2f51d00ffa2a41c76fe8a492383e1c1124137694 Mon Sep 17 00:00:00 2001 From: Paulo Assis Date: Sun, 7 Mar 2010 06:56:56 -0300 Subject: V4L/DVB: gspca - main: Use ktime instead of jiffies for buffer timestamping MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gspca.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 222af479150..415949526ee 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include #include "gspca.h" @@ -442,8 +442,7 @@ void gspca_frame_add(struct gspca_dev *gspca_dev, * is not queued, discard the whole frame */ if (packet_type == FIRST_PACKET) { frame->data_end = frame->data; - jiffies_to_timeval(get_jiffies_64(), - &frame->v4l2_buf.timestamp); + frame->v4l2_buf.timestamp = ktime_to_timeval(ktime_get()); frame->v4l2_buf.sequence = ++gspca_dev->sequence; } else if (gspca_dev->last_packet_type == DISCARD_PACKET) { if (packet_type == LAST_PACKET) @@ -2124,7 +2123,7 @@ static ssize_t dev_read(struct file *file, char __user *data, } /* get a frame */ - jiffies_to_timeval(get_jiffies_64(), ×tamp); + timestamp = ktime_to_timeval(ktime_get()); timestamp.tv_sec--; n = 2; for (;;) { -- cgit v1.2.3-70-g09d2 From a4fa8e9e8586bc769b14069bbb663e2738abe7be Mon Sep 17 00:00:00 2001 From: Jean-François Moine Date: Sun, 7 Mar 2010 07:18:59 -0300 Subject: V4L/DVB: gspca - cpia1 / sn9c2028: Make control descriptors constant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/cpia1.c | 2 +- drivers/media/video/gspca/sn9c2028.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/cpia1.c b/drivers/media/video/gspca/cpia1.c index 82945ed5cbe..8fa98439c3f 100644 --- a/drivers/media/video/gspca/cpia1.c +++ b/drivers/media/video/gspca/cpia1.c @@ -374,7 +374,7 @@ static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setcomptarget(struct gspca_dev *gspca_dev, __s32 val); static int sd_getcomptarget(struct gspca_dev *gspca_dev, __s32 *val); -static struct ctrl sd_ctrls[] = { +static const struct ctrl sd_ctrls[] = { { { .id = V4L2_CID_BRIGHTNESS, diff --git a/drivers/media/video/gspca/sn9c2028.c b/drivers/media/video/gspca/sn9c2028.c index dda5fd4aa69..71d9447a798 100644 --- a/drivers/media/video/gspca/sn9c2028.c +++ b/drivers/media/video/gspca/sn9c2028.c @@ -39,7 +39,7 @@ struct init_command { }; /* V4L2 controls supported by the driver */ -static struct ctrl sd_ctrls[] = { +static const struct ctrl sd_ctrls[] = { }; /* How to change the resolution of any of the VGA cams is unknown */ -- cgit v1.2.3-70-g09d2 From 4de39f5d6f8267a0b062cba70eaa84fb161007e4 Mon Sep 17 00:00:00 2001 From: Dean Anderson Date: Wed, 3 Mar 2010 19:39:19 -0300 Subject: V4L/DVB: s2255drv: adding video input status capability Video status capability for inputs on Sensoray 2255 driver. Signed-off-by: Dean Anderson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s2255drv.c | 85 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 81 insertions(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index 3de914deb8e..a9c53335fd8 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c @@ -1,7 +1,7 @@ /* * s2255drv.c - a driver for the Sensoray 2255 USB video capture device * - * Copyright (C) 2007-2008 by Sensoray Company Inc. + * Copyright (C) 2007-2010 by Sensoray Company Inc. * Dean Anderson * * Some video buffer code based on vivi driver: @@ -76,11 +76,13 @@ #define S2255_LOAD_TIMEOUT (5000 + S2255_DSP_BOOTTIME) #define S2255_DEF_BUFS 16 #define S2255_SETMODE_TIMEOUT 500 +#define S2255_VIDSTATUS_TIMEOUT 350 #define MAX_CHANNELS 4 #define S2255_MARKER_FRAME 0x2255DA4AL #define S2255_MARKER_RESPONSE 0x2255ACACL #define S2255_RESPONSE_SETMODE 0x01 #define S2255_RESPONSE_FW 0x10 +#define S2255_RESPONSE_STATUS 0x20 #define S2255_USB_XFER_SIZE (16 * 1024) #define MAX_CHANNELS 4 #define MAX_PIPE_BUFFERS 1 @@ -261,9 +263,16 @@ struct s2255_dev { int chn_configured[MAX_CHANNELS]; wait_queue_head_t wait_setmode[MAX_CHANNELS]; int setmode_ready[MAX_CHANNELS]; + /* video status items */ + int vidstatus[MAX_CHANNELS]; + wait_queue_head_t wait_vidstatus[MAX_CHANNELS]; + int vidstatus_ready[MAX_CHANNELS]; + int chn_ready; struct kref kref; spinlock_t slock; + /* dsp firmware version (f2255usb.bin) */ + int dsp_fw_ver; }; #define to_s2255_dev(d) container_of(d, struct s2255_dev, kref) @@ -296,8 +305,12 @@ struct s2255_fh { /* current cypress EEPROM firmware version */ #define S2255_CUR_USB_FWVER ((3 << 8) | 6) +/* current DSP FW version */ +#define S2255_CUR_DSP_FWVER 5 +/* Need DSP version 5+ for video status feature */ +#define S2255_MIN_DSP_STATUS 5 #define S2255_MAJOR_VERSION 1 -#define S2255_MINOR_VERSION 14 +#define S2255_MINOR_VERSION 15 #define S2255_RELEASE 0 #define S2255_VERSION KERNEL_VERSION(S2255_MAJOR_VERSION, \ S2255_MINOR_VERSION, \ @@ -1261,6 +1274,42 @@ static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn, return res; } +static int s2255_cmd_status(struct s2255_dev *dev, unsigned long chn, + u32 *pstatus) +{ + int res; + u32 *buffer; + u32 chn_rev; + mutex_lock(&dev->lock); + chn_rev = G_chnmap[chn]; + dprintk(4, "%s chan %d\n", __func__, chn_rev); + buffer = kzalloc(512, GFP_KERNEL); + if (buffer == NULL) { + dev_err(&dev->udev->dev, "out of mem\n"); + mutex_unlock(&dev->lock); + return -ENOMEM; + } + /* form the get vid status command */ + buffer[0] = IN_DATA_TOKEN; + buffer[1] = chn_rev; + buffer[2] = CMD_STATUS; + *pstatus = 0; + dev->vidstatus_ready[chn] = 0; + res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512); + kfree(buffer); + wait_event_timeout(dev->wait_vidstatus[chn], + (dev->vidstatus_ready[chn] != 0), + msecs_to_jiffies(S2255_VIDSTATUS_TIMEOUT)); + if (dev->vidstatus_ready[chn] != 1) { + printk(KERN_DEBUG "s2255: no vidstatus response\n"); + res = -EFAULT; + } + *pstatus = dev->vidstatus[chn]; + dprintk(4, "%s, vid status %d\n", __func__, *pstatus); + mutex_unlock(&dev->lock); + return res; +} + static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) { int res; @@ -1386,11 +1435,24 @@ out_s_std: static int vidioc_enum_input(struct file *file, void *priv, struct v4l2_input *inp) { + struct s2255_fh *fh = priv; + struct s2255_dev *dev = fh->dev; + u32 status = 0; + if (inp->index != 0) return -EINVAL; inp->type = V4L2_INPUT_TYPE_CAMERA; inp->std = S2255_NORMS; + inp->status = 0; + if (dev->dsp_fw_ver >= S2255_MIN_DSP_STATUS) { + int rc; + rc = s2255_cmd_status(dev, fh->channel, &status); + dprintk(4, "s2255_cmd_status rc: %d status %x\n", rc, status); + if (rc == 0) + inp->status = (status & 0x01) ? 0 + : V4L2_IN_ST_NO_SIGNAL; + } strlcpy(inp->name, "Camera", sizeof(inp->name)); return 0; } @@ -1700,6 +1762,8 @@ static void s2255_destroy(struct kref *kref) for (i = 0; i < MAX_CHANNELS; i++) { dev->setmode_ready[i] = 1; wake_up(&dev->wait_setmode[i]); + dev->vidstatus_ready[i] = 1; + wake_up(&dev->wait_vidstatus[i]); } mutex_lock(&dev->open_lock); /* reset the DSP so firmware can be reload next time */ @@ -1965,6 +2029,13 @@ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info) S2255_FW_SUCCESS); wake_up(&dev->fw_data->wait_fw); break; + case S2255_RESPONSE_STATUS: + dev->vidstatus[cc] = pdword[3]; + dev->vidstatus_ready[cc] = 1; + wake_up(&dev->wait_vidstatus[cc]); + dprintk(5, "got vidstatus %x chan %d\n", + pdword[3], cc); + break; default: printk(KERN_INFO "s2255 unknown resp\n"); } @@ -2527,9 +2598,10 @@ static int s2255_probe(struct usb_interface *interface, dev->timer.data = (unsigned long)dev->fw_data; init_waitqueue_head(&dev->fw_data->wait_fw); - for (i = 0; i < MAX_CHANNELS; i++) + for (i = 0; i < MAX_CHANNELS; i++) { init_waitqueue_head(&dev->wait_setmode[i]); - + init_waitqueue_head(&dev->wait_vidstatus[i]); + } dev->fw_data->fw_urb = usb_alloc_urb(0, GFP_KERNEL); @@ -2561,6 +2633,9 @@ static int s2255_probe(struct usb_interface *interface, __le32 *pRel; pRel = (__le32 *) &dev->fw_data->fw->data[fw_size - 4]; printk(KERN_INFO "s2255 dsp fw version %x\n", *pRel); + dev->dsp_fw_ver = *pRel; + if (*pRel < S2255_CUR_DSP_FWVER) + printk(KERN_INFO "s2255: f2255usb.bin out of date.\n"); } /* loads v4l specific */ s2255_probe_v4l(dev); @@ -2597,6 +2672,8 @@ static void s2255_disconnect(struct usb_interface *interface) for (i = 0; i < MAX_CHANNELS; i++) { dev->setmode_ready[i] = 1; wake_up(&dev->wait_setmode[i]); + dev->vidstatus_ready[i] = 1; + wake_up(&dev->wait_vidstatus[i]); } mutex_lock(&dev->open_lock); -- cgit v1.2.3-70-g09d2 From 811fab623f435932f2a26aa64b40ec6102618cc6 Mon Sep 17 00:00:00 2001 From: Antonio Larrosa Date: Thu, 4 Mar 2010 22:19:48 -0300 Subject: V4L/DVB: em28xx: Support for Kworld VS-DVB-T 323UR This patch adapts the changes submitted by Dainius Ridzevicius to the linux-media mailing list on 8/14/09, to the current sources in order to make the Kworld VS-DVB-T 323UR usb device work. I also removed the "not validated" flag since I own the device and validated that it works fine after the patch is applied. Thanks to Devin Heitmueller for his guidance with the code. Signed-off-by: Antonio Larrosa Acked-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-cards.c | 7 ++++++- drivers/media/video/em28xx/em28xx-dvb.c | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index b0fb0833771..5ed834ee756 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -1404,10 +1404,14 @@ struct em28xx_board em28xx_boards[] = { }, [EM2882_BOARD_KWORLD_VS_DVBT] = { .name = "Kworld VS-DVB-T 323UR", - .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_XC2028, .tuner_gpio = default_tuner_gpio, .decoder = EM28XX_TVP5150, + .mts_firmware = 1, + .has_dvb = 1, + .dvb_gpio = kworld_330u_digital, + .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, /* NEC IR */ + .ir_codes = &ir_codes_kworld_315u_table, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, @@ -2138,6 +2142,7 @@ static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl) break; case EM2883_BOARD_KWORLD_HYBRID_330U: case EM2882_BOARD_DIKOM_DK300: + case EM2882_BOARD_KWORLD_VS_DVBT: ctl->demod = XC3028_FE_CHINA; ctl->fname = XC2028_DEFAULT_FIRMWARE; break; diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index bcd3c371009..e7b3d537155 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c @@ -506,6 +506,7 @@ static int dvb_init(struct em28xx *dev) case EM2880_BOARD_TERRATEC_HYBRID_XS_FR: case EM2881_BOARD_PINNACLE_HYBRID_PRO: case EM2882_BOARD_DIKOM_DK300: + case EM2882_BOARD_KWORLD_VS_DVBT: dvb->frontend = dvb_attach(zl10353_attach, &em28xx_zl10353_xc3028_no_i2c_gate, &dev->i2c_adap); -- cgit v1.2.3-70-g09d2 From 3fa0060526eafe3eeda1db681b4aab5b79d4543e Mon Sep 17 00:00:00 2001 From: Dean Anderson Date: Thu, 4 Mar 2010 20:47:33 -0300 Subject: V4L/DVB: s2255drv: fixes for big endian arch s2255drv fixes for big endian architecture Signed-off-by: Dean Anderson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s2255drv.c | 55 +++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 30 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index a9c53335fd8..882a79679dc 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c @@ -78,11 +78,11 @@ #define S2255_SETMODE_TIMEOUT 500 #define S2255_VIDSTATUS_TIMEOUT 350 #define MAX_CHANNELS 4 -#define S2255_MARKER_FRAME 0x2255DA4AL -#define S2255_MARKER_RESPONSE 0x2255ACACL -#define S2255_RESPONSE_SETMODE 0x01 -#define S2255_RESPONSE_FW 0x10 -#define S2255_RESPONSE_STATUS 0x20 +#define S2255_MARKER_FRAME cpu_to_le32(0x2255DA4AL) +#define S2255_MARKER_RESPONSE cpu_to_le32(0x2255ACACL) +#define S2255_RESPONSE_SETMODE cpu_to_le32(0x01) +#define S2255_RESPONSE_FW cpu_to_le32(0x10) +#define S2255_RESPONSE_STATUS cpu_to_le32(0x20) #define S2255_USB_XFER_SIZE (16 * 1024) #define MAX_CHANNELS 4 #define MAX_PIPE_BUFFERS 1 @@ -141,12 +141,12 @@ #define DEF_HUE 0 /* usb config commands */ -#define IN_DATA_TOKEN 0x2255c0de -#define CMD_2255 0xc2255000 -#define CMD_SET_MODE (CMD_2255 | 0x10) -#define CMD_START (CMD_2255 | 0x20) -#define CMD_STOP (CMD_2255 | 0x30) -#define CMD_STATUS (CMD_2255 | 0x40) +#define IN_DATA_TOKEN cpu_to_le32(0x2255c0de) +#define CMD_2255 cpu_to_le32(0xc2255000) +#define CMD_SET_MODE cpu_to_le32((CMD_2255 | 0x10)) +#define CMD_START cpu_to_le32((CMD_2255 | 0x20)) +#define CMD_STOP cpu_to_le32((CMD_2255 | 0x30)) +#define CMD_STATUS cpu_to_le32((CMD_2255 | 0x40)) struct s2255_mode { u32 format; /* input video format (NTSC, PAL) */ @@ -310,7 +310,7 @@ struct s2255_fh { /* Need DSP version 5+ for video status feature */ #define S2255_MIN_DSP_STATUS 5 #define S2255_MAJOR_VERSION 1 -#define S2255_MINOR_VERSION 15 +#define S2255_MINOR_VERSION 16 #define S2255_RELEASE 0 #define S2255_VERSION KERNEL_VERSION(S2255_MAJOR_VERSION, \ S2255_MINOR_VERSION, \ @@ -1219,9 +1219,8 @@ static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn, struct s2255_mode *mode) { int res; - u32 *buffer; + __le32 *buffer; unsigned long chn_rev; - mutex_lock(&dev->lock); chn_rev = G_chnmap[chn]; dprintk(3, "mode scale [%ld] %p %d\n", chn, mode, mode->scale); @@ -1247,7 +1246,7 @@ static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn, /* set the mode */ buffer[0] = IN_DATA_TOKEN; - buffer[1] = (u32) chn_rev; + buffer[1] = (__le32) cpu_to_le32(chn_rev); buffer[2] = CMD_SET_MODE; memcpy(&buffer[3], &dev->mode[chn], sizeof(struct s2255_mode)); dev->setmode_ready[chn] = 0; @@ -1278,7 +1277,7 @@ static int s2255_cmd_status(struct s2255_dev *dev, unsigned long chn, u32 *pstatus) { int res; - u32 *buffer; + __le32 *buffer; u32 chn_rev; mutex_lock(&dev->lock); chn_rev = G_chnmap[chn]; @@ -1291,7 +1290,7 @@ static int s2255_cmd_status(struct s2255_dev *dev, unsigned long chn, } /* form the get vid status command */ buffer[0] = IN_DATA_TOKEN; - buffer[1] = chn_rev; + buffer[1] = (__le32) cpu_to_le32(chn_rev); buffer[2] = CMD_STATUS; *pstatus = 0; dev->vidstatus_ready[chn] = 0; @@ -1971,14 +1970,14 @@ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info) if (frm->ulState == S2255_READ_IDLE) { int jj; unsigned int cc; - s32 *pdword; + __le32 *pdword; /*data from dsp is little endian */ int payload; /* search for marker codes */ pdata = (unsigned char *)pipe_info->transfer_buffer; + pdword = (__le32 *)pdata; for (jj = 0; jj < (pipe_info->cur_transfer_size - 12); jj++) { - switch (*(s32 *) pdata) { + switch (*pdword) { case S2255_MARKER_FRAME: - pdword = (s32 *)pdata; dprintk(4, "found frame marker at offset:" " %d [%x %x]\n", jj, pdata[0], pdata[1]); @@ -2002,7 +2001,6 @@ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info) dev->jpg_size[dev->cc] = pdword[4]; break; case S2255_MARKER_RESPONSE: - pdword = (s32 *)pdata; pdata += DEF_USB_BLOCK; jj += DEF_USB_BLOCK; if (pdword[1] >= MAX_CHANNELS) @@ -2437,9 +2435,9 @@ static int s2255_start_acquire(struct s2255_dev *dev, unsigned long chn) } /* send the start command */ - *(u32 *) buffer = IN_DATA_TOKEN; - *((u32 *) buffer + 1) = (u32) chn_rev; - *((u32 *) buffer + 2) = (u32) CMD_START; + *(__le32 *) buffer = IN_DATA_TOKEN; + *((__le32 *) buffer + 1) = (__le32) cpu_to_le32(chn_rev); + *((__le32 *) buffer + 2) = CMD_START; res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512); if (res != 0) dev_err(&dev->udev->dev, "CMD_START error\n"); @@ -2454,24 +2452,21 @@ static int s2255_stop_acquire(struct s2255_dev *dev, unsigned long chn) unsigned char *buffer; int res; unsigned long chn_rev; - if (chn >= MAX_CHANNELS) { dprintk(2, "stop acquire failed, bad channel %lu\n", chn); return -1; } chn_rev = G_chnmap[chn]; - buffer = kzalloc(512, GFP_KERNEL); if (buffer == NULL) { dev_err(&dev->udev->dev, "out of mem\n"); return -ENOMEM; } - /* send the stop command */ dprintk(4, "stop acquire %lu\n", chn); - *(u32 *) buffer = IN_DATA_TOKEN; - *((u32 *) buffer + 1) = (u32) chn_rev; - *((u32 *) buffer + 2) = CMD_STOP; + *(__le32 *) buffer = IN_DATA_TOKEN; + *((__le32 *) buffer + 1) = (__le32) cpu_to_le32(chn_rev); + *((__le32 *) buffer + 2) = CMD_STOP; res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512); if (res != 0) -- cgit v1.2.3-70-g09d2 From 2e70db9a4553e0f79cb4db05c0552d33932cca80 Mon Sep 17 00:00:00 2001 From: Dean Anderson Date: Fri, 5 Mar 2010 14:29:09 -0300 Subject: V4L/DVB: s2255drv: cleanup of V4L2 controls Signed-off-by: Dean Anderson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s2255drv.c | 166 +++++++++++++++-------------------------- 1 file changed, 62 insertions(+), 104 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index 882a79679dc..631a84eea1a 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c @@ -310,7 +310,7 @@ struct s2255_fh { /* Need DSP version 5+ for video status feature */ #define S2255_MIN_DSP_STATUS 5 #define S2255_MAJOR_VERSION 1 -#define S2255_MINOR_VERSION 16 +#define S2255_MINOR_VERSION 17 #define S2255_RELEASE 0 #define S2255_VERSION KERNEL_VERSION(S2255_MAJOR_VERSION, \ S2255_MINOR_VERSION, \ @@ -384,49 +384,6 @@ MODULE_DEVICE_TABLE(usb, s2255_table); #define BUFFER_TIMEOUT msecs_to_jiffies(400) -/* supported controls */ -static struct v4l2_queryctrl s2255_qctrl[] = { - { - .id = V4L2_CID_BRIGHTNESS, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Brightness", - .minimum = -127, - .maximum = 128, - .step = 1, - .default_value = 0, - .flags = 0, - }, { - .id = V4L2_CID_CONTRAST, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Contrast", - .minimum = 0, - .maximum = 255, - .step = 0x1, - .default_value = DEF_CONTRAST, - .flags = 0, - }, { - .id = V4L2_CID_SATURATION, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Saturation", - .minimum = 0, - .maximum = 255, - .step = 0x1, - .default_value = DEF_SATURATION, - .flags = 0, - }, { - .id = V4L2_CID_HUE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Hue", - .minimum = 0, - .maximum = 255, - .step = 0x1, - .default_value = DEF_HUE, - .flags = 0, - } -}; - -static int qctl_regs[ARRAY_SIZE(s2255_qctrl)]; - /* image formats. */ static const struct s2255_fmt formats[] = { { @@ -1472,74 +1429,82 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i) static int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qc) { - int i; - - for (i = 0; i < ARRAY_SIZE(s2255_qctrl); i++) - if (qc->id && qc->id == s2255_qctrl[i].id) { - memcpy(qc, &(s2255_qctrl[i]), sizeof(*qc)); - return 0; - } - - dprintk(4, "query_ctrl -EINVAL %d\n", qc->id); - return -EINVAL; + switch (qc->id) { + case V4L2_CID_BRIGHTNESS: + v4l2_ctrl_query_fill(qc, -127, 127, 1, DEF_BRIGHT); + break; + case V4L2_CID_CONTRAST: + v4l2_ctrl_query_fill(qc, 0, 255, 1, DEF_CONTRAST); + break; + case V4L2_CID_SATURATION: + v4l2_ctrl_query_fill(qc, 0, 255, 1, DEF_SATURATION); + break; + case V4L2_CID_HUE: + v4l2_ctrl_query_fill(qc, 0, 255, 1, DEF_HUE); + break; + default: + return -EINVAL; + } + dprintk(4, "%s, id %d\n", __func__, qc->id); + return 0; } static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - int i; - - for (i = 0; i < ARRAY_SIZE(s2255_qctrl); i++) - if (ctrl->id == s2255_qctrl[i].id) { - ctrl->value = qctl_regs[i]; - return 0; - } - dprintk(4, "g_ctrl -EINVAL\n"); - - return -EINVAL; + struct s2255_fh *fh = priv; + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + ctrl->value = fh->mode.bright; + break; + case V4L2_CID_CONTRAST: + ctrl->value = fh->mode.contrast; + break; + case V4L2_CID_SATURATION: + ctrl->value = fh->mode.saturation; + break; + case V4L2_CID_HUE: + ctrl->value = fh->mode.hue; + break; + default: + return -EINVAL; + } + dprintk(4, "%s, id %d val %d\n", __func__, ctrl->id, ctrl->value); + return 0; } static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - int i; struct s2255_fh *fh = priv; struct s2255_dev *dev = fh->dev; struct s2255_mode *mode; mode = &fh->mode; - dprintk(4, "vidioc_s_ctrl\n"); - for (i = 0; i < ARRAY_SIZE(s2255_qctrl); i++) { - if (ctrl->id == s2255_qctrl[i].id) { - if (ctrl->value < s2255_qctrl[i].minimum || - ctrl->value > s2255_qctrl[i].maximum) - return -ERANGE; - - qctl_regs[i] = ctrl->value; - /* update the mode to the corresponding value */ - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - mode->bright = ctrl->value; - break; - case V4L2_CID_CONTRAST: - mode->contrast = ctrl->value; - break; - case V4L2_CID_HUE: - mode->hue = ctrl->value; - break; - case V4L2_CID_SATURATION: - mode->saturation = ctrl->value; - break; - } - mode->restart = 0; - /* set mode here. Note: stream does not need restarted. - some V4L programs restart stream unnecessarily - after a s_crtl. - */ - s2255_set_mode(dev, fh->channel, mode); - return 0; - } + dprintk(4, "%s\n", __func__); + /* update the mode to the corresponding value */ + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + mode->bright = ctrl->value; + break; + case V4L2_CID_CONTRAST: + mode->contrast = ctrl->value; + break; + case V4L2_CID_HUE: + mode->hue = ctrl->value; + break; + case V4L2_CID_SATURATION: + mode->saturation = ctrl->value; + break; + default: + return -EINVAL; } - return -EINVAL; + mode->restart = 0; + /* set mode here. Note: stream does not need restarted. + some V4L programs restart stream unnecessarily + after a s_crtl. + */ + s2255_set_mode(dev, fh->channel, mode); + return 0; } static int vidioc_g_jpegcomp(struct file *file, void *priv, @@ -1701,18 +1666,11 @@ static int s2255_open(struct file *file) fh->width = LINE_SZ_4CIFS_NTSC; fh->height = NUM_LINES_4CIFS_NTSC * 2; fh->channel = cur_channel; - /* configure channel to default state */ if (!dev->chn_configured[cur_channel]) { s2255_set_mode(dev, cur_channel, &fh->mode); dev->chn_configured[cur_channel] = 1; } - - - /* Put all controls at a sane state */ - for (i = 0; i < ARRAY_SIZE(s2255_qctrl); i++) - qctl_regs[i] = s2255_qctrl[i].default_value; - dprintk(1, "s2255drv: open dev=%s type=%s users=%d\n", video_device_node_name(vdev), v4l2_type_names[type], dev->users[cur_channel]); -- cgit v1.2.3-70-g09d2 From 5a34d9dfaf3cb690c448fac67923effac08c902d Mon Sep 17 00:00:00 2001 From: Dean Anderson Date: Fri, 5 Mar 2010 19:59:48 -0300 Subject: V4L/DVB: s2255drv: Add support for 2257 device 2257 is 2255 with 2 svideo inputs Signed-off-by: Dean Anderson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s2255drv.c | 154 ++++++++++++++++++++++++++++++++++------- 1 file changed, 129 insertions(+), 25 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index 631a84eea1a..745f557200a 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c @@ -120,9 +120,10 @@ #define COLOR_YUVPK 2 /* YUV packed */ #define COLOR_Y8 4 /* monochrome */ #define COLOR_JPG 5 /* JPEG */ -#define MASK_COLOR 0xff -#define MASK_JPG_QUALITY 0xff00 +#define MASK_COLOR 0x000000ff +#define MASK_JPG_QUALITY 0x0000ff00 +#define MASK_INPUT_TYPE 0x000f0000 /* frame decimation. Not implemented by V4L yet(experimental in V4L) */ #define FDEC_1 1 /* capture every frame. default */ #define FDEC_2 2 /* capture every 2nd frame */ @@ -196,7 +197,6 @@ struct s2255_dmaqueue { #define S2255_FW_SUCCESS 2 #define S2255_FW_FAILED 3 #define S2255_FW_DISCONNECTING 4 - #define S2255_FW_MARKER cpu_to_le32(0x22552f2f) /* 2255 read states */ #define S2255_READ_IDLE 0 @@ -267,12 +267,12 @@ struct s2255_dev { int vidstatus[MAX_CHANNELS]; wait_queue_head_t wait_vidstatus[MAX_CHANNELS]; int vidstatus_ready[MAX_CHANNELS]; - int chn_ready; - struct kref kref; spinlock_t slock; /* dsp firmware version (f2255usb.bin) */ int dsp_fw_ver; + u16 pid; /* product id */ + struct kref kref; }; #define to_s2255_dev(d) container_of(d, struct s2255_dev, kref) @@ -306,20 +306,49 @@ struct s2255_fh { /* current cypress EEPROM firmware version */ #define S2255_CUR_USB_FWVER ((3 << 8) | 6) /* current DSP FW version */ -#define S2255_CUR_DSP_FWVER 5 +#define S2255_CUR_DSP_FWVER 8 /* Need DSP version 5+ for video status feature */ -#define S2255_MIN_DSP_STATUS 5 +#define S2255_MIN_DSP_STATUS 5 +#define S2255_MIN_DSP_COLORFILTER 8 #define S2255_MAJOR_VERSION 1 -#define S2255_MINOR_VERSION 17 +#define S2255_MINOR_VERSION 18 #define S2255_RELEASE 0 #define S2255_VERSION KERNEL_VERSION(S2255_MAJOR_VERSION, \ S2255_MINOR_VERSION, \ S2255_RELEASE) -/* vendor ids */ -#define USB_S2255_VENDOR_ID 0x1943 -#define USB_S2255_PRODUCT_ID 0x2255 #define S2255_NORMS (V4L2_STD_PAL | V4L2_STD_NTSC) + +/* private V4L2 controls */ + +/* + * The following chart displays how COLORFILTER should be set + * ========================================================= + * = fourcc = COLORFILTER = + * = =============================== + * = = 0 = 1 = + * ========================================================= + * = V4L2_PIX_FMT_GREY(Y8) = monochrome from = monochrome= + * = = s-video or = composite = + * = = B/W camera = input = + * ========================================================= + * = other = color, svideo = color, = + * = = = composite = + * ========================================================= + * + * Notes: + * channels 0-3 on 2255 are composite + * channels 0-1 on 2257 are composite, 2-3 are s-video + * If COLORFILTER is 0 with a composite color camera connected, + * the output will appear monochrome but hatching + * will occur. + * COLORFILTER is different from "color killer" and "color effects" + * for reasons above. + */ +#define S2255_V4L2_YC_ON 1 +#define S2255_V4L2_YC_OFF 0 +#define V4L2_CID_PRIVATE_COLORFILTER (V4L2_CID_PRIVATE_BASE + 0) + /* frame prefix size (sent once every frame) */ #define PREFIX_SIZE 512 @@ -360,7 +389,6 @@ static long s2255_vendor_req(struct s2255_dev *dev, unsigned char req, static struct usb_driver s2255_driver; - /* Declare static vars that will be used as parameters */ static unsigned int vid_limit = 16; /* Video memory limit, in Mb */ @@ -375,13 +403,14 @@ module_param(video_nr, int, 0644); MODULE_PARM_DESC(video_nr, "start video minor(-1 default autodetect)"); /* USB device table */ +#define USB_SENSORAY_VID 0x1943 static struct usb_device_id s2255_table[] = { - {USB_DEVICE(USB_S2255_VENDOR_ID, USB_S2255_PRODUCT_ID)}, + {USB_DEVICE(USB_SENSORAY_VID, 0x2255)}, + {USB_DEVICE(USB_SENSORAY_VID, 0x2257)}, /*same family as 2255*/ { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, s2255_table); - #define BUFFER_TIMEOUT msecs_to_jiffies(400) /* image formats. */ @@ -798,6 +827,28 @@ static void res_free(struct s2255_dev *dev, struct s2255_fh *fh) dprintk(1, "res: put\n"); } +static int vidioc_querymenu(struct file *file, void *priv, + struct v4l2_querymenu *qmenu) +{ + static const char *colorfilter[] = { + "Off", + "On", + NULL + }; + if (qmenu->id == V4L2_CID_PRIVATE_COLORFILTER) { + int i; + const char **menu_items = colorfilter; + for (i = 0; i < qmenu->index && menu_items[i]; i++) + ; /* do nothing (from v4l2-common.c) */ + if (menu_items[i] == NULL || menu_items[i][0] == '\0') + return -EINVAL; + strlcpy(qmenu->name, menu_items[qmenu->index], + sizeof(qmenu->name)); + return 0; + } + return v4l2_ctrl_query_menu(qmenu, NULL, NULL); +} + static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) @@ -1007,19 +1058,23 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, /* color mode */ switch (fh->fmt->fourcc) { case V4L2_PIX_FMT_GREY: - fh->mode.color = COLOR_Y8; + fh->mode.color &= ~MASK_COLOR; + fh->mode.color |= COLOR_Y8; break; case V4L2_PIX_FMT_JPEG: - fh->mode.color = COLOR_JPG | - (fh->dev->jc[fh->channel].quality << 8); + fh->mode.color &= ~MASK_COLOR; + fh->mode.color |= COLOR_JPG; + fh->mode.color |= (fh->dev->jc[fh->channel].quality << 8); break; case V4L2_PIX_FMT_YUV422P: - fh->mode.color = COLOR_YUVPL; + fh->mode.color &= ~MASK_COLOR; + fh->mode.color |= COLOR_YUVPL; break; case V4L2_PIX_FMT_YUYV: case V4L2_PIX_FMT_UYVY: default: - fh->mode.color = COLOR_YUVPK; + fh->mode.color &= ~MASK_COLOR; + fh->mode.color |= COLOR_YUVPK; break; } ret = 0; @@ -1186,8 +1241,12 @@ static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn, dprintk(2, "mode contrast %x\n", mode->contrast); /* if JPEG, set the quality */ - if ((mode->color & MASK_COLOR) == COLOR_JPG) - mode->color = (dev->jc[chn].quality << 8) | COLOR_JPG; + if ((mode->color & MASK_COLOR) == COLOR_JPG) { + mode->color &= ~MASK_COLOR; + mode->color |= COLOR_JPG; + mode->color &= ~MASK_JPG_QUALITY; + mode->color |= (dev->jc[chn].quality << 8); + } /* save the mode */ dev->mode[chn] = *mode; @@ -1296,7 +1355,7 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) new_mode = &fh->mode; old_mode = &fh->dev->mode[chn]; - if (new_mode->color != old_mode->color) + if ((new_mode->color & MASK_COLOR) != (old_mode->color & MASK_COLOR)) new_mode->restart = 1; else if (new_mode->scale != old_mode->scale) new_mode->restart = 1; @@ -1354,6 +1413,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i) int ret = 0; mutex_lock(&q->vb_lock); + if (videobuf_queue_is_busy(q)) { dprintk(1, "queue busy\n"); ret = -EBUSY; @@ -1366,7 +1426,6 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i) goto out_s_std; } mode = &fh->mode; - if (*i & V4L2_STD_NTSC) { dprintk(4, "vidioc_s_std NTSC\n"); mode->format = FORMAT_NTSC; @@ -1409,7 +1468,16 @@ static int vidioc_enum_input(struct file *file, void *priv, inp->status = (status & 0x01) ? 0 : V4L2_IN_ST_NO_SIGNAL; } - strlcpy(inp->name, "Camera", sizeof(inp->name)); + switch (dev->pid) { + case 0x2255: + default: + strlcpy(inp->name, "Composite", sizeof(inp->name)); + break; + case 0x2257: + strlcpy(inp->name, (fh->channel < 2) ? "Composite" : "S-Video", + sizeof(inp->name)); + break; + } return 0; } @@ -1429,6 +1497,8 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i) static int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qc) { + struct s2255_fh *fh = priv; + struct s2255_dev *dev = fh->dev; switch (qc->id) { case V4L2_CID_BRIGHTNESS: v4l2_ctrl_query_fill(qc, -127, 127, 1, DEF_BRIGHT); @@ -1442,6 +1512,19 @@ static int vidioc_queryctrl(struct file *file, void *priv, case V4L2_CID_HUE: v4l2_ctrl_query_fill(qc, 0, 255, 1, DEF_HUE); break; + case V4L2_CID_PRIVATE_COLORFILTER: + if (dev->dsp_fw_ver < S2255_MIN_DSP_COLORFILTER) + return -EINVAL; + if ((dev->pid == 0x2257) && (fh->channel > 1)) + return -EINVAL; + strlcpy(qc->name, "Color Filter", sizeof(qc->name)); + qc->type = V4L2_CTRL_TYPE_MENU; + qc->minimum = 0; + qc->maximum = 1; + qc->step = 1; + qc->default_value = 1; + qc->flags = 0; + break; default: return -EINVAL; } @@ -1453,6 +1536,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { struct s2255_fh *fh = priv; + struct s2255_dev *dev = fh->dev; switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: ctrl->value = fh->mode.bright; @@ -1466,6 +1550,13 @@ static int vidioc_g_ctrl(struct file *file, void *priv, case V4L2_CID_HUE: ctrl->value = fh->mode.hue; break; + case V4L2_CID_PRIVATE_COLORFILTER: + if (dev->dsp_fw_ver < S2255_MIN_DSP_COLORFILTER) + return -EINVAL; + if ((dev->pid == 0x2257) && (fh->channel > 1)) + return -EINVAL; + ctrl->value = !((fh->mode.color & MASK_INPUT_TYPE) >> 16); + break; default: return -EINVAL; } @@ -1495,6 +1586,14 @@ static int vidioc_s_ctrl(struct file *file, void *priv, case V4L2_CID_SATURATION: mode->saturation = ctrl->value; break; + case V4L2_CID_PRIVATE_COLORFILTER: + if (dev->dsp_fw_ver < S2255_MIN_DSP_COLORFILTER) + return -EINVAL; + if ((dev->pid == 0x2257) && (fh->channel > 1)) + return -EINVAL; + mode->color &= ~MASK_INPUT_TYPE; + mode->color |= ((ctrl->value ? 0 : 1) << 16); + break; default: return -EINVAL; } @@ -1807,6 +1906,7 @@ static const struct v4l2_file_operations s2255_fops_v4l = { }; static const struct v4l2_ioctl_ops s2255_ioctl_ops = { + .vidioc_querymenu = vidioc_querymenu, .vidioc_querycap = vidioc_querycap, .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, @@ -2230,6 +2330,8 @@ static int s2255_board_init(struct s2255_dev *dev) for (j = 0; j < MAX_CHANNELS; j++) { dev->b_acquire[j] = 0; dev->mode[j] = mode_def; + if (dev->pid == 0x2257 && j > 1) + dev->mode[j].color |= (1 << 16); dev->jc[j].quality = S2255_DEF_JPEG_QUAL; dev->cur_fmt[j] = &formats[0]; dev->mode[j].restart = 1; @@ -2506,7 +2608,7 @@ static int s2255_probe(struct usb_interface *interface, s2255_dev_err(&interface->dev, "out of memory\n"); goto error; } - + dev->pid = id->idProduct; dev->fw_data = kzalloc(sizeof(struct s2255_fw), GFP_KERNEL); if (!dev->fw_data) goto error; @@ -2589,6 +2691,8 @@ static int s2255_probe(struct usb_interface *interface, dev->dsp_fw_ver = *pRel; if (*pRel < S2255_CUR_DSP_FWVER) printk(KERN_INFO "s2255: f2255usb.bin out of date.\n"); + if (dev->pid == 0x2257 && *pRel < S2255_MIN_DSP_COLORFILTER) + printk(KERN_WARNING "s2255: 2257 requires firmware 8 or above.\n"); } /* loads v4l specific */ s2255_probe_v4l(dev); -- cgit v1.2.3-70-g09d2 From 2ffbb64c671261c80703cd8b7fec5ebd21e58b0c Mon Sep 17 00:00:00 2001 From: Dmitri Belimov Date: Thu, 4 Mar 2010 02:40:37 -0300 Subject: V4L/DVB: fix broken I2C IR for Beholder Fix broken I2C IR for TV cards of Beholder. Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-input.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 58a0cdc8414..a2b16693ee9 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -837,6 +837,7 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) dev->init_data.name = "BeholdTV"; dev->init_data.get_key = get_key_beholdm6xx; dev->init_data.ir_codes = &ir_codes_behold_table; + dev->init_data.type = IR_TYPE_NEC; info.addr = 0x2d; break; case SAA7134_BOARD_AVERMEDIA_CARDBUS_501: -- cgit v1.2.3-70-g09d2 From e7c3ee6302ef0dde86c1918bae3b0783839e6a39 Mon Sep 17 00:00:00 2001 From: Márton Németh Date: Sun, 7 Mar 2010 03:33:45 -0300 Subject: V4L/DVB: gspca cpia1: make local functions static MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the local functions static. Note that the function command_setlights() is currently not called from anywhere. This will remove the following sparse warnings (see "make C=1"): * symbol 'command_setformat' was not declared. Should it be static? * symbol 'command_setcolourparams' was not declared. Should it be static? * symbol 'command_setapcor' was not declared. Should it be static? * symbol 'command_setvloffset' was not declared. Should it be static? * symbol 'command_setexposure' was not declared. Should it be static? * symbol 'command_setcolourbalance' was not declared. Should it be static? * symbol 'command_setcompressiontarget' was not declared. Should it be static? * symbol 'command_setyuvtresh' was not declared. Should it be static? * symbol 'command_setcompressionparams' was not declared. Should it be static? * symbol 'command_setcompression' was not declared. Should it be static? * symbol 'command_setsensorfps' was not declared. Should it be static? * symbol 'command_setflickerctrl' was not declared. Should it be static? * symbol 'command_setecptiming' was not declared. Should it be static? * symbol 'command_pause' was not declared. Should it be static? * symbol 'command_resume' was not declared. Should it be static? * symbol 'command_setlights' was not declared. Should it be static? Signed-off-by: Márton Németh Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/cpia1.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/cpia1.c b/drivers/media/video/gspca/cpia1.c index 8fa98439c3f..92879c072e9 100644 --- a/drivers/media/video/gspca/cpia1.c +++ b/drivers/media/video/gspca/cpia1.c @@ -861,7 +861,7 @@ static int save_camera_state(struct gspca_dev *gspca_dev) return do_command(gspca_dev, CPIA_COMMAND_GetExposure, 0, 0, 0, 0); } -int command_setformat(struct gspca_dev *gspca_dev) +static int command_setformat(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int ret; @@ -878,7 +878,7 @@ int command_setformat(struct gspca_dev *gspca_dev) sd->params.roi.rowStart, sd->params.roi.rowEnd); } -int command_setcolourparams(struct gspca_dev *gspca_dev) +static int command_setcolourparams(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; return do_command(gspca_dev, CPIA_COMMAND_SetColourParams, @@ -887,7 +887,7 @@ int command_setcolourparams(struct gspca_dev *gspca_dev) sd->params.colourParams.saturation, 0); } -int command_setapcor(struct gspca_dev *gspca_dev) +static int command_setapcor(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; return do_command(gspca_dev, CPIA_COMMAND_SetApcor, @@ -897,7 +897,7 @@ int command_setapcor(struct gspca_dev *gspca_dev) sd->params.apcor.gain8); } -int command_setvloffset(struct gspca_dev *gspca_dev) +static int command_setvloffset(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; return do_command(gspca_dev, CPIA_COMMAND_SetVLOffset, @@ -907,7 +907,7 @@ int command_setvloffset(struct gspca_dev *gspca_dev) sd->params.vlOffset.gain8); } -int command_setexposure(struct gspca_dev *gspca_dev) +static int command_setexposure(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int ret; @@ -943,7 +943,7 @@ int command_setexposure(struct gspca_dev *gspca_dev) return ret; } -int command_setcolourbalance(struct gspca_dev *gspca_dev) +static int command_setcolourbalance(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -973,7 +973,7 @@ int command_setcolourbalance(struct gspca_dev *gspca_dev) return -EINVAL; } -int command_setcompressiontarget(struct gspca_dev *gspca_dev) +static int command_setcompressiontarget(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -983,7 +983,7 @@ int command_setcompressiontarget(struct gspca_dev *gspca_dev) sd->params.compressionTarget.targetQ, 0); } -int command_setyuvtresh(struct gspca_dev *gspca_dev) +static int command_setyuvtresh(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -992,7 +992,7 @@ int command_setyuvtresh(struct gspca_dev *gspca_dev) sd->params.yuvThreshold.uvThreshold, 0, 0); } -int command_setcompressionparams(struct gspca_dev *gspca_dev) +static int command_setcompressionparams(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -1009,7 +1009,7 @@ int command_setcompressionparams(struct gspca_dev *gspca_dev) sd->params.compressionParams.decimationThreshMod); } -int command_setcompression(struct gspca_dev *gspca_dev) +static int command_setcompression(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -1018,7 +1018,7 @@ int command_setcompression(struct gspca_dev *gspca_dev) sd->params.compression.decimation, 0, 0); } -int command_setsensorfps(struct gspca_dev *gspca_dev) +static int command_setsensorfps(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -1027,7 +1027,7 @@ int command_setsensorfps(struct gspca_dev *gspca_dev) sd->params.sensorFps.baserate, 0, 0); } -int command_setflickerctrl(struct gspca_dev *gspca_dev) +static int command_setflickerctrl(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -1038,7 +1038,7 @@ int command_setflickerctrl(struct gspca_dev *gspca_dev) 0); } -int command_setecptiming(struct gspca_dev *gspca_dev) +static int command_setecptiming(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -1046,12 +1046,12 @@ int command_setecptiming(struct gspca_dev *gspca_dev) sd->params.ecpTiming, 0, 0, 0); } -int command_pause(struct gspca_dev *gspca_dev) +static int command_pause(struct gspca_dev *gspca_dev) { return do_command(gspca_dev, CPIA_COMMAND_EndStreamCap, 0, 0, 0, 0); } -int command_resume(struct gspca_dev *gspca_dev) +static int command_resume(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -1059,7 +1059,7 @@ int command_resume(struct gspca_dev *gspca_dev) 0, sd->params.streamStartLine, 0, 0); } -int command_setlights(struct gspca_dev *gspca_dev) +static int command_setlights(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int ret, p1, p2; -- cgit v1.2.3-70-g09d2 From e6b44bc521b48048e3089ed773950867e409f886 Mon Sep 17 00:00:00 2001 From: Dean Anderson Date: Mon, 8 Mar 2010 20:04:48 -0300 Subject: V4L/DVB: s2255drv: support for frame skipping adds hardware frame skipping using VIDIOC_S_PARM ioctl. adds support for VIDIOC_ENUM_FRAMEINTERVALS. Signed-off-by: Dean Anderson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s2255drv.c | 113 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 105 insertions(+), 8 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index 745f557200a..0092ff52bb2 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c @@ -1427,11 +1427,19 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i) } mode = &fh->mode; if (*i & V4L2_STD_NTSC) { - dprintk(4, "vidioc_s_std NTSC\n"); - mode->format = FORMAT_NTSC; + dprintk(4, "%s NTSC\n", __func__); + /* if changing format, reset frame decimation/intervals */ + if (mode->format != FORMAT_NTSC) { + mode->format = FORMAT_NTSC; + mode->fdec = FDEC_1; + } } else if (*i & V4L2_STD_PAL) { - dprintk(4, "vidioc_s_std PAL\n"); + dprintk(4, "%s PAL\n", __func__); mode->format = FORMAT_PAL; + if (mode->format != FORMAT_PAL) { + mode->format = FORMAT_PAL; + mode->fdec = FDEC_1; + } } else { ret = -EINVAL; } @@ -1633,10 +1641,34 @@ static int vidioc_g_parm(struct file *file, void *priv, { struct s2255_fh *fh = priv; struct s2255_dev *dev = fh->dev; + __u32 def_num, def_dem; if (sp->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; + memset(sp, 0, sizeof(struct v4l2_streamparm)); + sp->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; sp->parm.capture.capturemode = dev->cap_parm[fh->channel].capturemode; - dprintk(2, "getting parm %d\n", sp->parm.capture.capturemode); + def_num = (fh->mode.format == FORMAT_NTSC) ? 1001 : 1000; + def_dem = (fh->mode.format == FORMAT_NTSC) ? 30000 : 25000; + sp->parm.capture.timeperframe.denominator = def_dem; + switch (fh->mode.fdec) { + default: + case FDEC_1: + sp->parm.capture.timeperframe.numerator = def_num; + break; + case FDEC_2: + sp->parm.capture.timeperframe.numerator = def_num * 2; + break; + case FDEC_3: + sp->parm.capture.timeperframe.numerator = def_num * 3; + break; + case FDEC_5: + sp->parm.capture.timeperframe.numerator = def_num * 5; + break; + } + dprintk(4, "%s capture mode, %d timeperframe %d/%d\n", __func__, + sp->parm.capture.capturemode, + sp->parm.capture.timeperframe.numerator, + sp->parm.capture.timeperframe.denominator); return 0; } @@ -1645,15 +1677,79 @@ static int vidioc_s_parm(struct file *file, void *priv, { struct s2255_fh *fh = priv; struct s2255_dev *dev = fh->dev; - + int fdec = FDEC_1; + __u32 def_num, def_dem; if (sp->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; + /* high quality capture mode requires a stream restart */ + if (dev->cap_parm[fh->channel].capturemode + != sp->parm.capture.capturemode && res_locked(fh->dev, fh)) + return -EBUSY; + def_num = (fh->mode.format == FORMAT_NTSC) ? 1001 : 1000; + def_dem = (fh->mode.format == FORMAT_NTSC) ? 30000 : 25000; + if (def_dem != sp->parm.capture.timeperframe.denominator) + sp->parm.capture.timeperframe.numerator = def_num; + else if (sp->parm.capture.timeperframe.numerator <= def_num) + sp->parm.capture.timeperframe.numerator = def_num; + else if (sp->parm.capture.timeperframe.numerator <= (def_num * 2)) { + sp->parm.capture.timeperframe.numerator = def_num * 2; + fdec = FDEC_2; + } else if (sp->parm.capture.timeperframe.numerator <= (def_num * 3)) { + sp->parm.capture.timeperframe.numerator = def_num * 3; + fdec = FDEC_3; + } else { + sp->parm.capture.timeperframe.numerator = def_num * 5; + fdec = FDEC_5; + } + fh->mode.fdec = fdec; + sp->parm.capture.timeperframe.denominator = def_dem; + s2255_set_mode(dev, fh->channel, &fh->mode); + dprintk(4, "%s capture mode, %d timeperframe %d/%d, fdec %d\n", + __func__, + sp->parm.capture.capturemode, + sp->parm.capture.timeperframe.numerator, + sp->parm.capture.timeperframe.denominator, fdec); + return 0; +} - dev->cap_parm[fh->channel].capturemode = sp->parm.capture.capturemode; - dprintk(2, "setting param capture mode %d\n", - sp->parm.capture.capturemode); +static int vidioc_enum_frameintervals(struct file *file, void *priv, + struct v4l2_frmivalenum *fe) +{ + int is_ntsc = 0; +#define NUM_FRAME_ENUMS 4 + int frm_dec[NUM_FRAME_ENUMS] = {1, 2, 3, 5}; + if (fe->index < 0 || fe->index >= NUM_FRAME_ENUMS) + return -EINVAL; + switch (fe->width) { + case 640: + if (fe->height != 240 && fe->height != 480) + return -EINVAL; + is_ntsc = 1; + break; + case 320: + if (fe->height != 240) + return -EINVAL; + is_ntsc = 1; + break; + case 704: + if (fe->height != 288 && fe->height != 576) + return -EINVAL; + break; + case 352: + if (fe->height != 288) + return -EINVAL; + break; + default: + return -EINVAL; + } + fe->type = V4L2_FRMIVAL_TYPE_DISCRETE; + fe->discrete.denominator = is_ntsc ? 30000 : 25000; + fe->discrete.numerator = (is_ntsc ? 1001 : 1000) * frm_dec[fe->index]; + dprintk(4, "%s discrete %d/%d\n", __func__, fe->discrete.numerator, + fe->discrete.denominator); return 0; } + static int s2255_open(struct file *file) { struct video_device *vdev = video_devdata(file); @@ -1932,6 +2028,7 @@ static const struct v4l2_ioctl_ops s2255_ioctl_ops = { .vidioc_g_jpegcomp = vidioc_g_jpegcomp, .vidioc_s_parm = vidioc_s_parm, .vidioc_g_parm = vidioc_g_parm, + .vidioc_enum_frameintervals = vidioc_enum_frameintervals, }; static struct video_device template = { -- cgit v1.2.3-70-g09d2 From 2a8f96085449f3aa6fe99b27d7ee506e808059b9 Mon Sep 17 00:00:00 2001 From: Abylay Ospan Date: Sat, 6 Mar 2010 15:46:39 -0300 Subject: V4L/DVB: configurable IRQ from CAM IRQ from CAM disabled by default. In some environment enabled IRQ can cause of machine freeze. Signed-off-by: Abylay Ospan Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx23885/cimax2.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx23885/cimax2.c b/drivers/media/video/cx23885/cimax2.c index d4a9d2c5947..c95e7bc1474 100644 --- a/drivers/media/video/cx23885/cimax2.c +++ b/drivers/media/video/cx23885/cimax2.c @@ -60,12 +60,18 @@ static unsigned int ci_dbg; module_param(ci_dbg, int, 0644); MODULE_PARM_DESC(ci_dbg, "Enable CI debugging"); +static unsigned int ci_irq_enable; +module_param(ci_irq_enable, int, 0644); +MODULE_PARM_DESC(ci_irq_enable, "Enable IRQ from CAM"); + #define ci_dbg_print(args...) \ do { \ if (ci_dbg) \ printk(KERN_DEBUG args); \ } while (0) +#define ci_irq_flags() (ci_irq_enable ? NETUP_IRQ_IRQAM : 0) + /* stores all private variables for communication with CI */ struct netup_ci_state { struct dvb_ca_en50221 ca; @@ -392,7 +398,7 @@ int netup_poll_ci_slot_status(struct dvb_ca_en50221 *en50221, int slot, int open if (0 != slot) return -EINVAL; - netup_ci_set_irq(en50221, open ? (NETUP_IRQ_DETAM | NETUP_IRQ_IRQAM) + netup_ci_set_irq(en50221, open ? (NETUP_IRQ_DETAM | ci_irq_flags()) : NETUP_IRQ_DETAM); return state->status; @@ -429,7 +435,7 @@ int netup_ci_init(struct cx23885_tsport *port) 0x01, /* power on (use it like store place) */ 0x00, /* RFU */ 0x00, /* int status read only */ - NETUP_IRQ_IRQAM | NETUP_IRQ_DETAM, /* DETAM, IRQAM unmasked */ + ci_irq_flags() | NETUP_IRQ_DETAM, /* DETAM, IRQAM unmasked */ 0x05, /* EXTINT=active-high, INT=push-pull */ 0x00, /* USCG1 */ 0x04, /* ack active low */ @@ -470,7 +476,7 @@ int netup_ci_init(struct cx23885_tsport *port) state->ca.poll_slot_status = netup_poll_ci_slot_status; state->ca.data = state; state->priv = port; - state->current_irq_mode = NETUP_IRQ_IRQAM | NETUP_IRQ_DETAM; + state->current_irq_mode = ci_irq_flags() | NETUP_IRQ_DETAM; ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr, 0, &cimax_init[0], 34); -- cgit v1.2.3-70-g09d2 From 283328c29db4463c31ee59f9ab418449cfa376b3 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 6 Mar 2010 21:08:35 -0300 Subject: V4L/DVB: ivtv: Combine capture start delays into a single delay Combine the two 150 ms delays into a single 300 ms delay. Ian Armstrong has noted that the delay between CX2341X_ENC_INITIALIZE_INPUT and CX2341X_ENC_START_CAPTURE can cause problems if the temporal filter is allowed to be enabled. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtv-streams.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c index 1f9387f6ca2..a994b0adb44 100644 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ b/drivers/media/video/ivtv/ivtv-streams.c @@ -581,10 +581,9 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s) v4l2_subdev_call(itv->sd_audio, audio, s_stream, 1); /* Avoid unpredictable PCI bus hang - disable video clocks */ v4l2_subdev_call(itv->sd_video, video, s_stream, 0); - ivtv_msleep_timeout(150, 1); + ivtv_msleep_timeout(300, 1); ivtv_vapi(itv, CX2341X_ENC_INITIALIZE_INPUT, 0); v4l2_subdev_call(itv->sd_video, video, s_stream, 1); - ivtv_msleep_timeout(150, 1); } /* begin_capture */ -- cgit v1.2.3-70-g09d2 From 9a766d55b72a439b2e16ecf2ac3eb831ab25e0d3 Mon Sep 17 00:00:00 2001 From: Ian Armstrong Date: Sat, 6 Mar 2010 21:37:04 -0300 Subject: V4L/DVB: ivtv: Really stop capture on device close When a capture is started, the firmware also appears to start a secondary stream. Unless this secondary stream is also stopped, the encoder will remain active and not reinitialise for the next capture. Unfortunately, setting up the video source can glitch the encoder and result in undesirable effects that this initialisation will clear. Signed-off-by: Ian Armstrong Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtv-streams.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c index a994b0adb44..6917c497fb7 100644 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ b/drivers/media/video/ivtv/ivtv-streams.c @@ -829,6 +829,10 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end) ivtv_set_irq_mask(itv, IVTV_IRQ_ENC_VIM_RST); } + /* Raw-passthrough is implied on start. Make sure it's stopped so + the encoder will re-initialize when next started */ + ivtv_vapi(itv, CX2341X_ENC_STOP_CAPTURE, 3, 1, 2, 7); + wake_up(&s->waitq); return 0; -- cgit v1.2.3-70-g09d2 From 947f04cba2159ff731a59766b05a643536eb6262 Mon Sep 17 00:00:00 2001 From: Ian Armstrong Date: Sat, 6 Mar 2010 21:43:04 -0300 Subject: V4L/DVB: cx2341x: Remove temporal filter control restriction Since the change that stops the CX23415/6 firmware-intiiated secondary stream appears to fix the temporal filter, it's now fully re-enabled for all capture resolutions. Signed-off-by: Ian Armstrong Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx2341x.c | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx2341x.c b/drivers/media/video/cx2341x.c index 4c8e95853fa..022b480918c 100644 --- a/drivers/media/video/cx2341x.c +++ b/drivers/media/video/cx2341x.c @@ -1000,20 +1000,6 @@ int cx2341x_update(void *priv, cx2341x_mbox_func func, h, w); if (err) return err; } - - if (new->width != 720 || new->height != (new->is_50hz ? 576 : 480)) { - /* Adjust temporal filter if necessary. The problem with the - temporal filter is that it works well with full resolution - capturing, but not when the capture window is scaled (the - filter introduces a ghosting effect). So if the capture - window is scaled, then force the filter to 0. - - For full resolution the filter really improves the video - quality, especially if the original video quality is - suboptimal. */ - temporal = 0; - } - if (force || NEQ(stream_type)) { err = cx2341x_api(priv, func, CX2341X_ENC_SET_STREAM_TYPE, 1, mpeg_stream_type[new->stream_type]); -- cgit v1.2.3-70-g09d2 From c3f52f630d067c7590ed438bfb0a82bcb91e0b21 Mon Sep 17 00:00:00 2001 From: Max Thrun Date: Sat, 27 Feb 2010 17:20:18 -0300 Subject: V4L/DVB: gspca- ov534: Remove ambiguous controls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove Blue/Red Channel Target Value, they are meant for Black Level Calibration but it is not completely clear how to use them. Signed-off-by: Max Thrun Signed-off-by: Antonio Ospite Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/ov534.c | 100 +++----------------------------------- 1 file changed, 6 insertions(+), 94 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index 957e05e2d08..2a0e8a3e794 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c @@ -60,8 +60,6 @@ struct sd { u8 contrast; u8 gain; u8 exposure; - u8 redblc; - u8 blueblc; u8 hue; u8 autogain; u8 awb; @@ -76,10 +74,6 @@ static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); -static int sd_setredblc(struct gspca_dev *gspca_dev, __s32 val); -static int sd_getredblc(struct gspca_dev *gspca_dev, __s32 *val); -static int sd_setblueblc(struct gspca_dev *gspca_dev, __s32 val); -static int sd_getblueblc(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val); @@ -155,34 +149,6 @@ static const struct ctrl sd_ctrls[] = { .get = sd_getexposure, }, { /* 4 */ - { - .id = V4L2_CID_RED_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Red Balance", - .minimum = 0, - .maximum = 255, - .step = 1, -#define RED_BALANCE_DEF 128 - .default_value = RED_BALANCE_DEF, - }, - .set = sd_setredblc, - .get = sd_getredblc, - }, - { /* 5 */ - { - .id = V4L2_CID_BLUE_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Blue Balance", - .minimum = 0, - .maximum = 255, - .step = 1, -#define BLUE_BALANCE_DEF 128 - .default_value = BLUE_BALANCE_DEF, - }, - .set = sd_setblueblc, - .get = sd_getblueblc, - }, - { /* 6 */ { .id = V4L2_CID_HUE, .type = V4L2_CTRL_TYPE_INTEGER, @@ -196,7 +162,7 @@ static const struct ctrl sd_ctrls[] = { .set = sd_sethue, .get = sd_gethue, }, - { /* 7 */ + { /* 5 */ { .id = V4L2_CID_AUTOGAIN, .type = V4L2_CTRL_TYPE_BOOLEAN, @@ -210,8 +176,8 @@ static const struct ctrl sd_ctrls[] = { .set = sd_setautogain, .get = sd_getautogain, }, -#define AWB_IDX 8 - { /* 8 */ +#define AWB_IDX 6 + { /* 6 */ { .id = V4L2_CID_AUTO_WHITE_BALANCE, .type = V4L2_CTRL_TYPE_BOOLEAN, @@ -225,7 +191,7 @@ static const struct ctrl sd_ctrls[] = { .set = sd_setawb, .get = sd_getawb, }, - { /* 9 */ + { /* 7 */ { .id = V4L2_CID_SHARPNESS, .type = V4L2_CTRL_TYPE_INTEGER, @@ -239,7 +205,7 @@ static const struct ctrl sd_ctrls[] = { .set = sd_setsharpness, .get = sd_getsharpness, }, - { /* 10 */ + { /* 8 */ { .id = V4L2_CID_HFLIP, .type = V4L2_CTRL_TYPE_BOOLEAN, @@ -253,7 +219,7 @@ static const struct ctrl sd_ctrls[] = { .set = sd_sethflip, .get = sd_gethflip, }, - { /* 11 */ + { /* 9 */ { .id = V4L2_CID_VFLIP, .type = V4L2_CTRL_TYPE_BOOLEAN, @@ -722,20 +688,6 @@ static void setexposure(struct gspca_dev *gspca_dev) sccb_reg_write(gspca_dev, 0x10, val << 1); } -static void setredblc(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sccb_reg_write(gspca_dev, 0x43, sd->redblc); -} - -static void setblueblc(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sccb_reg_write(gspca_dev, 0x42, sd->blueblc); -} - static void sethue(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -825,8 +777,6 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->contrast = CONTRAST_DEF; sd->gain = GAIN_DEF; sd->exposure = EXPO_DEF; - sd->redblc = RED_BALANCE_DEF; - sd->blueblc = BLUE_BALANCE_DEF; sd->hue = HUE_DEF; #if AUTOGAIN_DEF != 0 sd->autogain = AUTOGAIN_DEF; @@ -907,8 +857,6 @@ static int sd_start(struct gspca_dev *gspca_dev) setautogain(gspca_dev); setawb(gspca_dev); setgain(gspca_dev); - setredblc(gspca_dev); - setblueblc(gspca_dev); sethue(gspca_dev); setexposure(gspca_dev); setbrightness(gspca_dev); @@ -1092,42 +1040,6 @@ static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) return 0; } -static int sd_setredblc(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->redblc = val; - if (gspca_dev->streaming) - setredblc(gspca_dev); - return 0; -} - -static int sd_getredblc(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - *val = sd->redblc; - return 0; -} - -static int sd_setblueblc(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->blueblc = val; - if (gspca_dev->streaming) - setblueblc(gspca_dev); - return 0; -} - -static int sd_getblueblc(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - *val = sd->blueblc; - return 0; -} - static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; -- cgit v1.2.3-70-g09d2 From 0c41acf158b61577dd8e50ba00f3cadabdc3c756 Mon Sep 17 00:00:00 2001 From: Antonio Ospite Date: Sat, 27 Feb 2010 17:20:19 -0300 Subject: V4L/DVB: gspca - ov534: Remove hue control MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hue control doesn't work and the sensor datasheet is not clear about how to set hue properly. Signed-off-by: Antonio Ospite Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/ov534.c | 54 ++++----------------------------------- 1 file changed, 5 insertions(+), 49 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index 2a0e8a3e794..186827a0d27 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c @@ -60,7 +60,6 @@ struct sd { u8 contrast; u8 gain; u8 exposure; - u8 hue; u8 autogain; u8 awb; s8 sharpness; @@ -82,8 +81,6 @@ static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val); static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val); -static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val); -static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setawb(struct gspca_dev *gspca_dev, __s32 val); static int sd_getawb(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); @@ -149,20 +146,6 @@ static const struct ctrl sd_ctrls[] = { .get = sd_getexposure, }, { /* 4 */ - { - .id = V4L2_CID_HUE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Hue", - .minimum = 0, - .maximum = 255, - .step = 1, -#define HUE_DEF 143 - .default_value = HUE_DEF, - }, - .set = sd_sethue, - .get = sd_gethue, - }, - { /* 5 */ { .id = V4L2_CID_AUTOGAIN, .type = V4L2_CTRL_TYPE_BOOLEAN, @@ -176,8 +159,8 @@ static const struct ctrl sd_ctrls[] = { .set = sd_setautogain, .get = sd_getautogain, }, -#define AWB_IDX 6 - { /* 6 */ +#define AWB_IDX 5 + { /* 5 */ { .id = V4L2_CID_AUTO_WHITE_BALANCE, .type = V4L2_CTRL_TYPE_BOOLEAN, @@ -191,7 +174,7 @@ static const struct ctrl sd_ctrls[] = { .set = sd_setawb, .get = sd_getawb, }, - { /* 7 */ + { /* 6 */ { .id = V4L2_CID_SHARPNESS, .type = V4L2_CTRL_TYPE_INTEGER, @@ -205,7 +188,7 @@ static const struct ctrl sd_ctrls[] = { .set = sd_setsharpness, .get = sd_getsharpness, }, - { /* 8 */ + { /* 7 */ { .id = V4L2_CID_HFLIP, .type = V4L2_CTRL_TYPE_BOOLEAN, @@ -219,7 +202,7 @@ static const struct ctrl sd_ctrls[] = { .set = sd_sethflip, .get = sd_gethflip, }, - { /* 9 */ + { /* 8 */ { .id = V4L2_CID_VFLIP, .type = V4L2_CTRL_TYPE_BOOLEAN, @@ -688,13 +671,6 @@ static void setexposure(struct gspca_dev *gspca_dev) sccb_reg_write(gspca_dev, 0x10, val << 1); } -static void sethue(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sccb_reg_write(gspca_dev, 0x01, sd->hue); -} - static void setautogain(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -777,7 +753,6 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->contrast = CONTRAST_DEF; sd->gain = GAIN_DEF; sd->exposure = EXPO_DEF; - sd->hue = HUE_DEF; #if AUTOGAIN_DEF != 0 sd->autogain = AUTOGAIN_DEF; #else @@ -857,7 +832,6 @@ static int sd_start(struct gspca_dev *gspca_dev) setautogain(gspca_dev); setawb(gspca_dev); setgain(gspca_dev); - sethue(gspca_dev); setexposure(gspca_dev); setbrightness(gspca_dev); setcontrast(gspca_dev); @@ -1040,24 +1014,6 @@ static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) return 0; } -static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->hue = val; - if (gspca_dev->streaming) - sethue(gspca_dev); - return 0; -} - -static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - *val = sd->hue; - return 0; -} - static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; -- cgit v1.2.3-70-g09d2 From 8b7fbda484176b46a7760fd474d605ca5152c86d Mon Sep 17 00:00:00 2001 From: Max Thrun Date: Sat, 27 Feb 2010 17:20:20 -0300 Subject: V4L/DVB: gspca - ov534: Fix autogain control, enable it by default MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Use 'agc' instead of 'autogain' in the code so to align the naming as in AEC/AWB. * Tweak brightness and contrast default values. * Fix setting/resetting registers values for AGC. * Set actual gain back when disabling AGC. * Skip setting GAIN register when AGC is enabled. * Enable AGC by default. Note that as Auto Gain Control is now enabled by default, if you are using the driver for visual computing applications you might need to disable it explicitly in your software. Signed-off-by: Max Thrun Signed-off-by: Antonio Ospite Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/ov534.c | 53 ++++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 23 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index 186827a0d27..4058e224d6a 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c @@ -60,7 +60,7 @@ struct sd { u8 contrast; u8 gain; u8 exposure; - u8 autogain; + u8 agc; u8 awb; s8 sharpness; u8 hflip; @@ -73,8 +73,8 @@ static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); -static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); -static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); +static int sd_setagc(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getagc(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val); static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val); @@ -97,7 +97,7 @@ static const struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 255, .step = 1, -#define BRIGHTNESS_DEF 20 +#define BRIGHTNESS_DEF 0 .default_value = BRIGHTNESS_DEF, }, .set = sd_setbrightness, @@ -111,7 +111,7 @@ static const struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 255, .step = 1, -#define CONTRAST_DEF 37 +#define CONTRAST_DEF 32 .default_value = CONTRAST_DEF, }, .set = sd_setcontrast, @@ -149,15 +149,15 @@ static const struct ctrl sd_ctrls[] = { { .id = V4L2_CID_AUTOGAIN, .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "Autogain", + .name = "Auto Gain", .minimum = 0, .maximum = 1, .step = 1, -#define AUTOGAIN_DEF 0 - .default_value = AUTOGAIN_DEF, +#define AGC_DEF 1 + .default_value = AGC_DEF, }, - .set = sd_setautogain, - .get = sd_getautogain, + .set = sd_setagc, + .get = sd_getagc, }, #define AWB_IDX 5 { /* 5 */ @@ -639,6 +639,9 @@ static void setgain(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; u8 val; + if (sd->agc) + return; + val = sd->gain; switch (val & 0x30) { case 0x00: @@ -671,18 +674,22 @@ static void setexposure(struct gspca_dev *gspca_dev) sccb_reg_write(gspca_dev, 0x10, val << 1); } -static void setautogain(struct gspca_dev *gspca_dev) +static void setagc(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - if (sd->autogain) { - sccb_reg_write(gspca_dev, 0x13, 0xf7); /* AGC,AEC,AWB ON */ + if (sd->agc) { + sccb_reg_write(gspca_dev, 0x13, + sccb_reg_read(gspca_dev, 0x13) | 0x04); sccb_reg_write(gspca_dev, 0x64, sccb_reg_read(gspca_dev, 0x64) | 0x03); } else { - sccb_reg_write(gspca_dev, 0x13, 0xf0); /* AGC,AEC,AWB OFF */ + sccb_reg_write(gspca_dev, 0x13, + sccb_reg_read(gspca_dev, 0x13) & ~0x04); sccb_reg_write(gspca_dev, 0x64, - sccb_reg_read(gspca_dev, 0x64) & 0xfc); + sccb_reg_read(gspca_dev, 0x64) & ~0x03); + + setgain(gspca_dev); } } @@ -753,8 +760,8 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->contrast = CONTRAST_DEF; sd->gain = GAIN_DEF; sd->exposure = EXPO_DEF; -#if AUTOGAIN_DEF != 0 - sd->autogain = AUTOGAIN_DEF; +#if AGC_DEF != 0 + sd->agc = AGC_DEF; #else gspca_dev->ctrl_inac |= (1 << AWB_IDX); #endif @@ -829,7 +836,7 @@ static int sd_start(struct gspca_dev *gspca_dev) } set_frame_rate(gspca_dev); - setautogain(gspca_dev); + setagc(gspca_dev); setawb(gspca_dev); setgain(gspca_dev); setexposure(gspca_dev); @@ -1014,11 +1021,11 @@ static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) return 0; } -static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) +static int sd_setagc(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; - sd->autogain = val; + sd->agc = val; if (gspca_dev->streaming) { @@ -1028,16 +1035,16 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) gspca_dev->ctrl_inac &= ~(1 << AWB_IDX); else gspca_dev->ctrl_inac |= (1 << AWB_IDX); - setautogain(gspca_dev); + setagc(gspca_dev); } return 0; } -static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) +static int sd_getagc(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; - *val = sd->autogain; + *val = sd->agc; return 0; } -- cgit v1.2.3-70-g09d2 From f2938822523739e99a39fd634943865a432e9c00 Mon Sep 17 00:00:00 2001 From: Max Thrun Date: Sat, 27 Feb 2010 17:20:21 -0300 Subject: V4L/DVB: gspca - ov534: Add Auto Exposure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This also makes manual exposure actually work: it never worked before because AEC was always enabled. Signed-off-by: Max Thrun Signed-off-by: Antonio Ospite Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/ov534.c | 55 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index 4058e224d6a..2d896500307 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c @@ -62,6 +62,7 @@ struct sd { u8 exposure; u8 agc; u8 awb; + u8 aec; s8 sharpness; u8 hflip; u8 vflip; @@ -83,6 +84,8 @@ static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setawb(struct gspca_dev *gspca_dev, __s32 val); static int sd_getawb(struct gspca_dev *gspca_dev, __s32 *val); +static int sd_setaec(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getaec(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); @@ -175,6 +178,20 @@ static const struct ctrl sd_ctrls[] = { .get = sd_getawb, }, { /* 6 */ + { + .id = V4L2_CID_EXPOSURE_AUTO, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Auto Exposure", + .minimum = 0, + .maximum = 1, + .step = 1, +#define AEC_DEF 1 + .default_value = AEC_DEF, + }, + .set = sd_setaec, + .get = sd_getaec, + }, + { /* 7 */ { .id = V4L2_CID_SHARPNESS, .type = V4L2_CTRL_TYPE_INTEGER, @@ -188,7 +205,7 @@ static const struct ctrl sd_ctrls[] = { .set = sd_setsharpness, .get = sd_getsharpness, }, - { /* 7 */ + { /* 8 */ { .id = V4L2_CID_HFLIP, .type = V4L2_CTRL_TYPE_BOOLEAN, @@ -202,7 +219,7 @@ static const struct ctrl sd_ctrls[] = { .set = sd_sethflip, .get = sd_gethflip, }, - { /* 8 */ + { /* 9 */ { .id = V4L2_CID_VFLIP, .type = V4L2_CTRL_TYPE_BOOLEAN, @@ -703,6 +720,20 @@ static void setawb(struct gspca_dev *gspca_dev) sccb_reg_write(gspca_dev, 0x63, 0xaa); /* AWB off */ } +static void setaec(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + + if (sd->aec) + sccb_reg_write(gspca_dev, 0x13, + sccb_reg_read(gspca_dev, 0x13) | 0x01); + else { + sccb_reg_write(gspca_dev, 0x13, + sccb_reg_read(gspca_dev, 0x13) & ~0x01); + setexposure(gspca_dev); + } +} + static void setsharpness(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -768,6 +799,7 @@ static int sd_config(struct gspca_dev *gspca_dev, #if AWB_DEF != 0 sd->awb = AWB_DEF #endif + sd->aec = AEC_DEF; #if SHARPNESS_DEF != 0 sd->sharpness = SHARPNESS_DEF; #endif @@ -838,6 +870,7 @@ static int sd_start(struct gspca_dev *gspca_dev) setagc(gspca_dev); setawb(gspca_dev); + setaec(gspca_dev); setgain(gspca_dev); setexposure(gspca_dev); setbrightness(gspca_dev); @@ -1066,6 +1099,24 @@ static int sd_getawb(struct gspca_dev *gspca_dev, __s32 *val) return 0; } +static int sd_setaec(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->aec = val; + if (gspca_dev->streaming) + setaec(gspca_dev); + return 0; +} + +static int sd_getaec(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->aec; + return 0; +} + static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; -- cgit v1.2.3-70-g09d2 From 18cf8c91ad558f8d2d0177656df493f81949cfe6 Mon Sep 17 00:00:00 2001 From: Antonio Ospite Date: Mon, 1 Mar 2010 08:53:34 -0300 Subject: V4L/DVB: gspca - ov534: Fix and document setting manual exposure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Document that even if the state is a u8 value, both MSB and LSB are set as sd->exposure represents half of the value we are going to set into registers. Skip setting exposure when AEC is enabled. Signed-off-by: Antonio Ospite Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/ov534.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index 2d896500307..4fda0980be0 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c @@ -686,6 +686,15 @@ static void setexposure(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; u8 val; + if (sd->aec) + return; + + /* 'val' is one byte and represents half of the exposure value we are + * going to set into registers, a two bytes value: + * + * MSB: ((u16) val << 1) >> 8 == val >> 7 + * LSB: ((u16) val << 1) & 0xff == val << 1 + */ val = sd->exposure; sccb_reg_write(gspca_dev, 0x08, val >> 7); sccb_reg_write(gspca_dev, 0x10, val << 1); -- cgit v1.2.3-70-g09d2 From 8fef9d962237e29b3d84243387b1f3487b3caaf4 Mon Sep 17 00:00:00 2001 From: Max Thrun Date: Sat, 27 Feb 2010 17:20:23 -0300 Subject: V4L/DVB: gspca - ov534: Fix Auto White Balance control MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Set only the needed bits for AWB, and enable it by default. Signed-off-by: Max Thrun Signed-off-by: Antonio Ospite Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/ov534.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index 4fda0980be0..3b538d735ec 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c @@ -171,7 +171,7 @@ static const struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 1, .step = 1, -#define AWB_DEF 0 +#define AWB_DEF 1 .default_value = AWB_DEF, }, .set = sd_setawb, @@ -723,10 +723,17 @@ static void setawb(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - if (sd->awb) - sccb_reg_write(gspca_dev, 0x63, 0xe0); /* AWB on */ - else - sccb_reg_write(gspca_dev, 0x63, 0xaa); /* AWB off */ + if (sd->awb) { + sccb_reg_write(gspca_dev, 0x13, + sccb_reg_read(gspca_dev, 0x13) | 0x02); + sccb_reg_write(gspca_dev, 0x63, + sccb_reg_read(gspca_dev, 0x63) | 0xc0); + } else { + sccb_reg_write(gspca_dev, 0x13, + sccb_reg_read(gspca_dev, 0x13) & ~0x02); + sccb_reg_write(gspca_dev, 0x63, + sccb_reg_read(gspca_dev, 0x63) & ~0xc0); + } } static void setaec(struct gspca_dev *gspca_dev) @@ -805,9 +812,7 @@ static int sd_config(struct gspca_dev *gspca_dev, #else gspca_dev->ctrl_inac |= (1 << AWB_IDX); #endif -#if AWB_DEF != 0 - sd->awb = AWB_DEF -#endif + sd->awb = AWB_DEF; sd->aec = AEC_DEF; #if SHARPNESS_DEF != 0 sd->sharpness = SHARPNESS_DEF; -- cgit v1.2.3-70-g09d2 From 3149cfbfaca7912995a32d72ddd2381e66ca845e Mon Sep 17 00:00:00 2001 From: Max Thrun Date: Sat, 27 Feb 2010 17:20:24 -0300 Subject: V4L/DVB: gspca - ov534: Fixes for sharpness control MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Adjust comments for sharpness control * Set default value unconditionally, for readability Signed-off-by: Max Thrun Signed-off-by: Antonio Ospite Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/ov534.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index 3b538d735ec..f2077eaa619 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c @@ -756,8 +756,8 @@ static void setsharpness(struct gspca_dev *gspca_dev) u8 val; val = sd->sharpness; - sccb_reg_write(gspca_dev, 0x91, val); /* vga noise */ - sccb_reg_write(gspca_dev, 0x8e, val); /* qvga noise */ + sccb_reg_write(gspca_dev, 0x91, val); /* Auto de-noise threshold */ + sccb_reg_write(gspca_dev, 0x8e, val); /* De-noise threshold */ } static void sethflip(struct gspca_dev *gspca_dev) @@ -814,9 +814,7 @@ static int sd_config(struct gspca_dev *gspca_dev, #endif sd->awb = AWB_DEF; sd->aec = AEC_DEF; -#if SHARPNESS_DEF != 0 sd->sharpness = SHARPNESS_DEF; -#endif #if HFLIP_DEF != 0 sd->hflip = HFLIP_DEF; #endif -- cgit v1.2.3-70-g09d2 From eb171073b6f941e83f01b6444ab347e893785faf Mon Sep 17 00:00:00 2001 From: Max Thrun Date: Sat, 27 Feb 2010 17:20:25 -0300 Subject: V4L/DVB: gspca - ov534: Fix unsetting hflip and vflip bits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also set default values unconditionally, for readability. Signed-off-by: Max Thrun Signed-off-by: Antonio Ospite Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/ov534.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index f2077eaa619..8f01201956c 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c @@ -769,7 +769,7 @@ static void sethflip(struct gspca_dev *gspca_dev) sccb_reg_read(gspca_dev, 0x0c) | 0x40); else sccb_reg_write(gspca_dev, 0x0c, - sccb_reg_read(gspca_dev, 0x0c) & 0xbf); + sccb_reg_read(gspca_dev, 0x0c) & ~0x40); } static void setvflip(struct gspca_dev *gspca_dev) @@ -781,7 +781,7 @@ static void setvflip(struct gspca_dev *gspca_dev) sccb_reg_read(gspca_dev, 0x0c) | 0x80); else sccb_reg_write(gspca_dev, 0x0c, - sccb_reg_read(gspca_dev, 0x0c) & 0x7f); + sccb_reg_read(gspca_dev, 0x0c) & ~0x80); } /* this function is called at probe time */ @@ -815,12 +815,8 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->awb = AWB_DEF; sd->aec = AEC_DEF; sd->sharpness = SHARPNESS_DEF; -#if HFLIP_DEF != 0 sd->hflip = HFLIP_DEF; -#endif -#if VFLIP_DEF != 0 sd->vflip = VFLIP_DEF; -#endif return 0; } -- cgit v1.2.3-70-g09d2 From 7f9e9e8dc2d5b226819e486e13c9532f40a0fbda Mon Sep 17 00:00:00 2001 From: Antonio Ospite Date: Mon, 1 Mar 2010 08:54:33 -0300 Subject: V4L/DVB: gspca - ov534: Cosmetics: fix indentation and hex digits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Indent with tabs, not with spaces, nor with mixed style. * Less indentation for controls index comments. * Use lowercase hex digits. Signed-off-by: Antonio Ospite Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/ov534.c | 244 +++++++++++++++++++------------------- 1 file changed, 122 insertions(+), 122 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index 8f01201956c..87838444248 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c @@ -92,147 +92,147 @@ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); static const struct ctrl sd_ctrls[] = { - { /* 0 */ - { - .id = V4L2_CID_BRIGHTNESS, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Brightness", - .minimum = 0, - .maximum = 255, - .step = 1, + { /* 0 */ + { + .id = V4L2_CID_BRIGHTNESS, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Brightness", + .minimum = 0, + .maximum = 255, + .step = 1, #define BRIGHTNESS_DEF 0 - .default_value = BRIGHTNESS_DEF, + .default_value = BRIGHTNESS_DEF, + }, + .set = sd_setbrightness, + .get = sd_getbrightness, }, - .set = sd_setbrightness, - .get = sd_getbrightness, - }, - { /* 1 */ - { - .id = V4L2_CID_CONTRAST, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Contrast", - .minimum = 0, - .maximum = 255, - .step = 1, + { /* 1 */ + { + .id = V4L2_CID_CONTRAST, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Contrast", + .minimum = 0, + .maximum = 255, + .step = 1, #define CONTRAST_DEF 32 - .default_value = CONTRAST_DEF, + .default_value = CONTRAST_DEF, + }, + .set = sd_setcontrast, + .get = sd_getcontrast, }, - .set = sd_setcontrast, - .get = sd_getcontrast, - }, - { /* 2 */ - { - .id = V4L2_CID_GAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Main Gain", - .minimum = 0, - .maximum = 63, - .step = 1, + { /* 2 */ + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Main Gain", + .minimum = 0, + .maximum = 63, + .step = 1, #define GAIN_DEF 20 - .default_value = GAIN_DEF, + .default_value = GAIN_DEF, + }, + .set = sd_setgain, + .get = sd_getgain, }, - .set = sd_setgain, - .get = sd_getgain, - }, - { /* 3 */ - { - .id = V4L2_CID_EXPOSURE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Exposure", - .minimum = 0, - .maximum = 255, - .step = 1, + { /* 3 */ + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Exposure", + .minimum = 0, + .maximum = 255, + .step = 1, #define EXPO_DEF 120 - .default_value = EXPO_DEF, + .default_value = EXPO_DEF, + }, + .set = sd_setexposure, + .get = sd_getexposure, }, - .set = sd_setexposure, - .get = sd_getexposure, - }, - { /* 4 */ - { - .id = V4L2_CID_AUTOGAIN, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "Auto Gain", - .minimum = 0, - .maximum = 1, - .step = 1, + { /* 4 */ + { + .id = V4L2_CID_AUTOGAIN, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Auto Gain", + .minimum = 0, + .maximum = 1, + .step = 1, #define AGC_DEF 1 - .default_value = AGC_DEF, + .default_value = AGC_DEF, + }, + .set = sd_setagc, + .get = sd_getagc, }, - .set = sd_setagc, - .get = sd_getagc, - }, #define AWB_IDX 5 - { /* 5 */ - { - .id = V4L2_CID_AUTO_WHITE_BALANCE, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "Auto White Balance", - .minimum = 0, - .maximum = 1, - .step = 1, + { /* 5 */ + { + .id = V4L2_CID_AUTO_WHITE_BALANCE, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Auto White Balance", + .minimum = 0, + .maximum = 1, + .step = 1, #define AWB_DEF 1 - .default_value = AWB_DEF, + .default_value = AWB_DEF, + }, + .set = sd_setawb, + .get = sd_getawb, }, - .set = sd_setawb, - .get = sd_getawb, - }, - { /* 6 */ - { - .id = V4L2_CID_EXPOSURE_AUTO, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "Auto Exposure", - .minimum = 0, - .maximum = 1, - .step = 1, + { /* 6 */ + { + .id = V4L2_CID_EXPOSURE_AUTO, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Auto Exposure", + .minimum = 0, + .maximum = 1, + .step = 1, #define AEC_DEF 1 - .default_value = AEC_DEF, + .default_value = AEC_DEF, + }, + .set = sd_setaec, + .get = sd_getaec, }, - .set = sd_setaec, - .get = sd_getaec, - }, - { /* 7 */ - { - .id = V4L2_CID_SHARPNESS, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Sharpness", - .minimum = 0, - .maximum = 63, - .step = 1, + { /* 7 */ + { + .id = V4L2_CID_SHARPNESS, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Sharpness", + .minimum = 0, + .maximum = 63, + .step = 1, #define SHARPNESS_DEF 0 - .default_value = SHARPNESS_DEF, + .default_value = SHARPNESS_DEF, + }, + .set = sd_setsharpness, + .get = sd_getsharpness, }, - .set = sd_setsharpness, - .get = sd_getsharpness, - }, - { /* 8 */ - { - .id = V4L2_CID_HFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "HFlip", - .minimum = 0, - .maximum = 1, - .step = 1, + { /* 8 */ + { + .id = V4L2_CID_HFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "HFlip", + .minimum = 0, + .maximum = 1, + .step = 1, #define HFLIP_DEF 0 - .default_value = HFLIP_DEF, + .default_value = HFLIP_DEF, + }, + .set = sd_sethflip, + .get = sd_gethflip, }, - .set = sd_sethflip, - .get = sd_gethflip, - }, - { /* 9 */ - { - .id = V4L2_CID_VFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "VFlip", - .minimum = 0, - .maximum = 1, - .step = 1, + { /* 9 */ + { + .id = V4L2_CID_VFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "VFlip", + .minimum = 0, + .maximum = 1, + .step = 1, #define VFLIP_DEF 0 - .default_value = VFLIP_DEF, + .default_value = VFLIP_DEF, + }, + .set = sd_setvflip, + .get = sd_getvflip, }, - .set = sd_setvflip, - .get = sd_getvflip, - }, }; static const struct v4l2_pix_format ov772x_mode[] = { @@ -641,14 +641,14 @@ static void setbrightness(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - sccb_reg_write(gspca_dev, 0x9B, sd->brightness); + sccb_reg_write(gspca_dev, 0x9b, sd->brightness); } static void setcontrast(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - sccb_reg_write(gspca_dev, 0x9C, sd->contrast); + sccb_reg_write(gspca_dev, 0x9c, sd->contrast); } static void setgain(struct gspca_dev *gspca_dev) -- cgit v1.2.3-70-g09d2 From 4b7875407b2fb56433586877ca0a564b8d999f4e Mon Sep 17 00:00:00 2001 From: Mosalam Ebrahimi Date: Mon, 8 Mar 2010 13:52:17 -0300 Subject: V4L/DVB: gspca - ov534: Add Powerline Frequency control MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Note that setting this options to 50Hz can reduce the framerate, so it is still disabled (60Hz) by default. Signed-off-by: Mosalam Ebrahimi Signed-off-by: Antonio Ospite Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/ov534.c | 71 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index 87838444248..29af17e173d 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c @@ -66,7 +66,7 @@ struct sd { s8 sharpness; u8 hflip; u8 vflip; - + u8 freqfltr; }; /* V4L2 controls supported by the driver */ @@ -90,6 +90,10 @@ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); +static int sd_setfreqfltr(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getfreqfltr(struct gspca_dev *gspca_dev, __s32 *val); +static int sd_querymenu(struct gspca_dev *gspca_dev, + struct v4l2_querymenu *menu); static const struct ctrl sd_ctrls[] = { { /* 0 */ @@ -233,6 +237,20 @@ static const struct ctrl sd_ctrls[] = { .set = sd_setvflip, .get = sd_getvflip, }, + { /* 10 */ + { + .id = V4L2_CID_POWER_LINE_FREQUENCY, + .type = V4L2_CTRL_TYPE_MENU, + .name = "Light Frequency Filter", + .minimum = 0, + .maximum = 1, + .step = 1, +#define FREQFLTR_DEF 0 + .default_value = FREQFLTR_DEF, + }, + .set = sd_setfreqfltr, + .get = sd_getfreqfltr, + }, }; static const struct v4l2_pix_format ov772x_mode[] = { @@ -784,6 +802,17 @@ static void setvflip(struct gspca_dev *gspca_dev) sccb_reg_read(gspca_dev, 0x0c) & ~0x80); } +static void setfreqfltr(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + + if (sd->freqfltr == 0) + sccb_reg_write(gspca_dev, 0x2b, 0x00); + else + sccb_reg_write(gspca_dev, 0x2b, 0x9e); +} + + /* this function is called at probe time */ static int sd_config(struct gspca_dev *gspca_dev, const struct usb_device_id *id) @@ -817,6 +846,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->sharpness = SHARPNESS_DEF; sd->hflip = HFLIP_DEF; sd->vflip = VFLIP_DEF; + sd->freqfltr = FREQFLTR_DEF; return 0; } @@ -886,6 +916,7 @@ static int sd_start(struct gspca_dev *gspca_dev) setsharpness(gspca_dev); setvflip(gspca_dev); sethflip(gspca_dev); + setfreqfltr(gspca_dev); ov534_set_led(gspca_dev, 1); ov534_reg_write(gspca_dev, 0xe0, 0x00); @@ -1179,6 +1210,43 @@ static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val) return 0; } +static int sd_setfreqfltr(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->freqfltr = val; + if (gspca_dev->streaming) + setfreqfltr(gspca_dev); + return 0; +} + +static int sd_getfreqfltr(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->freqfltr; + return 0; +} + +static int sd_querymenu(struct gspca_dev *gspca_dev, + struct v4l2_querymenu *menu) +{ + switch (menu->id) { + case V4L2_CID_POWER_LINE_FREQUENCY: + switch (menu->index) { + case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */ + strcpy((char *) menu->name, "Disabled"); + return 0; + case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */ + strcpy((char *) menu->name, "50 Hz"); + return 0; + } + break; + } + + return -EINVAL; +} + /* get stream parameters (framerate) */ static int sd_get_streamparm(struct gspca_dev *gspca_dev, struct v4l2_streamparm *parm) @@ -1230,6 +1298,7 @@ static const struct sd_desc sd_desc = { .start = sd_start, .stopN = sd_stopN, .pkt_scan = sd_pkt_scan, + .querymenu = sd_querymenu, .get_streamparm = sd_get_streamparm, .set_streamparm = sd_set_streamparm, }; -- cgit v1.2.3-70-g09d2 From 6721b51ece65967fe628007fee3e16479c07afd1 Mon Sep 17 00:00:00 2001 From: Max Thrun Date: Sat, 27 Feb 2010 17:20:28 -0300 Subject: V4L/DVB: gspca - ov534: Update copyright info MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Max Thrun Signed-off-by: Antonio Ospite Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/ov534.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index 29af17e173d..8cd193d18b7 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c @@ -10,8 +10,8 @@ * https://jim.sh/svn/jim/devl/playstation/ps3/eye/test/ * * PS3 Eye camera enhanced by Richard Kaswy http://kaswy.free.fr - * PS3 Eye camera, brightness, contrast, hue, AWB control added - * by Max Thrun + * PS3 Eye camera - brightness, contrast, awb, agc, aec controls + * added by Max Thrun * * 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 -- cgit v1.2.3-70-g09d2 From 000f64efc7fe6693261a78a0164c0e805553631b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 11 Mar 2010 01:58:12 -0300 Subject: V4L/DVB: Fix bad whitespacing Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/az6027.c | 10 +++++----- drivers/media/dvb/frontends/atbm8830_priv.h | 2 +- drivers/media/dvb/mantis/mantis_vp1041.c | 10 +++++----- drivers/media/video/davinci/isif_regs.h | 2 +- drivers/media/video/gspca/ov534.c | 2 +- drivers/media/video/ov9640.c | 6 +++--- 6 files changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/dvb/dvb-usb/az6027.c b/drivers/media/dvb/dvb-usb/az6027.c index 60787a28edb..30ea3eff1ef 100644 --- a/drivers/media/dvb/dvb-usb/az6027.c +++ b/drivers/media/dvb/dvb-usb/az6027.c @@ -125,12 +125,12 @@ static const struct stb0899_s1_reg az6027_stb0899_s1_init_3[] = { { STB0899_RCOMPC , 0xc9 }, { STB0899_AGC1CN , 0x01 }, { STB0899_AGC1REF , 0x10 }, - { STB0899_RTC , 0x23 }, + { STB0899_RTC , 0x23 }, { STB0899_TMGCFG , 0x4e }, { STB0899_AGC2REF , 0x34 }, { STB0899_TLSR , 0x84 }, { STB0899_CFD , 0xf7 }, - { STB0899_ACLC , 0x87 }, + { STB0899_ACLC , 0x87 }, { STB0899_BCLC , 0x94 }, { STB0899_EQON , 0x41 }, { STB0899_LDT , 0xf1 }, @@ -183,10 +183,10 @@ static const struct stb0899_s1_reg az6027_stb0899_s1_init_3[] = { { STB0899_ECNT3M , 0x0a }, { STB0899_ECNT3L , 0xad }, { STB0899_FECAUTO1 , 0x06 }, - { STB0899_FECM , 0x01 }, + { STB0899_FECM , 0x01 }, { STB0899_VTH12 , 0xb0 }, { STB0899_VTH23 , 0x7a }, - { STB0899_VTH34 , 0x58 }, + { STB0899_VTH34 , 0x58 }, { STB0899_VTH56 , 0x38 }, { STB0899_VTH67 , 0x34 }, { STB0899_VTH78 , 0x24 }, @@ -195,7 +195,7 @@ static const struct stb0899_s1_reg az6027_stb0899_s1_init_3[] = { { STB0899_RSULC , 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */ { STB0899_TSULC , 0x42 }, { STB0899_RSLLC , 0x41 }, - { STB0899_TSLPL , 0x12 }, + { STB0899_TSLPL , 0x12 }, { STB0899_TSCFGH , 0x0c }, { STB0899_TSCFGM , 0x00 }, { STB0899_TSCFGL , 0x00 }, diff --git a/drivers/media/dvb/frontends/atbm8830_priv.h b/drivers/media/dvb/frontends/atbm8830_priv.h index ce960f76092..d460058d497 100644 --- a/drivers/media/dvb/frontends/atbm8830_priv.h +++ b/drivers/media/dvb/frontends/atbm8830_priv.h @@ -18,7 +18,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - + #ifndef __ATBM8830_PRIV_H #define __ATBM8830_PRIV_H diff --git a/drivers/media/dvb/mantis/mantis_vp1041.c b/drivers/media/dvb/mantis/mantis_vp1041.c index 515346dd31d..d1aa2bc0c15 100644 --- a/drivers/media/dvb/mantis/mantis_vp1041.c +++ b/drivers/media/dvb/mantis/mantis_vp1041.c @@ -136,12 +136,12 @@ static const struct stb0899_s1_reg vp1041_stb0899_s1_init_3[] = { { STB0899_RCOMPC , 0xc9 }, { STB0899_AGC1CN , 0x01 }, { STB0899_AGC1REF , 0x10 }, - { STB0899_RTC , 0x23 }, + { STB0899_RTC , 0x23 }, { STB0899_TMGCFG , 0x4e }, { STB0899_AGC2REF , 0x34 }, { STB0899_TLSR , 0x84 }, { STB0899_CFD , 0xf7 }, - { STB0899_ACLC , 0x87 }, + { STB0899_ACLC , 0x87 }, { STB0899_BCLC , 0x94 }, { STB0899_EQON , 0x41 }, { STB0899_LDT , 0xf1 }, @@ -194,10 +194,10 @@ static const struct stb0899_s1_reg vp1041_stb0899_s1_init_3[] = { { STB0899_ECNT3M , 0x0a }, { STB0899_ECNT3L , 0xad }, { STB0899_FECAUTO1 , 0x06 }, - { STB0899_FECM , 0x01 }, + { STB0899_FECM , 0x01 }, { STB0899_VTH12 , 0xb0 }, { STB0899_VTH23 , 0x7a }, - { STB0899_VTH34 , 0x58 }, + { STB0899_VTH34 , 0x58 }, { STB0899_VTH56 , 0x38 }, { STB0899_VTH67 , 0x34 }, { STB0899_VTH78 , 0x24 }, @@ -206,7 +206,7 @@ static const struct stb0899_s1_reg vp1041_stb0899_s1_init_3[] = { { STB0899_RSULC , 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */ { STB0899_TSULC , 0x42 }, { STB0899_RSLLC , 0x41 }, - { STB0899_TSLPL , 0x12 }, + { STB0899_TSLPL , 0x12 }, { STB0899_TSCFGH , 0x0c }, { STB0899_TSCFGM , 0x00 }, { STB0899_TSCFGL , 0x00 }, diff --git a/drivers/media/video/davinci/isif_regs.h b/drivers/media/video/davinci/isif_regs.h index f7b8893a295..aa69a463c12 100644 --- a/drivers/media/video/davinci/isif_regs.h +++ b/drivers/media/video/davinci/isif_regs.h @@ -158,7 +158,7 @@ /* gain - offset masks */ #define GAIN_INTEGER_SHIFT 9 -#define OFFSET_MASK 0xFFF +#define OFFSET_MASK 0xFFF #define GAIN_SDRAM_EN_SHIFT 12 #define GAIN_IPIPE_EN_SHIFT 13 #define GAIN_H3A_EN_SHIFT 14 diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index 8cd193d18b7..dc1e4efe30f 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c @@ -709,7 +709,7 @@ static void setexposure(struct gspca_dev *gspca_dev) /* 'val' is one byte and represents half of the exposure value we are * going to set into registers, a two bytes value: - * + * * MSB: ((u16) val << 1) >> 8 == val >> 7 * LSB: ((u16) val << 1) & 0xff == val << 1 */ diff --git a/drivers/media/video/ov9640.c b/drivers/media/video/ov9640.c index 47bf60ceb7a..36599a65f54 100644 --- a/drivers/media/video/ov9640.c +++ b/drivers/media/video/ov9640.c @@ -59,9 +59,9 @@ static const struct ov9640_reg ov9640_regs_dflt[] = { * COM12 |= OV9640_COM12_YUV_AVG * * for RGB, alter the following registers: - * COM7 |= OV9640_COM7_RGB - * COM13 |= OV9640_COM13_RGB_AVG - * COM15 |= proper RGB color encoding mode + * COM7 |= OV9640_COM7_RGB + * COM13 |= OV9640_COM13_RGB_AVG + * COM15 |= proper RGB color encoding mode */ static const struct ov9640_reg ov9640_regs_qqcif[] = { { OV9640_CLKRC, OV9640_CLKRC_DPLL_EN | OV9640_CLKRC_DIV(0x0f) }, -- cgit v1.2.3-70-g09d2 From 727e625cc2c114e449a78f851b0c12edac897a83 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 12 Mar 2010 21:18:14 -0300 Subject: V4L/DVB: ir-core: export driver name used by IR via uevent Now, both driver and keytable names are exported to userspace. This will help userspace to decide when a table need to be replaced by another one. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-keytable.c | 7 ++++++- drivers/media/IR/ir-sysfs.c | 2 ++ drivers/media/dvb/dm1105/dm1105.c | 4 +++- drivers/media/dvb/mantis/mantis_input.c | 4 +++- drivers/media/dvb/ttpci/budget-ci.c | 4 +++- drivers/media/video/bt8xx/bttv-input.c | 4 +++- drivers/media/video/cx231xx/cx231xx-input.c | 5 ++++- drivers/media/video/cx23885/cx23885-input.c | 4 +++- drivers/media/video/cx88/cx88-input.c | 4 +++- drivers/media/video/em28xx/em28xx-input.c | 4 +++- drivers/media/video/ir-kbd-i2c.c | 8 ++++---- drivers/media/video/saa7134/saa7134-input.c | 4 +++- include/media/ir-core.h | 4 +++- 13 files changed, 43 insertions(+), 15 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c index 6db3ff74659..73fe4bec83b 100644 --- a/drivers/media/IR/ir-keytable.c +++ b/drivers/media/IR/ir-keytable.c @@ -404,7 +404,8 @@ EXPORT_SYMBOL_GPL(ir_g_keycode_from_table); */ int ir_input_register(struct input_dev *input_dev, const struct ir_scancode_table *rc_tab, - const struct ir_dev_props *props) + const struct ir_dev_props *props, + const char *driver_name) { struct ir_input_dev *ir_dev; struct ir_scancode *keymap = rc_tab->scan; @@ -419,6 +420,10 @@ int ir_input_register(struct input_dev *input_dev, spin_lock_init(&ir_dev->rc_tab.lock); + ir_dev->driver_name = kmalloc(strlen(driver_name) + 1, GFP_KERNEL); + if (!ir_dev->driver_name) + return -ENOMEM; + strcpy(ir_dev->driver_name, driver_name); ir_dev->rc_tab.name = rc_tab->name; ir_dev->rc_tab.size = ir_roundup_tablesize(rc_tab->size); ir_dev->rc_tab.scan = kzalloc(ir_dev->rc_tab.size * diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c index 6d63657b568..0592515a19f 100644 --- a/drivers/media/IR/ir-sysfs.c +++ b/drivers/media/IR/ir-sysfs.c @@ -140,6 +140,8 @@ static int ir_dev_uevent(struct device *device, struct kobj_uevent_env *env) if (ir_dev->rc_tab.name) ADD_HOTPLUG_VAR("NAME=\"%s\"", ir_dev->rc_tab.name); + if (ir_dev->driver_name) + ADD_HOTPLUG_VAR("DRV_NAME=\"%s\"", ir_dev->driver_name); return 0; } diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c index b6d46961a99..3229ff325c5 100644 --- a/drivers/media/dvb/dm1105/dm1105.c +++ b/drivers/media/dvb/dm1105/dm1105.c @@ -46,6 +46,8 @@ #include "z0194a.h" #include "ds3000.h" +#define MODULE_NAME "dm1105" + #define UNSET (-1U) #define DM1105_BOARD_NOAUTO UNSET @@ -628,7 +630,7 @@ int __devinit dm1105_ir_init(struct dm1105_dev *dm1105) INIT_WORK(&dm1105->ir.work, dm1105_emit_key); - err = ir_input_register(input_dev, ir_codes, NULL); + err = ir_input_register(input_dev, ir_codes, NULL, MODULE_NAME); return err; } diff --git a/drivers/media/dvb/mantis/mantis_input.c b/drivers/media/dvb/mantis/mantis_input.c index 4675a3b53c7..6baf3022968 100644 --- a/drivers/media/dvb/mantis/mantis_input.c +++ b/drivers/media/dvb/mantis/mantis_input.c @@ -32,6 +32,8 @@ #include "mantis_reg.h" #include "mantis_uart.h" +#define MODULE_NAME "mantis_core" + static struct ir_scancode mantis_ir_table[] = { { 0x29, KEY_POWER }, { 0x28, KEY_FAVORITES }, @@ -126,7 +128,7 @@ int mantis_input_init(struct mantis_pci *mantis) rc->id.version = 1; rc->dev = mantis->pdev->dev; - err = ir_input_register(rc, &ir_mantis, NULL); + err = ir_input_register(rc, &ir_mantis, NULL, MODULE_NAME); if (err) { dprintk(MANTIS_ERROR, 1, "IR device registration failed, ret = %d", err); input_free_device(rc); diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index 49c2a817a06..ec89afd3891 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -54,6 +54,8 @@ #include "tda1002x.h" #include "tda827x.h" +#define MODULE_NAME "budget_ci" + /* * Regarding DEBIADDR_IR: * Some CI modules hang if random addresses are read. @@ -254,7 +256,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci) budget_ci->ir.timer_keyup.function = msp430_ir_keyup; budget_ci->ir.timer_keyup.data = (unsigned long) &budget_ci->ir; budget_ci->ir.last_raw = 0xffff; /* An impossible value */ - error = ir_input_register(input_dev, ir_codes, NULL); + error = ir_input_register(input_dev, ir_codes, NULL, MODULE_NAME); if (error) { printk(KERN_ERR "budget_ci: could not init driver for IR device (code %d)\n", error); return error; diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c index aa153a986ad..d17a9b7911e 100644 --- a/drivers/media/video/bt8xx/bttv-input.c +++ b/drivers/media/video/bt8xx/bttv-input.c @@ -49,6 +49,8 @@ module_param(ir_rc5_key_timeout, int, 0644); #define DEVNAME "bttv-input" +#define MODULE_NAME "bttv" + /* ---------------------------------------------------------------------- */ static void ir_handle_key(struct bttv *btv) @@ -390,7 +392,7 @@ int bttv_input_init(struct bttv *btv) bttv_ir_start(btv, ir); /* all done */ - err = ir_input_register(btv->remote->dev, ir_codes, NULL); + err = ir_input_register(btv->remote->dev, ir_codes, NULL, MODULE_NAME); if (err) goto err_out_stop; diff --git a/drivers/media/video/cx231xx/cx231xx-input.c b/drivers/media/video/cx231xx/cx231xx-input.c index b473cd8367f..a0e8bb88d67 100644 --- a/drivers/media/video/cx231xx/cx231xx-input.c +++ b/drivers/media/video/cx231xx/cx231xx-input.c @@ -35,6 +35,8 @@ static unsigned int ir_debug; module_param(ir_debug, int, 0644); MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]"); +#define MODULE_NAME "cx231xx" + #define i2cdprintk(fmt, arg...) \ if (ir_debug) { \ printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \ @@ -217,7 +219,8 @@ int cx231xx_ir_init(struct cx231xx *dev) cx231xx_ir_start(ir); /* all done */ - err = ir_input_register(ir->input, dev->board.ir_codes, NULL); + err = ir_input_register(ir->input, dev->board.ir_codes, + NULL, MODULE_NAME); if (err) goto err_out_stop; diff --git a/drivers/media/video/cx23885/cx23885-input.c b/drivers/media/video/cx23885/cx23885-input.c index 8e9d990dbe9..ef1db2d9668 100644 --- a/drivers/media/video/cx23885/cx23885-input.c +++ b/drivers/media/video/cx23885/cx23885-input.c @@ -51,6 +51,8 @@ #define RC5_EXTENDED_COMMAND_OFFSET 64 +#define MODULE_NAME "cx23885" + static inline unsigned int rc5_command(u32 rc5_baseband) { return RC5_INSTR(rc5_baseband) + @@ -398,7 +400,7 @@ int cx23885_input_init(struct cx23885_dev *dev) dev->ir_input = ir; cx23885_input_ir_start(dev); - ret = ir_input_register(ir->dev, ir_codes, NULL); + ret = ir_input_register(ir->dev, ir_codes, NULL, MODULE_NAME); if (ret) goto err_out_stop; diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index 6b6abf062c2..8b52546c6e1 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -32,6 +32,8 @@ #include "cx88.h" #include +#define MODULE_NAME "cx88xx" + /* ---------------------------------------------------------------------- */ struct cx88_IR { @@ -384,7 +386,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) cx88_ir_start(core, ir); /* all done */ - err = ir_input_register(ir->input, ir_codes, NULL); + err = ir_input_register(ir->input, ir_codes, NULL, MODULE_NAME); if (err) goto err_out_stop; diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index 20a0001e888..32f376654c0 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c @@ -39,6 +39,8 @@ static unsigned int ir_debug; module_param(ir_debug, int, 0644); MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]"); +#define MODULE_NAME "em28xx" + #define i2cdprintk(fmt, arg...) \ if (ir_debug) { \ printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \ @@ -474,7 +476,7 @@ int em28xx_ir_init(struct em28xx *dev) /* all done */ err = ir_input_register(ir->input, dev->board.ir_codes, - &ir->props); + &ir->props, MODULE_NAME); if (err) goto err_out_stop; diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index da18d698e7f..6af69d5c849 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -61,9 +61,9 @@ module_param(hauppauge, int, 0644); /* Choose Hauppauge remote */ MODULE_PARM_DESC(hauppauge, "Specify Hauppauge remote: 0=black, 1=grey (defaults to 0)"); -#define DEVNAME "ir-kbd-i2c" +#define MODULE_NAME "ir-kbd-i2c" #define dprintk(level, fmt, arg...) if (debug >= level) \ - printk(KERN_DEBUG DEVNAME ": " fmt , ## arg) + printk(KERN_DEBUG MODULE_NAME ": " fmt , ## arg) /* ----------------------------------------------------------------------- */ @@ -447,11 +447,11 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) input_dev->name = ir->name; input_dev->phys = ir->phys; - err = ir_input_register(ir->input, ir->ir_codes, NULL); + err = ir_input_register(ir->input, ir->ir_codes, NULL, MODULE_NAME); if (err) goto err_out_free; - printk(DEVNAME ": %s detected at %s [%s]\n", + printk(MODULE_NAME ": %s detected at %s [%s]\n", ir->input->name, ir->input->phys, adap->name); /* start polling via eventd */ diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index a2b16693ee9..c1fe7c9369b 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -28,6 +28,8 @@ #include "saa7134-reg.h" #include "saa7134.h" +#define MODULE_NAME "saa7134" + static unsigned int disable_ir; module_param(disable_ir, int, 0444); MODULE_PARM_DESC(disable_ir,"disable infrared remote support"); @@ -730,7 +732,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) dev->remote = ir; saa7134_ir_start(dev, ir); - err = ir_input_register(ir->dev, ir_codes, NULL); + err = ir_input_register(ir->dev, ir_codes, NULL, MODULE_NAME); if (err) goto err_out_stop; diff --git a/include/media/ir-core.h b/include/media/ir-core.h index 9ab8a777422..1eae72d518e 100644 --- a/include/media/ir-core.h +++ b/include/media/ir-core.h @@ -49,6 +49,7 @@ struct ir_dev_props { struct ir_input_dev { struct device dev; /* device */ + char *driver_name; /* Name of the driver module */ struct ir_scancode_table rc_tab; /* scan/key table */ unsigned long devno; /* device number */ const struct ir_dev_props *props; /* Device properties */ @@ -62,7 +63,8 @@ u32 ir_g_keycode_from_table(struct input_dev *input_dev, int ir_input_register(struct input_dev *dev, const struct ir_scancode_table *ir_codes, - const struct ir_dev_props *props); + const struct ir_dev_props *props, + const char *driver_name); void ir_input_unregister(struct input_dev *input_dev); /* Routines from ir-sysfs.c */ -- cgit v1.2.3-70-g09d2 From c6ebc6c4acbedcc766a8af147ccb9c39e77578ae Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 14 Mar 2010 22:57:56 -0300 Subject: V4L/DVB: saa7134: Fix IR support of some ASUS TV-FM 7135 variants Some variants of the ASUS TV-FM 7135 are handled as the ASUSTeK P7131 Analog (card=146). However, by the time we find out, some card-specific initialization is missed. In particular, the fact that the IR is GPIO-based. Set it when we change the card type, and run saa7134_input_init1(). Signed-off-by: Jean Delvare Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-cards.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 297833fb3b4..aa07cb11e10 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -7215,6 +7215,11 @@ int saa7134_board_init2(struct saa7134_dev *dev) printk(KERN_INFO "%s: P7131 analog only, using " "entry of %s\n", dev->name, saa7134_boards[dev->board].name); + + /* IR init has already happened for other cards, so + * we have to catch up. */ + dev->has_remote = SAA7134_REMOTE_GPIO; + saa7134_input_init1(dev); } break; case SAA7134_BOARD_HAUPPAUGE_HVR1150: -- cgit v1.2.3-70-g09d2 From d9a325a865becc082d592d16a15f01a9684ef82e Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 13 Mar 2010 16:40:03 -0300 Subject: V4L/DVB: cx18: Add support for component video inputs Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-av-core.c | 33 +++++++++++++++++++++++++++++---- drivers/media/video/cx18/cx18-av-core.h | 19 +++++++++++++++++++ drivers/media/video/cx18/cx18-cards.c | 2 +- drivers/media/video/cx18/cx18-cards.h | 4 ++-- 4 files changed, 51 insertions(+), 7 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c index 4392c76af5d..3ce45297e56 100644 --- a/drivers/media/video/cx18/cx18-av-core.c +++ b/drivers/media/video/cx18/cx18-av-core.c @@ -579,6 +579,7 @@ static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input, u8 afe_mux_cfg; u8 adc2_cfg; + u8 input_mode; u32 afe_cfg; int i; @@ -589,6 +590,30 @@ static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input, vid_input <= CX18_AV_COMPOSITE8) { afe_mux_cfg = 0xf0 + (vid_input - CX18_AV_COMPOSITE1); ch[0] = CVBS; + input_mode = 0x0; + } else if (vid_input >= CX18_AV_COMPONENT_LUMA1) { + int luma = vid_input & 0xf000; + int r_chroma = vid_input & 0xf0000; + int b_chroma = vid_input & 0xf00000; + + if ((vid_input & ~0xfff000) || + luma < CX18_AV_COMPONENT_LUMA1 || + luma > CX18_AV_COMPONENT_LUMA8 || + r_chroma < CX18_AV_COMPONENT_R_CHROMA4 || + r_chroma > CX18_AV_COMPONENT_R_CHROMA6 || + b_chroma < CX18_AV_COMPONENT_B_CHROMA7 || + b_chroma > CX18_AV_COMPONENT_B_CHROMA8) { + CX18_ERR_DEV(sd, "0x%06x is not a valid video input!\n", + vid_input); + return -EINVAL; + } + afe_mux_cfg = (luma - CX18_AV_COMPONENT_LUMA1) >> 12; + ch[0] = Y; + afe_mux_cfg |= (r_chroma - CX18_AV_COMPONENT_R_CHROMA4) >> 12; + ch[1] = Pr; + afe_mux_cfg |= (b_chroma - CX18_AV_COMPONENT_B_CHROMA7) >> 14; + ch[2] = Pb; + input_mode = 0x6; } else { int luma = vid_input & 0xf0; int chroma = vid_input & 0xf00; @@ -598,7 +623,7 @@ static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input, luma > CX18_AV_SVIDEO_LUMA8 || chroma < CX18_AV_SVIDEO_CHROMA4 || chroma > CX18_AV_SVIDEO_CHROMA8) { - CX18_ERR_DEV(sd, "0x%04x is not a valid video input!\n", + CX18_ERR_DEV(sd, "0x%06x is not a valid video input!\n", vid_input); return -EINVAL; } @@ -613,8 +638,8 @@ static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input, afe_mux_cfg |= (chroma - CX18_AV_SVIDEO_CHROMA4) >> 4; ch[1] = C; } + input_mode = 0x2; } - /* TODO: LeadTek WinFast DVR3100 H & WinFast PVR2100 can do Y/Pb/Pr */ switch (aud_input) { case CX18_AV_AUDIO_SERIAL1: @@ -650,8 +675,8 @@ static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input, /* Set up analog front end multiplexers */ cx18_av_write_expect(cx, 0x103, afe_mux_cfg, afe_mux_cfg, 0xf7); - /* Set INPUT_MODE to Composite (0) or S-Video (1) */ - cx18_av_and_or(cx, 0x401, ~0x6, ch[0] == CVBS ? 0 : 0x02); + /* Set INPUT_MODE to Composite, S-Video, or Component */ + cx18_av_and_or(cx, 0x401, ~0x6, input_mode); /* Set CH_SEL_ADC2 to 1 if input comes from CH3 */ adc2_cfg = cx18_av_read(cx, 0x102); diff --git a/drivers/media/video/cx18/cx18-av-core.h b/drivers/media/video/cx18/cx18-av-core.h index cafb7e99b9a..74546806b03 100644 --- a/drivers/media/video/cx18/cx18-av-core.h +++ b/drivers/media/video/cx18/cx18-av-core.h @@ -61,6 +61,25 @@ enum cx18_av_video_input { CX18_AV_SVIDEO2 = 0x620, CX18_AV_SVIDEO3 = 0x730, CX18_AV_SVIDEO4 = 0x840, + + /* Component Video inputs consist of one luma input (In1-In8) ORed + with a red chroma (In4-In6) and blue chroma input (In7-In8) */ + CX18_AV_COMPONENT_LUMA1 = 0x1000, + CX18_AV_COMPONENT_LUMA2 = 0x2000, + CX18_AV_COMPONENT_LUMA3 = 0x3000, + CX18_AV_COMPONENT_LUMA4 = 0x4000, + CX18_AV_COMPONENT_LUMA5 = 0x5000, + CX18_AV_COMPONENT_LUMA6 = 0x6000, + CX18_AV_COMPONENT_LUMA7 = 0x7000, + CX18_AV_COMPONENT_LUMA8 = 0x8000, + CX18_AV_COMPONENT_R_CHROMA4 = 0x40000, + CX18_AV_COMPONENT_R_CHROMA5 = 0x50000, + CX18_AV_COMPONENT_R_CHROMA6 = 0x60000, + CX18_AV_COMPONENT_B_CHROMA7 = 0x700000, + CX18_AV_COMPONENT_B_CHROMA8 = 0x800000, + + /* Component Video aliases for common combinations */ + CX18_AV_COMPONENT1 = 0x861000, }; enum cx18_av_audio_input { diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c index f808fb6fc1c..3d35f58e311 100644 --- a/drivers/media/video/cx18/cx18-cards.c +++ b/drivers/media/video/cx18/cx18-cards.c @@ -480,7 +480,7 @@ int cx18_get_input(struct cx18 *cx, u16 index, struct v4l2_input *input) "S-Video 2", "Composite 1", "Composite 2", - "Composite 3" + "Component 1" }; memset(input, 0, sizeof(*input)); diff --git a/drivers/media/video/cx18/cx18-cards.h b/drivers/media/video/cx18/cx18-cards.h index af3d71607dc..796e517300a 100644 --- a/drivers/media/video/cx18/cx18-cards.h +++ b/drivers/media/video/cx18/cx18-cards.h @@ -43,7 +43,7 @@ #define CX18_CARD_INPUT_SVIDEO2 3 #define CX18_CARD_INPUT_COMPOSITE1 4 #define CX18_CARD_INPUT_COMPOSITE2 5 -#define CX18_CARD_INPUT_COMPOSITE3 6 +#define CX18_CARD_INPUT_COMPONENT1 6 /* audio inputs */ #define CX18_CARD_INPUT_AUD_TUNER 1 @@ -62,7 +62,7 @@ struct cx18_card_video_input { u8 video_type; /* video input type */ u8 audio_index; /* index in cx18_card_audio_input array */ - u16 video_input; /* hardware video input */ + u32 video_input; /* hardware video input */ }; struct cx18_card_audio_input { -- cgit v1.2.3-70-g09d2 From f978ac90b2cfa79cb075f74fd5c403e9f9ec4246 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 13 Mar 2010 16:40:34 -0300 Subject: V4L/DVB: cx18: Add a component video input to the PVR2100 and DVR3200H card entries This is a guess at the proper configuration for component video on the Leadtek PVR2100 and DVR3100 H. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-cards.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c index 3d35f58e311..74e122b5fc4 100644 --- a/drivers/media/video/cx18/cx18-cards.c +++ b/drivers/media/video/cx18/cx18-cards.c @@ -370,6 +370,7 @@ static const struct cx18_card cx18_card_leadtek_pvr2100 = { { CX18_CARD_INPUT_SVIDEO1, 1, CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 }, { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE7 }, + { CX18_CARD_INPUT_COMPONENT1, 1, CX18_AV_COMPONENT1 }, }, .audio_inputs = { { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 0 }, @@ -422,6 +423,7 @@ static const struct cx18_card cx18_card_leadtek_dvr3100h = { { CX18_CARD_INPUT_SVIDEO1, 1, CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 }, { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE7 }, + { CX18_CARD_INPUT_COMPONENT1, 1, CX18_AV_COMPONENT1 }, }, .audio_inputs = { { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 0 }, -- cgit v1.2.3-70-g09d2 From 2443baeaa01388f56824c55c087510312b8d8197 Mon Sep 17 00:00:00 2001 From: Ian Armstrong Date: Sat, 13 Mar 2010 20:22:34 -0300 Subject: V4L/DVB: ivtv: Avoid hard system lock on decoder output mode change Changing the decoder video standard just prior to, or during, the output of the lower field may result in a hard system lock. To avoid this, try to ensure the firmware call occurs only during the first 100 lines of the top field. (Minor comment addition and a line break added Andy Walls .) Signed-off-by: Ian Armstrong Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtv-driver.c | 5 ++++- drivers/media/video/ivtv/ivtv-ioctl.c | 21 +++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index 9a250548be4..1b79475ca13 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c @@ -1293,7 +1293,6 @@ int ivtv_init_on_first_open(struct ivtv *itv) ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 1); ivtv_init_mpeg_decoder(itv); } - ivtv_s_std(NULL, &fh, &itv->tuner_std); /* On a cx23416 this seems to be able to enable DMA to the chip? */ if (!itv->has_cx23415) @@ -1310,6 +1309,10 @@ int ivtv_init_on_first_open(struct ivtv *itv) } else ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT); + + /* For cards with video out, this call needs interrupts enabled */ + ivtv_s_std(NULL, &fh, &itv->tuner_std); + return 0; } diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index 99f3c39a118..2192bc42c6b 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c @@ -1087,8 +1087,10 @@ static int ivtv_g_std(struct file *file, void *fh, v4l2_std_id *std) int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std) { + DEFINE_WAIT(wait); struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv; struct yuv_playback_info *yi = &itv->yuv_info; + int f; if ((*std & V4L2_STD_ALL) == 0) return -EINVAL; @@ -1128,6 +1130,25 @@ int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std) itv->is_out_60hz = itv->is_60hz; itv->is_out_50hz = itv->is_50hz; ivtv_call_all(itv, video, s_std_output, itv->std_out); + + /* + * The next firmware call is time sensitive. Time it to + * avoid risk of a hard lock, by trying to ensure the call + * happens within the first 100 lines of the top field. + * Make 4 attempts to sync to the decoder before giving up. + */ + for (f = 0; f < 4; f++) { + prepare_to_wait(&itv->vsync_waitq, &wait, + TASK_UNINTERRUPTIBLE); + if ((read_reg(0x28c0) >> 16) < 100) + break; + schedule_timeout(msecs_to_jiffies(25)); + } + finish_wait(&itv->vsync_waitq, &wait); + + if (f == 4) + IVTV_WARN("Mode change failed to sync to decoder\n"); + ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, 1, itv->is_out_50hz); itv->main_rect.left = itv->main_rect.top = 0; itv->main_rect.width = 720; -- cgit v1.2.3-70-g09d2 From 4e1af31aaaa8cc4a5cc1d894bdf04dfc7450d47f Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 13 Mar 2010 20:37:25 -0300 Subject: V4L/DVB: ivtv, ivtvfb: Use a define for the output line and field register address Get rid of the magic number 0x28c0 used in several places in the ivtv and ivtvfb driver and define the register address to a meaningful name. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtv-driver.h | 3 +++ drivers/media/video/ivtv/ivtv-ioctl.c | 2 +- drivers/media/video/ivtv/ivtv-irq.c | 8 +++++--- drivers/media/video/ivtv/ivtvfb.c | 2 +- 4 files changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h index 5028e31c564..851f07de529 100644 --- a/drivers/media/video/ivtv/ivtv-driver.h +++ b/drivers/media/video/ivtv/ivtv-driver.h @@ -116,6 +116,9 @@ #define IVTV_REG_VPU (0x9058) #define IVTV_REG_APU (0xA064) +/* Other registers */ +#define IVTV_REG_DEC_LINE_FIELD (0x28C0) + /* debugging */ extern int ivtv_debug; diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index 2192bc42c6b..c29ff983d43 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c @@ -1140,7 +1140,7 @@ int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std) for (f = 0; f < 4; f++) { prepare_to_wait(&itv->vsync_waitq, &wait, TASK_UNINTERRUPTIBLE); - if ((read_reg(0x28c0) >> 16) < 100) + if ((read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16) < 100) break; schedule_timeout(msecs_to_jiffies(25)); } diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c index 12d36ca91d5..dbd46c5d697 100644 --- a/drivers/media/video/ivtv/ivtv-irq.c +++ b/drivers/media/video/ivtv/ivtv-irq.c @@ -752,7 +752,7 @@ static void ivtv_irq_vsync(struct ivtv *itv) * to determine the line being displayed and ensure we handle * one vsync per frame. */ - unsigned int frame = read_reg(0x28c0) & 1; + unsigned int frame = read_reg(IVTV_REG_DEC_LINE_FIELD) & 1; struct yuv_playback_info *yi = &itv->yuv_info; int last_dma_frame = atomic_read(&yi->next_dma_frame); struct yuv_frame_info *f = &yi->new_frame_info[last_dma_frame]; @@ -852,9 +852,11 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id) */ if (~itv->irqmask & IVTV_IRQ_DEC_VSYNC) { /* vsync is enabled, see if we're in a new field */ - if ((itv->last_vsync_field & 1) != (read_reg(0x28c0) & 1)) { + if ((itv->last_vsync_field & 1) != + (read_reg(IVTV_REG_DEC_LINE_FIELD) & 1)) { /* New field, looks like we missed it */ - IVTV_DEBUG_YUV("VSync interrupt missed %d\n",read_reg(0x28c0)>>16); + IVTV_DEBUG_YUV("VSync interrupt missed %d\n", + read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16); vsync_force = 1; } } diff --git a/drivers/media/video/ivtv/ivtvfb.c b/drivers/media/video/ivtv/ivtvfb.c index de2ff1c6ac3..49e1a283ed3 100644 --- a/drivers/media/video/ivtv/ivtvfb.c +++ b/drivers/media/video/ivtv/ivtvfb.c @@ -460,7 +460,7 @@ static int ivtvfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long ar vblank.flags = FB_VBLANK_HAVE_COUNT |FB_VBLANK_HAVE_VCOUNT | FB_VBLANK_HAVE_VSYNC; - trace = read_reg(0x028c0) >> 16; + trace = read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16; if (itv->is_50hz && trace > 312) trace -= 312; else if (itv->is_60hz && trace > 262) -- cgit v1.2.3-70-g09d2 From 728385c4d31469b9124953f36fb42015435466c9 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 12 Mar 2010 06:15:32 -0300 Subject: V4L/DVB: drivers/media/video: move dereference after NULL test In quickcam_messenger.c, if the NULL test on uvd is needed, then the dereference should be after the NULL test. In vpif_display.c, std_info is initialized to the address of a structure field. This seems unlikely to be NULL. Test std_info->stdid instead. In saa7134-alsa.c, the function is only called from one place, where the chip argument has already been dereferenced. On the other hand, if it should be kept, then card should be initialized after it. A simplified version of the semantic match that detects this problem is as follows (http://coccinelle.lip6.fr/): // @match exists@ expression x, E; identifier fld; @@ * x->fld ... when != \(x = E\|&x\) * x == NULL // Signed-off-by: Julia Lawall Acked-by: Muralidharan Karicheri Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/davinci/vpif_display.c | 2 +- drivers/media/video/saa7134/saa7134-alsa.c | 2 -- drivers/media/video/usbvideo/quickcam_messenger.c | 3 ++- 3 files changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/davinci/vpif_display.c b/drivers/media/video/davinci/vpif_display.c index 13c3a1b9776..e5bab3d0d53 100644 --- a/drivers/media/video/davinci/vpif_display.c +++ b/drivers/media/video/davinci/vpif_display.c @@ -384,7 +384,7 @@ static int vpif_get_std_info(struct channel_obj *ch) int index; std_info->stdid = vid_ch->stdid; - if (!std_info) + if (!std_info->stdid) return -1; for (index = 0; index < ARRAY_SIZE(ch_params); index++) { diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index d48c450ed77..d3bd82ad010 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c @@ -1011,8 +1011,6 @@ static int snd_card_saa7134_new_mixer(snd_card_saa7134_t * chip) unsigned int idx; int err, addr; - if (snd_BUG_ON(!chip)) - return -EINVAL; strcpy(card->mixername, "SAA7134 Mixer"); for (idx = 0; idx < ARRAY_SIZE(snd_saa7134_volume_controls); idx++) { diff --git a/drivers/media/video/usbvideo/quickcam_messenger.c b/drivers/media/video/usbvideo/quickcam_messenger.c index fab48ec6c0e..fbd665fa197 100644 --- a/drivers/media/video/usbvideo/quickcam_messenger.c +++ b/drivers/media/video/usbvideo/quickcam_messenger.c @@ -693,12 +693,13 @@ static int qcm_start_data(struct uvd *uvd) static void qcm_stop_data(struct uvd *uvd) { - struct qcm *cam = (struct qcm *) uvd->user_data; + struct qcm *cam; int i, j; int ret; if ((uvd == NULL) || (!uvd->streaming) || (uvd->dev == NULL)) return; + cam = (struct qcm *) uvd->user_data; ret = qcm_camera_off(uvd); if (ret) -- cgit v1.2.3-70-g09d2 From 4d36ec7fbf619a48c506eaa497d21619297a2b4f Mon Sep 17 00:00:00 2001 From: Huang Weiyi Date: Fri, 12 Mar 2010 11:12:22 -0300 Subject: V4L/DVB: tlg2300: remove unused #include Remove unused #include ('s) in drivers/media/video/tlg2300/pd-main.c Signed-off-by: Huang Weiyi Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tlg2300/pd-main.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/tlg2300/pd-main.c b/drivers/media/video/tlg2300/pd-main.c index 832b7c7b13d..c267e0cfb54 100644 --- a/drivers/media/video/tlg2300/pd-main.c +++ b/drivers/media/video/tlg2300/pd-main.c @@ -24,7 +24,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include #include #include -- cgit v1.2.3-70-g09d2 From a3415c15e1b5965c8efe0c0eb84b49689ed954ef Mon Sep 17 00:00:00 2001 From: Frank Schaefer Date: Sun, 14 Mar 2010 14:28:54 -0300 Subject: V4L/DVB: v4l2_ctrl_get_name(): add missing control names, and make title for V4L2_CID_BG_COLOR consistent v4l2_ctrl_get_name(): add missing control names, and make title for V4L2_CID_BG_COLOR consistent V4L2_CID_AUTOBRIGHTNESS was introduced with kernel 2.6.31 V4L2_CID_BAND_STOP_FILTER was introduced with kernel 2.6.32 Signed-off-by: Frank Schaefer Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-common.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index 36b5cb86fb5..e6798346100 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -431,8 +431,10 @@ const char *v4l2_ctrl_get_name(u32 id) case V4L2_CID_CHROMA_AGC: return "Chroma AGC"; case V4L2_CID_COLOR_KILLER: return "Color Killer"; case V4L2_CID_COLORFX: return "Color Effects"; + case V4L2_CID_AUTOBRIGHTNESS: return "Brightness, Automatic"; + case V4L2_CID_BAND_STOP_FILTER: return "Band-Stop Filter"; case V4L2_CID_ROTATE: return "Rotate"; - case V4L2_CID_BG_COLOR: return "Background color"; + case V4L2_CID_BG_COLOR: return "Background Color"; /* MPEG controls */ case V4L2_CID_MPEG_CLASS: return "MPEG Encoder Controls"; -- cgit v1.2.3-70-g09d2 From 8f27fd9605a28225bb71f2b3ade5d248231cd824 Mon Sep 17 00:00:00 2001 From: Vladimir Ermakov Date: Wed, 10 Mar 2010 12:44:57 -0300 Subject: V4L/DVB: saa7134: add capture boards Hawell HW-404M7 and HW-808M7 Adds new capture boards Hawell HW-404M7 and HW-808M7. Those cards have 4 or 8 SAA7130 chips and for the work it only needs initialize registers. The value of those registers were dumped under Windows using flytest. But board haven't EEPROM. For the first chip: SAA7130 (0x7130, SubVenID:1131, SubDevID:0000, Rev: 01) I2C slave devices found: No devices GPIO pins: Mode : 0x00389C00 Value: 0x00016C00 Video input: 3 Audio input: Analog Line1 For other chips: SAA7130 (0x7130, SubVenID:1131, SubDevID:0000, Rev: 01) I2C slave devices found: No devices GPIO pins: Mode : 0x00389200 Value: 0x00010000 Video input: 3 Audio input: Analog Line1 Signed-off-by: Vladimir Ermakov Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.saa7134 | 1 + drivers/media/video/saa7134/saa7134-cards.c | 17 +++++++++++++++++ drivers/media/video/saa7134/saa7134-input.c | 1 + drivers/media/video/saa7134/saa7134.h | 1 + 4 files changed, 20 insertions(+) (limited to 'drivers/media/video') diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index b4a767060ed..3de042a9c4f 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -175,3 +175,4 @@ 174 -> Asus Europa Hybrid OEM [1043:4847] 175 -> Leadtek Winfast DTV1000S [107d:6655] 176 -> Beholder BeholdTV 505 RDS [0000:5051] +177 -> Hawell HW-404M7 / HW-808M7 diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index aa07cb11e10..655068f6c49 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -5355,6 +5355,23 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE2, }, }, + [SAA7134_BOARD_HAWELL_HW_404M7] = { + /* Hawell HW-404M7 & Hawell HW-808M7 */ + /* Bogoslovskiy Viktor */ + .name = "Hawell HW-404M7", + .audio_clock = 0x00200000, + .tuner_type = UNSET, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .gpiomask = 0x01fc00, + .inputs = {{ + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + .gpio = 0x389c00, + } }, + }, }; diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index c1fe7c9369b..ac62b77e5ed 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -475,6 +475,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) switch (dev->board) { case SAA7134_BOARD_FLYVIDEO2000: case SAA7134_BOARD_FLYVIDEO3000: + case SAA7134_BOARD_HAWELL_HW_404M7: case SAA7134_BOARD_FLYTVPLATINUM_FM: case SAA7134_BOARD_FLYTVPLATINUM_MINI2: case SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM: diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index bf130967ed1..c3a1ae0adca 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -300,6 +300,7 @@ struct saa7134_format { #define SAA7134_BOARD_ASUS_EUROPA_HYBRID 174 #define SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S 175 #define SAA7134_BOARD_BEHOLD_505RDS_MK3 176 +#define SAA7134_BOARD_HAWELL_HW_404M7 177 #define SAA7134_MAXBOARDS 32 #define SAA7134_INPUT_MAX 8 -- cgit v1.2.3-70-g09d2 From 771075bb4667078687ae3c570a17c274f389e01e Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 13 Mar 2010 11:47:06 -0300 Subject: V4L/DVB: videobuf-core: fix spelling mistake in debug message Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c index bb0a1c8de41..471178e1701 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/video/videobuf-core.c @@ -567,7 +567,7 @@ int videobuf_qbuf(struct videobuf_queue *q, q->ops->buf_queue(q, buf); spin_unlock_irqrestore(q->irqlock, flags); } - dprintk(1, "qbuf: succeded\n"); + dprintk(1, "qbuf: succeeded\n"); retval = 0; wake_up_interruptible_sync(&q->wait); -- cgit v1.2.3-70-g09d2 From 9c33afc6102517764fb5d308dcf49bf42893da2c Mon Sep 17 00:00:00 2001 From: Jean-François Moine Date: Wed, 17 Mar 2010 15:25:32 -0300 Subject: V4L/DVB: gspca - sonixj: More static const and better array initialization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sonixj.c | 136 +++++++++++++++++++++---------------- 1 file changed, 78 insertions(+), 58 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 1d61b92f6bf..20ca161bc3d 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -67,17 +67,19 @@ struct sd { #define BRIDGE_SN9C110 2 #define BRIDGE_SN9C120 3 u8 sensor; /* Type of image sensor chip */ -#define SENSOR_ADCM1700 0 -#define SENSOR_HV7131R 1 -#define SENSOR_MI0360 2 -#define SENSOR_MO4000 3 -#define SENSOR_MT9V111 4 -#define SENSOR_OM6802 5 -#define SENSOR_OV7630 6 -#define SENSOR_OV7648 7 -#define SENSOR_OV7660 8 -#define SENSOR_PO1030 9 -#define SENSOR_SP80708 10 +enum { + SENSOR_ADCM1700, + SENSOR_HV7131R, + SENSOR_MI0360, + SENSOR_MO4000, + SENSOR_MT9V111, + SENSOR_OM6802, + SENSOR_OV7630, + SENSOR_OV7648, + SENSOR_OV7660, + SENSOR_PO1030, + SENSOR_SP80708, +} sensors; u8 i2c_addr; u8 *jpeg_hdr; @@ -281,29 +283,47 @@ static const struct ctrl sd_ctrls[] = { }; /* table of the disabled controls */ -static __u32 ctrl_dis[] = { - (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX) | - (1 << AUTOGAIN_IDX), /* SENSOR_ADCM1700 0 */ - (1 << INFRARED_IDX) | (1 << FREQ_IDX), - /* SENSOR_HV7131R 1 */ - (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX), - /* SENSOR_MI0360 2 */ - (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX), - /* SENSOR_MO4000 3 */ - (1 << VFLIP_IDX) | (1 << FREQ_IDX), - /* SENSOR_MT9V111 4 */ - (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX), - /* SENSOR_OM6802 5 */ - (1 << INFRARED_IDX), - /* SENSOR_OV7630 6 */ - (1 << INFRARED_IDX), - /* SENSOR_OV7648 7 */ - (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX), - /* SENSOR_OV7660 8 */ - (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | - (1 << FREQ_IDX), /* SENSOR_PO1030 9 */ - (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | - (1 << FREQ_IDX), /* SENSOR_SP80708 10 */ +static const __u32 ctrl_dis[] = { +[SENSOR_ADCM1700] = (1 << AUTOGAIN_IDX) | + (1 << INFRARED_IDX) | + (1 << VFLIP_IDX) | + (1 << FREQ_IDX), + +[SENSOR_HV7131R] = (1 << INFRARED_IDX) | + (1 << FREQ_IDX), + +[SENSOR_MI0360] = (1 << INFRARED_IDX) | + (1 << VFLIP_IDX) | + (1 << FREQ_IDX), + +[SENSOR_MO4000] = (1 << INFRARED_IDX) | + (1 << VFLIP_IDX) | + (1 << FREQ_IDX), + +[SENSOR_MT9V111] = (1 << VFLIP_IDX) | + (1 << FREQ_IDX), + +[SENSOR_OM6802] = (1 << INFRARED_IDX) | + (1 << VFLIP_IDX) | + (1 << FREQ_IDX), + +[SENSOR_OV7630] = (1 << INFRARED_IDX), + +[SENSOR_OV7648] = (1 << INFRARED_IDX), + +[SENSOR_OV7660] = (1 << AUTOGAIN_IDX) | + (1 << INFRARED_IDX) | + (1 << VFLIP_IDX), + +[SENSOR_PO1030] = (1 << AUTOGAIN_IDX) | + (1 << INFRARED_IDX) | + (1 << VFLIP_IDX) | + (1 << FREQ_IDX), + +[SENSOR_SP80708] = (1 << AUTOGAIN_IDX) | + (1 << INFRARED_IDX) | + (1 << VFLIP_IDX) | + (1 << FREQ_IDX), }; static const struct v4l2_pix_format cif_mode[] = { @@ -456,17 +476,17 @@ static const u8 sn_sp80708[0x1c] = { /* sequence specific to the sensors - !! index = SENSOR_xxx */ static const u8 *sn_tb[] = { - sn_adcm1700, - sn_hv7131, - sn_mi0360, - sn_mo4000, - sn_mt9v111, - sn_om6802, - sn_ov7630, - sn_ov7648, - sn_ov7660, - sn_po1030, - sn_sp80708 +[SENSOR_ADCM1700] = sn_adcm1700, +[SENSOR_HV7131R] = sn_hv7131, +[SENSOR_MI0360] = sn_mi0360, +[SENSOR_MO4000] = sn_mo4000, +[SENSOR_MT9V111] = sn_mt9v111, +[SENSOR_OM6802] = sn_om6802, +[SENSOR_OV7630] = sn_ov7630, +[SENSOR_OV7648] = sn_ov7648, +[SENSOR_OV7660] = sn_ov7660, +[SENSOR_PO1030] = sn_po1030, +[SENSOR_SP80708] = sn_sp80708 }; /* default gamma table */ @@ -1069,18 +1089,18 @@ static const u8 sp80708_sensor_param1[][8] = { {} }; -static const u8 (*sensor_init[11])[8] = { - adcm1700_sensor_init, /* ADCM1700 0 */ - hv7131r_sensor_init, /* HV7131R 1 */ - mi0360_sensor_init, /* MI0360 2 */ - mo4000_sensor_init, /* MO4000 3 */ - mt9v111_sensor_init, /* MT9V111 4 */ - om6802_sensor_init, /* OM6802 5 */ - ov7630_sensor_init, /* OV7630 6 */ - ov7648_sensor_init, /* OV7648 7 */ - ov7660_sensor_init, /* OV7660 8 */ - po1030_sensor_init, /* PO1030 9 */ - sp80708_sensor_init, /* SP80708 10 */ +static const u8 (*sensor_init[])[8] = { +[SENSOR_ADCM1700] = adcm1700_sensor_init, +[SENSOR_HV7131R] = hv7131r_sensor_init, +[SENSOR_MI0360] = mi0360_sensor_init, +[SENSOR_MO4000] = mo4000_sensor_init, +[SENSOR_MT9V111] = mt9v111_sensor_init, +[SENSOR_OM6802] = om6802_sensor_init, +[SENSOR_OV7630] = ov7630_sensor_init, +[SENSOR_OV7648] = ov7648_sensor_init, +[SENSOR_OV7660] = ov7660_sensor_init, +[SENSOR_PO1030] = po1030_sensor_init, +[SENSOR_SP80708] = sp80708_sensor_init, }; /* read bytes to gspca_dev->usb_buf */ @@ -1703,7 +1723,7 @@ static void setcolors(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; int i, v; u8 reg8a[12]; /* U & V gains */ - static s16 uv[6] = { /* same as reg84 in signed decimal */ + static const s16 uv[6] = { /* same as reg84 in signed decimal */ -24, -38, 64, /* UR UG UB */ 62, -51, -9 /* VR VG VB */ }; -- cgit v1.2.3-70-g09d2 From ad98c0f674796848c6fd8fe614ef83ef971ebfcf Mon Sep 17 00:00:00 2001 From: Jean-François Moine Date: Thu, 18 Mar 2010 05:15:30 -0300 Subject: V4L/DVB: gspca - sonixj: Add webcam 0c45:6142 with sensors gc0307 and po2030n MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/gspca.txt | 1 + drivers/media/video/gspca/sonixj.c | 297 +++++++++++++++++++++++++++++++++++- 2 files changed, 290 insertions(+), 8 deletions(-) (limited to 'drivers/media/video') diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt index 181b9e6fd98..9475e1e1441 100644 --- a/Documentation/video4linux/gspca.txt +++ b/Documentation/video4linux/gspca.txt @@ -305,6 +305,7 @@ sonixj 0c45:6138 Sn9c120 Mo4000 sonixj 0c45:613a Microdia Sonix PC Camera sonixj 0c45:613b Surfer SN-206 sonixj 0c45:613c Sonix Pccam168 +sonixj 0c45:6142 Hama PC-Webcam AC-150 sonixj 0c45:6143 Sonix Pccam168 sonixj 0c45:6148 Digitus DA-70811/ZSMC USB PC Camera ZS211/Microdia sonixj 0c45:614a Frontech E-Ccam (JIL-2225) diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 20ca161bc3d..aaa68ddb1fb 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -69,6 +69,7 @@ struct sd { u8 sensor; /* Type of image sensor chip */ enum { SENSOR_ADCM1700, + SENSOR_GC0307, SENSOR_HV7131R, SENSOR_MI0360, SENSOR_MO4000, @@ -78,6 +79,7 @@ enum { SENSOR_OV7648, SENSOR_OV7660, SENSOR_PO1030, + SENSOR_PO2030N, SENSOR_SP80708, } sensors; u8 i2c_addr; @@ -289,6 +291,11 @@ static const __u32 ctrl_dis[] = { (1 << VFLIP_IDX) | (1 << FREQ_IDX), +[SENSOR_GC0307] = (1 << AUTOGAIN_IDX) | + (1 << INFRARED_IDX) | + (1 << VFLIP_IDX) | + (1 << FREQ_IDX), + [SENSOR_HV7131R] = (1 << INFRARED_IDX) | (1 << FREQ_IDX), @@ -320,6 +327,11 @@ static const __u32 ctrl_dis[] = { (1 << VFLIP_IDX) | (1 << FREQ_IDX), +[SENSOR_PO2030N] = (1 << AUTOGAIN_IDX) | + (1 << INFRARED_IDX) | + (1 << VFLIP_IDX) | + (1 << FREQ_IDX), + [SENSOR_SP80708] = (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | @@ -363,7 +375,17 @@ static const u8 sn_adcm1700[0x1c] = { 0x06, 0x00, 0x00, 0x00 }; -/*Data from sn9c102p+hv7131r */ +static const u8 sn_gc0307[0x1c] = { +/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ + 0x00, 0x61, 0x62, 0x00, 0x1a, 0x00, 0x00, 0x00, +/* reg8 reg9 rega regb regc regd rege regf */ + 0x80, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ + 0x03, 0x00, 0x03, 0x01, 0x08, 0x28, 0x1e, 0x02, +/* reg18 reg19 reg1a reg1b */ + 0x06, 0x00, 0x00, 0x00 +}; + static const u8 sn_hv7131[0x1c] = { /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ 0x00, 0x03, 0x64, 0x00, 0x1a, 0x20, 0x20, 0x20, @@ -463,6 +485,17 @@ static const u8 sn_po1030[0x1c] = { 0x07, 0x00, 0x00, 0x00 }; +static const u8 sn_po2030n[0x1c] = { +/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ + 0x00, 0x63, 0x40, 0x00, 0x1a, 0x00, 0x00, 0x00, +/* reg8 reg9 rega regb regc regd rege regf */ + 0x81, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ + 0x03, 0x00, 0x00, 0x01, 0x14, 0x28, 0x1e, 0x00, +/* reg18 reg19 reg1a reg1b */ + 0x07, 0x00, 0x00, 0x00 +}; + static const u8 sn_sp80708[0x1c] = { /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ 0x00, 0x63, 0x60, 0x00, 0x1a, 0x20, 0x20, 0x20, @@ -477,6 +510,7 @@ static const u8 sn_sp80708[0x1c] = { /* sequence specific to the sensors - !! index = SENSOR_xxx */ static const u8 *sn_tb[] = { [SENSOR_ADCM1700] = sn_adcm1700, +[SENSOR_GC0307] = sn_gc0307, [SENSOR_HV7131R] = sn_hv7131, [SENSOR_MI0360] = sn_mi0360, [SENSOR_MO4000] = sn_mo4000, @@ -486,6 +520,7 @@ static const u8 *sn_tb[] = { [SENSOR_OV7648] = sn_ov7648, [SENSOR_OV7660] = sn_ov7660, [SENSOR_PO1030] = sn_po1030, +[SENSOR_PO2030N] = sn_po2030n, [SENSOR_SP80708] = sn_sp80708 }; @@ -504,8 +539,13 @@ static const u8 gamma_spec_1[17] = { 0x08, 0x3a, 0x52, 0x65, 0x75, 0x83, 0x91, 0x9d, 0xa9, 0xb4, 0xbe, 0xc8, 0xd2, 0xdb, 0xe4, 0xed, 0xf5 }; -/* gamma for sensor SP80708 */ +/* gamma for sensor GC0307 */ static const u8 gamma_spec_2[17] = { + 0x14, 0x37, 0x50, 0x6a, 0x7c, 0x8d, 0x9d, 0xab, + 0xb5, 0xbf, 0xc2, 0xcb, 0xd1, 0xd6, 0xdb, 0xe1, 0xeb +}; +/* gamma for sensor SP80708 */ +static const u8 gamma_spec_3[17] = { 0x0a, 0x2d, 0x4e, 0x68, 0x7d, 0x8f, 0x9f, 0xab, 0xb7, 0xc2, 0xcc, 0xd3, 0xd8, 0xde, 0xe2, 0xe5, 0xe6 }; @@ -553,6 +593,64 @@ static const u8 adcm1700_sensor_param1[][8] = { {0xb0, 0x51, 0x32, 0x00, 0xa2, 0x00, 0x00, 0x10}, {} }; +static const u8 gc0307_sensor_init[][8] = { + {0xa0, 0x21, 0x43, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x21, 0x44, 0xa2, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x21, 0x01, 0x6a, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x21, 0x02, 0x70, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x21, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x21, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x21, 0x11, 0x05, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x21, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x21, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x21, 0x08, 0x02, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x21, 0x09, 0x01, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x21, 0x0a, 0xe8, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x21, 0x0b, 0x02, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x21, 0x0c, 0x80, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x21, 0x0d, 0x22, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x21, 0x0e, 0x02, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x21, 0x0f, 0xb2, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x21, 0x12, 0x70, 0x00, 0x00, 0x00, 0x10}, + {0xdd, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*delay 10ms*/ + {0xa0, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x21, 0x15, 0xb8, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x21, 0x16, 0x13, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x21, 0x17, 0x52, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x21, 0x18, 0x50, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x21, 0x1e, 0x0d, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x21, 0x1f, 0x32, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x21, 0x61, 0x90, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x21, 0x63, 0x70, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x21, 0x65, 0x98, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x21, 0x67, 0x90, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x21, 0x04, 0x96, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x21, 0x45, 0x27, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x21, 0x47, 0x2c, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x21, 0x43, 0x47, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x21, 0x44, 0xd8, 0x00, 0x00, 0x00, 0x10}, + {} +}; +static const u8 gc0307_sensor_param1[][8] = { + {0xa0, 0x21, 0x68, 0x13, 0x00, 0x00, 0x00, 0x10}, + {0xd0, 0x21, 0x61, 0x80, 0x00, 0x80, 0x00, 0x10}, + {0xc0, 0x21, 0x65, 0x80, 0x00, 0x80, 0x00, 0x10}, + {0xc0, 0x21, 0x63, 0xa0, 0x00, 0xa6, 0x00, 0x10}, +/*param3*/ + {0xa0, 0x21, 0x01, 0x6e, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x21, 0x02, 0x88, 0x00, 0x00, 0x00, 0x10}, + + {0xa0, 0x21, 0x68, 0x22, 0x00, 0x00, 0x00, 0x10}, + {0xdd, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0xa0, 0x21, 0x03, 0x07, 0x00, 0x00, 0x00, 0x10}, + {0xdd, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0xa0, 0x21, 0x04, 0x91, 0x00, 0x00, 0x00, 0x10}, + {} +}; + static const u8 hv7131r_sensor_init[][8] = { {0xc1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10}, {0xb1, 0x11, 0x34, 0x17, 0x7f, 0x00, 0x00, 0x10}, @@ -1004,6 +1102,82 @@ static const u8 po1030_sensor_param1[][8] = { {} }; +static const u8 po2030n_sensor_init[][8] = { + {0xa1, 0x6e, 0x1e, 0x1a, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x6e, 0x1f, 0x99, 0x00, 0x00, 0x00, 0x10}, + {0xdd, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 10ms */ + {0xa1, 0x6e, 0x1e, 0x0a, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x6e, 0x1f, 0x19, 0x00, 0x00, 0x00, 0x10}, + {0xdd, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 10ms */ + {0xa1, 0x6e, 0x20, 0x44, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x6e, 0x04, 0x03, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x6e, 0x05, 0x70, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x6e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x6e, 0x07, 0x25, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x6e, 0x08, 0x00, 0xd0, 0x00, 0x08, 0x10}, + {0xd1, 0x6e, 0x0c, 0x03, 0x50, 0x01, 0xe8, 0x10}, + {0xd1, 0x6e, 0x1d, 0x20, 0x0a, 0x19, 0x44, 0x10}, + {0xd1, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x6e, 0x25, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x6e, 0x29, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x6e, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x6e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x6e, 0x35, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x6e, 0x39, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x6e, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x6e, 0x41, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x6e, 0x45, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x6e, 0x49, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x6e, 0x4d, 0x00, 0x00, 0x00, 0xed, 0x10}, + {0xd1, 0x6e, 0x51, 0x17, 0x4a, 0x2f, 0xc0, 0x10}, + {0xd1, 0x6e, 0x55, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x6e, 0x59, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x6e, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x6e, 0x61, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x6e, 0x65, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x6e, 0x69, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x6e, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x6e, 0x71, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x6e, 0x75, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x6e, 0x79, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x6e, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x6e, 0x81, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x6e, 0x85, 0x00, 0x00, 0x00, 0x08, 0x10}, + {0xd1, 0x6e, 0x89, 0x01, 0xe8, 0x00, 0x01, 0x10}, + {0xa1, 0x6e, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x6e, 0x25, 0x00, 0x00, 0x00, 0x01, 0x10}, + {0xd1, 0x6e, 0x29, 0xe6, 0x00, 0xbd, 0x03, 0x10}, + {0xd1, 0x6e, 0x2d, 0x41, 0x38, 0x68, 0x40, 0x10}, + {0xd1, 0x6e, 0x31, 0x2b, 0x00, 0x36, 0x00, 0x10}, + {0xd1, 0x6e, 0x35, 0x30, 0x30, 0x08, 0x00, 0x10}, + {0xd1, 0x6e, 0x39, 0x00, 0x00, 0x33, 0x06, 0x10}, + {0xb1, 0x6e, 0x3d, 0x06, 0x02, 0x00, 0x00, 0x10}, + {} +}; +static const u8 po2030n_sensor_param1[][8] = { + {0xa1, 0x6e, 0x1a, 0x01, 0x00, 0x00, 0x00, 0x10}, + {0xdd, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 8ms */ + {0xa1, 0x6e, 0x1b, 0xf4, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x6e, 0x15, 0x04, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x6e, 0x16, 0x50, 0x40, 0x49, 0x40, 0x10}, +/*param2*/ + {0xa1, 0x6e, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x6e, 0x04, 0x03, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x6e, 0x05, 0x6f, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x6e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x6e, 0x07, 0x25, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x6e, 0x15, 0x04, 0x00, 0x00, 0x00, 0x10}, + {0xc1, 0x6e, 0x16, 0x52, 0x40, 0x48, 0x00, 0x10}, +/*after start*/ + {0xa1, 0x6e, 0x15, 0x0f, 0x00, 0x00, 0x00, 0x10}, + {0xdd, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 5ms */ + {0xa1, 0x6e, 0x1a, 0x05, 0x00, 0x00, 0x00, 0x10}, + {0xdd, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 5ms */ + {0xa1, 0x6e, 0x1b, 0x53, 0x00, 0x00, 0x00, 0x10}, + {} +}; + static const u8 sp80708_sensor_init[][8] = { {0xa1, 0x18, 0x06, 0xf9, 0x00, 0x00, 0x00, 0x10}, {0xa1, 0x18, 0x09, 0x1f, 0x00, 0x00, 0x00, 0x10}, @@ -1091,6 +1265,7 @@ static const u8 sp80708_sensor_param1[][8] = { static const u8 (*sensor_init[])[8] = { [SENSOR_ADCM1700] = adcm1700_sensor_init, +[SENSOR_GC0307] = gc0307_sensor_init, [SENSOR_HV7131R] = hv7131r_sensor_init, [SENSOR_MI0360] = mi0360_sensor_init, [SENSOR_MO4000] = mo4000_sensor_init, @@ -1100,6 +1275,7 @@ static const u8 (*sensor_init[])[8] = { [SENSOR_OV7648] = ov7648_sensor_init, [SENSOR_OV7660] = ov7660_sensor_init, [SENSOR_PO1030] = po1030_sensor_init, +[SENSOR_PO2030N] = po2030n_sensor_init, [SENSOR_SP80708] = sp80708_sensor_init, }; @@ -1169,7 +1345,8 @@ static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val) PDEBUG(D_USBO, "i2c_w2 [%02x] = %02x", reg, val); switch (sd->sensor) { case SENSOR_ADCM1700: - case SENSOR_OM6802: /* i2c command = a0 (100 kHz) */ + case SENSOR_OM6802: + case SENSOR_GC0307: /* i2c command = a0 (100 kHz) */ gspca_dev->usb_buf[0] = 0x80 | (2 << 4); break; default: /* i2c command = a1 (400 kHz) */ @@ -1216,7 +1393,8 @@ static void i2c_r(struct gspca_dev *gspca_dev, u8 reg, int len) switch (sd->sensor) { case SENSOR_ADCM1700: - case SENSOR_OM6802: /* i2c command = 90 (100 kHz) */ + case SENSOR_OM6802: + case SENSOR_GC0307: /* i2c command = a0 (100 kHz) */ mode[0] = 0x80 | 0x10; break; default: /* i2c command = 91 (400 kHz) */ @@ -1355,6 +1533,46 @@ static void ov7648_probe(struct gspca_dev *gspca_dev) gspca_dev->usb_buf[3], gspca_dev->usb_buf[4]); } +/* 0c45:6142 sensor may be po2030n, gc0305 or gc0307 */ +static void po2030n_probe(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + + /* check gc0307 */ + reg_w1(gspca_dev, 0x17, 0x62); + reg_w1(gspca_dev, 0x01, 0x08); + reg_w1(gspca_dev, 0x02, 0x22); + sd->i2c_addr = 0x21; + i2c_r(gspca_dev, 0x00, 1); + + reg_w1(gspca_dev, 0x01, 0x29); /* reset */ + reg_w1(gspca_dev, 0x17, 0x42); + + if (gspca_dev->usb_buf[4] == 0x99) { /* gc0307 (?) */ + PDEBUG(D_PROBE, "Sensor gc0307"); + sd->sensor = SENSOR_GC0307; + return; + } + + /* check po2030n */ + reg_w1(gspca_dev, 0x17, 0x62); + reg_w1(gspca_dev, 0x01, 0x0a); + sd->i2c_addr = 0x6e; + i2c_r(gspca_dev, 0x00, 2); + + reg_w1(gspca_dev, 0x01, 0x29); + reg_w1(gspca_dev, 0x17, 0x42); + + if (gspca_dev->usb_buf[3] == 0x20 + && gspca_dev->usb_buf[4] == 0x30) + PDEBUG(D_PROBE, "Sensor po2030n"); +/* sd->sensor = SENSOR_PO2030N; */ + else + PDEBUG(D_PROBE, "Unknown sensor ID %02x%02x", + gspca_dev->usb_buf[3], + gspca_dev->usb_buf[4]); +} + static void bridge_init(struct gspca_dev *gspca_dev, const u8 *sn9c1xx) { @@ -1375,8 +1593,10 @@ static void bridge_init(struct gspca_dev *gspca_dev, reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2); reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); switch (sd->sensor) { + case SENSOR_GC0307: case SENSOR_OV7660: case SENSOR_PO1030: + case SENSOR_PO2030N: case SENSOR_SP80708: reg9a = reg9a_spec; break; @@ -1397,6 +1617,14 @@ static void bridge_init(struct gspca_dev *gspca_dev, reg_w1(gspca_dev, 0x01, 0x42); reg_w1(gspca_dev, 0x01, 0x42); break; + case SENSOR_GC0307: + msleep(50); + reg_w1(gspca_dev, 0x01, 0x61); + reg_w1(gspca_dev, 0x17, 0x22); + reg_w1(gspca_dev, 0x01, 0x60); + reg_w1(gspca_dev, 0x01, 0x40); + msleep(50); + break; case SENSOR_MT9V111: reg_w1(gspca_dev, 0x01, 0x61); reg_w1(gspca_dev, 0x17, 0x61); @@ -1439,6 +1667,12 @@ static void bridge_init(struct gspca_dev *gspca_dev, reg_w1(gspca_dev, 0x01, 0x60); reg_w1(gspca_dev, 0x01, 0x40); break; + case SENSOR_PO2030N: + reg_w1(gspca_dev, 0x01, 0x63); + reg_w1(gspca_dev, 0x17, 0x20); + reg_w1(gspca_dev, 0x01, 0x62); + reg_w1(gspca_dev, 0x01, 0x42); + break; case SENSOR_OV7660: /* fall thru */ case SENSOR_SP80708: @@ -1546,6 +1780,9 @@ static int sd_init(struct gspca_dev *gspca_dev) case SENSOR_OV7648: ov7648_probe(gspca_dev); break; + case SENSOR_PO2030N: + po2030n_probe(gspca_dev); + break; } regGpio[1] = 0x70; reg_w(gspca_dev, 0x01, regGpio, 2); @@ -1764,9 +2001,12 @@ static void setgamma(struct gspca_dev *gspca_dev) case SENSOR_MT9V111: gamma_base = gamma_spec_1; break; - case SENSOR_SP80708: + case SENSOR_GC0307: gamma_base = gamma_spec_2; break; + case SENSOR_SP80708: + gamma_base = gamma_spec_3; + break; default: gamma_base = gamma_def; break; @@ -1957,9 +2197,15 @@ static int sd_start(struct gspca_dev *gspca_dev) static const u8 CA[] = { 0x28, 0xd8, 0x14, 0xec }; static const u8 CA_adcm1700[] = { 0x14, 0xec, 0x0a, 0xf6 }; + static const u8 CA_po2030n[] = + { 0x1e, 0xe2, 0x14, 0xec }; static const u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */ + static const u8 CE_gc0307[] = + { 0x32, 0xce, 0x2d, 0xd3 }; static const u8 CE_ov76xx[] = { 0x32, 0xdd, 0x32, 0xdd }; + static const u8 CE_po2030n[] = + { 0x14, 0xe7, 0x1e, 0xdd }; /* create the JPEG header */ sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); @@ -2016,6 +2262,9 @@ static int sd_start(struct gspca_dev *gspca_dev) } reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]); switch (sd->sensor) { + case SENSOR_GC0307: + reg17 = 0xa2; + break; case SENSOR_MT9V111: reg17 = 0xe0; break; @@ -2030,6 +2279,7 @@ static int sd_start(struct gspca_dev *gspca_dev) reg17 = 0xa0; break; case SENSOR_PO1030: + case SENSOR_PO2030N: reg17 = 0xa0; break; default: @@ -2054,12 +2304,16 @@ static int sd_start(struct gspca_dev *gspca_dev) case SENSOR_SP80708: reg_w1(gspca_dev, 0x9a, 0x05); break; + case SENSOR_GC0307: case SENSOR_MT9V111: reg_w1(gspca_dev, 0x9a, 0x07); break; case SENSOR_OV7648: reg_w1(gspca_dev, 0x9a, 0x0a); break; + case SENSOR_PO2030N: + reg_w1(gspca_dev, 0x9a, 0x06); + break; default: reg_w1(gspca_dev, 0x9a, 0x08); break; @@ -2084,6 +2338,11 @@ static int sd_start(struct gspca_dev *gspca_dev) reg1 = 0x46; reg17 = 0xe2; break; + case SENSOR_GC0307: + init = gc0307_sensor_param1; + reg17 = 0xa2; + reg1 = 0x44; + break; case SENSOR_MO4000: if (mode) { /* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */ @@ -2133,6 +2392,11 @@ static int sd_start(struct gspca_dev *gspca_dev) reg17 = 0xa2; reg1 = 0x44; break; + case SENSOR_PO2030N: + init = po2030n_sensor_param1; + reg1 = 0x46; + reg17 = 0xa2; + break; default: /* case SENSOR_SP80708: */ init = sp80708_sensor_param1; @@ -2152,10 +2416,18 @@ static int sd_start(struct gspca_dev *gspca_dev) } reg_w(gspca_dev, 0xc0, C0, 6); - if (sd->sensor == SENSOR_ADCM1700) + switch (sd->sensor) { + case SENSOR_ADCM1700: + case SENSOR_GC0307: reg_w(gspca_dev, 0xca, CA_adcm1700, 4); - else + break; + case SENSOR_PO2030N: + reg_w(gspca_dev, 0xca, CA_po2030n, 4); + break; + default: reg_w(gspca_dev, 0xca, CA, 4); + break; + } switch (sd->sensor) { case SENSOR_ADCM1700: case SENSOR_OV7630: @@ -2163,6 +2435,12 @@ static int sd_start(struct gspca_dev *gspca_dev) case SENSOR_OV7660: reg_w(gspca_dev, 0xce, CE_ov76xx, 4); break; + case SENSOR_GC0307: + reg_w(gspca_dev, 0xce, CE_gc0307, 4); + break; + case SENSOR_PO2030N: + reg_w(gspca_dev, 0xce, CE_po2030n, 4); + break; default: reg_w(gspca_dev, 0xce, CE, 4); /* ?? {0x1e, 0xdd, 0x2d, 0xe7} */ @@ -2200,6 +2478,9 @@ static void sd_stopN(struct gspca_dev *gspca_dev) data = 0x0b; switch (sd->sensor) { + case SENSOR_GC0307: + data = 0x29; + break; case SENSOR_HV7131R: i2c_w8(gspca_dev, stophv7131); data = 0x2b; @@ -2676,7 +2957,7 @@ static const __devinitdata struct usb_device_id device_table[] = { #endif {USB_DEVICE(0x0c45, 0x613c), BS(SN9C120, HV7131R)}, {USB_DEVICE(0x0c45, 0x613e), BS(SN9C120, OV7630)}, -/* {USB_DEVICE(0x0c45, 0x6142), BS(SN9C120, PO2030N)}, *sn9c120b*/ + {USB_DEVICE(0x0c45, 0x6142), BS(SN9C120, PO2030N)}, /*sn9c120b*/ {USB_DEVICE(0x0c45, 0x6143), BS(SN9C120, SP80708)}, /*sn9c120b*/ {USB_DEVICE(0x0c45, 0x6148), BS(SN9C120, OM6802)}, /*sn9c120b*/ {USB_DEVICE(0x0c45, 0x614a), BS(SN9C120, ADCM1700)}, /*sn9c120b*/ -- cgit v1.2.3-70-g09d2 From a39db27a08ef85ae37beab261744d8b38f21225c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 18 May 2010 00:49:44 -0300 Subject: V4L/DVB: gspca - sn9c20x: use gspca's input device handling Drop custom code for handling the input button in favor of using gspca's input hanlding mechinism. Signed-off-by: Brian Johnson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/Kconfig | 6 -- drivers/media/video/gspca/sn9c20x.c | 147 +++++++++--------------------------- 2 files changed, 34 insertions(+), 119 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig index e0060c1f054..5d920e584de 100644 --- a/drivers/media/video/gspca/Kconfig +++ b/drivers/media/video/gspca/Kconfig @@ -172,12 +172,6 @@ config USB_GSPCA_SN9C20X To compile this driver as a module, choose M here: the module will be called gspca_sn9c20x. -config USB_GSPCA_SN9C20X_EVDEV - bool "Enable evdev support" - depends on USB_GSPCA_SN9C20X && INPUT - ---help--- - Say Y here in order to enable evdev support for sn9c20x webcam button. - config USB_GSPCA_SONIXB tristate "SONIX Bayer USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c index 04bf80ddfbb..1653567e992 100644 --- a/drivers/media/video/gspca/sn9c20x.c +++ b/drivers/media/video/gspca/sn9c20x.c @@ -18,10 +18,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef CONFIG_USB_GSPCA_SN9C20X_EVDEV -#include -#include -#include +#ifdef CONFIG_INPUT #include #include #endif @@ -55,6 +52,9 @@ MODULE_LICENSE("GPL"); #define SENSOR_HV7131R 10 #define SENSOR_MT9VPRB 20 +/* camera flags */ +#define HAS_BUTTON 0x1 + /* specific webcam descriptor */ struct sd { struct gspca_dev gspca_dev; @@ -88,11 +88,7 @@ struct sd { u8 *jpeg_hdr; u8 quality; -#ifdef CONFIG_USB_GSPCA_SN9C20X_EVDEV - struct input_dev *input_dev; - u8 input_gpio; - struct task_struct *input_task; -#endif + u8 flags; }; struct i2c_reg_u8 { @@ -1421,87 +1417,6 @@ static int hv7131r_init_sensor(struct gspca_dev *gspca_dev) return 0; } -#ifdef CONFIG_USB_GSPCA_SN9C20X_EVDEV -static int input_kthread(void *data) -{ - struct gspca_dev *gspca_dev = (struct gspca_dev *)data; - struct sd *sd = (struct sd *) gspca_dev; - - DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wait); - set_freezable(); - for (;;) { - if (kthread_should_stop()) - break; - - if (reg_r(gspca_dev, 0x1005, 1) < 0) - continue; - - input_report_key(sd->input_dev, - KEY_CAMERA, - gspca_dev->usb_buf[0] & sd->input_gpio); - input_sync(sd->input_dev); - - wait_event_freezable_timeout(wait, - kthread_should_stop(), - msecs_to_jiffies(100)); - } - return 0; -} - - -static int sn9c20x_input_init(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - if (sd->input_gpio == 0) - return 0; - - sd->input_dev = input_allocate_device(); - if (!sd->input_dev) - return -ENOMEM; - - sd->input_dev->name = "SN9C20X Webcam"; - - sd->input_dev->phys = kasprintf(GFP_KERNEL, "usb-%s-%s", - gspca_dev->dev->bus->bus_name, - gspca_dev->dev->devpath); - - if (!sd->input_dev->phys) - return -ENOMEM; - - usb_to_input_id(gspca_dev->dev, &sd->input_dev->id); - sd->input_dev->dev.parent = &gspca_dev->dev->dev; - - set_bit(EV_KEY, sd->input_dev->evbit); - set_bit(KEY_CAMERA, sd->input_dev->keybit); - - if (input_register_device(sd->input_dev)) - return -EINVAL; - - sd->input_task = kthread_run(input_kthread, gspca_dev, "sn9c20x/%s-%s", - gspca_dev->dev->bus->bus_name, - gspca_dev->dev->devpath); - - if (IS_ERR(sd->input_task)) - return -EINVAL; - - return 0; -} - -static void sn9c20x_input_cleanup(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - if (sd->input_task != NULL && !IS_ERR(sd->input_task)) - kthread_stop(sd->input_task); - - if (sd->input_dev != NULL) { - input_unregister_device(sd->input_dev); - kfree(sd->input_dev->phys); - input_free_device(sd->input_dev); - sd->input_dev = NULL; - } -} -#endif - static int set_cmatrix(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -2005,6 +1920,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->sensor = (id->driver_info >> 8) & 0xff; sd->i2c_addr = id->driver_info & 0xff; + sd->flags = (id->driver_info >> 16) & 0xff; switch (sd->sensor) { case SENSOR_MT9M111: @@ -2039,11 +1955,6 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->quality = 95; -#ifdef CONFIG_USB_GSPCA_SN9C20X_EVDEV - sd->input_gpio = (id->driver_info >> 16) & 0xff; - if (sn9c20x_input_init(gspca_dev) < 0) - return -ENODEV; -#endif return 0; } @@ -2343,6 +2254,24 @@ static void sd_dqcallback(struct gspca_dev *gspca_dev) do_autoexposure(gspca_dev, avg_lum); } +#ifdef CONFIG_INPUT +static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, + u8 *data, /* interrupt packet */ + int len) /* interrupt packet length */ +{ + struct sd *sd = (struct sd *) gspca_dev; + int ret = -EINVAL; + if (sd->flags & HAS_BUTTON && len == 1) { + input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); + input_sync(gspca_dev->input_dev); + input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); + input_sync(gspca_dev->input_dev); + ret = 0; + } + return ret; +} +#endif + static void sd_pkt_scan(struct gspca_dev *gspca_dev, u8 *data, /* isoc packet */ int len) /* iso packet length */ @@ -2409,6 +2338,9 @@ static const struct sd_desc sd_desc = { .stopN = sd_stopN, .stop0 = sd_stop0, .pkt_scan = sd_pkt_scan, +#ifdef CONFIG_INPUT + .int_pkt_scan = sd_int_pkt_scan, +#endif .dq_callback = sd_dqcallback, #ifdef CONFIG_VIDEO_ADV_DEBUG .set_register = sd_dbg_s_register, @@ -2417,8 +2349,8 @@ static const struct sd_desc sd_desc = { .get_chip_ident = sd_chip_ident, }; -#define SN9C20X(sensor, i2c_addr, button_mask) \ - .driver_info = (button_mask << 16) \ +#define SN9C20X(sensor, i2c_addr, flags) \ + .driver_info = (flags << 16) \ | (SENSOR_ ## sensor << 8) \ | (i2c_addr) @@ -2426,7 +2358,7 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x0c45, 0x6240), SN9C20X(MT9M001, 0x5d, 0)}, {USB_DEVICE(0x0c45, 0x6242), SN9C20X(MT9M111, 0x5d, 0)}, {USB_DEVICE(0x0c45, 0x6248), SN9C20X(OV9655, 0x30, 0)}, - {USB_DEVICE(0x0c45, 0x624e), SN9C20X(SOI968, 0x30, 0x10)}, + {USB_DEVICE(0x0c45, 0x624e), SN9C20X(SOI968, 0x30, HAS_BUTTON)}, {USB_DEVICE(0x0c45, 0x624f), SN9C20X(OV9650, 0x30, 0)}, {USB_DEVICE(0x0c45, 0x6251), SN9C20X(OV9650, 0x30, 0)}, {USB_DEVICE(0x0c45, 0x6253), SN9C20X(OV9650, 0x30, 0)}, @@ -2437,13 +2369,13 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x0c45, 0x627f), SN9C20X(OV9650, 0x30, 0)}, {USB_DEVICE(0x0c45, 0x6280), SN9C20X(MT9M001, 0x5d, 0)}, {USB_DEVICE(0x0c45, 0x6282), SN9C20X(MT9M111, 0x5d, 0)}, - {USB_DEVICE(0x0c45, 0x6288), SN9C20X(OV9655, 0x30, 0)}, + {USB_DEVICE(0x0c45, 0x6288), SN9C20X(OV9655, 0x30, HAS_BUTTON)}, {USB_DEVICE(0x0c45, 0x628e), SN9C20X(SOI968, 0x30, 0)}, {USB_DEVICE(0x0c45, 0x628f), SN9C20X(OV9650, 0x30, 0)}, {USB_DEVICE(0x0c45, 0x62a0), SN9C20X(OV7670, 0x21, 0)}, {USB_DEVICE(0x0c45, 0x62b0), SN9C20X(MT9VPRB, 0x00, 0)}, {USB_DEVICE(0x0c45, 0x62b3), SN9C20X(OV9655, 0x30, 0)}, - {USB_DEVICE(0x0c45, 0x62bb), SN9C20X(OV7660, 0x21, 0)}, + {USB_DEVICE(0x0c45, 0x62bb), SN9C20X(OV7660, 0x21, HAS_BUTTON)}, {USB_DEVICE(0x0c45, 0x62bc), SN9C20X(HV7131R, 0x11, 0)}, {USB_DEVICE(0x045e, 0x00f4), SN9C20X(OV9650, 0x30, 0)}, {USB_DEVICE(0x145f, 0x013d), SN9C20X(OV7660, 0x21, 0)}, @@ -2452,7 +2384,7 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0xa168, 0x0611), SN9C20X(HV7131R, 0x11, 0)}, {USB_DEVICE(0xa168, 0x0613), SN9C20X(HV7131R, 0x11, 0)}, {USB_DEVICE(0xa168, 0x0618), SN9C20X(HV7131R, 0x11, 0)}, - {USB_DEVICE(0xa168, 0x0614), SN9C20X(MT9M111, 0x5d, 0)}, + {USB_DEVICE(0xa168, 0x0614), SN9C20X(MT9M111, 0x5d, HAS_BUTTON)}, {USB_DEVICE(0xa168, 0x0615), SN9C20X(MT9M111, 0x5d, 0)}, {USB_DEVICE(0xa168, 0x0617), SN9C20X(MT9M111, 0x5d, 0)}, {} @@ -2467,22 +2399,11 @@ static int sd_probe(struct usb_interface *intf, THIS_MODULE); } -static void sd_disconnect(struct usb_interface *intf) -{ -#ifdef CONFIG_USB_GSPCA_SN9C20X_EVDEV - struct gspca_dev *gspca_dev = usb_get_intfdata(intf); - - sn9c20x_input_cleanup(gspca_dev); -#endif - - gspca_disconnect(intf); -} - static struct usb_driver sd_driver = { .name = MODULE_NAME, .id_table = device_table, .probe = sd_probe, - .disconnect = sd_disconnect, + .disconnect = gspca_disconnect, #ifdef CONFIG_PM .suspend = gspca_suspend, .resume = gspca_resume, -- cgit v1.2.3-70-g09d2 From 0c045eb752259d4176eabacbdf28a627644a071a Mon Sep 17 00:00:00 2001 From: Brian Johnson Date: Tue, 16 Mar 2010 13:58:27 -0300 Subject: V4L/DVB: gspca - sn9c20x: Add support for camera LEDs Signed-off-by: Brian Johnson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sn9c20x.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c index 1653567e992..825d5b8dfd6 100644 --- a/drivers/media/video/gspca/sn9c20x.c +++ b/drivers/media/video/gspca/sn9c20x.c @@ -54,6 +54,7 @@ MODULE_LICENSE("GPL"); /* camera flags */ #define HAS_BUTTON 0x1 +#define LED_REVERSE 0x2 /* some cameras unset gpio to turn on leds */ /* specific webcam descriptor */ struct sd { @@ -731,7 +732,8 @@ static u16 bridge_init[][2] = { {0x11be, 0xf0}, {0x11bf, 0x00}, {0x118c, 0x1f}, {0x118d, 0x1f}, {0x118e, 0x1f}, {0x118f, 0x1f}, {0x1180, 0x01}, {0x1181, 0x00}, {0x1182, 0x01}, - {0x1183, 0x00}, {0x1184, 0x50}, {0x1185, 0x80} + {0x1183, 0x00}, {0x1184, 0x50}, {0x1185, 0x80}, + {0x1007, 0x00} }; /* Gain = (bit[3:0] / 16 + 1) * (bit[4] + 1) * (bit[5] + 1) * (bit[6] + 1) */ @@ -1974,6 +1976,11 @@ static int sd_init(struct gspca_dev *gspca_dev) } } + if (sd->flags & LED_REVERSE) + reg_w1(gspca_dev, 0x1006, 0x00); + else + reg_w1(gspca_dev, 0x1006, 0x20); + if (reg_w(gspca_dev, 0x10c0, i2c_init, 9) < 0) { err("Device initialization failed"); return -ENODEV; @@ -2154,6 +2161,8 @@ static int sd_start(struct gspca_dev *gspca_dev) set_exposure(gspca_dev); set_hvflip(gspca_dev); + reg_w1(gspca_dev, 0x1007, 0x20); + reg_r(gspca_dev, 0x1061, 1); reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] | 0x02); return 0; @@ -2161,6 +2170,8 @@ static int sd_start(struct gspca_dev *gspca_dev) static void sd_stopN(struct gspca_dev *gspca_dev) { + reg_w1(gspca_dev, 0x1007, 0x00); + reg_r(gspca_dev, 0x1061, 1); reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] & ~0x02); } @@ -2350,7 +2361,7 @@ static const struct sd_desc sd_desc = { }; #define SN9C20X(sensor, i2c_addr, flags) \ - .driver_info = (flags << 16) \ + .driver_info = ((flags & 0xff) << 16) \ | (SENSOR_ ## sensor << 8) \ | (i2c_addr) @@ -2358,7 +2369,8 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x0c45, 0x6240), SN9C20X(MT9M001, 0x5d, 0)}, {USB_DEVICE(0x0c45, 0x6242), SN9C20X(MT9M111, 0x5d, 0)}, {USB_DEVICE(0x0c45, 0x6248), SN9C20X(OV9655, 0x30, 0)}, - {USB_DEVICE(0x0c45, 0x624e), SN9C20X(SOI968, 0x30, HAS_BUTTON)}, + {USB_DEVICE(0x0c45, 0x624e), SN9C20X(SOI968, 0x30, + (HAS_BUTTON | LED_REVERSE))}, {USB_DEVICE(0x0c45, 0x624f), SN9C20X(OV9650, 0x30, 0)}, {USB_DEVICE(0x0c45, 0x6251), SN9C20X(OV9650, 0x30, 0)}, {USB_DEVICE(0x0c45, 0x6253), SN9C20X(OV9650, 0x30, 0)}, -- cgit v1.2.3-70-g09d2 From 7ddaac7fcb01eed38692f1bfa81f5f4348d848d7 Mon Sep 17 00:00:00 2001 From: Brian Johnson Date: Tue, 16 Mar 2010 13:58:27 -0300 Subject: V4L/DVB: gspca - sn9c20x: Add upside down detection Add support for detecting webcams that are mounted upside down in laptops. Currently the only two known are two MSI modesl using the 0c45:624f. Signed-off-by: Brian Johnson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sn9c20x.c | 50 +++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 10 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c index 825d5b8dfd6..06c75dbecae 100644 --- a/drivers/media/video/gspca/sn9c20x.c +++ b/drivers/media/video/gspca/sn9c20x.c @@ -27,6 +27,7 @@ #include "jpeg.h" #include +#include MODULE_AUTHOR("Brian Johnson , " "microdia project "); @@ -55,6 +56,7 @@ MODULE_LICENSE("GPL"); /* camera flags */ #define HAS_BUTTON 0x1 #define LED_REVERSE 0x2 /* some cameras unset gpio to turn on leds */ +#define FLIP_DETECT 0x4 /* specific webcam descriptor */ struct sd { @@ -127,6 +129,25 @@ static int sd_getexposure(struct gspca_dev *gspca_dev, s32 *val); static int sd_setautoexposure(struct gspca_dev *gspca_dev, s32 val); static int sd_getautoexposure(struct gspca_dev *gspca_dev, s32 *val); +static const struct dmi_system_id flip_dmi_table[] = { + { + .ident = "MSI MS-1034", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "MICRO-STAR INT'L CO.,LTD."), + DMI_MATCH(DMI_PRODUCT_NAME, "MS-1034"), + DMI_MATCH(DMI_PRODUCT_VERSION, "0341") + } + }, + { + .ident = "MSI MS-1632", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "MSI"), + DMI_MATCH(DMI_BOARD_NAME, "MS-1632") + } + }, + {} +}; + static const struct ctrl sd_ctrls[] = { { #define BRIGHTNESS_IDX 0 @@ -1496,17 +1517,26 @@ static int set_redblue(struct gspca_dev *gspca_dev) static int set_hvflip(struct gspca_dev *gspca_dev) { - u8 value, tslb; + u8 value, tslb, hflip, vflip; u16 value2; struct sd *sd = (struct sd *) gspca_dev; + + if ((sd->flags & FLIP_DETECT) && dmi_check_system(flip_dmi_table)) { + hflip = !sd->hflip; + vflip = !sd->vflip; + } else { + hflip = sd->hflip; + vflip = sd->vflip; + } + switch (sd->sensor) { case SENSOR_OV9650: i2c_r1(gspca_dev, 0x1e, &value); value &= ~0x30; tslb = 0x01; - if (sd->hflip) + if (hflip) value |= 0x20; - if (sd->vflip) { + if (vflip) { value |= 0x10; tslb = 0x49; } @@ -1517,9 +1547,9 @@ static int set_hvflip(struct gspca_dev *gspca_dev) case SENSOR_MT9V011: i2c_r2(gspca_dev, 0x20, &value2); value2 &= ~0xc0a0; - if (sd->hflip) + if (hflip) value2 |= 0x8080; - if (sd->vflip) + if (vflip) value2 |= 0x4020; i2c_w2(gspca_dev, 0x20, value2); break; @@ -1527,18 +1557,18 @@ static int set_hvflip(struct gspca_dev *gspca_dev) case SENSOR_MT9V112: i2c_r2(gspca_dev, 0x20, &value2); value2 &= ~0x0003; - if (sd->hflip) + if (hflip) value2 |= 0x0002; - if (sd->vflip) + if (vflip) value2 |= 0x0001; i2c_w2(gspca_dev, 0x20, value2); break; case SENSOR_HV7131R: i2c_r1(gspca_dev, 0x01, &value); value &= ~0x03; - if (sd->vflip) + if (vflip) value |= 0x01; - if (sd->hflip) + if (hflip) value |= 0x02; i2c_w1(gspca_dev, 0x01, value); break; @@ -2371,7 +2401,7 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x0c45, 0x6248), SN9C20X(OV9655, 0x30, 0)}, {USB_DEVICE(0x0c45, 0x624e), SN9C20X(SOI968, 0x30, (HAS_BUTTON | LED_REVERSE))}, - {USB_DEVICE(0x0c45, 0x624f), SN9C20X(OV9650, 0x30, 0)}, + {USB_DEVICE(0x0c45, 0x624f), SN9C20X(OV9650, 0x30, FLIP_DETECT)}, {USB_DEVICE(0x0c45, 0x6251), SN9C20X(OV9650, 0x30, 0)}, {USB_DEVICE(0x0c45, 0x6253), SN9C20X(OV9650, 0x30, 0)}, {USB_DEVICE(0x0c45, 0x6260), SN9C20X(OV7670, 0x21, 0)}, -- cgit v1.2.3-70-g09d2 From e99ac54da6d3e44e6152aaab693fa311279dec7c Mon Sep 17 00:00:00 2001 From: Brian Johnson Date: Tue, 16 Mar 2010 13:58:28 -0300 Subject: V4L/DVB: gspca - sn9c20x: Add support for cameras using the MT9M112 sensor Adds the following models: - 0c45:624c - 0c45:628c - 0458:704a - 0458:704c Signed-off-by: Brian Johnson Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/gspca.txt | 4 ++++ drivers/media/video/gspca/sn9c20x.c | 44 ++++++++++++++++++++++++++++++++++--- 2 files changed, 45 insertions(+), 3 deletions(-) (limited to 'drivers/media/video') diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt index 9475e1e1441..8f3f5d33327 100644 --- a/Documentation/video4linux/gspca.txt +++ b/Documentation/video4linux/gspca.txt @@ -50,6 +50,8 @@ zc3xx 0458:700f Genius VideoCam Web V2 sonixj 0458:7025 Genius Eye 311Q sn9c20x 0458:7029 Genius Look 320s sonixj 0458:702e Genius Slim 310 NB +sn9c20x 0458:704a Genius Slim 1320 +sn9c20x 0458:704c Genius i-Look 1321 sn9c20x 045e:00f4 LifeCam VX-6000 (SN9C20x + OV9650) sonixj 045e:00f5 MicroSoft VX3000 sonixj 045e:00f7 MicroSoft VX1000 @@ -312,6 +314,7 @@ sonixj 0c45:614a Frontech E-Ccam (JIL-2225) sn9c20x 0c45:6240 PC Camera (SN9C201 + MT9M001) sn9c20x 0c45:6242 PC Camera (SN9C201 + MT9M111) sn9c20x 0c45:6248 PC Camera (SN9C201 + OV9655) +sn9c20x 0c45:624c PC Camera (SN9C201 + MT9M112) sn9c20x 0c45:624e PC Camera (SN9C201 + SOI968) sn9c20x 0c45:624f PC Camera (SN9C201 + OV9650) sn9c20x 0c45:6251 PC Camera (SN9C201 + OV9650) @@ -324,6 +327,7 @@ sn9c20x 0c45:627f PC Camera (SN9C201 + OV9650) sn9c20x 0c45:6280 PC Camera (SN9C202 + MT9M001) sn9c20x 0c45:6282 PC Camera (SN9C202 + MT9M111) sn9c20x 0c45:6288 PC Camera (SN9C202 + OV9655) +sn9c20x 0c45:628c PC Camera (SN9C201 + MT9M112) sn9c20x 0c45:628e PC Camera (SN9C202 + SOI968) sn9c20x 0c45:628f PC Camera (SN9C202 + OV9650) sn9c20x 0c45:62a0 PC Camera (SN9C202 + OV7670) diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c index 06c75dbecae..479fdbb9e67 100644 --- a/drivers/media/video/gspca/sn9c20x.c +++ b/drivers/media/video/gspca/sn9c20x.c @@ -50,7 +50,8 @@ MODULE_LICENSE("GPL"); #define SENSOR_MT9V112 7 #define SENSOR_MT9M001 8 #define SENSOR_MT9M111 9 -#define SENSOR_HV7131R 10 +#define SENSOR_MT9M112 10 +#define SENSOR_HV7131R 11 #define SENSOR_MT9VPRB 20 /* camera flags */ @@ -731,6 +732,7 @@ static u16 i2c_ident[] = { V4L2_IDENT_MT9V112, V4L2_IDENT_MT9M001C12ST, V4L2_IDENT_MT9M111, + V4L2_IDENT_MT9M112, V4L2_IDENT_HV7131R, }; @@ -1062,6 +1064,13 @@ static struct i2c_reg_u16 mt9m111_init[] = { {0xf0, 0x0000}, }; +static struct i2c_reg_u16 mt9m112_init[] = { + {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008}, + {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300}, + {0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e}, + {0xf0, 0x0000}, +}; + static struct i2c_reg_u8 hv7131r_init[] = { {0x02, 0x08}, {0x02, 0x00}, {0x01, 0x08}, {0x02, 0x00}, {0x20, 0x00}, {0x21, 0xd0}, @@ -1388,6 +1397,23 @@ static int mt9v_init_sensor(struct gspca_dev *gspca_dev) return -ENODEV; } +static int mt9m112_init_sensor(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + int i; + for (i = 0; i < ARRAY_SIZE(mt9m112_init); i++) { + if (i2c_w2(gspca_dev, mt9m112_init[i].reg, + mt9m112_init[i].val) < 0) { + err("MT9M112 sensor initialization failed"); + return -ENODEV; + } + } + gspca_dev->ctrl_dis = (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX) | (1 << GAIN_IDX); + sd->hstart = 0; + sd->vstart = 2; + return 0; +} + static int mt9m111_init_sensor(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -1553,6 +1579,7 @@ static int set_hvflip(struct gspca_dev *gspca_dev) value2 |= 0x4020; i2c_w2(gspca_dev, 0x20, value2); break; + case SENSOR_MT9M112: case SENSOR_MT9M111: case SENSOR_MT9V112: i2c_r2(gspca_dev, 0x20, &value2); @@ -1878,7 +1905,7 @@ static int sd_dbg_g_register(struct gspca_dev *gspca_dev, if (reg->match.addr != sd->i2c_addr) return -EINVAL; if (sd->sensor >= SENSOR_MT9V011 && - sd->sensor <= SENSOR_MT9M111) { + sd->sensor <= SENSOR_MT9M112) { if (i2c_r2(gspca_dev, reg->reg, (u16 *)®->val) < 0) return -EINVAL; } else { @@ -1907,7 +1934,7 @@ static int sd_dbg_s_register(struct gspca_dev *gspca_dev, if (reg->match.addr != sd->i2c_addr) return -EINVAL; if (sd->sensor >= SENSOR_MT9V011 && - sd->sensor <= SENSOR_MT9M111) { + sd->sensor <= SENSOR_MT9M112) { if (i2c_w2(gspca_dev, reg->reg, reg->val) < 0) return -EINVAL; } else { @@ -1955,6 +1982,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->flags = (id->driver_info >> 16) & 0xff; switch (sd->sensor) { + case SENSOR_MT9M112: case SENSOR_MT9M111: case SENSOR_OV9650: case SENSOR_SOI968: @@ -2051,6 +2079,11 @@ static int sd_init(struct gspca_dev *gspca_dev) return -ENODEV; info("MT9M111 sensor detected"); break; + case SENSOR_MT9M112: + if (mt9m112_init_sensor(gspca_dev) < 0) + return -ENODEV; + info("MT9M112 sensor detected"); + break; case SENSOR_MT9M001: if (mt9m001_init_sensor(gspca_dev) < 0) return -ENODEV; @@ -2110,6 +2143,7 @@ static void configure_sensor_output(struct gspca_dev *gspca_dev, int mode) i2c_w1(gspca_dev, 0x12, (value & 0x7) | 0x40); } break; + case SENSOR_MT9M112: case SENSOR_MT9M111: if (mode & MODE_SXGA) { i2c_w2(gspca_dev, 0xf0, 0x0002); @@ -2399,6 +2433,7 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x0c45, 0x6240), SN9C20X(MT9M001, 0x5d, 0)}, {USB_DEVICE(0x0c45, 0x6242), SN9C20X(MT9M111, 0x5d, 0)}, {USB_DEVICE(0x0c45, 0x6248), SN9C20X(OV9655, 0x30, 0)}, + {USB_DEVICE(0x0c45, 0x624c), SN9C20X(MT9M112, 0x5d, 0)}, {USB_DEVICE(0x0c45, 0x624e), SN9C20X(SOI968, 0x30, (HAS_BUTTON | LED_REVERSE))}, {USB_DEVICE(0x0c45, 0x624f), SN9C20X(OV9650, 0x30, FLIP_DETECT)}, @@ -2412,6 +2447,7 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x0c45, 0x6280), SN9C20X(MT9M001, 0x5d, 0)}, {USB_DEVICE(0x0c45, 0x6282), SN9C20X(MT9M111, 0x5d, 0)}, {USB_DEVICE(0x0c45, 0x6288), SN9C20X(OV9655, 0x30, HAS_BUTTON)}, + {USB_DEVICE(0x0c45, 0x628c), SN9C20X(MT9M112, 0x5d, 0)}, {USB_DEVICE(0x0c45, 0x628e), SN9C20X(SOI968, 0x30, 0)}, {USB_DEVICE(0x0c45, 0x628f), SN9C20X(OV9650, 0x30, 0)}, {USB_DEVICE(0x0c45, 0x62a0), SN9C20X(OV7670, 0x21, 0)}, @@ -2422,6 +2458,8 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x045e, 0x00f4), SN9C20X(OV9650, 0x30, 0)}, {USB_DEVICE(0x145f, 0x013d), SN9C20X(OV7660, 0x21, 0)}, {USB_DEVICE(0x0458, 0x7029), SN9C20X(HV7131R, 0x11, 0)}, + {USB_DEVICE(0x0458, 0x704a), SN9C20X(MT9M112, 0x5d, 0)}, + {USB_DEVICE(0x0458, 0x704c), SN9C20X(MT9M112, 0x5d, 0)}, {USB_DEVICE(0xa168, 0x0610), SN9C20X(HV7131R, 0x11, 0)}, {USB_DEVICE(0xa168, 0x0611), SN9C20X(HV7131R, 0x11, 0)}, {USB_DEVICE(0xa168, 0x0613), SN9C20X(HV7131R, 0x11, 0)}, -- cgit v1.2.3-70-g09d2 From cc2a833590e4bf4920383345cd61bc310ba84af0 Mon Sep 17 00:00:00 2001 From: Brian Johnson Date: Tue, 16 Mar 2010 13:58:28 -0300 Subject: V4L/DVB: gspca - sn9c20x: Fix bug with OV9655 code Fixed buggy init sequence for the OV9655 sensor. Tested with a 0c45:6288 and 0c45:62b3. Signed-off-by: Brian Johnson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sn9c20x.c | 58 +++++++++++++++---------------------- 1 file changed, 24 insertions(+), 34 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c index 479fdbb9e67..4069f72ac3a 100644 --- a/drivers/media/video/gspca/sn9c20x.c +++ b/drivers/media/video/gspca/sn9c20x.c @@ -935,40 +935,30 @@ static struct i2c_reg_u8 ov9650_init[] = { }; static struct i2c_reg_u8 ov9655_init[] = { - {0x12, 0x80}, {0x12, 0x01}, {0x0d, 0x00}, {0x0e, 0x61}, - {0x11, 0x80}, {0x13, 0xba}, {0x14, 0x2e}, {0x16, 0x24}, - {0x1e, 0x04}, {0x1e, 0x04}, {0x1e, 0x04}, {0x27, 0x08}, - {0x28, 0x08}, {0x29, 0x15}, {0x2c, 0x08}, {0x32, 0xbf}, - {0x34, 0x3d}, {0x35, 0x00}, {0x36, 0xf8}, {0x38, 0x12}, - {0x39, 0x57}, {0x3a, 0x00}, {0x3b, 0xcc}, {0x3c, 0x0c}, - {0x3d, 0x19}, {0x3e, 0x0c}, {0x3f, 0x01}, {0x41, 0x40}, - {0x42, 0x80}, {0x45, 0x46}, {0x46, 0x62}, {0x47, 0x2a}, - {0x48, 0x3c}, {0x4a, 0xf0}, {0x4b, 0xdc}, {0x4c, 0xdc}, - {0x4d, 0xdc}, {0x4e, 0xdc}, {0x69, 0x02}, {0x6c, 0x04}, - {0x6f, 0x9e}, {0x70, 0x05}, {0x71, 0x78}, {0x77, 0x02}, - {0x8a, 0x23}, {0x8c, 0x0d}, {0x90, 0x7e}, {0x91, 0x7c}, - {0x9f, 0x6e}, {0xa0, 0x6e}, {0xa5, 0x68}, {0xa6, 0x60}, - {0xa8, 0xc1}, {0xa9, 0xfa}, {0xaa, 0x92}, {0xab, 0x04}, - {0xac, 0x80}, {0xad, 0x80}, {0xae, 0x80}, {0xaf, 0x80}, - {0xb2, 0xf2}, {0xb3, 0x20}, {0xb5, 0x00}, {0xb6, 0xaf}, - {0xbb, 0xae}, {0xbc, 0x44}, {0xbd, 0x44}, {0xbe, 0x3b}, - {0xbf, 0x3a}, {0xc0, 0xe2}, {0xc1, 0xc8}, {0xc2, 0x01}, + {0x12, 0x80}, {0x0e, 0x61}, {0x11, 0x80}, {0x13, 0xba}, + {0x14, 0x2e}, {0x16, 0x24}, {0x1e, 0x04}, {0x27, 0x08}, + {0x28, 0x08}, {0x29, 0x15}, {0x2c, 0x08}, {0x34, 0x3d}, + {0x35, 0x00}, {0x38, 0x12}, {0x0f, 0x42}, {0x39, 0x57}, + {0x3a, 0x00}, {0x3b, 0xcc}, {0x3c, 0x0c}, {0x3d, 0x19}, + {0x3e, 0x0c}, {0x3f, 0x01}, {0x41, 0x40}, {0x42, 0x80}, + {0x45, 0x46}, {0x46, 0x62}, {0x47, 0x2a}, {0x48, 0x3c}, + {0x4a, 0xf0}, {0x4b, 0xdc}, {0x4c, 0xdc}, {0x4d, 0xdc}, + {0x4e, 0xdc}, {0x6c, 0x04}, {0x6f, 0x9e}, {0x70, 0x05}, + {0x71, 0x78}, {0x77, 0x02}, {0x8a, 0x23}, {0x90, 0x7e}, + {0x91, 0x7c}, {0x9f, 0x6e}, {0xa0, 0x6e}, {0xa5, 0x68}, + {0xa6, 0x60}, {0xa8, 0xc1}, {0xa9, 0xfa}, {0xaa, 0x92}, + {0xab, 0x04}, {0xac, 0x80}, {0xad, 0x80}, {0xae, 0x80}, + {0xaf, 0x80}, {0xb2, 0xf2}, {0xb3, 0x20}, {0xb5, 0x00}, + {0xb6, 0xaf}, {0xbb, 0xae}, {0xbc, 0x44}, {0xbd, 0x44}, + {0xbe, 0x3b}, {0xbf, 0x3a}, {0xc1, 0xc8}, {0xc2, 0x01}, {0xc4, 0x00}, {0xc6, 0x85}, {0xc7, 0x81}, {0xc9, 0xe0}, - {0xca, 0xe8}, {0xcc, 0xd8}, {0xcd, 0x93}, {0x12, 0x61}, + {0xca, 0xe8}, {0xcc, 0xd8}, {0xcd, 0x93}, {0x2d, 0x00}, + {0x2e, 0x00}, {0x01, 0x80}, {0x02, 0x80}, {0x12, 0x61}, {0x36, 0xfa}, {0x8c, 0x8d}, {0xc0, 0xaa}, {0x69, 0x0a}, - {0x03, 0x12}, {0x17, 0x14}, {0x18, 0x00}, {0x19, 0x01}, - {0x1a, 0x3d}, {0x32, 0xbf}, {0x11, 0x80}, {0x2a, 0x10}, - {0x2b, 0x0a}, {0x92, 0x00}, {0x93, 0x00}, {0x1e, 0x04}, - {0x1e, 0x04}, {0x10, 0x7c}, {0x04, 0x03}, {0xa1, 0x00}, - {0x2d, 0x00}, {0x2e, 0x00}, {0x00, 0x00}, {0x01, 0x80}, - {0x02, 0x80}, {0x12, 0x61}, {0x36, 0xfa}, {0x8c, 0x8d}, - {0xc0, 0xaa}, {0x69, 0x0a}, {0x03, 0x12}, {0x17, 0x14}, - {0x18, 0x00}, {0x19, 0x01}, {0x1a, 0x3d}, {0x32, 0xbf}, - {0x11, 0x80}, {0x2a, 0x10}, {0x2b, 0x0a}, {0x92, 0x00}, - {0x93, 0x00}, {0x04, 0x01}, {0x10, 0x1f}, {0xa1, 0x00}, - {0x00, 0x0a}, {0xa1, 0x00}, {0x10, 0x5d}, {0x04, 0x03}, - {0x00, 0x01}, {0xa1, 0x00}, {0x10, 0x7c}, {0x04, 0x03}, - {0x00, 0x03}, {0x00, 0x0a}, {0x00, 0x10}, {0x00, 0x13}, + {0x03, 0x09}, {0x17, 0x16}, {0x18, 0x6e}, {0x19, 0x01}, + {0x1a, 0x3e}, {0x32, 0x09}, {0x2a, 0x10}, {0x2b, 0x0a}, + {0x92, 0x00}, {0x93, 0x00}, {0xa1, 0x00}, {0x10, 0x7c}, + {0x04, 0x03}, {0x00, 0x13}, }; static struct i2c_reg_u16 mt9v112_init[] = { @@ -1268,8 +1258,8 @@ static int ov9655_init_sensor(struct gspca_dev *gspca_dev) } /* disable hflip and vflip */ gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX); - sd->hstart = 0; - sd->vstart = 7; + sd->hstart = 1; + sd->vstart = 2; return 0; } -- cgit v1.2.3-70-g09d2 From 6b33e5e7fe03c6577ccbaeeb028ab4ec1f26f2b0 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 27 Feb 2010 07:18:14 -0300 Subject: V4L/DVB: gspca_spca561: Fix LED on rev12a cameras Fix LED control on rev12a cameras and remove the unneeded sd_stop0 callback function. Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/spca561.c | 34 +++++++++++----------------------- 1 file changed, 11 insertions(+), 23 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index b9c80e2103b..6346ddc6796 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c @@ -249,9 +249,9 @@ static const __u16 Pb100_2map8300[][2] = { }; static const __u16 spca561_161rev12A_data1[][2] = { - {0x29, 0x8118}, /* white balance - was 21 */ - {0x08, 0x8114}, /* white balance - was 01 */ - {0x0e, 0x8112}, /* white balance - was 00 */ + {0x29, 0x8118}, /* Control register (various enable bits) */ + {0x08, 0x8114}, /* GPIO: Led off */ + {0x0e, 0x8112}, /* 0x0e stream off 0x3e stream on */ {0x00, 0x8102}, /* white balance - new */ {0x92, 0x8804}, {0x04, 0x8802}, /* windows uses 08 */ @@ -263,15 +263,11 @@ static const __u16 spca561_161rev12A_data2[][2] = { {0x07, 0x8601}, {0x07, 0x8602}, {0x04, 0x8501}, - {0x21, 0x8118}, {0x07, 0x8201}, /* windows uses 02 */ {0x08, 0x8200}, {0x01, 0x8200}, - {0x00, 0x8114}, - {0x01, 0x8114}, /* windows uses 00 */ - {0x90, 0x8604}, {0x00, 0x8605}, {0xb0, 0x8603}, @@ -302,6 +298,9 @@ static const __u16 spca561_161rev12A_data2[][2] = { {0xf0, 0x8505}, {0x32, 0x850a}, /* {0x99, 0x8700}, * - white balance - new (removed) */ + /* HDG we used to do this in stop0, making the init state and the state + after a start / stop different, so do this here instead. */ + {0x29, 0x8118}, {} }; @@ -645,6 +644,9 @@ static int sd_start_12a(struct gspca_dev *gspca_dev) setwhite(gspca_dev); setgain(gspca_dev); setexposure(gspca_dev); + + /* Led ON (bit 3 -> 0 */ + reg_w_val(gspca_dev->dev, 0x8114, 0x00); return 0; } static int sd_start_72a(struct gspca_dev *gspca_dev) @@ -691,26 +693,14 @@ static void sd_stopN(struct gspca_dev *gspca_dev) if (sd->chip_revision == Rev012A) { reg_w_val(gspca_dev->dev, 0x8112, 0x0e); + /* Led Off (bit 3 -> 1 */ + reg_w_val(gspca_dev->dev, 0x8114, 0x08); } else { reg_w_val(gspca_dev->dev, 0x8112, 0x20); /* reg_w_val(gspca_dev->dev, 0x8102, 0x00); ?? */ } } -/* called on streamoff with alt 0 and on disconnect */ -static void sd_stop0(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (!gspca_dev->present) - return; - if (sd->chip_revision == Rev012A) { - reg_w_val(gspca_dev->dev, 0x8118, 0x29); - reg_w_val(gspca_dev->dev, 0x8114, 0x08); - } -/* reg_w_val(gspca_dev->dev, 0x8114, 0); */ -} - static void do_autogain(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -1028,7 +1018,6 @@ static const struct sd_desc sd_desc_12a = { .init = sd_init_12a, .start = sd_start_12a, .stopN = sd_stopN, - .stop0 = sd_stop0, .pkt_scan = sd_pkt_scan, }; static const struct sd_desc sd_desc_72a = { @@ -1039,7 +1028,6 @@ static const struct sd_desc sd_desc_72a = { .init = sd_init_72a, .start = sd_start_72a, .stopN = sd_stopN, - .stop0 = sd_stop0, .pkt_scan = sd_pkt_scan, .dq_callback = do_autogain, }; -- cgit v1.2.3-70-g09d2 From 436c2c533a2a2f98d95347f4d5b4022becb046f6 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 28 Feb 2010 09:41:04 -0300 Subject: V4L/DVB: gspca_spca561: Add support for camera button gspca_spca561: Add support for camera button Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/spca561.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index 6346ddc6796..7bb2355005d 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c @@ -22,6 +22,7 @@ #define MODULE_NAME "spca561" +#include #include "gspca.h" MODULE_AUTHOR("Michel Xhaard "); @@ -778,6 +779,23 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, switch (*data++) { /* sequence number */ case 0: /* start of frame */ gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); + + /* This should never happen */ + if (len < 2) { + PDEBUG(D_ERR, "Short SOF packet, ignoring"); + gspca_dev->last_packet_type = DISCARD_PACKET; + return; + } + +#ifdef CONFIG_INPUT + if (data[0] & 0x20) { + input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); + input_sync(gspca_dev->input_dev); + input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); + input_sync(gspca_dev->input_dev); + } +#endif + if (data[1] & 0x10) { /* compressed bayer */ gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); @@ -1019,6 +1037,9 @@ static const struct sd_desc sd_desc_12a = { .start = sd_start_12a, .stopN = sd_stopN, .pkt_scan = sd_pkt_scan, +#ifdef CONFIG_INPUT + .other_input = 1, +#endif }; static const struct sd_desc sd_desc_72a = { .name = MODULE_NAME, @@ -1030,6 +1051,9 @@ static const struct sd_desc sd_desc_72a = { .stopN = sd_stopN, .pkt_scan = sd_pkt_scan, .dq_callback = do_autogain, +#ifdef CONFIG_INPUT + .other_input = 1, +#endif }; static const struct sd_desc *sd_desc[2] = { &sd_desc_12a, -- cgit v1.2.3-70-g09d2 From f0dbf82bf1ff97c24af228328fb21c93fcfcb983 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 11 Mar 2010 06:12:39 -0300 Subject: V4L/DVB: sn9c102: Make hv7131d sensor code also recognize the HV7131E The hv7131d sensor code also works for the hv7131e, this patch changes it to also recognize the hv7131e sensor id. Tested-by: Frank Danapfel Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/sn9c102/sn9c102_hv7131d.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/sn9c102/sn9c102_hv7131d.c b/drivers/media/video/sn9c102/sn9c102_hv7131d.c index db243494893..2dce5c908c8 100644 --- a/drivers/media/video/sn9c102/sn9c102_hv7131d.c +++ b/drivers/media/video/sn9c102/sn9c102_hv7131d.c @@ -255,7 +255,7 @@ int sn9c102_probe_hv7131d(struct sn9c102_device* cam) if (err || r0 < 0 || r1 < 0) return -EIO; - if (r0 != 0x00 || r1 != 0x04) + if ((r0 != 0x00 && r0 != 0x01) || r1 != 0x04) return -ENODEV; sn9c102_attach_sensor(cam, &hv7131d); -- cgit v1.2.3-70-g09d2 From 33c02facb5a3123212587295cc1c241ee7e03adb Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Fri, 22 Jan 2010 01:53:17 -0300 Subject: V4L/DVB: em28xx: adjust number of packets per URB Increase the packets per URB count from 40 to 64. I suspect that whoever was looking at the usbsnoop captures saw "0x40" packets and mistook it for "40". As a result of this change, I can see a 25% reduction in the number of interrupts generated via powertop. This work was sponsored by EyeMagnet Limited. Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index ba6fe5daff8..526c0658215 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -140,10 +140,10 @@ #define EM28XX_NUM_BUFS 5 /* number of packets for each buffer - windows requests only 40 packets .. so we better do the same + windows requests only 64 packets .. so we better do the same this is what I found out for all alternate numbers there! */ -#define EM28XX_NUM_PACKETS 40 +#define EM28XX_NUM_PACKETS 64 #define EM28XX_INTERLACED_DEFAULT 1 -- cgit v1.2.3-70-g09d2 From 1744feab9a2241f2adf03be5ef8ecbd279f5944b Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Fri, 22 Jan 2010 02:05:24 -0300 Subject: V4L/DVB: em28xx: reduce cropping for VBI area It turns up we can reduce the starting line for the active area, which results in more data being captured when under PAL (while the full VBI capture window still stays properly encoded). This work was sponsored by EyeMagnet Limited. Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-core.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index a41cc556677..258041d0be9 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -782,11 +782,15 @@ int em28xx_resolution_set(struct em28xx *dev) em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2); - /* If we don't set the start position to 4 in VBI mode, we end up - with line 21 being YUYV encoded instead of being in 8-bit - greyscale */ + /* If we don't set the start position to 2 in VBI mode, we end up + with line 20/21 being YUYV encoded instead of being in 8-bit + greyscale. The core of the issue is that line 21 (and line 23 for + PAL WSS) are inside of active video region, and as a result they + get the pixelformatting associated with that area. So by cropping + it out, we end up with the same format as the rest of the VBI + region */ if (em28xx_vbi_supported(dev) == 1) - em28xx_capture_area_set(dev, 0, 4, width >> 2, height >> 2); + em28xx_capture_area_set(dev, 0, 2, width >> 2, height >> 2); else em28xx_capture_area_set(dev, 0, 0, width >> 2, height >> 2); -- cgit v1.2.3-70-g09d2 From 5fee334039550bdd5efed9e69af7860a66a9de37 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Fri, 22 Jan 2010 02:34:32 -0300 Subject: V4L/DVB: em28xx: rework buffer pointer tracking for offset to start of video Rework the logic for tracking the amount of data copied to the VBI buffer, to address problem found where the video lines are several bytes shifted to the right (and the leading pixels in the first line rendered are garbage). This would occur because the copy function would advance the pointer when detecting headers, but the caller would not adjust the length actually copied. This work was sponsored by EyeMagnet Limited. Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-video.c | 61 ++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 22 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 0fe20110bfd..b6ac99de97d 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -203,12 +203,6 @@ static void em28xx_copy_video(struct em28xx *dev, if (dma_q->pos + len > buf->vb.size) len = buf->vb.size - dma_q->pos; - if (p[0] != 0x88 && p[0] != 0x22) { - em28xx_isocdbg("frame is not complete\n"); - len += 4; - } else - p += 4; - startread = p; remain = len; @@ -309,14 +303,6 @@ static void em28xx_copy_vbi(struct em28xx *dev, if (dma_q->pos + len > buf->vb.size) len = buf->vb.size - dma_q->pos; - if ((p[0] == 0x33 && p[1] == 0x95) || - (p[0] == 0x88 && p[1] == 0x88)) { - /* Header field, advance past it */ - p += 4; - } else { - len += 4; - } - startread = p; startwrite = outp + dma_q->pos; @@ -507,8 +493,15 @@ static inline int em28xx_isoc_copy(struct em28xx *dev, struct urb *urb) dma_q->pos = 0; } - if (buf != NULL) + if (buf != NULL) { + if (p[0] != 0x88 && p[0] != 0x22) { + em28xx_isocdbg("frame is not complete\n"); + len += 4; + } else { + p += 4; + } em28xx_copy_video(dev, dma_q, buf, p, outp, len); + } } return rc; } @@ -555,8 +548,7 @@ static inline int em28xx_isoc_copy_vbi(struct em28xx *dev, struct urb *urb) continue; } - len = urb->iso_frame_desc[i].actual_length - 4; - + len = urb->iso_frame_desc[i].actual_length; if (urb->iso_frame_desc[i].actual_length <= 0) { /* em28xx_isocdbg("packet %d is empty",i); - spammy */ continue; @@ -577,6 +569,17 @@ static inline int em28xx_isoc_copy_vbi(struct em28xx *dev, struct urb *urb) dev->vbi_read = 0; em28xx_isocdbg("VBI START HEADER!!!\n"); dev->cur_field = p[2]; + p += 4; + len -= 4; + } else if (p[0] == 0x88 && p[1] == 0x88 && + p[2] == 0x88 && p[3] == 0x88) { + /* continuation */ + p += 4; + len -= 4; + } else if (p[0] == 0x22 && p[1] == 0x5a) { + /* start video */ + p += 4; + len -= 4; } vbi_size = dev->vbi_width * dev->vbi_height; @@ -631,9 +634,6 @@ static inline int em28xx_isoc_copy_vbi(struct em28xx *dev, struct urb *urb) if (dev->capture_type == 1) { dev->capture_type = 2; - em28xx_isocdbg("Video frame %d, length=%i, %s\n", p[2], - len, (p[2] & 1) ? "odd" : "even"); - if (dev->progressive || !(dev->cur_field & 1)) { if (buf != NULL) buffer_filled(dev, dma_q, buf); @@ -652,8 +652,25 @@ static inline int em28xx_isoc_copy_vbi(struct em28xx *dev, struct urb *urb) dma_q->pos = 0; } - if (buf != NULL && dev->capture_type == 2) - em28xx_copy_video(dev, dma_q, buf, p, outp, len); + + if (buf != NULL && dev->capture_type == 2) { + if (len > 4 && p[0] == 0x88 && p[1] == 0x88 && + p[2] == 0x88 && p[3] == 0x88) { + p += 4; + len -= 4; + } + if (len > 4 && p[0] == 0x22 && p[1] == 0x5a) { + em28xx_isocdbg("Video frame %d, len=%i, %s\n", + p[2], len, (p[2] & 1) ? + "odd" : "even"); + p += 4; + len -= 4; + } + + if (len > 0) + em28xx_copy_video(dev, dma_q, buf, p, outp, + len); + } } return rc; } -- cgit v1.2.3-70-g09d2 From fea551fae99c79f43e519cf53e35462ff5ce2a03 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 3 Feb 2010 00:33:48 -0300 Subject: V4L/DVB: saa7115: enable anti-alias filter This patch enables the anti-alias filter, which was originally enabled for the saa7113, but the saa7115_init_misc was trampling the value. Without this patch, there would be visible vertical bands in the chroma. Thanks to Andy Walls for helping test this change against other ivtv products. This work was sponsored by EyeMagnet Limited. Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7115.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index c0a7f8a369f..7d11660922f 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -592,7 +592,7 @@ static const unsigned char saa7115_init_misc[] = { R_5D_DID, 0xbd, R_5E_SDID, 0x35, - R_02_INPUT_CNTL_1, 0x84, /* input tuner -> input 4, amplifier active */ + R_02_INPUT_CNTL_1, 0xc4, /* input tuner -> input 4, amplifier active */ R_80_GLOBAL_CNTL_1, 0x20, /* enable task B */ R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, -- cgit v1.2.3-70-g09d2 From 87a6fe4a530cc01081d19cdec4738433972fb0ee Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Thu, 11 Mar 2010 21:49:24 -0300 Subject: V4L/DVB: saa115: add support for chroma AGC and chroma gain Add support for chroma agc and gain to the saa7115 driver. This allows for users to do manual adjustment for abnormal signal conditions. This work was sponsored by EyeMagnet Limited. Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7115.c | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index 7d11660922f..f96071c6605 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -74,6 +74,7 @@ struct saa711x_state { int contrast; int hue; int sat; + int chroma_agc; int width; int height; u32 ident; @@ -743,6 +744,7 @@ static int saa711x_s_clock_freq(struct v4l2_subdev *sd, u32 freq) static int saa711x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { struct saa711x_state *state = to_state(sd); + u8 val; switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: @@ -784,7 +786,21 @@ static int saa711x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) state->hue = ctrl->value; saa711x_write(sd, R_0D_CHROMA_HUE_CNTL, state->hue); break; - + case V4L2_CID_CHROMA_AGC: + val = saa711x_read(sd, R_0F_CHROMA_GAIN_CNTL); + state->chroma_agc = ctrl->value; + if (ctrl->value) + val &= 0x7f; + else + val |= 0x80; + saa711x_write(sd, R_0F_CHROMA_GAIN_CNTL, val); + break; + case V4L2_CID_CHROMA_GAIN: + /* Chroma gain cannot be set when AGC is enabled */ + if (state->chroma_agc == 1) + return -EINVAL; + saa711x_write(sd, R_0F_CHROMA_GAIN_CNTL, ctrl->value | 0x80); + break; default: return -EINVAL; } @@ -809,6 +825,12 @@ static int saa711x_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) case V4L2_CID_HUE: ctrl->value = state->hue; break; + case V4L2_CID_CHROMA_AGC: + ctrl->value = state->chroma_agc; + break; + case V4L2_CID_CHROMA_GAIN: + ctrl->value = saa711x_read(sd, R_0F_CHROMA_GAIN_CNTL) & 0x7f; + break; default: return -EINVAL; } @@ -1209,6 +1231,19 @@ static int saa711x_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) return v4l2_ctrl_query_fill(qc, 0, 127, 1, 64); case V4L2_CID_HUE: return v4l2_ctrl_query_fill(qc, -128, 127, 1, 0); + case V4L2_CID_CHROMA_AGC: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); + case V4L2_CID_CHROMA_GAIN: + qc->type = V4L2_CTRL_TYPE_INTEGER; + qc->flags = V4L2_CTRL_FLAG_SLIDER; + qc->minimum = 0; + qc->maximum = 127; + qc->step = 1; + qc->default_value = 0x30; + qc->reserved[0] = 0; + qc->reserved[1] = 0; + strlcpy(qc->name, "chroma_gain", sizeof(qc->name)); + return 0; default: return -EINVAL; } @@ -1593,6 +1628,7 @@ static int saa711x_probe(struct i2c_client *client, state->contrast = 64; state->hue = 0; state->sat = 64; + state->chroma_agc = 1; switch (chip_id) { case '1': state->ident = V4L2_IDENT_SAA7111; -- cgit v1.2.3-70-g09d2 From f1a4f9eab2bac10d3145d75342eb372c0ef9f125 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Thu, 11 Mar 2010 22:00:13 -0300 Subject: V4L/DVB: v4l2-common: add ability to use v4l2_ctrl_query_fill for chroma gain Add the ability to use the v4l2_ctrl_query_fill() function for the newly introduced chroma gain control. Also, make use of the centralized function by the one caller. This work was sponsored by EyeMagnet Limited. Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7115.c | 11 +---------- drivers/media/video/v4l2-common.c | 2 ++ 2 files changed, 3 insertions(+), 10 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index f96071c6605..72eaa662b66 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -1234,16 +1234,7 @@ static int saa711x_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) case V4L2_CID_CHROMA_AGC: return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); case V4L2_CID_CHROMA_GAIN: - qc->type = V4L2_CTRL_TYPE_INTEGER; - qc->flags = V4L2_CTRL_FLAG_SLIDER; - qc->minimum = 0; - qc->maximum = 127; - qc->step = 1; - qc->default_value = 0x30; - qc->reserved[0] = 0; - qc->reserved[1] = 0; - strlcpy(qc->name, "chroma_gain", sizeof(qc->name)); - return 0; + return v4l2_ctrl_query_fill(qc, 0, 127, 1, 48); default: return -EINVAL; } diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index e6798346100..6a3d0b71f78 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -429,6 +429,7 @@ const char *v4l2_ctrl_get_name(u32 id) case V4L2_CID_SHARPNESS: return "Sharpness"; case V4L2_CID_BACKLIGHT_COMPENSATION: return "Backlight Compensation"; case V4L2_CID_CHROMA_AGC: return "Chroma AGC"; + case V4L2_CID_CHROMA_GAIN: return "Chroma Gain"; case V4L2_CID_COLOR_KILLER: return "Color Killer"; case V4L2_CID_COLORFX: return "Color Effects"; case V4L2_CID_AUTOBRIGHTNESS: return "Brightness, Automatic"; @@ -622,6 +623,7 @@ int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 ste case V4L2_CID_BLUE_BALANCE: case V4L2_CID_GAMMA: case V4L2_CID_SHARPNESS: + case V4L2_CID_CHROMA_GAIN: case V4L2_CID_RDS_TX_DEVIATION: case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME: case V4L2_CID_AUDIO_LIMITER_DEVIATION: -- cgit v1.2.3-70-g09d2 From d1875d65599e187feb92994af33f409612e05ca3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 24 Mar 2010 09:36:32 -0300 Subject: V4L/DVB: gspca: fixes compilation when input is not selected It seems that I merged a wrong version of the patch or that changeset 4d770eeb926d0bc44c0bd68d051d3d2a5568ef41 got mangled somehow: It were missed the #else to avoid compilation troubles. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gspca.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 415949526ee..1830ea9e73b 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -279,10 +279,6 @@ static void gspca_input_destroy_urb(struct gspca_dev *gspca_dev) usb_free_urb(urb); } } -#else -#define gspca_input_connect(gspca_dev) 0 -#define gspca_input_create_urb(gspca_dev) -#define gspca_input_destroy_urb(gspca_dev) #endif /* get the current input frame buffer */ -- cgit v1.2.3-70-g09d2 From 443fed9fa42bbeacdb8d336b8a5002a262cac15c Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Fri, 19 Mar 2010 23:53:12 -0300 Subject: V4L/DVB: em28xx: add em286x/tvp5150 reference design Add support for design which has an em2863/tvp5150 and uses the standard empia USB ID. In Sander's case, it was branded as an "Eminent model EM3705" Thanks to Sander Van Ginkel for testing and help debugging the support. [mchehab@redhat.com: move it to a vague card number slot (card=29)] Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.em28xx | 3 ++- drivers/media/video/em28xx/em28xx-cards.c | 17 +++++++++++++++++ drivers/media/video/em28xx/em28xx.h | 1 + 3 files changed, 20 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx index 76c39081c29..3a623aaeae5 100644 --- a/Documentation/video4linux/CARDLIST.em28xx +++ b/Documentation/video4linux/CARDLIST.em28xx @@ -1,5 +1,5 @@ 0 -> Unknown EM2800 video grabber (em2800) [eb1a:2800] - 1 -> Unknown EM2750/28xx video grabber (em2820/em2840) [eb1a:2710,eb1a:2820,eb1a:2821,eb1a:2860,eb1a:2861,eb1a:2862,eb1a:2870,eb1a:2881,eb1a:2883,eb1a:2868] + 1 -> Unknown EM2750/28xx video grabber (em2820/em2840) [eb1a:2710,eb1a:2820,eb1a:2821,eb1a:2860,eb1a:2861,eb1a:2862,eb1a:2863,eb1a:2870,eb1a:2881,eb1a:2883,eb1a:2868] 2 -> Terratec Cinergy 250 USB (em2820/em2840) [0ccd:0036] 3 -> Pinnacle PCTV USB 2 (em2820/em2840) [2304:0208] 4 -> Hauppauge WinTV USB 2 (em2820/em2840) [2040:4200,2040:4201] @@ -27,6 +27,7 @@ 26 -> Hercules Smart TV USB 2.0 (em2820/em2840) 27 -> Pinnacle PCTV USB 2 (Philips FM1216ME) (em2820/em2840) 28 -> Leadtek Winfast USB II Deluxe (em2820/em2840) + 29 -> EM2860/TVP5150 Reference Design (em2860) 30 -> Videology 20K14XUSB USB2.0 (em2820/em2840) 31 -> Usbgear VD204v9 (em2821) 32 -> Supercomp USB 2.0 TV (em2821) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 5ed834ee756..7b0ca583de5 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -681,6 +681,20 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_LINE_IN, } }, }, + [EM2860_BOARD_TVP5150_REFERENCE_DESIGN] = { + .name = "EM2860/TVP5150 Reference Design", + .tuner_type = TUNER_ABSENT, /* Capture only device */ + .decoder = EM28XX_TVP5150, + .input = { { + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = TVP5150_COMPOSITE1, + .amux = EM28XX_AMUX_LINE_IN, + }, { + .type = EM28XX_VMUX_SVIDEO, + .vmux = TVP5150_SVIDEO, + .amux = EM28XX_AMUX_LINE_IN, + } }, + }, [EM2861_BOARD_PLEXTOR_PX_TV100U] = { .name = "Plextor ConvertX PX-TV100U", .tuner_type = TUNER_TNF_5335MF, @@ -1676,6 +1690,8 @@ struct usb_device_id em28xx_id_table[] = { .driver_info = EM2820_BOARD_UNKNOWN }, { USB_DEVICE(0xeb1a, 0x2862), .driver_info = EM2820_BOARD_UNKNOWN }, + { USB_DEVICE(0xeb1a, 0x2863), + .driver_info = EM2820_BOARD_UNKNOWN }, { USB_DEVICE(0xeb1a, 0x2870), .driver_info = EM2820_BOARD_UNKNOWN }, { USB_DEVICE(0xeb1a, 0x2881), @@ -1796,6 +1812,7 @@ static struct em28xx_hash_table em28xx_i2c_hash[] = { {0xb06a32c3, EM2800_BOARD_TERRATEC_CINERGY_200, TUNER_LG_PAL_NEW_TAPC}, {0xf51200e3, EM2800_BOARD_VGEAR_POCKETTV, TUNER_LG_PAL_NEW_TAPC}, {0x1ba50080, EM2860_BOARD_SAA711X_REFERENCE_DESIGN, TUNER_ABSENT}, + {0x77800080, EM2860_BOARD_TVP5150_REFERENCE_DESIGN, TUNER_ABSENT}, {0xc51200e3, EM2820_BOARD_GADMEI_TVR200, TUNER_LG_PAL_NEW_TAPC}, {0x4ba50080, EM2861_BOARD_GADMEI_UTV330PLUS, TUNER_TNF_5335MF}, }; diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 526c0658215..eec12910c8c 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -68,6 +68,7 @@ #define EM2820_BOARD_HERCULES_SMART_TV_USB2 26 #define EM2820_BOARD_PINNACLE_USB_2_FM1216ME 27 #define EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE 28 +#define EM2860_BOARD_TVP5150_REFERENCE_DESIGN 29 #define EM2820_BOARD_VIDEOLOGY_20K14XUSB 30 #define EM2821_BOARD_USBGEAR_VD204 31 #define EM2821_BOARD_SUPERCOMP_USB_2 32 -- cgit v1.2.3-70-g09d2 From 85e092190b5f7dfe9b78556440472c5590a32b4e Mon Sep 17 00:00:00 2001 From: Dmitri Belimov Date: Tue, 23 Mar 2010 11:23:29 -0300 Subject: V4L/DVB: Add SPI support to V4L2 Add support SPI bus to v4l2. Useful for control some device with SPI bus like hardware MPEG2 encoders and etc. Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-common.c | 63 +++++++++++++++++++++++++++++++++++++++ drivers/media/video/v4l2-device.c | 11 +++++++ include/media/v4l2-common.h | 19 ++++++++++++ include/media/v4l2-subdev.h | 2 ++ 4 files changed, 95 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index 6a3d0b71f78..cd1f21d9b07 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -51,6 +51,9 @@ #include #include #include +#if defined(CONFIG_SPI) +#include +#endif #include #include #include @@ -955,6 +958,66 @@ EXPORT_SYMBOL_GPL(v4l2_i2c_tuner_addrs); #endif /* defined(CONFIG_I2C) */ +#if defined(CONFIG_SPI) + +/* Load a spi sub-device. */ + +void v4l2_spi_subdev_init(struct v4l2_subdev *sd, struct spi_device *spi, + const struct v4l2_subdev_ops *ops) +{ + v4l2_subdev_init(sd, ops); + sd->flags |= V4L2_SUBDEV_FL_IS_SPI; + /* the owner is the same as the spi_device's driver owner */ + sd->owner = spi->dev.driver->owner; + /* spi_device and v4l2_subdev point to one another */ + v4l2_set_subdevdata(sd, spi); + spi_set_drvdata(spi, sd); + /* initialize name */ + strlcpy(sd->name, spi->dev.driver->name, sizeof(sd->name)); +} +EXPORT_SYMBOL_GPL(v4l2_spi_subdev_init); + +struct v4l2_subdev *v4l2_spi_new_subdev(struct v4l2_device *v4l2_dev, + struct spi_master *master, struct spi_board_info *info) +{ + struct v4l2_subdev *sd = NULL; + struct spi_device *spi = NULL; + + BUG_ON(!v4l2_dev); + + if (info->modalias) + request_module(info->modalias); + + spi = spi_new_device(master, info); + + if (spi == NULL || spi->dev.driver == NULL) + goto error; + + if (!try_module_get(spi->dev.driver->owner)) + goto error; + + sd = spi_get_drvdata(spi); + + /* Register with the v4l2_device which increases the module's + use count as well. */ + if (v4l2_device_register_subdev(v4l2_dev, sd)) + sd = NULL; + + /* Decrease the module use count to match the first try_module_get. */ + module_put(spi->dev.driver->owner); + +error: + /* If we have a client but no subdev, then something went wrong and + we must unregister the client. */ + if (spi && sd == NULL) + spi_unregister_device(spi); + + return sd; +} +EXPORT_SYMBOL_GPL(v4l2_spi_new_subdev); + +#endif /* defined(CONFIG_SPI) */ + /* Clamp x to be between min and max, aligned to a multiple of 2^align. min * and max don't have to be aligned, but there must be at least one valid * value. E.g., min=17,max=31,align=4 is not allowed as there are no multiples diff --git a/drivers/media/video/v4l2-device.c b/drivers/media/video/v4l2-device.c index 0d06e7cbd5b..5a7dc4afe92 100644 --- a/drivers/media/video/v4l2-device.c +++ b/drivers/media/video/v4l2-device.c @@ -21,6 +21,9 @@ #include #include #include +#if defined(CONFIG_SPI) +#include +#endif #include #include @@ -96,6 +99,14 @@ void v4l2_device_unregister(struct v4l2_device *v4l2_dev) if (client) i2c_unregister_device(client); } +#endif +#if defined(CONFIG_SPI) + if (sd->flags & V4L2_SUBDEV_FL_IS_SPI) { + struct spi_device *spi = v4l2_get_subdevdata(sd); + + if (spi) + spi_unregister_device(spi); + } #endif } } diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index 1c7b259f341..3b2efdc6d06 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h @@ -184,6 +184,25 @@ const unsigned short *v4l2_i2c_tuner_addrs(enum v4l2_i2c_tuner_type type); /* ------------------------------------------------------------------------- */ +/* SPI Helper functions */ +#if defined(CONFIG_SPI) + +#include + +struct spi_device; + +/* Load an spi module and return an initialized v4l2_subdev struct. + The client_type argument is the name of the chip that's on the adapter. */ +struct v4l2_subdev *v4l2_spi_new_subdev(struct v4l2_device *v4l2_dev, + struct spi_master *master, struct spi_board_info *info); + +/* Initialize an v4l2_subdev with data from an spi_device struct */ +void v4l2_spi_subdev_init(struct v4l2_subdev *sd, struct spi_device *spi, + const struct v4l2_subdev_ops *ops); +#endif + +/* ------------------------------------------------------------------------- */ + /* Note: these remaining ioctls/structs should be removed as well, but they are still used in tuner-simple.c (TUNER_SET_CONFIG), cx18/ivtv (RESET) and v4l2-int-device.h (v4l2_routing). To remove these ioctls some more cleanup diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 2bcdca0a57f..09758789be0 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -387,6 +387,8 @@ struct v4l2_subdev_ops { /* Set this flag if this subdev is a i2c device. */ #define V4L2_SUBDEV_FL_IS_I2C (1U << 0) +/* Set this flag if this subdev is a spi device. */ +#define V4L2_SUBDEV_FL_IS_SPI (1U << 1) /* Each instance of a subdev driver should create this struct, either stand-alone or embedded in a larger struct. -- cgit v1.2.3-70-g09d2 From 7a02264ca9ec5409e22b9d41f32b431d08eadbce Mon Sep 17 00:00:00 2001 From: Pawel Osciak Date: Wed, 17 Mar 2010 04:01:04 -0300 Subject: V4L/DVB: v4l: videobuf: code cleanup Make videobuf pass checkpatch; minor code cleanups. Signed-off-by: Pawel Osciak Reviewed-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-core.c | 116 +++++++------- drivers/media/video/videobuf-dma-sg.c | 276 +++++++++++++++++---------------- drivers/media/video/videobuf-vmalloc.c | 112 +++++++------ include/media/videobuf-core.h | 10 +- include/media/videobuf-dma-sg.h | 27 ++-- include/media/videobuf-vmalloc.h | 12 +- 6 files changed, 272 insertions(+), 281 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c index 471178e1701..63d7043502d 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/video/videobuf-core.c @@ -24,10 +24,15 @@ #include #define MAGIC_BUFFER 0x20070728 -#define MAGIC_CHECK(is, should) do { \ - if (unlikely((is) != (should))) { \ - printk(KERN_ERR "magic mismatch: %x (expected %x)\n", is, should); \ - BUG(); } } while (0) +#define MAGIC_CHECK(is, should) \ + do { \ + if (unlikely((is) != (should))) { \ + printk(KERN_ERR \ + "magic mismatch: %x (expected %x)\n", \ + is, should); \ + BUG(); \ + } \ + } while (0) static int debug; module_param(debug, int, 0644); @@ -36,9 +41,11 @@ MODULE_DESCRIPTION("helper module to manage video4linux buffers"); MODULE_AUTHOR("Mauro Carvalho Chehab "); MODULE_LICENSE("GPL"); -#define dprintk(level, fmt, arg...) do { \ - if (debug >= level) \ - printk(KERN_DEBUG "vbuf: " fmt , ## arg); } while (0) +#define dprintk(level, fmt, arg...) \ + do { \ + if (debug >= level) \ + printk(KERN_DEBUG "vbuf: " fmt, ## arg); \ + } while (0) /* --------------------------------------------------------------------- */ @@ -57,14 +64,14 @@ void *videobuf_alloc(struct videobuf_queue *q) } vb = q->int_ops->alloc(q->msize); - if (NULL != vb) { init_waitqueue_head(&vb->done); - vb->magic = MAGIC_BUFFER; + vb->magic = MAGIC_BUFFER; } return vb; } +EXPORT_SYMBOL_GPL(videobuf_alloc); #define WAITON_CONDITION (vb->state != VIDEOBUF_ACTIVE &&\ vb->state != VIDEOBUF_QUEUED) @@ -86,6 +93,7 @@ int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr) return 0; } +EXPORT_SYMBOL_GPL(videobuf_waiton); int videobuf_iolock(struct videobuf_queue *q, struct videobuf_buffer *vb, struct v4l2_framebuffer *fbuf) @@ -95,9 +103,10 @@ int videobuf_iolock(struct videobuf_queue *q, struct videobuf_buffer *vb, return CALL(q, iolock, q, vb, fbuf); } +EXPORT_SYMBOL_GPL(videobuf_iolock); -void *videobuf_queue_to_vmalloc (struct videobuf_queue *q, - struct videobuf_buffer *buf) +void *videobuf_queue_to_vmalloc(struct videobuf_queue *q, + struct videobuf_buffer *buf) { if (q->int_ops->vmalloc) return q->int_ops->vmalloc(buf); @@ -146,6 +155,7 @@ void videobuf_queue_core_init(struct videobuf_queue *q, init_waitqueue_head(&q->wait); INIT_LIST_HEAD(&q->stream); } +EXPORT_SYMBOL_GPL(videobuf_queue_core_init); /* Locking: Only usage in bttv unsafe find way to remove */ int videobuf_queue_is_busy(struct videobuf_queue *q) @@ -184,6 +194,7 @@ int videobuf_queue_is_busy(struct videobuf_queue *q) } return 0; } +EXPORT_SYMBOL_GPL(videobuf_queue_is_busy); /* Locking: Caller holds q->vb_lock */ void videobuf_queue_cancel(struct videobuf_queue *q) @@ -216,6 +227,7 @@ void videobuf_queue_cancel(struct videobuf_queue *q) } INIT_LIST_HEAD(&q->stream); } +EXPORT_SYMBOL_GPL(videobuf_queue_cancel); /* --------------------------------------------------------------------- */ @@ -237,6 +249,7 @@ enum v4l2_field videobuf_next_field(struct videobuf_queue *q) } return field; } +EXPORT_SYMBOL_GPL(videobuf_next_field); /* Locking: Caller holds q->vb_lock */ static void videobuf_status(struct videobuf_queue *q, struct v4l2_buffer *b, @@ -305,8 +318,7 @@ static int __videobuf_mmap_free(struct videobuf_queue *q) MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); - - rc = CALL(q, mmap_free, q); + rc = CALL(q, mmap_free, q); q->is_mmapped = 0; @@ -332,6 +344,7 @@ int videobuf_mmap_free(struct videobuf_queue *q) mutex_unlock(&q->vb_lock); return ret; } +EXPORT_SYMBOL_GPL(videobuf_mmap_free); /* Locking: Caller holds q->vb_lock */ int __videobuf_mmap_setup(struct videobuf_queue *q, @@ -351,7 +364,7 @@ int __videobuf_mmap_setup(struct videobuf_queue *q, for (i = 0; i < bcount; i++) { q->bufs[i] = videobuf_alloc(q); - if (q->bufs[i] == NULL) + if (NULL == q->bufs[i]) break; q->bufs[i]->i = i; @@ -372,11 +385,11 @@ int __videobuf_mmap_setup(struct videobuf_queue *q, if (!i) return -ENOMEM; - dprintk(1, "mmap setup: %d buffers, %d bytes each\n", - i, bsize); + dprintk(1, "mmap setup: %d buffers, %d bytes each\n", i, bsize); return i; } +EXPORT_SYMBOL_GPL(__videobuf_mmap_setup); int videobuf_mmap_setup(struct videobuf_queue *q, unsigned int bcount, unsigned int bsize, @@ -388,6 +401,7 @@ int videobuf_mmap_setup(struct videobuf_queue *q, mutex_unlock(&q->vb_lock); return ret; } +EXPORT_SYMBOL_GPL(videobuf_mmap_setup); int videobuf_reqbufs(struct videobuf_queue *q, struct v4l2_requestbuffers *req) @@ -432,7 +446,7 @@ int videobuf_reqbufs(struct videobuf_queue *q, q->ops->buf_setup(q, &count, &size); dprintk(1, "reqbufs: bufs=%d, size=0x%x [%u pages total]\n", count, size, - (unsigned int)((count*PAGE_ALIGN(size))>>PAGE_SHIFT) ); + (unsigned int)((count * PAGE_ALIGN(size)) >> PAGE_SHIFT)); retval = __videobuf_mmap_setup(q, count, size, req->memory); if (retval < 0) { @@ -447,6 +461,7 @@ int videobuf_reqbufs(struct videobuf_queue *q, mutex_unlock(&q->vb_lock); return retval; } +EXPORT_SYMBOL_GPL(videobuf_reqbufs); int videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b) { @@ -473,9 +488,9 @@ done: mutex_unlock(&q->vb_lock); return ret; } +EXPORT_SYMBOL_GPL(videobuf_querybuf); -int videobuf_qbuf(struct videobuf_queue *q, - struct v4l2_buffer *b) +int videobuf_qbuf(struct videobuf_queue *q, struct v4l2_buffer *b) { struct videobuf_buffer *buf; enum v4l2_field field; @@ -571,7 +586,7 @@ int videobuf_qbuf(struct videobuf_queue *q, retval = 0; wake_up_interruptible_sync(&q->wait); - done: +done: mutex_unlock(&q->vb_lock); if (b->memory == V4L2_MEMORY_MMAP) @@ -579,7 +594,7 @@ int videobuf_qbuf(struct videobuf_queue *q, return retval; } - +EXPORT_SYMBOL_GPL(videobuf_qbuf); /* Locking: Caller holds q->vb_lock */ static int stream_next_buffer_check_queue(struct videobuf_queue *q, int noblock) @@ -624,7 +639,6 @@ done: return retval; } - /* Locking: Caller holds q->vb_lock */ static int stream_next_buffer(struct videobuf_queue *q, struct videobuf_buffer **vb, int nonblocking) @@ -647,7 +661,7 @@ done: } int videobuf_dqbuf(struct videobuf_queue *q, - struct v4l2_buffer *b, int nonblocking) + struct v4l2_buffer *b, int nonblocking) { struct videobuf_buffer *buf = NULL; int retval; @@ -682,11 +696,11 @@ int videobuf_dqbuf(struct videobuf_queue *q, list_del(&buf->stream); memset(b, 0, sizeof(*b)); videobuf_status(q, b, buf, q->type); - - done: +done: mutex_unlock(&q->vb_lock); return retval; } +EXPORT_SYMBOL_GPL(videobuf_dqbuf); int videobuf_streamon(struct videobuf_queue *q) { @@ -709,10 +723,11 @@ int videobuf_streamon(struct videobuf_queue *q) spin_unlock_irqrestore(q->irqlock, flags); wake_up_interruptible_sync(&q->wait); - done: +done: mutex_unlock(&q->vb_lock); return retval; } +EXPORT_SYMBOL_GPL(videobuf_streamon); /* Locking: Caller holds q->vb_lock */ static int __videobuf_streamoff(struct videobuf_queue *q) @@ -735,6 +750,7 @@ int videobuf_streamoff(struct videobuf_queue *q) return retval; } +EXPORT_SYMBOL_GPL(videobuf_streamoff); /* Locking: Caller holds q->vb_lock */ static ssize_t videobuf_read_zerocopy(struct videobuf_queue *q, @@ -774,7 +790,7 @@ static ssize_t videobuf_read_zerocopy(struct videobuf_queue *q, retval = q->read_buf->size; } - done: +done: /* cleanup */ q->ops->buf_release(q, q->read_buf); kfree(q->read_buf); @@ -862,10 +878,11 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, q->read_buf = NULL; } - done: +done: mutex_unlock(&q->vb_lock); return retval; } +EXPORT_SYMBOL_GPL(videobuf_read_one); /* Locking: Caller holds q->vb_lock */ static int __videobuf_read_start(struct videobuf_queue *q) @@ -917,7 +934,6 @@ static void __videobuf_read_stop(struct videobuf_queue *q) q->bufs[i] = NULL; } q->read_buf = NULL; - } int videobuf_read_start(struct videobuf_queue *q) @@ -930,6 +946,7 @@ int videobuf_read_start(struct videobuf_queue *q) return rc; } +EXPORT_SYMBOL_GPL(videobuf_read_start); void videobuf_read_stop(struct videobuf_queue *q) { @@ -937,6 +954,7 @@ void videobuf_read_stop(struct videobuf_queue *q) __videobuf_read_stop(q); mutex_unlock(&q->vb_lock); } +EXPORT_SYMBOL_GPL(videobuf_read_stop); void videobuf_stop(struct videobuf_queue *q) { @@ -950,7 +968,7 @@ void videobuf_stop(struct videobuf_queue *q) mutex_unlock(&q->vb_lock); } - +EXPORT_SYMBOL_GPL(videobuf_stop); ssize_t videobuf_read_stream(struct videobuf_queue *q, char __user *data, size_t count, loff_t *ppos, @@ -1019,10 +1037,11 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q, break; } - done: +done: mutex_unlock(&q->vb_lock); return retval; } +EXPORT_SYMBOL_GPL(videobuf_read_stream); unsigned int videobuf_poll_stream(struct file *file, struct videobuf_queue *q, @@ -1062,9 +1081,9 @@ unsigned int videobuf_poll_stream(struct file *file, mutex_unlock(&q->vb_lock); return rc; } +EXPORT_SYMBOL_GPL(videobuf_poll_stream); -int videobuf_mmap_mapper(struct videobuf_queue *q, - struct vm_area_struct *vma) +int videobuf_mmap_mapper(struct videobuf_queue *q, struct vm_area_struct *vma) { int retval; @@ -1077,6 +1096,7 @@ int videobuf_mmap_mapper(struct videobuf_queue *q, return retval; } +EXPORT_SYMBOL_GPL(videobuf_mmap_mapper); #ifdef CONFIG_VIDEO_V4L1_COMPAT int videobuf_cgmbuf(struct videobuf_queue *q, @@ -1107,33 +1127,3 @@ int videobuf_cgmbuf(struct videobuf_queue *q, EXPORT_SYMBOL_GPL(videobuf_cgmbuf); #endif -/* --------------------------------------------------------------------- */ - -EXPORT_SYMBOL_GPL(videobuf_waiton); -EXPORT_SYMBOL_GPL(videobuf_iolock); - -EXPORT_SYMBOL_GPL(videobuf_alloc); - -EXPORT_SYMBOL_GPL(videobuf_queue_core_init); -EXPORT_SYMBOL_GPL(videobuf_queue_cancel); -EXPORT_SYMBOL_GPL(videobuf_queue_is_busy); - -EXPORT_SYMBOL_GPL(videobuf_next_field); -EXPORT_SYMBOL_GPL(videobuf_reqbufs); -EXPORT_SYMBOL_GPL(videobuf_querybuf); -EXPORT_SYMBOL_GPL(videobuf_qbuf); -EXPORT_SYMBOL_GPL(videobuf_dqbuf); -EXPORT_SYMBOL_GPL(videobuf_streamon); -EXPORT_SYMBOL_GPL(videobuf_streamoff); - -EXPORT_SYMBOL_GPL(videobuf_read_start); -EXPORT_SYMBOL_GPL(videobuf_read_stop); -EXPORT_SYMBOL_GPL(videobuf_stop); -EXPORT_SYMBOL_GPL(videobuf_read_stream); -EXPORT_SYMBOL_GPL(videobuf_read_one); -EXPORT_SYMBOL_GPL(videobuf_poll_stream); - -EXPORT_SYMBOL_GPL(__videobuf_mmap_setup); -EXPORT_SYMBOL_GPL(videobuf_mmap_setup); -EXPORT_SYMBOL_GPL(videobuf_mmap_free); -EXPORT_SYMBOL_GPL(videobuf_mmap_mapper); diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c index fcd045e7a1c..c9d946a388e 100644 --- a/drivers/media/video/videobuf-dma-sg.c +++ b/drivers/media/video/videobuf-dma-sg.c @@ -37,8 +37,12 @@ #define MAGIC_DMABUF 0x19721112 #define MAGIC_SG_MEM 0x17890714 -#define MAGIC_CHECK(is,should) if (unlikely((is) != (should))) \ - { printk(KERN_ERR "magic mismatch: %x (expected %x)\n",is,should); BUG(); } +#define MAGIC_CHECK(is, should) \ + if (unlikely((is) != (should))) { \ + printk(KERN_ERR "magic mismatch: %x (expected %x)\n", \ + is, should); \ + BUG(); \ + } static int debug; module_param(debug, int, 0644); @@ -47,13 +51,13 @@ MODULE_DESCRIPTION("helper module to manage video4linux dma sg buffers"); MODULE_AUTHOR("Mauro Carvalho Chehab "); MODULE_LICENSE("GPL"); -#define dprintk(level, fmt, arg...) if (debug >= level) \ - printk(KERN_DEBUG "vbuf-sg: " fmt , ## arg) +#define dprintk(level, fmt, arg...) \ + if (debug >= level) \ + printk(KERN_DEBUG "vbuf-sg: " fmt , ## arg) /* --------------------------------------------------------------------- */ -struct scatterlist* -videobuf_vmalloc_to_sg(unsigned char *virt, int nr_pages) +struct scatterlist *videobuf_vmalloc_to_sg(unsigned char *virt, int nr_pages) { struct scatterlist *sglist; struct page *pg; @@ -73,13 +77,14 @@ videobuf_vmalloc_to_sg(unsigned char *virt, int nr_pages) } return sglist; - err: +err: vfree(sglist); return NULL; } +EXPORT_SYMBOL_GPL(videobuf_vmalloc_to_sg); -struct scatterlist* -videobuf_pages_to_sg(struct page **pages, int nr_pages, int offset) +struct scatterlist *videobuf_pages_to_sg(struct page **pages, int nr_pages, + int offset) { struct scatterlist *sglist; int i; @@ -104,20 +109,20 @@ videobuf_pages_to_sg(struct page **pages, int nr_pages, int offset) } return sglist; - nopage: - dprintk(2,"sgl: oops - no page\n"); +nopage: + dprintk(2, "sgl: oops - no page\n"); vfree(sglist); return NULL; - highmem: - dprintk(2,"sgl: oops - highmem page\n"); +highmem: + dprintk(2, "sgl: oops - highmem page\n"); vfree(sglist); return NULL; } /* --------------------------------------------------------------------- */ -struct videobuf_dmabuf *videobuf_to_dma (struct videobuf_buffer *buf) +struct videobuf_dmabuf *videobuf_to_dma(struct videobuf_buffer *buf) { struct videobuf_dma_sg_memory *mem = buf->priv; BUG_ON(!mem); @@ -126,17 +131,19 @@ struct videobuf_dmabuf *videobuf_to_dma (struct videobuf_buffer *buf) return &mem->dma; } +EXPORT_SYMBOL_GPL(videobuf_to_dma); void videobuf_dma_init(struct videobuf_dmabuf *dma) { - memset(dma,0,sizeof(*dma)); + memset(dma, 0, sizeof(*dma)); dma->magic = MAGIC_DMABUF; } +EXPORT_SYMBOL_GPL(videobuf_dma_init); static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma, int direction, unsigned long data, unsigned long size) { - unsigned long first,last; + unsigned long first, last; int err, rw = 0; dma->direction = direction; @@ -155,21 +162,21 @@ static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma, last = ((data+size-1) & PAGE_MASK) >> PAGE_SHIFT; dma->offset = data & ~PAGE_MASK; dma->nr_pages = last-first+1; - dma->pages = kmalloc(dma->nr_pages * sizeof(struct page*), - GFP_KERNEL); + dma->pages = kmalloc(dma->nr_pages * sizeof(struct page *), GFP_KERNEL); if (NULL == dma->pages) return -ENOMEM; - dprintk(1,"init user [0x%lx+0x%lx => %d pages]\n", - data,size,dma->nr_pages); - err = get_user_pages(current,current->mm, + dprintk(1, "init user [0x%lx+0x%lx => %d pages]\n", + data, size, dma->nr_pages); + + err = get_user_pages(current, current->mm, data & PAGE_MASK, dma->nr_pages, rw == READ, 1, /* force */ dma->pages, NULL); if (err != dma->nr_pages) { dma->nr_pages = (err >= 0) ? err : 0; - dprintk(1,"get_user_pages: err=%d [%d]\n",err,dma->nr_pages); + dprintk(1, "get_user_pages: err=%d [%d]\n", err, dma->nr_pages); return err < 0 ? err : -EINVAL; } return 0; @@ -179,48 +186,58 @@ int videobuf_dma_init_user(struct videobuf_dmabuf *dma, int direction, unsigned long data, unsigned long size) { int ret; + down_read(¤t->mm->mmap_sem); ret = videobuf_dma_init_user_locked(dma, direction, data, size); up_read(¤t->mm->mmap_sem); return ret; } +EXPORT_SYMBOL_GPL(videobuf_dma_init_user); int videobuf_dma_init_kernel(struct videobuf_dmabuf *dma, int direction, int nr_pages) { - dprintk(1,"init kernel [%d pages]\n",nr_pages); + dprintk(1, "init kernel [%d pages]\n", nr_pages); + dma->direction = direction; dma->vmalloc = vmalloc_32(nr_pages << PAGE_SHIFT); if (NULL == dma->vmalloc) { - dprintk(1,"vmalloc_32(%d pages) failed\n",nr_pages); + dprintk(1, "vmalloc_32(%d pages) failed\n", nr_pages); return -ENOMEM; } - dprintk(1,"vmalloc is at addr 0x%08lx, size=%d\n", + + dprintk(1, "vmalloc is at addr 0x%08lx, size=%d\n", (unsigned long)dma->vmalloc, nr_pages << PAGE_SHIFT); - memset(dma->vmalloc,0,nr_pages << PAGE_SHIFT); + + memset(dma->vmalloc, 0, nr_pages << PAGE_SHIFT); dma->nr_pages = nr_pages; + return 0; } +EXPORT_SYMBOL_GPL(videobuf_dma_init_kernel); int videobuf_dma_init_overlay(struct videobuf_dmabuf *dma, int direction, dma_addr_t addr, int nr_pages) { - dprintk(1,"init overlay [%d pages @ bus 0x%lx]\n", - nr_pages,(unsigned long)addr); + dprintk(1, "init overlay [%d pages @ bus 0x%lx]\n", + nr_pages, (unsigned long)addr); dma->direction = direction; + if (0 == addr) return -EINVAL; dma->bus_addr = addr; dma->nr_pages = nr_pages; + return 0; } +EXPORT_SYMBOL_GPL(videobuf_dma_init_overlay); -int videobuf_dma_map(struct videobuf_queue* q, struct videobuf_dmabuf *dma) +int videobuf_dma_map(struct videobuf_queue *q, struct videobuf_dmabuf *dma) { - MAGIC_CHECK(dma->magic,MAGIC_DMABUF); + MAGIC_CHECK(dma->magic, MAGIC_DMABUF); BUG_ON(0 == dma->nr_pages); if (dma->pages) { @@ -228,20 +245,21 @@ int videobuf_dma_map(struct videobuf_queue* q, struct videobuf_dmabuf *dma) dma->offset); } if (dma->vmalloc) { - dma->sglist = videobuf_vmalloc_to_sg - (dma->vmalloc,dma->nr_pages); + dma->sglist = videobuf_vmalloc_to_sg(dma->vmalloc, + dma->nr_pages); } if (dma->bus_addr) { dma->sglist = vmalloc(sizeof(*dma->sglist)); if (NULL != dma->sglist) { - dma->sglen = 1; - sg_dma_address(&dma->sglist[0]) = dma->bus_addr & PAGE_MASK; - dma->sglist[0].offset = dma->bus_addr & ~PAGE_MASK; - sg_dma_len(&dma->sglist[0]) = dma->nr_pages * PAGE_SIZE; + dma->sglen = 1; + sg_dma_address(&dma->sglist[0]) = dma->bus_addr + & PAGE_MASK; + dma->sglist[0].offset = dma->bus_addr & ~PAGE_MASK; + sg_dma_len(&dma->sglist[0]) = dma->nr_pages * PAGE_SIZE; } } if (NULL == dma->sglist) { - dprintk(1,"scatterlist is NULL\n"); + dprintk(1, "scatterlist is NULL\n"); return -ENOMEM; } if (!dma->bus_addr) { @@ -249,15 +267,17 @@ int videobuf_dma_map(struct videobuf_queue* q, struct videobuf_dmabuf *dma) dma->nr_pages, dma->direction); if (0 == dma->sglen) { printk(KERN_WARNING - "%s: videobuf_map_sg failed\n",__func__); + "%s: videobuf_map_sg failed\n", __func__); vfree(dma->sglist); dma->sglist = NULL; dma->sglen = 0; return -ENOMEM; } } + return 0; } +EXPORT_SYMBOL_GPL(videobuf_dma_map); int videobuf_dma_sync(struct videobuf_queue *q, struct videobuf_dmabuf *dma) { @@ -265,12 +285,15 @@ int videobuf_dma_sync(struct videobuf_queue *q, struct videobuf_dmabuf *dma) BUG_ON(!dma->sglen); dma_sync_sg_for_cpu(q->dev, dma->sglist, dma->nr_pages, dma->direction); + return 0; } +EXPORT_SYMBOL_GPL(videobuf_dma_sync); -int videobuf_dma_unmap(struct videobuf_queue* q,struct videobuf_dmabuf *dma) +int videobuf_dma_unmap(struct videobuf_queue *q, struct videobuf_dmabuf *dma) { MAGIC_CHECK(dma->magic, MAGIC_DMABUF); + if (!dma->sglen) return 0; @@ -279,17 +302,19 @@ int videobuf_dma_unmap(struct videobuf_queue* q,struct videobuf_dmabuf *dma) vfree(dma->sglist); dma->sglist = NULL; dma->sglen = 0; + return 0; } +EXPORT_SYMBOL_GPL(videobuf_dma_unmap); int videobuf_dma_free(struct videobuf_dmabuf *dma) { - MAGIC_CHECK(dma->magic,MAGIC_DMABUF); + int i; + MAGIC_CHECK(dma->magic, MAGIC_DMABUF); BUG_ON(dma->sglen); if (dma->pages) { - int i; - for (i=0; i < dma->nr_pages; i++) + for (i = 0; i < dma->nr_pages; i++) page_cache_release(dma->pages[i]); kfree(dma->pages); dma->pages = NULL; @@ -298,12 +323,13 @@ int videobuf_dma_free(struct videobuf_dmabuf *dma) vfree(dma->vmalloc); dma->vmalloc = NULL; - if (dma->bus_addr) { + if (dma->bus_addr) dma->bus_addr = 0; - } dma->direction = DMA_NONE; + return 0; } +EXPORT_SYMBOL_GPL(videobuf_dma_free); /* --------------------------------------------------------------------- */ @@ -315,6 +341,7 @@ int videobuf_sg_dma_map(struct device *dev, struct videobuf_dmabuf *dma) return videobuf_dma_map(&q, dma); } +EXPORT_SYMBOL_GPL(videobuf_sg_dma_map); int videobuf_sg_dma_unmap(struct device *dev, struct videobuf_dmabuf *dma) { @@ -324,49 +351,48 @@ int videobuf_sg_dma_unmap(struct device *dev, struct videobuf_dmabuf *dma) return videobuf_dma_unmap(&q, dma); } +EXPORT_SYMBOL_GPL(videobuf_sg_dma_unmap); /* --------------------------------------------------------------------- */ -static void -videobuf_vm_open(struct vm_area_struct *vma) +static void videobuf_vm_open(struct vm_area_struct *vma) { struct videobuf_mapping *map = vma->vm_private_data; - dprintk(2,"vm_open %p [count=%d,vma=%08lx-%08lx]\n",map, - map->count,vma->vm_start,vma->vm_end); + dprintk(2, "vm_open %p [count=%d,vma=%08lx-%08lx]\n", map, + map->count, vma->vm_start, vma->vm_end); + map->count++; } -static void -videobuf_vm_close(struct vm_area_struct *vma) +static void videobuf_vm_close(struct vm_area_struct *vma) { struct videobuf_mapping *map = vma->vm_private_data; struct videobuf_queue *q = map->q; struct videobuf_dma_sg_memory *mem; int i; - dprintk(2,"vm_close %p [count=%d,vma=%08lx-%08lx]\n",map, - map->count,vma->vm_start,vma->vm_end); + dprintk(2, "vm_close %p [count=%d,vma=%08lx-%08lx]\n", map, + map->count, vma->vm_start, vma->vm_end); map->count--; if (0 == map->count) { - dprintk(1,"munmap %p q=%p\n",map,q); + dprintk(1, "munmap %p q=%p\n", map, q); mutex_lock(&q->vb_lock); for (i = 0; i < VIDEO_MAX_FRAME; i++) { if (NULL == q->bufs[i]) continue; - mem=q->bufs[i]->priv; - + mem = q->bufs[i]->priv; if (!mem) continue; - MAGIC_CHECK(mem->magic,MAGIC_SG_MEM); + MAGIC_CHECK(mem->magic, MAGIC_SG_MEM); if (q->bufs[i]->map != map) continue; q->bufs[i]->map = NULL; q->bufs[i]->baddr = 0; - q->ops->buf_release(q,q->bufs[i]); + q->ops->buf_release(q, q->bufs[i]); } mutex_unlock(&q->vb_lock); kfree(map); @@ -380,26 +406,27 @@ videobuf_vm_close(struct vm_area_struct *vma) * now ...). Bounce buffers don't work very well for the data rates * video capture has. */ -static int -videobuf_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) +static int videobuf_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { struct page *page; - dprintk(3,"fault: fault @ %08lx [vma %08lx-%08lx]\n", - (unsigned long)vmf->virtual_address,vma->vm_start,vma->vm_end); + dprintk(3, "fault: fault @ %08lx [vma %08lx-%08lx]\n", + (unsigned long)vmf->virtual_address, + vma->vm_start, vma->vm_end); + page = alloc_page(GFP_USER | __GFP_DMA32); if (!page) return VM_FAULT_OOM; clear_user_highpage(page, (unsigned long)vmf->virtual_address); vmf->page = page; + return 0; } -static const struct vm_operations_struct videobuf_vm_ops = -{ - .open = videobuf_vm_open, - .close = videobuf_vm_close, - .fault = videobuf_vm_fault, +static const struct vm_operations_struct videobuf_vm_ops = { + .open = videobuf_vm_open, + .close = videobuf_vm_close, + .fault = videobuf_vm_fault, }; /* --------------------------------------------------------------------- @@ -417,23 +444,23 @@ static void *__videobuf_alloc(size_t size) struct videobuf_dma_sg_memory *mem; struct videobuf_buffer *vb; - vb = kzalloc(size+sizeof(*mem),GFP_KERNEL); + vb = kzalloc(size + sizeof(*mem), GFP_KERNEL); if (!vb) return vb; - mem = vb->priv = ((char *)vb)+size; - mem->magic=MAGIC_SG_MEM; + mem = vb->priv = ((char *)vb) + size; + mem->magic = MAGIC_SG_MEM; videobuf_dma_init(&mem->dma); - dprintk(1,"%s: allocated at %p(%ld+%ld) & %p(%ld)\n", - __func__,vb,(long)sizeof(*vb),(long)size-sizeof(*vb), - mem,(long)sizeof(*mem)); + dprintk(1, "%s: allocated at %p(%ld+%ld) & %p(%ld)\n", + __func__, vb, (long)sizeof(*vb), (long)size - sizeof(*vb), + mem, (long)sizeof(*mem)); return vb; } -static void *__videobuf_to_vmalloc (struct videobuf_buffer *buf) +static void *__videobuf_to_vmalloc(struct videobuf_buffer *buf) { struct videobuf_dma_sg_memory *mem = buf->priv; BUG_ON(!mem); @@ -443,11 +470,11 @@ static void *__videobuf_to_vmalloc (struct videobuf_buffer *buf) return mem->dma.vmalloc; } -static int __videobuf_iolock (struct videobuf_queue* q, - struct videobuf_buffer *vb, - struct v4l2_framebuffer *fbuf) +static int __videobuf_iolock(struct videobuf_queue *q, + struct videobuf_buffer *vb, + struct v4l2_framebuffer *fbuf) { - int err,pages; + int err, pages; dma_addr_t bus; struct videobuf_dma_sg_memory *mem = vb->priv; BUG_ON(!mem); @@ -460,16 +487,16 @@ static int __videobuf_iolock (struct videobuf_queue* q, if (0 == vb->baddr) { /* no userspace addr -- kernel bounce buffer */ pages = PAGE_ALIGN(vb->size) >> PAGE_SHIFT; - err = videobuf_dma_init_kernel( &mem->dma, - DMA_FROM_DEVICE, - pages ); + err = videobuf_dma_init_kernel(&mem->dma, + DMA_FROM_DEVICE, + pages); if (0 != err) return err; } else if (vb->memory == V4L2_MEMORY_USERPTR) { /* dma directly to userspace */ - err = videobuf_dma_init_user( &mem->dma, - DMA_FROM_DEVICE, - vb->baddr,vb->bsize ); + err = videobuf_dma_init_user(&mem->dma, + DMA_FROM_DEVICE, + vb->baddr, vb->bsize); if (0 != err) return err; } else { @@ -516,9 +543,9 @@ static int __videobuf_sync(struct videobuf_queue *q, { struct videobuf_dma_sg_memory *mem = buf->priv; BUG_ON(!mem); - MAGIC_CHECK(mem->magic,MAGIC_SG_MEM); + MAGIC_CHECK(mem->magic, MAGIC_SG_MEM); - return videobuf_dma_sync(q,&mem->dma); + return videobuf_dma_sync(q, &mem->dma); } static int __videobuf_mmap_free(struct videobuf_queue *q) @@ -540,16 +567,16 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, { struct videobuf_dma_sg_memory *mem; struct videobuf_mapping *map; - unsigned int first,last,size,i; + unsigned int first, last, size, i; int retval; retval = -EINVAL; if (!(vma->vm_flags & VM_WRITE)) { - dprintk(1,"mmap app bug: PROT_WRITE please\n"); + dprintk(1, "mmap app bug: PROT_WRITE please\n"); goto done; } if (!(vma->vm_flags & VM_SHARED)) { - dprintk(1,"mmap app bug: MAP_SHARED please\n"); + dprintk(1, "mmap app bug: MAP_SHARED please\n"); goto done; } @@ -565,9 +592,9 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, for (first = 0; first < VIDEO_MAX_FRAME; first++) { if (NULL == q->bufs[first]) continue; - mem=q->bufs[first]->priv; + mem = q->bufs[first]->priv; BUG_ON(!mem); - MAGIC_CHECK(mem->magic,MAGIC_SG_MEM); + MAGIC_CHECK(mem->magic, MAGIC_SG_MEM); if (V4L2_MEMORY_MMAP != q->bufs[first]->memory) continue; @@ -575,7 +602,7 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, break; } if (VIDEO_MAX_FRAME == first) { - dprintk(1,"mmap app bug: offset invalid [offset=0x%lx]\n", + dprintk(1, "mmap app bug: offset invalid [offset=0x%lx]\n", (vma->vm_pgoff << PAGE_SHIFT)); goto done; } @@ -595,14 +622,14 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, break; } if (VIDEO_MAX_FRAME == last) { - dprintk(1,"mmap app bug: size invalid [size=0x%lx]\n", + dprintk(1, "mmap app bug: size invalid [size=0x%lx]\n", (vma->vm_end - vma->vm_start)); goto done; } /* create mapping + update buffer list */ retval = -ENOMEM; - map = kmalloc(sizeof(struct videobuf_mapping),GFP_KERNEL); + map = kmalloc(sizeof(struct videobuf_mapping), GFP_KERNEL); if (NULL == map) goto done; @@ -623,21 +650,21 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED; vma->vm_flags &= ~VM_IO; /* using shared anonymous pages */ vma->vm_private_data = map; - dprintk(1,"mmap %p: q=%p %08lx-%08lx pgoff %08lx bufs %d-%d\n", - map,q,vma->vm_start,vma->vm_end,vma->vm_pgoff,first,last); + dprintk(1, "mmap %p: q=%p %08lx-%08lx pgoff %08lx bufs %d-%d\n", + map, q, vma->vm_start, vma->vm_end, vma->vm_pgoff, first, last); retval = 0; - done: +done: return retval; } -static int __videobuf_copy_to_user ( struct videobuf_queue *q, +static int __videobuf_copy_to_user(struct videobuf_queue *q, char __user *data, size_t count, - int nonblocking ) + int nonblocking) { struct videobuf_dma_sg_memory *mem = q->read_buf->priv; BUG_ON(!mem); - MAGIC_CHECK(mem->magic,MAGIC_SG_MEM); + MAGIC_CHECK(mem->magic, MAGIC_SG_MEM); /* copy to userspace */ if (count > q->read_buf->size - q->read_off) @@ -649,30 +676,30 @@ static int __videobuf_copy_to_user ( struct videobuf_queue *q, return count; } -static int __videobuf_copy_stream ( struct videobuf_queue *q, +static int __videobuf_copy_stream(struct videobuf_queue *q, char __user *data, size_t count, size_t pos, - int vbihack, int nonblocking ) + int vbihack, int nonblocking) { - unsigned int *fc; + unsigned int *fc; struct videobuf_dma_sg_memory *mem = q->read_buf->priv; BUG_ON(!mem); - MAGIC_CHECK(mem->magic,MAGIC_SG_MEM); + MAGIC_CHECK(mem->magic, MAGIC_SG_MEM); if (vbihack) { /* dirty, undocumented hack -- pass the frame counter - * within the last four bytes of each vbi data block. - * We need that one to maintain backward compatibility - * to all vbi decoding software out there ... */ - fc = (unsigned int*)mem->dma.vmalloc; - fc += (q->read_buf->size>>2) -1; + * within the last four bytes of each vbi data block. + * We need that one to maintain backward compatibility + * to all vbi decoding software out there ... */ + fc = (unsigned int *)mem->dma.vmalloc; + fc += (q->read_buf->size >> 2) - 1; *fc = q->read_buf->field_count >> 1; - dprintk(1,"vbihack: %d\n",*fc); + dprintk(1, "vbihack: %d\n", *fc); } /* copy stuff using the common method */ - count = __videobuf_copy_to_user (q,data,count,nonblocking); + count = __videobuf_copy_to_user(q, data, count, nonblocking); - if ( (count==-EFAULT) && (0 == pos) ) + if ((count == -EFAULT) && (0 == pos)) return -EFAULT; return count; @@ -702,8 +729,9 @@ void *videobuf_sg_alloc(size_t size) return videobuf_alloc(&q); } +EXPORT_SYMBOL_GPL(videobuf_sg_alloc); -void videobuf_queue_sg_init(struct videobuf_queue* q, +void videobuf_queue_sg_init(struct videobuf_queue *q, const struct videobuf_queue_ops *ops, struct device *dev, spinlock_t *irqlock, @@ -715,29 +743,5 @@ void videobuf_queue_sg_init(struct videobuf_queue* q, videobuf_queue_core_init(q, ops, dev, irqlock, type, field, msize, priv, &sg_ops); } - -/* --------------------------------------------------------------------- */ - -EXPORT_SYMBOL_GPL(videobuf_vmalloc_to_sg); - -EXPORT_SYMBOL_GPL(videobuf_to_dma); -EXPORT_SYMBOL_GPL(videobuf_dma_init); -EXPORT_SYMBOL_GPL(videobuf_dma_init_user); -EXPORT_SYMBOL_GPL(videobuf_dma_init_kernel); -EXPORT_SYMBOL_GPL(videobuf_dma_init_overlay); -EXPORT_SYMBOL_GPL(videobuf_dma_map); -EXPORT_SYMBOL_GPL(videobuf_dma_sync); -EXPORT_SYMBOL_GPL(videobuf_dma_unmap); -EXPORT_SYMBOL_GPL(videobuf_dma_free); - -EXPORT_SYMBOL_GPL(videobuf_sg_dma_map); -EXPORT_SYMBOL_GPL(videobuf_sg_dma_unmap); -EXPORT_SYMBOL_GPL(videobuf_sg_alloc); - EXPORT_SYMBOL_GPL(videobuf_queue_sg_init); -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/video/videobuf-vmalloc.c b/drivers/media/video/videobuf-vmalloc.c index 136e09383c0..d6a8a38dc9c 100644 --- a/drivers/media/video/videobuf-vmalloc.c +++ b/drivers/media/video/videobuf-vmalloc.c @@ -30,8 +30,12 @@ #define MAGIC_DMABUF 0x17760309 #define MAGIC_VMAL_MEM 0x18221223 -#define MAGIC_CHECK(is,should) if (unlikely((is) != (should))) \ - { printk(KERN_ERR "magic mismatch: %x (expected %x)\n",is,should); BUG(); } +#define MAGIC_CHECK(is, should) \ + if (unlikely((is) != (should))) { \ + printk(KERN_ERR "magic mismatch: %x (expected %x)\n", \ + is, should); \ + BUG(); \ + } static int debug; module_param(debug, int, 0644); @@ -40,19 +44,19 @@ MODULE_DESCRIPTION("helper module to manage video4linux vmalloc buffers"); MODULE_AUTHOR("Mauro Carvalho Chehab "); MODULE_LICENSE("GPL"); -#define dprintk(level, fmt, arg...) if (debug >= level) \ - printk(KERN_DEBUG "vbuf-vmalloc: " fmt , ## arg) +#define dprintk(level, fmt, arg...) \ + if (debug >= level) \ + printk(KERN_DEBUG "vbuf-vmalloc: " fmt , ## arg) /***************************************************************************/ -static void -videobuf_vm_open(struct vm_area_struct *vma) +static void videobuf_vm_open(struct vm_area_struct *vma) { struct videobuf_mapping *map = vma->vm_private_data; - dprintk(2,"vm_open %p [count=%u,vma=%08lx-%08lx]\n",map, - map->count,vma->vm_start,vma->vm_end); + dprintk(2, "vm_open %p [count=%u,vma=%08lx-%08lx]\n", map, + map->count, vma->vm_start, vma->vm_end); map->count++; } @@ -63,7 +67,7 @@ static void videobuf_vm_close(struct vm_area_struct *vma) struct videobuf_queue *q = map->q; int i; - dprintk(2,"vm_close %p [count=%u,vma=%08lx-%08lx]\n", map, + dprintk(2, "vm_close %p [count=%u,vma=%08lx-%08lx]\n", map, map->count, vma->vm_start, vma->vm_end); map->count--; @@ -116,8 +120,7 @@ static void videobuf_vm_close(struct vm_area_struct *vma) return; } -static const struct vm_operations_struct videobuf_vm_ops = -{ +static const struct vm_operations_struct videobuf_vm_ops = { .open = videobuf_vm_open, .close = videobuf_vm_close, }; @@ -137,23 +140,23 @@ static void *__videobuf_alloc(size_t size) struct videobuf_vmalloc_memory *mem; struct videobuf_buffer *vb; - vb = kzalloc(size+sizeof(*mem),GFP_KERNEL); + vb = kzalloc(size + sizeof(*mem), GFP_KERNEL); if (!vb) return vb; - mem = vb->priv = ((char *)vb)+size; - mem->magic=MAGIC_VMAL_MEM; + mem = vb->priv = ((char *)vb) + size; + mem->magic = MAGIC_VMAL_MEM; - dprintk(1,"%s: allocated at %p(%ld+%ld) & %p(%ld)\n", - __func__,vb,(long)sizeof(*vb),(long)size-sizeof(*vb), - mem,(long)sizeof(*mem)); + dprintk(1, "%s: allocated at %p(%ld+%ld) & %p(%ld)\n", + __func__, vb, (long)sizeof(*vb), (long)size - sizeof(*vb), + mem, (long)sizeof(*mem)); return vb; } -static int __videobuf_iolock (struct videobuf_queue* q, - struct videobuf_buffer *vb, - struct v4l2_framebuffer *fbuf) +static int __videobuf_iolock(struct videobuf_queue *q, + struct videobuf_buffer *vb, + struct v4l2_framebuffer *fbuf) { struct videobuf_vmalloc_memory *mem = vb->priv; int pages; @@ -177,15 +180,13 @@ static int __videobuf_iolock (struct videobuf_queue* q, dprintk(1, "%s memory method USERPTR\n", __func__); -#if 1 if (vb->baddr) { printk(KERN_ERR "USERPTR is currently not supported\n"); return -EINVAL; } -#endif /* The only USERPTR currently supported is the one needed for - read() method. + * read() method. */ mem->vmalloc = vmalloc_user(pages); @@ -210,7 +211,7 @@ static int __videobuf_iolock (struct videobuf_queue* q, /* Try to remap memory */ rc = remap_vmalloc_range(mem->vma, (void *)vb->baddr, 0); if (rc < 0) { - printk(KERN_ERR "mmap: remap failed with error %d. ", rc); + printk(KERN_ERR "mmap: remap failed with error %d", rc); return -ENOMEM; } #endif @@ -273,7 +274,7 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, break; } if (VIDEO_MAX_FRAME == first) { - dprintk(1,"mmap app bug: offset invalid [offset=0x%lx]\n", + dprintk(1, "mmap app bug: offset invalid [offset=0x%lx]\n", (vma->vm_pgoff << PAGE_SHIFT)); return -EINVAL; } @@ -300,8 +301,7 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, printk(KERN_ERR "vmalloc (%d pages) failed\n", pages); goto error; } - dprintk(1, "vmalloc is at addr %p (%d pages)\n", - mem->vmalloc, pages); + dprintk(1, "vmalloc is at addr %p (%d pages)\n", mem->vmalloc, pages); /* Try to remap memory */ retval = remap_vmalloc_range(vma, mem->vmalloc, 0); @@ -315,7 +315,7 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED; vma->vm_private_data = map; - dprintk(1,"mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n", + dprintk(1, "mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n", map, q, vma->vm_start, vma->vm_end, (long int) q->bufs[first]->bsize, vma->vm_pgoff, first); @@ -330,15 +330,15 @@ error: return -ENOMEM; } -static int __videobuf_copy_to_user ( struct videobuf_queue *q, - char __user *data, size_t count, - int nonblocking ) +static int __videobuf_copy_to_user(struct videobuf_queue *q, + char __user *data, size_t count, + int nonblocking) { - struct videobuf_vmalloc_memory *mem=q->read_buf->priv; - BUG_ON (!mem); - MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM); + struct videobuf_vmalloc_memory *mem = q->read_buf->priv; + BUG_ON(!mem); + MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM); - BUG_ON (!mem->vmalloc); + BUG_ON(!mem->vmalloc); /* copy to userspace */ if (count > q->read_buf->size - q->read_off) @@ -350,30 +350,30 @@ static int __videobuf_copy_to_user ( struct videobuf_queue *q, return count; } -static int __videobuf_copy_stream ( struct videobuf_queue *q, - char __user *data, size_t count, size_t pos, - int vbihack, int nonblocking ) +static int __videobuf_copy_stream(struct videobuf_queue *q, + char __user *data, size_t count, size_t pos, + int vbihack, int nonblocking) { - unsigned int *fc; - struct videobuf_vmalloc_memory *mem=q->read_buf->priv; - BUG_ON (!mem); - MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM); + unsigned int *fc; + struct videobuf_vmalloc_memory *mem = q->read_buf->priv; + BUG_ON(!mem); + MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM); if (vbihack) { /* dirty, undocumented hack -- pass the frame counter * within the last four bytes of each vbi data block. * We need that one to maintain backward compatibility * to all vbi decoding software out there ... */ - fc = (unsigned int*)mem->vmalloc; - fc += (q->read_buf->size>>2) -1; + fc = (unsigned int *)mem->vmalloc; + fc += (q->read_buf->size >> 2) - 1; *fc = q->read_buf->field_count >> 1; - dprintk(1,"vbihack: %d\n",*fc); + dprintk(1, "vbihack: %d\n", *fc); } /* copy stuff using the common method */ - count = __videobuf_copy_to_user (q,data,count,nonblocking); + count = __videobuf_copy_to_user(q, data, count, nonblocking); - if ( (count==-EFAULT) && (0 == pos) ) + if ((count == -EFAULT) && (0 == pos)) return -EFAULT; return count; @@ -392,7 +392,7 @@ static struct videobuf_qtype_ops qops = { .vmalloc = videobuf_to_vmalloc, }; -void videobuf_queue_vmalloc_init(struct videobuf_queue* q, +void videobuf_queue_vmalloc_init(struct videobuf_queue *q, const struct videobuf_queue_ops *ops, struct device *dev, spinlock_t *irqlock, @@ -404,20 +404,19 @@ void videobuf_queue_vmalloc_init(struct videobuf_queue* q, videobuf_queue_core_init(q, ops, dev, irqlock, type, field, msize, priv, &qops); } - EXPORT_SYMBOL_GPL(videobuf_queue_vmalloc_init); -void *videobuf_to_vmalloc (struct videobuf_buffer *buf) +void *videobuf_to_vmalloc(struct videobuf_buffer *buf) { - struct videobuf_vmalloc_memory *mem=buf->priv; - BUG_ON (!mem); - MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM); + struct videobuf_vmalloc_memory *mem = buf->priv; + BUG_ON(!mem); + MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM); return mem->vmalloc; } EXPORT_SYMBOL_GPL(videobuf_to_vmalloc); -void videobuf_vmalloc_free (struct videobuf_buffer *buf) +void videobuf_vmalloc_free(struct videobuf_buffer *buf) { struct videobuf_vmalloc_memory *mem = buf->priv; @@ -442,8 +441,3 @@ void videobuf_vmalloc_free (struct videobuf_buffer *buf) } EXPORT_SYMBOL_GPL(videobuf_vmalloc_free); -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/include/media/videobuf-core.h b/include/media/videobuf-core.h index 316fdccdcaa..b1f7bf423fd 100644 --- a/include/media/videobuf-core.h +++ b/include/media/videobuf-core.h @@ -129,14 +129,14 @@ struct videobuf_qtype_ops { void *(*alloc) (size_t size); void *(*vmalloc) (struct videobuf_buffer *buf); - int (*iolock) (struct videobuf_queue* q, + int (*iolock) (struct videobuf_queue *q, struct videobuf_buffer *vb, struct v4l2_framebuffer *fbuf); int (*mmap) (struct videobuf_queue *q, unsigned int *count, unsigned int *size, enum v4l2_memory memory); - int (*sync) (struct videobuf_queue* q, + int (*sync) (struct videobuf_queue *q, struct videobuf_buffer *buf); int (*video_copy_to_user)(struct videobuf_queue *q, char __user *data, @@ -185,14 +185,14 @@ struct videobuf_queue { }; int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr); -int videobuf_iolock(struct videobuf_queue* q, struct videobuf_buffer *vb, +int videobuf_iolock(struct videobuf_queue *q, struct videobuf_buffer *vb, struct v4l2_framebuffer *fbuf); void *videobuf_alloc(struct videobuf_queue* q); /* Used on videobuf-dvb */ -void *videobuf_queue_to_vmalloc (struct videobuf_queue* q, - struct videobuf_buffer *buf); +void *videobuf_queue_to_vmalloc(struct videobuf_queue *q, + struct videobuf_buffer *buf); void videobuf_queue_core_init(struct videobuf_queue *q, const struct videobuf_queue_ops *ops, diff --git a/include/media/videobuf-dma-sg.h b/include/media/videobuf-dma-sg.h index 53e72f78717..dbfd8cf7b7c 100644 --- a/include/media/videobuf-dma-sg.h +++ b/include/media/videobuf-dma-sg.h @@ -17,6 +17,8 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 */ +#ifndef _VIDEOBUF_DMA_SG_H +#define _VIDEOBUF_DMA_SG_H #include @@ -27,14 +29,14 @@ * block (NULL on errors). Memory for the scatterlist is allocated * using kmalloc. The caller must free the memory. */ -struct scatterlist* videobuf_vmalloc_to_sg(unsigned char *virt, int nr_pages); +struct scatterlist *videobuf_vmalloc_to_sg(unsigned char *virt, int nr_pages); /* * Return a scatterlist for a an array of userpages (NULL on errors). * Memory for the scatterlist is allocated using kmalloc. The caller * must free the memory. */ -struct scatterlist* videobuf_pages_to_sg(struct page **pages, int nr_pages, +struct scatterlist *videobuf_pages_to_sg(struct page **pages, int nr_pages, int offset); /* --------------------------------------------------------------------- */ @@ -78,8 +80,7 @@ struct videobuf_dmabuf { int direction; }; -struct videobuf_dma_sg_memory -{ +struct videobuf_dma_sg_memory { u32 magic; /* for mmap'ed buffers */ @@ -95,14 +96,14 @@ int videobuf_dma_init_overlay(struct videobuf_dmabuf *dma, int direction, dma_addr_t addr, int nr_pages); int videobuf_dma_free(struct videobuf_dmabuf *dma); -int videobuf_dma_map(struct videobuf_queue* q,struct videobuf_dmabuf *dma); -int videobuf_dma_sync(struct videobuf_queue* q,struct videobuf_dmabuf *dma); -int videobuf_dma_unmap(struct videobuf_queue* q,struct videobuf_dmabuf *dma); -struct videobuf_dmabuf *videobuf_to_dma (struct videobuf_buffer *buf); +int videobuf_dma_map(struct videobuf_queue *q, struct videobuf_dmabuf *dma); +int videobuf_dma_sync(struct videobuf_queue *q, struct videobuf_dmabuf *dma); +int videobuf_dma_unmap(struct videobuf_queue *q, struct videobuf_dmabuf *dma); +struct videobuf_dmabuf *videobuf_to_dma(struct videobuf_buffer *buf); void *videobuf_sg_alloc(size_t size); -void videobuf_queue_sg_init(struct videobuf_queue* q, +void videobuf_queue_sg_init(struct videobuf_queue *q, const struct videobuf_queue_ops *ops, struct device *dev, spinlock_t *irqlock, @@ -111,9 +112,11 @@ void videobuf_queue_sg_init(struct videobuf_queue* q, unsigned int msize, void *priv); - /*FIXME: these variants are used only on *-alsa code, where videobuf is - * used without queue - */ +/*FIXME: these variants are used only on *-alsa code, where videobuf is + * used without queue + */ int videobuf_sg_dma_map(struct device *dev, struct videobuf_dmabuf *dma); int videobuf_sg_dma_unmap(struct device *dev, struct videobuf_dmabuf *dma); +#endif /* _VIDEOBUF_DMA_SG_H */ + diff --git a/include/media/videobuf-vmalloc.h b/include/media/videobuf-vmalloc.h index 4b419a257a7..851eb1a2ff2 100644 --- a/include/media/videobuf-vmalloc.h +++ b/include/media/videobuf-vmalloc.h @@ -19,17 +19,17 @@ /* --------------------------------------------------------------------- */ -struct videobuf_vmalloc_memory -{ +struct videobuf_vmalloc_memory { u32 magic; void *vmalloc; - /* remap_vmalloc_range seems to need to run after mmap() on some cases */ + /* remap_vmalloc_range seems to need to run + * after mmap() on some cases */ struct vm_area_struct *vma; }; -void videobuf_queue_vmalloc_init(struct videobuf_queue* q, +void videobuf_queue_vmalloc_init(struct videobuf_queue *q, const struct videobuf_queue_ops *ops, struct device *dev, spinlock_t *irqlock, @@ -38,8 +38,8 @@ void videobuf_queue_vmalloc_init(struct videobuf_queue* q, unsigned int msize, void *priv); -void *videobuf_to_vmalloc (struct videobuf_buffer *buf); +void *videobuf_to_vmalloc(struct videobuf_buffer *buf); -void videobuf_vmalloc_free (struct videobuf_buffer *buf); +void videobuf_vmalloc_free(struct videobuf_buffer *buf); #endif -- cgit v1.2.3-70-g09d2 From d72d7c1df98628315298102dd1d442bcf24dc44c Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 17 Mar 2010 12:11:56 -0300 Subject: V4L/DVB: ivtv: sizeof() => ARRAY_SIZE() This fixes a smatch warning: drivers/media/video/ivtv/ivtv-vbi.c +138 ivtv_write_vbi(43) error: buffer overflow 'vi->cc_payload' 256 <= 1023 Signed-off-by: Dan Carpenter Reviewed-by: Andy Walls Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtv-vbi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/ivtv/ivtv-vbi.c b/drivers/media/video/ivtv/ivtv-vbi.c index f420d31b937..d73af45dede 100644 --- a/drivers/media/video/ivtv/ivtv-vbi.c +++ b/drivers/media/video/ivtv/ivtv-vbi.c @@ -134,7 +134,7 @@ void ivtv_write_vbi(struct ivtv *itv, const struct v4l2_sliced_vbi_data *sliced, } } } - if (found_cc && vi->cc_payload_idx < sizeof(vi->cc_payload)) { + if (found_cc && vi->cc_payload_idx < ARRAY_SIZE(vi->cc_payload)) { vi->cc_payload[vi->cc_payload_idx++] = cc; set_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags); } -- cgit v1.2.3-70-g09d2 From 935539c97ed5f4f46867e7f44e42ad2048403f4e Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 22 Mar 2010 12:39:09 -0300 Subject: V4L/DVB: cx231xx: card->driver "Conexant cx231xx Audio" too long card->driver is 15 characters and a NULL, the original code could cause a buffer overflow. Signed-off-by: Dan Carpenter Acked-by: Takashi Iwai Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx231xx/cx231xx-audio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx231xx/cx231xx-audio.c b/drivers/media/video/cx231xx/cx231xx-audio.c index 7793d60966d..7cae95a2245 100644 --- a/drivers/media/video/cx231xx/cx231xx-audio.c +++ b/drivers/media/video/cx231xx/cx231xx-audio.c @@ -495,7 +495,7 @@ static int cx231xx_audio_init(struct cx231xx *dev) pcm->info_flags = 0; pcm->private_data = dev; strcpy(pcm->name, "Conexant cx231xx Capture"); - strcpy(card->driver, "Conexant cx231xx Audio"); + strcpy(card->driver, "Cx231xx-Audio"); strcpy(card->shortname, "Cx231xx Audio"); strcpy(card->longname, "Conexant cx231xx Audio"); -- cgit v1.2.3-70-g09d2 From 4a3eaee4d0d2724d86cbb18ad4b0088ce0b7f8a2 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 23 Mar 2010 08:40:43 -0300 Subject: V4L/DVB: em28xx: "Empia Em28xx Audio" too long card->driver is 15 characters and a NULL. The original code goes past the end of the array. Signed-off-by: Dan Carpenter Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-audio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c index bd783387b37..e182abf476c 100644 --- a/drivers/media/video/em28xx/em28xx-audio.c +++ b/drivers/media/video/em28xx/em28xx-audio.c @@ -491,7 +491,7 @@ static int em28xx_audio_init(struct em28xx *dev) strcpy(pcm->name, "Empia 28xx Capture"); snd_card_set_dev(card, &dev->udev->dev); - strcpy(card->driver, "Empia Em28xx Audio"); + strcpy(card->driver, "Em28xx-Audio"); strcpy(card->shortname, "Em28xx Audio"); strcpy(card->longname, "Empia Em28xx Audio"); -- cgit v1.2.3-70-g09d2 From 97693f9178ba83068f6b4e419a47ffd3d1a20897 Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Sun, 21 Mar 2010 17:33:50 -0300 Subject: V4L/DVB: ov7670: Use CCIR601 in all video modes Also provide for a longer delay after reset - the XO 1.5 needs it. Signed-off-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ov7670.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/ov7670.c b/drivers/media/video/ov7670.c index aaa50f9b8e7..b44762adb1e 100644 --- a/drivers/media/video/ov7670.c +++ b/drivers/media/video/ov7670.c @@ -351,7 +351,7 @@ static struct regval_list ov7670_default_regs[] = { static struct regval_list ov7670_fmt_yuv422[] = { { REG_COM7, 0x0 }, /* Selects YUV mode */ { REG_RGB444, 0 }, /* No RGB444 please */ - { REG_COM1, 0 }, + { REG_COM1, 0 }, /* CCIR601 */ { REG_COM15, COM15_R00FF }, { REG_COM9, 0x18 }, /* 4x gain ceiling; 0x8 is reserved bit */ { 0x4f, 0x80 }, /* "matrix coefficient 1" */ @@ -367,7 +367,7 @@ static struct regval_list ov7670_fmt_yuv422[] = { static struct regval_list ov7670_fmt_rgb565[] = { { REG_COM7, COM7_RGB }, /* Selects RGB mode */ { REG_RGB444, 0 }, /* No RGB444 please */ - { REG_COM1, 0x0 }, + { REG_COM1, 0x0 }, /* CCIR601 */ { REG_COM15, COM15_RGB565 }, { REG_COM9, 0x38 }, /* 16x gain ceiling; 0x8 is reserved bit */ { 0x4f, 0xb3 }, /* "matrix coefficient 1" */ @@ -383,7 +383,7 @@ static struct regval_list ov7670_fmt_rgb565[] = { static struct regval_list ov7670_fmt_rgb444[] = { { REG_COM7, COM7_RGB }, /* Selects RGB mode */ { REG_RGB444, R444_ENABLE }, /* Enable xxxxrrrr ggggbbbb */ - { REG_COM1, 0x40 }, /* Magic reserved bit */ + { REG_COM1, 0x0 }, /* CCIR601 */ { REG_COM15, COM15_R01FE|COM15_RGB565 }, /* Data range needed? */ { REG_COM9, 0x38 }, /* 16x gain ceiling; 0x8 is reserved bit */ { 0x4f, 0xb3 }, /* "matrix coefficient 1" */ @@ -432,7 +432,7 @@ static int ov7670_write(struct v4l2_subdev *sd, unsigned char reg, int ret = i2c_smbus_write_byte_data(client, reg, value); if (reg == REG_COM7 && (value & COM7_RESET)) - msleep(2); /* Wait for reset to run */ + msleep(5); /* Wait for reset to run */ return ret; } -- cgit v1.2.3-70-g09d2 From d8d201552f518370d0a64cb758684f667fdd2012 Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Sun, 20 Dec 2009 11:39:47 -0300 Subject: V4L/DVB: ov7670: Avoid reading clkrc Reading the clkrc register creates flaky behavior in some situations, and we can easily track its state separately. Signed-off-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ov7670.c | 45 ++++++++++++++++++-------------------------- 1 file changed, 18 insertions(+), 27 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/ov7670.c b/drivers/media/video/ov7670.c index b44762adb1e..b2e6f8e730a 100644 --- a/drivers/media/video/ov7670.c +++ b/drivers/media/video/ov7670.c @@ -198,6 +198,7 @@ struct ov7670_info { struct ov7670_format_struct *fmt; /* Current format */ unsigned char sat; /* Saturation value */ int hue; /* Hue value */ + u8 clkrc; /* Clock divider value */ }; static inline struct ov7670_info *to_state(struct v4l2_subdev *sd) @@ -744,21 +745,11 @@ static int ov7670_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) struct ov7670_format_struct *ovfmt; struct ov7670_win_size *wsize; struct ov7670_info *info = to_state(sd); - unsigned char com7, clkrc = 0; + unsigned char com7; ret = ov7670_try_fmt_internal(sd, fmt, &ovfmt, &wsize); if (ret) return ret; - /* - * HACK: if we're running rgb565 we need to grab then rewrite - * CLKRC. If we're *not*, however, then rewriting clkrc hoses - * the colors. - */ - if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565) { - ret = ov7670_read(sd, REG_CLKRC, &clkrc); - if (ret) - return ret; - } /* * COM7 is a pain in the ass, it doesn't like to be read then * quickly written afterward. But we have everything we need @@ -779,8 +770,14 @@ static int ov7670_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) ret = ov7670_write_array(sd, wsize->regs); info->fmt = ovfmt; + /* + * If we're running RGB565, we must rewrite clkrc after setting + * the other parameters or the image looks poor. If we're *not* + * doing RGB565, we must not rewrite clkrc or the image looks + * *really* poor. + */ if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565 && ret == 0) - ret = ov7670_write(sd, REG_CLKRC, clkrc); + ret = ov7670_write(sd, REG_CLKRC, info->clkrc); return ret; } @@ -791,20 +788,17 @@ static int ov7670_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) static int ov7670_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) { struct v4l2_captureparm *cp = &parms->parm.capture; - unsigned char clkrc; - int ret; + struct ov7670_info *info = to_state(sd); if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - ret = ov7670_read(sd, REG_CLKRC, &clkrc); - if (ret < 0) - return ret; + memset(cp, 0, sizeof(struct v4l2_captureparm)); cp->capability = V4L2_CAP_TIMEPERFRAME; cp->timeperframe.numerator = 1; cp->timeperframe.denominator = OV7670_FRAME_RATE; - if ((clkrc & CLK_EXT) == 0 && (clkrc & CLK_SCALE) > 1) - cp->timeperframe.denominator /= (clkrc & CLK_SCALE); + if ((info->clkrc & CLK_EXT) == 0 && (info->clkrc & CLK_SCALE) > 1) + cp->timeperframe.denominator /= (info->clkrc & CLK_SCALE); return 0; } @@ -812,6 +806,7 @@ static int ov7670_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) { struct v4l2_captureparm *cp = &parms->parm.capture; struct v4l2_fract *tpf = &cp->timeperframe; + struct ov7670_info *info = to_state(sd); unsigned char clkrc; int ret, div; @@ -819,12 +814,7 @@ static int ov7670_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) return -EINVAL; if (cp->extendedmode != 0) return -EINVAL; - /* - * CLKRC has a reserved bit, so let's preserve it. - */ - ret = ov7670_read(sd, REG_CLKRC, &clkrc); - if (ret < 0) - return ret; + if (tpf->numerator == 0 || tpf->denominator == 0) div = 1; /* Reset to full rate */ else @@ -833,10 +823,10 @@ static int ov7670_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) div = 1; else if (div > CLK_SCALE) div = CLK_SCALE; - clkrc = (clkrc & 0x80) | div; + info->clkrc = (info->clkrc & 0x80) | div; tpf->numerator = 1; tpf->denominator = OV7670_FRAME_RATE/div; - return ov7670_write(sd, REG_CLKRC, clkrc); + return ov7670_write(sd, REG_CLKRC, info->clkrc); } @@ -1268,6 +1258,7 @@ static int ov7670_probe(struct i2c_client *client, info->fmt = &ov7670_formats[0]; info->sat = 128; /* Review this */ + info->clkrc = 1; /* 30fps */ return 0; } -- cgit v1.2.3-70-g09d2 From 2bf7de48888fceed8d8e5cddd51f1d474bdbfae6 Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Sun, 28 Feb 2010 21:02:55 -0300 Subject: V4L/DVB: ov7670: Don't use SMBUS I/O Contrary to my earlier belief, the ov7670 is not actually an SMBUS device, though it will pretend to be one if it's in a good mood. Unfortunately, it's rarely in a good mood, especially on the XO 1.5. So use low-level i2c I/O instead. Signed-off-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ov7670.c | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/ov7670.c b/drivers/media/video/ov7670.c index b2e6f8e730a..95507770f12 100644 --- a/drivers/media/video/ov7670.c +++ b/drivers/media/video/ov7670.c @@ -410,16 +410,33 @@ static struct regval_list ov7670_fmt_raw[] = { /* * Low-level register I/O. */ - static int ov7670_read(struct v4l2_subdev *sd, unsigned char reg, unsigned char *value) { struct i2c_client *client = v4l2_get_subdevdata(sd); + u8 data = reg; + struct i2c_msg msg; int ret; - ret = i2c_smbus_read_byte_data(client, reg); + /* + * Send out the register address... + */ + msg.addr = client->addr; + msg.flags = 0; + msg.len = 1; + msg.buf = &data; + ret = i2c_transfer(client->adapter, &msg, 1); + if (ret < 0) { + printk(KERN_ERR "Error %d on register write\n", ret); + return ret; + } + /* + * ...then read back the result. + */ + msg.flags = I2C_M_RD; + ret = i2c_transfer(client->adapter, &msg, 1); if (ret >= 0) { - *value = (unsigned char)ret; + *value = data; ret = 0; } return ret; @@ -430,8 +447,17 @@ static int ov7670_write(struct v4l2_subdev *sd, unsigned char reg, unsigned char value) { struct i2c_client *client = v4l2_get_subdevdata(sd); - int ret = i2c_smbus_write_byte_data(client, reg, value); + struct i2c_msg msg; + unsigned char data[2] = { reg, value }; + int ret; + msg.addr = client->addr; + msg.flags = 0; + msg.len = 2; + msg.buf = data; + ret = i2c_transfer(client->adapter, &msg, 1); + if (ret > 0) + ret = 0; if (reg == REG_COM7 && (value & COM7_RESET)) msleep(5); /* Wait for reset to run */ return ret; -- cgit v1.2.3-70-g09d2 From 81898671247a6cfa6bfd6a32faee18b3999b6610 Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Thu, 4 Mar 2010 18:50:34 -0300 Subject: V4L/DVB: ov7670: Wire up V4L2_CID_GAIN and V4L2_CID_AUTOGAIN Allow applications to play with the gain settings. Signed-off-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ov7670.c | 73 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/ov7670.c b/drivers/media/video/ov7670.c index 95507770f12..e7555d1f90e 100644 --- a/drivers/media/video/ov7670.c +++ b/drivers/media/video/ov7670.c @@ -1131,6 +1131,67 @@ static int ov7670_s_vflip(struct v4l2_subdev *sd, int value) return ret; } +/* + * GAIN is split between REG_GAIN and REG_VREF[7:6]. If one believes + * the data sheet, the VREF parts should be the most significant, but + * experience shows otherwise. There seems to be little value in + * messing with the VREF bits, so we leave them alone. + */ +static int ov7670_g_gain(struct v4l2_subdev *sd, __s32 *value) +{ + int ret; + unsigned char gain; + + ret = ov7670_read(sd, REG_GAIN, &gain); + *value = gain; + return ret; +} + +static int ov7670_s_gain(struct v4l2_subdev *sd, int value) +{ + int ret; + unsigned char com8; + + ret = ov7670_write(sd, REG_GAIN, value & 0xff); + /* Have to turn off AGC as well */ + if (ret == 0) { + ret = ov7670_read(sd, REG_COM8, &com8); + ret = ov7670_write(sd, REG_COM8, com8 & ~COM8_AGC); + } + return ret; +} + +/* + * Tweak autogain. + */ +static int ov7670_g_autogain(struct v4l2_subdev *sd, __s32 *value) +{ + int ret; + unsigned char com8; + + ret = ov7670_read(sd, REG_COM8, &com8); + *value = (com8 & COM8_AGC) != 0; + return ret; +} + +static int ov7670_s_autogain(struct v4l2_subdev *sd, int value) +{ + int ret; + unsigned char com8; + + ret = ov7670_read(sd, REG_COM8, &com8); + if (ret == 0) { + if (value) + com8 |= COM8_AGC; + else + com8 &= ~COM8_AGC; + ret = ov7670_write(sd, REG_COM8, com8); + } + return ret; +} + + + static int ov7670_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) { @@ -1147,6 +1208,10 @@ static int ov7670_queryctrl(struct v4l2_subdev *sd, return v4l2_ctrl_query_fill(qc, 0, 256, 1, 128); case V4L2_CID_HUE: return v4l2_ctrl_query_fill(qc, -180, 180, 5, 0); + case V4L2_CID_GAIN: + return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128); + case V4L2_CID_AUTOGAIN: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); } return -EINVAL; } @@ -1166,6 +1231,10 @@ static int ov7670_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) return ov7670_g_vflip(sd, &ctrl->value); case V4L2_CID_HFLIP: return ov7670_g_hflip(sd, &ctrl->value); + case V4L2_CID_GAIN: + return ov7670_g_gain(sd, &ctrl->value); + case V4L2_CID_AUTOGAIN: + return ov7670_g_autogain(sd, &ctrl->value); } return -EINVAL; } @@ -1185,6 +1254,10 @@ static int ov7670_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) return ov7670_s_vflip(sd, ctrl->value); case V4L2_CID_HFLIP: return ov7670_s_hflip(sd, ctrl->value); + case V4L2_CID_GAIN: + return ov7670_s_gain(sd, ctrl->value); + case V4L2_CID_AUTOGAIN: + return ov7670_s_autogain(sd, ctrl->value); } return -EINVAL; } -- cgit v1.2.3-70-g09d2 From 364e93372fb21ef5de18d0122c78789f065ddbf5 Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Fri, 5 Mar 2010 16:48:39 -0300 Subject: V4L/DVB: ov7670: wire up controls for exposure and autoexposure Signed-off-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ov7670.c | 86 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/ov7670.c b/drivers/media/video/ov7670.c index e7555d1f90e..90c44598dd5 100644 --- a/drivers/media/video/ov7670.c +++ b/drivers/media/video/ov7670.c @@ -1190,6 +1190,79 @@ static int ov7670_s_autogain(struct v4l2_subdev *sd, int value) return ret; } +/* + * Exposure is spread all over the place: top 6 bits in AECHH, middle + * 8 in AECH, and two stashed in COM1 just for the hell of it. + */ +static int ov7670_g_exp(struct v4l2_subdev *sd, __s32 *value) +{ + int ret; + unsigned char com1, aech, aechh; + + ret = ov7670_read(sd, REG_COM1, &com1) + + ov7670_read(sd, REG_AECH, &aech) + + ov7670_read(sd, REG_AECHH, &aechh); + *value = ((aechh & 0x3f) << 10) | (aech << 2) | (com1 & 0x03); + return ret; +} + +static int ov7670_s_exp(struct v4l2_subdev *sd, int value) +{ + int ret; + unsigned char com1, com8, aech, aechh; + + ret = ov7670_read(sd, REG_COM1, &com1) + + ov7670_read(sd, REG_COM8, &com8); + ov7670_read(sd, REG_AECHH, &aechh); + if (ret) + return ret; + + com1 = (com1 & 0xfc) | (value & 0x03); + aech = (value >> 2) & 0xff; + aechh = (aechh & 0xc0) | ((value >> 10) & 0x3f); + ret = ov7670_write(sd, REG_COM1, com1) + + ov7670_write(sd, REG_AECH, aech) + + ov7670_write(sd, REG_AECHH, aechh); + /* Have to turn off AEC as well */ + if (ret == 0) + ret = ov7670_write(sd, REG_COM8, com8 & ~COM8_AEC); + return ret; +} + +/* + * Tweak autoexposure. + */ +static int ov7670_g_autoexp(struct v4l2_subdev *sd, __s32 *value) +{ + int ret; + unsigned char com8; + enum v4l2_exposure_auto_type *atype = (enum v4l2_exposure_auto_type *) value; + + ret = ov7670_read(sd, REG_COM8, &com8); + if (com8 & COM8_AEC) + *value = V4L2_EXPOSURE_AUTO; + else + *value = V4L2_EXPOSURE_MANUAL; + return ret; +} + +static int ov7670_s_autoexp(struct v4l2_subdev *sd, + enum v4l2_exposure_auto_type value) +{ + int ret; + unsigned char com8; + + ret = ov7670_read(sd, REG_COM8, &com8); + if (ret == 0) { + if (value == V4L2_EXPOSURE_AUTO) + com8 |= COM8_AEC; + else + com8 &= ~COM8_AEC; + ret = ov7670_write(sd, REG_COM8, com8); + } + return ret; +} + static int ov7670_queryctrl(struct v4l2_subdev *sd, @@ -1212,6 +1285,10 @@ static int ov7670_queryctrl(struct v4l2_subdev *sd, return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128); case V4L2_CID_AUTOGAIN: return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); + case V4L2_CID_EXPOSURE: + return v4l2_ctrl_query_fill(qc, 0, 65535, 1, 500); + case V4L2_CID_EXPOSURE_AUTO: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0); } return -EINVAL; } @@ -1235,6 +1312,10 @@ static int ov7670_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) return ov7670_g_gain(sd, &ctrl->value); case V4L2_CID_AUTOGAIN: return ov7670_g_autogain(sd, &ctrl->value); + case V4L2_CID_EXPOSURE: + return ov7670_g_exp(sd, &ctrl->value); + case V4L2_CID_EXPOSURE_AUTO: + return ov7670_g_autoexp(sd, &ctrl->value); } return -EINVAL; } @@ -1258,6 +1339,11 @@ static int ov7670_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) return ov7670_s_gain(sd, ctrl->value); case V4L2_CID_AUTOGAIN: return ov7670_s_autogain(sd, ctrl->value); + case V4L2_CID_EXPOSURE: + return ov7670_s_exp(sd, ctrl->value); + case V4L2_CID_EXPOSURE_AUTO: + return ov7670_s_autoexp(sd, + (enum v4l2_exposure_auto_type) ctrl->value); } return -EINVAL; } -- cgit v1.2.3-70-g09d2 From 467142093de1507833a08c50740d74b3b8c8eaca Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Fri, 19 Mar 2010 13:16:28 -0300 Subject: V4L/DVB: ov7670: Restore SMBUS I/O for the XO 1.0 The Cafe controller doesn't do non-SMBUS I/O, so we have to use it there. Signed-off-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ov7670.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/ov7670.c b/drivers/media/video/ov7670.c index 90c44598dd5..21243303755 100644 --- a/drivers/media/video/ov7670.c +++ b/drivers/media/video/ov7670.c @@ -409,6 +409,42 @@ static struct regval_list ov7670_fmt_raw[] = { /* * Low-level register I/O. + * + * Note that there are two versions of these. On the XO 1, the + * i2c controller only does SMBUS, so that's what we use. The + * ov7670 is not really an SMBUS device, though, so the communication + * is not always entirely reliable. + */ +#ifdef CONFIG_OLPC_XO_1 +static int ov7670_read(struct v4l2_subdev *sd, unsigned char reg, + unsigned char *value) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + int ret; + + ret = i2c_smbus_read_byte_data(client, reg); + if (ret >= 0) { + *value = (unsigned char)ret; + ret = 0; + } + return ret; +} + + +static int ov7670_write(struct v4l2_subdev *sd, unsigned char reg, + unsigned char value) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + int ret = i2c_smbus_write_byte_data(client, reg, value); + + if (reg == REG_COM7 && (value & COM7_RESET)) + msleep(5); /* Wait for reset to run */ + return ret; +} + +#else /* ! CONFIG_OLPC_XO_1 */ +/* + * On most platforms, we'd rather do straight i2c I/O. */ static int ov7670_read(struct v4l2_subdev *sd, unsigned char reg, unsigned char *value) @@ -462,6 +498,7 @@ static int ov7670_write(struct v4l2_subdev *sd, unsigned char reg, msleep(5); /* Wait for reset to run */ return ret; } +#endif /* CONFIG_OLPC_XO_1 */ /* -- cgit v1.2.3-70-g09d2 From a8e68c37c846236499ac05e95af76dff2e9aa1eb Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Thu, 18 Mar 2010 19:10:18 -0300 Subject: V4L/DVB: ov7670: Always rewrite clkrc when setting format That makes frame rate configuration persistent. Signed-off-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ov7670.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/ov7670.c b/drivers/media/video/ov7670.c index 21243303755..82d37d925eb 100644 --- a/drivers/media/video/ov7670.c +++ b/drivers/media/video/ov7670.c @@ -838,8 +838,12 @@ static int ov7670_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) * the other parameters or the image looks poor. If we're *not* * doing RGB565, we must not rewrite clkrc or the image looks * *really* poor. + * + * (Update) Now that we retain clkrc state, we should be able + * to write it unconditionally, and that will make the frame + * rate persistent too. */ - if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565 && ret == 0) + if (ret == 0) ret = ov7670_write(sd, REG_CLKRC, info->clkrc); return ret; } -- cgit v1.2.3-70-g09d2 From 380de498e264cca27d19deafe4dc44f624820d09 Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Fri, 26 Mar 2010 13:09:34 -0300 Subject: V4L/DVB: ov7670: silence some compiler warnings Get rid of some "unused variable" warnings. These were the result of sloppiness and should not have happened; I'll go stand in the corner now. Reported-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ov7670.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/ov7670.c b/drivers/media/video/ov7670.c index 82d37d925eb..91c886ab15c 100644 --- a/drivers/media/video/ov7670.c +++ b/drivers/media/video/ov7670.c @@ -874,8 +874,7 @@ static int ov7670_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) struct v4l2_captureparm *cp = &parms->parm.capture; struct v4l2_fract *tpf = &cp->timeperframe; struct ov7670_info *info = to_state(sd); - unsigned char clkrc; - int ret, div; + int div; if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; @@ -1281,9 +1280,9 @@ static int ov7670_g_autoexp(struct v4l2_subdev *sd, __s32 *value) ret = ov7670_read(sd, REG_COM8, &com8); if (com8 & COM8_AEC) - *value = V4L2_EXPOSURE_AUTO; + *atype = V4L2_EXPOSURE_AUTO; else - *value = V4L2_EXPOSURE_MANUAL; + *atype = V4L2_EXPOSURE_MANUAL; return ret; } -- cgit v1.2.3-70-g09d2 From 51224aa436238940e09e479db9c600cecfbebd20 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 22 Mar 2010 04:33:56 -0300 Subject: V4L/DVB: c-qcam: coding style cleanup Clean up the coding style before we convert this driver to V4L2. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/c-qcam.c | 483 +++++++++++++++++++++---------------------- 1 file changed, 237 insertions(+), 246 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c index e2cbebab959..8f1dd88b32a 100644 --- a/drivers/media/video/c-qcam.c +++ b/drivers/media/video/c-qcam.c @@ -79,17 +79,17 @@ static inline void qcam_set_ack(struct qcam_device *qcam, unsigned int i) { /* note: the QC specs refer to the PCAck pin by voltage, not software level. PC ports have builtin inverters. */ - parport_frob_control(qcam->pport, 8, i?8:0); + parport_frob_control(qcam->pport, 8, i ? 8 : 0); } static inline unsigned int qcam_ready1(struct qcam_device *qcam) { - return (parport_read_status(qcam->pport) & 0x8)?1:0; + return (parport_read_status(qcam->pport) & 0x8) ? 1 : 0; } static inline unsigned int qcam_ready2(struct qcam_device *qcam) { - return (parport_read_data(qcam->pport) & 0x1)?1:0; + return (parport_read_data(qcam->pport) & 0x1) ? 1 : 0; } static unsigned int qcam_await_ready1(struct qcam_device *qcam, @@ -99,14 +99,13 @@ static unsigned int qcam_await_ready1(struct qcam_device *qcam, unsigned int i; for (oldjiffies = jiffies; - time_before(jiffies, oldjiffies + msecs_to_jiffies(40)); ) + time_before(jiffies, oldjiffies + msecs_to_jiffies(40));) if (qcam_ready1(qcam) == value) return 0; /* If the camera didn't respond within 1/25 second, poll slowly for a while. */ - for (i = 0; i < 50; i++) - { + for (i = 0; i < 50; i++) { if (qcam_ready1(qcam) == value) return 0; msleep_interruptible(100); @@ -125,14 +124,13 @@ static unsigned int qcam_await_ready2(struct qcam_device *qcam, int value) unsigned int i; for (oldjiffies = jiffies; - time_before(jiffies, oldjiffies + msecs_to_jiffies(40)); ) + time_before(jiffies, oldjiffies + msecs_to_jiffies(40));) if (qcam_ready2(qcam) == value) return 0; /* If the camera didn't respond within 1/25 second, poll slowly for a while. */ - for (i = 0; i < 50; i++) - { + for (i = 0; i < 50; i++) { if (qcam_ready2(qcam) == value) return 0; msleep_interruptible(100); @@ -149,22 +147,25 @@ static unsigned int qcam_await_ready2(struct qcam_device *qcam, int value) static int qcam_read_data(struct qcam_device *qcam) { unsigned int idata; + qcam_set_ack(qcam, 0); - if (qcam_await_ready1(qcam, 1)) return -1; + if (qcam_await_ready1(qcam, 1)) + return -1; idata = parport_read_status(qcam->pport) & 0xf0; qcam_set_ack(qcam, 1); - if (qcam_await_ready1(qcam, 0)) return -1; - idata |= (parport_read_status(qcam->pport) >> 4); + if (qcam_await_ready1(qcam, 0)) + return -1; + idata |= parport_read_status(qcam->pport) >> 4; return idata; } static int qcam_write_data(struct qcam_device *qcam, unsigned int data) { unsigned int idata; + parport_write_data(qcam->pport, data); idata = qcam_read_data(qcam); - if (data != idata) - { + if (data != idata) { printk(KERN_WARNING "cqcam: sent %x but received %x\n", data, idata); return 1; @@ -212,13 +213,12 @@ static int qc_detect(struct qcam_device *qcam) /* look for a heartbeat */ ostat = stat = parport_read_status(qcam->pport); - for (i=0; i<250; i++) - { + for (i = 0; i < 250; i++) { mdelay(1); stat = parport_read_status(qcam->pport); - if (ostat != stat) - { - if (++count >= 3) return 1; + if (ostat != stat) { + if (++count >= 3) + return 1; ostat = stat; } } @@ -232,13 +232,12 @@ static int qc_detect(struct qcam_device *qcam) count = 0; ostat = stat = parport_read_status(qcam->pport); - for (i=0; i<250; i++) - { + for (i = 0; i < 250; i++) { mdelay(1); stat = parport_read_status(qcam->pport); - if (ostat != stat) - { - if (++count >= 3) return 1; + if (ostat != stat) { + if (++count >= 3) + return 1; ostat = stat; } } @@ -263,7 +262,7 @@ static void qc_setup(struct qcam_device *q) { qc_reset(q); - /* Set the brightness. */ + /* Set the brightness. */ qcam_set(q, 11, q->brightness); /* Set the height and width. These refer to the actual @@ -292,25 +291,25 @@ static unsigned int qcam_read_bytes(struct qcam_device *q, unsigned char *buf, u unsigned int bytes = 0; qcam_set_ack(q, 0); - if (q->bidirectional) - { + if (q->bidirectional) { /* It's a bidirectional port */ - while (bytes < nbytes) - { + while (bytes < nbytes) { unsigned int lo1, hi1, lo2, hi2; unsigned char r, g, b; - if (qcam_await_ready2(q, 1)) return bytes; + if (qcam_await_ready2(q, 1)) + return bytes; lo1 = parport_read_data(q->pport) >> 1; hi1 = ((parport_read_status(q->pport) >> 3) & 0x1f) ^ 0x10; qcam_set_ack(q, 1); - if (qcam_await_ready2(q, 0)) return bytes; + if (qcam_await_ready2(q, 0)) + return bytes; lo2 = parport_read_data(q->pport) >> 1; hi2 = ((parport_read_status(q->pport) >> 3) & 0x1f) ^ 0x10; qcam_set_ack(q, 0); - r = (lo1 | ((hi1 & 1)<<7)); - g = ((hi1 & 0x1e)<<3) | ((hi2 & 0x1e)>>1); - b = (lo2 | ((hi2 & 1)<<7)); + r = lo1 | ((hi1 & 1) << 7); + g = ((hi1 & 0x1e) << 3) | ((hi2 & 0x1e) >> 1); + b = lo2 | ((hi2 & 1) << 7); if (force_rgb) { buf[bytes++] = r; buf[bytes++] = g; @@ -321,21 +320,20 @@ static unsigned int qcam_read_bytes(struct qcam_device *q, unsigned char *buf, u buf[bytes++] = r; } } - } - else - { + } else { /* It's a unidirectional port */ int i = 0, n = bytes; unsigned char rgb[3]; - while (bytes < nbytes) - { + while (bytes < nbytes) { unsigned int hi, lo; - if (qcam_await_ready1(q, 1)) return bytes; + if (qcam_await_ready1(q, 1)) + return bytes; hi = (parport_read_status(q->pport) & 0xf0); qcam_set_ack(q, 1); - if (qcam_await_ready1(q, 0)) return bytes; + if (qcam_await_ready1(q, 0)) + return bytes; lo = (parport_read_status(q->pport) & 0xf0); qcam_set_ack(q, 0); /* flip some bits */ @@ -374,28 +372,26 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le return -EFAULT; /* Wait for camera to become ready */ - for (;;) - { + for (;;) { int i = qcam_get(q, 41); + if (i == -1) { qc_setup(q); return -EIO; } if ((i & 0x80) == 0) break; - else - schedule(); + schedule(); } - if (qcam_set(q, 7, (q->mode | (is_bi_dir?1:0)) + 1)) + if (qcam_set(q, 7, (q->mode | (is_bi_dir ? 1 : 0)) + 1)) return -EIO; lines = q->height; pixelsperline = q->width; bitsperxfer = (is_bi_dir) ? 24 : 8; - if (is_bi_dir) - { + if (is_bi_dir) { /* Turn the port around */ parport_data_reverse(q->pport); mdelay(3); @@ -413,16 +409,17 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le wantlen = lines * pixelsperline * 24 / 8; - while (wantlen) - { + while (wantlen) { size_t t, s; - s = (wantlen > BUFSZ)?BUFSZ:wantlen; + + s = (wantlen > BUFSZ) ? BUFSZ : wantlen; t = qcam_read_bytes(q, tmpbuf, s); - if (outptr < len) - { + if (outptr < len) { size_t sz = len - outptr; - if (sz > t) sz = t; - if (__copy_to_user(buf+outptr, tmpbuf, sz)) + + if (sz > t) + sz = t; + if (__copy_to_user(buf + outptr, tmpbuf, sz)) break; outptr += sz; } @@ -434,33 +431,31 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le len = outptr; - if (wantlen) - { - printk("qcam: short read.\n"); + if (wantlen) { + printk(KERN_ERR "qcam: short read.\n"); if (is_bi_dir) parport_data_forward(q->pport); qc_setup(q); return len; } - if (is_bi_dir) - { + if (is_bi_dir) { int l; + do { l = qcam_read_bytes(q, tmpbuf, 3); cond_resched(); } while (l && (tmpbuf[0] == 0x7e || tmpbuf[1] == 0x7e || tmpbuf[2] == 0x7e)); if (force_rgb) { if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf) - printk("qcam: bad EOF\n"); + printk(KERN_ERR "qcam: bad EOF\n"); } else { if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe) - printk("qcam: bad EOF\n"); + printk(KERN_ERR "qcam: bad EOF\n"); } qcam_set_ack(q, 0); - if (qcam_await_ready1(q, 1)) - { - printk("qcam: no ack after EOF\n"); + if (qcam_await_ready1(q, 1)) { + printk(KERN_ERR "qcam: no ack after EOF\n"); parport_data_forward(q->pport); qc_setup(q); return len; @@ -468,27 +463,25 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le parport_data_forward(q->pport); mdelay(3); qcam_set_ack(q, 1); - if (qcam_await_ready1(q, 0)) - { - printk("qcam: no ack to port turnaround\n"); + if (qcam_await_ready1(q, 0)) { + printk(KERN_ERR "qcam: no ack to port turnaround\n"); qc_setup(q); return len; } - } - else - { + } else { int l; + do { l = qcam_read_bytes(q, tmpbuf, 1); cond_resched(); } while (l && tmpbuf[0] == 0x7e); - l = qcam_read_bytes(q, tmpbuf+1, 2); + l = qcam_read_bytes(q, tmpbuf + 1, 2); if (force_rgb) { if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf) - printk("qcam: bad EOF\n"); + printk(KERN_ERR "qcam: bad EOF\n"); } else { if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe) - printk("qcam: bad EOF\n"); + printk(KERN_ERR "qcam: bad EOF\n"); } } @@ -503,164 +496,166 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le static long qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct video_device *dev = video_devdata(file); - struct qcam_device *qcam=(struct qcam_device *)dev; + struct qcam_device *qcam = (struct qcam_device *)dev; - switch(cmd) + switch (cmd) { + case VIDIOCGCAP: { - case VIDIOCGCAP: - { - struct video_capability *b = arg; - strcpy(b->name, "Quickcam"); - b->type = VID_TYPE_CAPTURE|VID_TYPE_SCALES; - b->channels = 1; - b->audios = 0; - b->maxwidth = 320; - b->maxheight = 240; - b->minwidth = 80; - b->minheight = 60; - return 0; - } - case VIDIOCGCHAN: - { - struct video_channel *v = arg; - if(v->channel!=0) - return -EINVAL; - v->flags=0; - v->tuners=0; - /* Good question.. its composite or SVHS so.. */ - v->type = VIDEO_TYPE_CAMERA; - strcpy(v->name, "Camera"); - return 0; - } - case VIDIOCSCHAN: - { - struct video_channel *v = arg; - if(v->channel!=0) - return -EINVAL; - return 0; - } - case VIDIOCGTUNER: - { - struct video_tuner *v = arg; - if(v->tuner) - return -EINVAL; - memset(v,0,sizeof(*v)); - strcpy(v->name, "Format"); - v->mode = VIDEO_MODE_AUTO; - return 0; - } - case VIDIOCSTUNER: - { - struct video_tuner *v = arg; - if(v->tuner) - return -EINVAL; - if(v->mode!=VIDEO_MODE_AUTO) - return -EINVAL; - return 0; - } - case VIDIOCGPICT: - { - struct video_picture *p = arg; - p->colour=0x8000; - p->hue=0x8000; - p->brightness=qcam->brightness<<8; - p->contrast=qcam->contrast<<8; - p->whiteness=qcam->whitebal<<8; - p->depth=24; - p->palette=VIDEO_PALETTE_RGB24; - return 0; + struct video_capability *b = arg; + + strcpy(b->name, "Quickcam"); + b->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES; + b->channels = 1; + b->audios = 0; + b->maxwidth = 320; + b->maxheight = 240; + b->minwidth = 80; + b->minheight = 60; + return 0; + } + case VIDIOCGCHAN: + { + struct video_channel *v = arg; + + if (v->channel != 0) + return -EINVAL; + v->flags = 0; + v->tuners = 0; + /* Good question.. its composite or SVHS so.. */ + v->type = VIDEO_TYPE_CAMERA; + strcpy(v->name, "Camera"); + return 0; + } + case VIDIOCSCHAN: + { + struct video_channel *v = arg; + + if (v->channel != 0) + return -EINVAL; + return 0; + } + case VIDIOCGTUNER: + { + struct video_tuner *v = arg; + + if (v->tuner) + return -EINVAL; + memset(v, 0, sizeof(*v)); + strcpy(v->name, "Format"); + v->mode = VIDEO_MODE_AUTO; + return 0; + } + case VIDIOCSTUNER: + { + struct video_tuner *v = arg; + + if (v->tuner) + return -EINVAL; + if (v->mode != VIDEO_MODE_AUTO) + return -EINVAL; + return 0; + } + case VIDIOCGPICT: + { + struct video_picture *p = arg; + + p->colour = 0x8000; + p->hue = 0x8000; + p->brightness = qcam->brightness << 8; + p->contrast = qcam->contrast << 8; + p->whiteness = qcam->whitebal << 8; + p->depth = 24; + p->palette = VIDEO_PALETTE_RGB24; + return 0; + } + case VIDIOCSPICT: + { + struct video_picture *p = arg; + + /* + * Sanity check args + */ + if (p->depth != 24 || p->palette != VIDEO_PALETTE_RGB24) + return -EINVAL; + + /* + * Now load the camera. + */ + qcam->brightness = p->brightness >> 8; + qcam->contrast = p->contrast >> 8; + qcam->whitebal = p->whiteness >> 8; + + mutex_lock(&qcam->lock); + parport_claim_or_block(qcam->pdev); + qc_setup(qcam); + parport_release(qcam->pdev); + mutex_unlock(&qcam->lock); + return 0; + } + case VIDIOCSWIN: + { + struct video_window *vw = arg; + + if (vw->flags) + return -EINVAL; + if (vw->clipcount) + return -EINVAL; + if (vw->height < 60 || vw->height > 240) + return -EINVAL; + if (vw->width < 80 || vw->width > 320) + return -EINVAL; + + qcam->width = 80; + qcam->height = 60; + qcam->mode = QC_DECIMATION_4; + + if (vw->width >= 160 && vw->height >= 120) { + qcam->width = 160; + qcam->height = 120; + qcam->mode = QC_DECIMATION_2; } - case VIDIOCSPICT: - { - struct video_picture *p = arg; - - /* - * Sanity check args - */ - if (p->depth != 24 || p->palette != VIDEO_PALETTE_RGB24) - return -EINVAL; - - /* - * Now load the camera. - */ - qcam->brightness = p->brightness>>8; - qcam->contrast = p->contrast>>8; - qcam->whitebal = p->whiteness>>8; - - mutex_lock(&qcam->lock); - parport_claim_or_block(qcam->pdev); - qc_setup(qcam); - parport_release(qcam->pdev); - mutex_unlock(&qcam->lock); - return 0; + if (vw->width >= 320 && vw->height >= 240) { + qcam->width = 320; + qcam->height = 240; + qcam->mode = QC_DECIMATION_1; } - case VIDIOCSWIN: - { - struct video_window *vw = arg; - - if(vw->flags) - return -EINVAL; - if(vw->clipcount) - return -EINVAL; - if(vw->height<60||vw->height>240) - return -EINVAL; - if(vw->width<80||vw->width>320) - return -EINVAL; - - qcam->width = 80; - qcam->height = 60; - qcam->mode = QC_DECIMATION_4; - - if(vw->width>=160 && vw->height>=120) - { - qcam->width = 160; - qcam->height = 120; - qcam->mode = QC_DECIMATION_2; - } - if(vw->width>=320 && vw->height>=240) - { - qcam->width = 320; - qcam->height = 240; - qcam->mode = QC_DECIMATION_1; - } - qcam->mode |= QC_MILLIONS; + qcam->mode |= QC_MILLIONS; #if 0 - if(vw->width>=640 && vw->height>=480) - { - qcam->width = 640; - qcam->height = 480; - qcam->mode = QC_BILLIONS | QC_DECIMATION_1; - } -#endif - /* Ok we figured out what to use from our - wide choice */ - mutex_lock(&qcam->lock); - parport_claim_or_block(qcam->pdev); - qc_setup(qcam); - parport_release(qcam->pdev); - mutex_unlock(&qcam->lock); - return 0; - } - case VIDIOCGWIN: - { - struct video_window *vw = arg; - memset(vw, 0, sizeof(*vw)); - vw->width=qcam->width; - vw->height=qcam->height; - return 0; + if (vw->width >= 640 && vw->height >= 480) { + qcam->width = 640; + qcam->height = 480; + qcam->mode = QC_BILLIONS | QC_DECIMATION_1; } - case VIDIOCKEY: - return 0; - case VIDIOCCAPTURE: - case VIDIOCGFBUF: - case VIDIOCSFBUF: - case VIDIOCGFREQ: - case VIDIOCSFREQ: - case VIDIOCGAUDIO: - case VIDIOCSAUDIO: - return -EINVAL; - default: - return -ENOIOCTLCMD; +#endif + /* Ok we figured out what to use from our + wide choice */ + mutex_lock(&qcam->lock); + parport_claim_or_block(qcam->pdev); + qc_setup(qcam); + parport_release(qcam->pdev); + mutex_unlock(&qcam->lock); + return 0; + } + case VIDIOCGWIN: + { + struct video_window *vw = arg; + memset(vw, 0, sizeof(*vw)); + vw->width = qcam->width; + vw->height = qcam->height; + return 0; + } + case VIDIOCKEY: + return 0; + case VIDIOCCAPTURE: + case VIDIOCGFBUF: + case VIDIOCSFBUF: + case VIDIOCGFREQ: + case VIDIOCSFREQ: + case VIDIOCGAUDIO: + case VIDIOCSAUDIO: + return -EINVAL; + default: + return -ENOIOCTLCMD; } return 0; } @@ -675,13 +670,13 @@ static ssize_t qcam_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { struct video_device *v = video_devdata(file); - struct qcam_device *qcam=(struct qcam_device *)v; + struct qcam_device *qcam = (struct qcam_device *)v; int len; mutex_lock(&qcam->lock); parport_claim_or_block(qcam->pdev); /* Probably should have a semaphore against multiple users */ - len = qc_capture(qcam, buf,count); + len = qc_capture(qcam, buf, count); parport_release(qcam->pdev); mutex_unlock(&qcam->lock); return len; @@ -713,8 +708,7 @@ static const struct v4l2_file_operations qcam_fops = { .read = qcam_read, }; -static struct video_device qcam_template= -{ +static struct video_device qcam_template = { .name = "Colour QuickCam", .fops = &qcam_fops, .release = video_device_release_empty, @@ -727,17 +721,16 @@ static struct qcam_device *qcam_init(struct parport *port) struct qcam_device *q; q = kmalloc(sizeof(struct qcam_device), GFP_KERNEL); - if(q==NULL) + if (q == NULL) return NULL; q->pport = port; q->pdev = parport_register_device(port, "c-qcam", NULL, NULL, NULL, 0, NULL); - q->bidirectional = (q->pport->modes & PARPORT_MODE_TRISTATE)?1:0; + q->bidirectional = (q->pport->modes & PARPORT_MODE_TRISTATE) ? 1 : 0; - if (q->pdev == NULL) - { + if (q->pdev == NULL) { printk(KERN_ERR "c-qcam: couldn't register for %s.\n", port->name); kfree(q); @@ -765,12 +758,11 @@ static int init_cqcam(struct parport *port) { struct qcam_device *qcam; - if (parport[0] != -1) - { + if (parport[0] != -1) { /* The user gave specific instructions */ int i, found = 0; - for (i = 0; i < MAX_CAMS && parport[i] != -1; i++) - { + + for (i = 0; i < MAX_CAMS && parport[i] != -1; i++) { if (parport[0] == port->number) found = 1; } @@ -782,15 +774,14 @@ static int init_cqcam(struct parport *port) return -ENOSPC; qcam = qcam_init(port); - if (qcam==NULL) + if (qcam == NULL) return -ENODEV; parport_claim_or_block(qcam->pdev); qc_reset(qcam); - if (probe && qc_detect(qcam)==0) - { + if (probe && qc_detect(qcam) == 0) { parport_release(qcam->pdev); parport_unregister_device(qcam->pdev); kfree(qcam); @@ -840,14 +831,14 @@ static struct parport_driver cqcam_driver = { .detach = cq_detach, }; -static int __init cqcam_init (void) +static int __init cqcam_init(void) { printk(BANNER "\n"); return parport_register_driver(&cqcam_driver); } -static void __exit cqcam_cleanup (void) +static void __exit cqcam_cleanup(void) { unsigned int i; @@ -862,9 +853,9 @@ MODULE_DESCRIPTION(BANNER); MODULE_LICENSE("GPL"); /* FIXME: parport=auto would never have worked, surely? --RR */ -MODULE_PARM_DESC(parport ,"parport= for port detection method\n\ -probe=<0|1|2> for camera detection method\n\ -force_rgb=<0|1> for RGB data format (default BGR)"); +MODULE_PARM_DESC(parport, "parport= for port detection method\n" + "probe=<0|1|2> for camera detection method\n" + "force_rgb=<0|1> for RGB data format (default BGR)"); module_param_array(parport, int, NULL, 0); module_param(probe, int, 0); module_param(force_rgb, bool, 0); -- cgit v1.2.3-70-g09d2 From 1d61aac0996d96847e17263a41d34ab54bf8e103 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 22 Mar 2010 04:36:04 -0300 Subject: V4L/DVB: bw-qcam: coding style cleanup Clean up the coding style before we convert this driver to V4L2. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bw-qcam.c | 452 +++++++++++++++++++----------------------- 1 file changed, 207 insertions(+), 245 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c index 9e39bc5f7b0..3c9e754d73a 100644 --- a/drivers/media/video/bw-qcam.c +++ b/drivers/media/video/bw-qcam.c @@ -80,8 +80,8 @@ OTHER DEALINGS IN THE SOFTWARE. #include "bw-qcam.h" -static unsigned int maxpoll=250; /* Maximum busy-loop count for qcam I/O */ -static unsigned int yieldlines=4; /* Yield after this many during capture */ +static unsigned int maxpoll = 250; /* Maximum busy-loop count for qcam I/O */ +static unsigned int yieldlines = 4; /* Yield after this many during capture */ static int video_nr = -1; static unsigned int force_init; /* Whether to probe aggressively */ @@ -156,7 +156,7 @@ static int qc_calibrate(struct qcam_device *q) mdelay(1); schedule(); count++; - } while (value == 0xff && count<2048); + } while (value == 0xff && count < 2048); q->whitebal = value; return value; @@ -170,16 +170,15 @@ static struct qcam_device *qcam_init(struct parport *port) struct qcam_device *q; q = kmalloc(sizeof(struct qcam_device), GFP_KERNEL); - if(q==NULL) + if (q == NULL) return NULL; q->pport = port; q->pdev = parport_register_device(port, "bw-qcam", NULL, NULL, - NULL, 0, NULL); - if (q->pdev == NULL) - { + NULL, 0, NULL); + if (q->pdev == NULL) { printk(KERN_ERR "bw-qcam: couldn't register for %s.\n", - port->name); + port->name); kfree(q); return NULL; } @@ -247,12 +246,10 @@ static int qc_readparam(struct qcam_device *q) static int qc_waithand(struct qcam_device *q, int val) { int status; - int runs=0; + int runs = 0; - if (val) - { - while (!((status = read_lpstatus(q)) & 8)) - { + if (val) { + while (!((status = read_lpstatus(q)) & 8)) { /* 1000 is enough spins on the I/O for all normal cases, at that point we start to poll slowly until the camera wakes up. However, we are @@ -260,18 +257,13 @@ static int qc_waithand(struct qcam_device *q, int val) setting it lower is much better for interactive response. */ - if(runs++>maxpoll) - { + if (runs++ > maxpoll) msleep_interruptible(5); - } - if(runs>(maxpoll+1000)) /* 5 seconds */ + if (runs > (maxpoll + 1000)) /* 5 seconds */ return -1; } - } - else - { - while (((status = read_lpstatus(q)) & 8)) - { + } else { + while (((status = read_lpstatus(q)) & 8)) { /* 1000 is enough spins on the I/O for all normal cases, at that point we start to poll slowly until the camera wakes up. However, we are @@ -279,11 +271,9 @@ static int qc_waithand(struct qcam_device *q, int val) setting it lower is much better for interactive response. */ - if(runs++>maxpoll) - { + if (runs++ > maxpoll) msleep_interruptible(5); - } - if(runs++>(maxpoll+1000)) /* 5 seconds */ + if (runs++ > (maxpoll + 1000)) /* 5 seconds */ return -1; } } @@ -299,10 +289,9 @@ static int qc_waithand(struct qcam_device *q, int val) static unsigned int qc_waithand2(struct qcam_device *q, int val) { unsigned int status; - int runs=0; + int runs = 0; - do - { + do { status = read_lpdata(q); /* 1000 is enough spins on the I/O for all normal cases, at that point we start to poll slowly @@ -311,14 +300,11 @@ static unsigned int qc_waithand2(struct qcam_device *q, int val) setting it lower is much better for interactive response. */ - if(runs++>maxpoll) - { + if (runs++ > maxpoll) msleep_interruptible(5); - } - if(runs++>(maxpoll+1000)) /* 5 seconds */ + if (runs++ > (maxpoll + 1000)) /* 5 seconds */ return 0; - } - while ((status & 1) != val); + } while ((status & 1) != val); return status; } @@ -342,8 +328,7 @@ static int qc_detect(struct qcam_device *q) lastreg = reg = read_lpstatus(q) & 0xf0; - for (i = 0; i < 500; i++) - { + for (i = 0; i < 500; i++) { reg = read_lpstatus(q) & 0xf0; if (reg != lastreg) count++; @@ -357,7 +342,7 @@ static int qc_detect(struct qcam_device *q) won't be flashing these bits. Possibly unloading the module in the middle of a grab? Or some timeout condition? I've seen this parameter as low as 19 on my 450Mhz box - mpc */ - printk("Debugging: QCam detection counter <30-200 counts as detected>: %d\n", count); + printk(KERN_DEBUG "Debugging: QCam detection counter <30-200 counts as detected>: %d\n", count); return 1; #endif @@ -367,7 +352,7 @@ static int qc_detect(struct qcam_device *q) return 1; /* found */ } else { printk(KERN_ERR "No Quickcam found on port %s\n", - q->pport->name); + q->pport->name); printk(KERN_DEBUG "Quickcam detection counter: %u\n", count); return 0; /* not found */ } @@ -381,26 +366,24 @@ static int qc_detect(struct qcam_device *q) static void qc_reset(struct qcam_device *q) { - switch (q->port_mode & QC_FORCE_MASK) - { - case QC_FORCE_UNIDIR: - q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR; - break; + switch (q->port_mode & QC_FORCE_MASK) { + case QC_FORCE_UNIDIR: + q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR; + break; - case QC_FORCE_BIDIR: - q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR; - break; + case QC_FORCE_BIDIR: + q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR; + break; - case QC_ANY: - write_lpcontrol(q, 0x20); - write_lpdata(q, 0x75); + case QC_ANY: + write_lpcontrol(q, 0x20); + write_lpdata(q, 0x75); - if (read_lpdata(q) != 0x75) { - q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR; - } else { - q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR; - } - break; + if (read_lpdata(q) != 0x75) + q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR; + else + q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR; + break; } write_lpcontrol(q, 0xb); @@ -423,36 +406,33 @@ static int qc_setscanmode(struct qcam_device *q) { int old_mode = q->mode; - switch (q->transfer_scale) - { - case 1: - q->mode = 0; - break; - case 2: - q->mode = 4; - break; - case 4: - q->mode = 8; - break; + switch (q->transfer_scale) { + case 1: + q->mode = 0; + break; + case 2: + q->mode = 4; + break; + case 4: + q->mode = 8; + break; } - switch (q->bpp) - { - case 4: - break; - case 6: - q->mode += 2; - break; + switch (q->bpp) { + case 4: + break; + case 6: + q->mode += 2; + break; } - switch (q->port_mode & QC_MODE_MASK) - { - case QC_BIDIR: - q->mode += 1; - break; - case QC_NOTSET: - case QC_UNIDIR: - break; + switch (q->port_mode & QC_MODE_MASK) { + case QC_BIDIR: + q->mode += 1; + break; + case QC_NOTSET: + case QC_UNIDIR: + break; } if (q->mode != old_mode) @@ -493,7 +473,7 @@ static void qc_set(struct qcam_device *q) } else { val = q->width * q->bpp; val2 = (((q->port_mode & QC_MODE_MASK) == QC_BIDIR) ? 24 : 8) * - q->transfer_scale; + q->transfer_scale; } val = DIV_ROUND_UP(val, val2); qc_command(q, 0x13); @@ -521,85 +501,80 @@ static void qc_set(struct qcam_device *q) static inline int qc_readbytes(struct qcam_device *q, char buffer[]) { - int ret=1; + int ret = 1; unsigned int hi, lo; unsigned int hi2, lo2; static int state; - if (buffer == NULL) - { + if (buffer == NULL) { state = 0; return 0; } - switch (q->port_mode & QC_MODE_MASK) - { - case QC_BIDIR: /* Bi-directional Port */ - write_lpcontrol(q, 0x26); - lo = (qc_waithand2(q, 1) >> 1); - hi = (read_lpstatus(q) >> 3) & 0x1f; - write_lpcontrol(q, 0x2e); - lo2 = (qc_waithand2(q, 0) >> 1); - hi2 = (read_lpstatus(q) >> 3) & 0x1f; - switch (q->bpp) - { - case 4: - buffer[0] = lo & 0xf; - buffer[1] = ((lo & 0x70) >> 4) | ((hi & 1) << 3); - buffer[2] = (hi & 0x1e) >> 1; - buffer[3] = lo2 & 0xf; - buffer[4] = ((lo2 & 0x70) >> 4) | ((hi2 & 1) << 3); - buffer[5] = (hi2 & 0x1e) >> 1; - ret = 6; - break; - case 6: - buffer[0] = lo & 0x3f; - buffer[1] = ((lo & 0x40) >> 6) | (hi << 1); - buffer[2] = lo2 & 0x3f; - buffer[3] = ((lo2 & 0x40) >> 6) | (hi2 << 1); - ret = 4; - break; - } + switch (q->port_mode & QC_MODE_MASK) { + case QC_BIDIR: /* Bi-directional Port */ + write_lpcontrol(q, 0x26); + lo = (qc_waithand2(q, 1) >> 1); + hi = (read_lpstatus(q) >> 3) & 0x1f; + write_lpcontrol(q, 0x2e); + lo2 = (qc_waithand2(q, 0) >> 1); + hi2 = (read_lpstatus(q) >> 3) & 0x1f; + switch (q->bpp) { + case 4: + buffer[0] = lo & 0xf; + buffer[1] = ((lo & 0x70) >> 4) | ((hi & 1) << 3); + buffer[2] = (hi & 0x1e) >> 1; + buffer[3] = lo2 & 0xf; + buffer[4] = ((lo2 & 0x70) >> 4) | ((hi2 & 1) << 3); + buffer[5] = (hi2 & 0x1e) >> 1; + ret = 6; + break; + case 6: + buffer[0] = lo & 0x3f; + buffer[1] = ((lo & 0x40) >> 6) | (hi << 1); + buffer[2] = lo2 & 0x3f; + buffer[3] = ((lo2 & 0x40) >> 6) | (hi2 << 1); + ret = 4; break; + } + break; + + case QC_UNIDIR: /* Unidirectional Port */ + write_lpcontrol(q, 6); + lo = (qc_waithand(q, 1) & 0xf0) >> 4; + write_lpcontrol(q, 0xe); + hi = (qc_waithand(q, 0) & 0xf0) >> 4; - case QC_UNIDIR: /* Unidirectional Port */ - write_lpcontrol(q, 6); - lo = (qc_waithand(q, 1) & 0xf0) >> 4; - write_lpcontrol(q, 0xe); - hi = (qc_waithand(q, 0) & 0xf0) >> 4; - - switch (q->bpp) - { - case 4: - buffer[0] = lo; - buffer[1] = hi; - ret = 2; - break; - case 6: - switch (state) - { - case 0: - buffer[0] = (lo << 2) | ((hi & 0xc) >> 2); - q->saved_bits = (hi & 3) << 4; - state = 1; - ret = 1; - break; - case 1: - buffer[0] = lo | q->saved_bits; - q->saved_bits = hi << 2; - state = 2; - ret = 1; - break; - case 2: - buffer[0] = ((lo & 0xc) >> 2) | q->saved_bits; - buffer[1] = ((lo & 3) << 4) | hi; - state = 0; - ret = 2; - break; - } - break; + switch (q->bpp) { + case 4: + buffer[0] = lo; + buffer[1] = hi; + ret = 2; + break; + case 6: + switch (state) { + case 0: + buffer[0] = (lo << 2) | ((hi & 0xc) >> 2); + q->saved_bits = (hi & 3) << 4; + state = 1; + ret = 1; + break; + case 1: + buffer[0] = lo | q->saved_bits; + q->saved_bits = hi << 2; + state = 2; + ret = 1; + break; + case 2: + buffer[0] = ((lo & 0xc) >> 2) | q->saved_bits; + buffer[1] = ((lo & 3) << 4) | hi; + state = 0; + ret = 2; + break; } break; + } + break; } return ret; } @@ -615,7 +590,7 @@ static inline int qc_readbytes(struct qcam_device *q, char buffer[]) * n=2^(bit depth)-1. Ask me for more details if you don't understand * this. */ -static long qc_capture(struct qcam_device * q, char __user *buf, unsigned long len) +static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long len) { int i, j, k, yield; int bytes; @@ -623,9 +598,9 @@ static long qc_capture(struct qcam_device * q, char __user *buf, unsigned long l int divisor; int pixels_per_line; int pixels_read = 0; - int got=0; + int got = 0; char buffer[6]; - int shift=8-q->bpp; + int shift = 8 - q->bpp; char invert; if (q->mode == -1) @@ -634,13 +609,12 @@ static long qc_capture(struct qcam_device * q, char __user *buf, unsigned long l qc_command(q, 0x7); qc_command(q, q->mode); - if ((q->port_mode & QC_MODE_MASK) == QC_BIDIR) - { + if ((q->port_mode & QC_MODE_MASK) == QC_BIDIR) { write_lpcontrol(q, 0x2e); /* turn port around */ write_lpcontrol(q, 0x26); - (void) qc_waithand(q, 1); + qc_waithand(q, 1); write_lpcontrol(q, 0x2e); - (void) qc_waithand(q, 0); + qc_waithand(q, 0); } /* strange -- should be 15:63 below, but 4bpp is odd */ @@ -650,33 +624,28 @@ static long qc_capture(struct qcam_device * q, char __user *buf, unsigned long l pixels_per_line = q->width / q->transfer_scale; transperline = q->width * q->bpp; divisor = (((q->port_mode & QC_MODE_MASK) == QC_BIDIR) ? 24 : 8) * - q->transfer_scale; + q->transfer_scale; transperline = DIV_ROUND_UP(transperline, divisor); - for (i = 0, yield = yieldlines; i < linestotrans; i++) - { - for (pixels_read = j = 0; j < transperline; j++) - { + for (i = 0, yield = yieldlines; i < linestotrans; i++) { + for (pixels_read = j = 0; j < transperline; j++) { bytes = qc_readbytes(q, buffer); - for (k = 0; k < bytes && (pixels_read + k) < pixels_per_line; k++) - { + for (k = 0; k < bytes && (pixels_read + k) < pixels_per_line; k++) { int o; - if (buffer[k] == 0 && invert == 16) - { + if (buffer[k] == 0 && invert == 16) { /* 4bpp is odd (again) -- inverter is 16, not 15, but output must be 0-15 -- bls */ buffer[k] = 16; } - o=i*pixels_per_line + pixels_read + k; - if(oport_mode & QC_MODE_MASK) == QC_BIDIR) - { + if ((q->port_mode & QC_MODE_MASK) == QC_BIDIR) { write_lpcontrol(q, 2); write_lpcontrol(q, 6); udelay(3); write_lpcontrol(q, 0xe); } - if(gotname, "Quickcam"); @@ -726,73 +693,73 @@ static long qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg) b->minheight = 60; return 0; } - case VIDIOCGCHAN: + case VIDIOCGCHAN: { struct video_channel *v = arg; - if(v->channel!=0) + if (v->channel != 0) return -EINVAL; - v->flags=0; - v->tuners=0; + v->flags = 0; + v->tuners = 0; /* Good question.. its composite or SVHS so.. */ v->type = VIDEO_TYPE_CAMERA; strcpy(v->name, "Camera"); return 0; } - case VIDIOCSCHAN: + case VIDIOCSCHAN: { struct video_channel *v = arg; - if(v->channel!=0) + if (v->channel != 0) return -EINVAL; return 0; } - case VIDIOCGTUNER: + case VIDIOCGTUNER: { struct video_tuner *v = arg; - if(v->tuner) + if (v->tuner) return -EINVAL; strcpy(v->name, "Format"); - v->rangelow=0; - v->rangehigh=0; - v->flags= 0; + v->rangelow = 0; + v->rangehigh = 0; + v->flags = 0; v->mode = VIDEO_MODE_AUTO; return 0; } - case VIDIOCSTUNER: + case VIDIOCSTUNER: { struct video_tuner *v = arg; - if(v->tuner) + if (v->tuner) return -EINVAL; - if(v->mode!=VIDEO_MODE_AUTO) + if (v->mode != VIDEO_MODE_AUTO) return -EINVAL; return 0; } - case VIDIOCGPICT: + case VIDIOCGPICT: { struct video_picture *p = arg; - p->colour=0x8000; - p->hue=0x8000; - p->brightness=qcam->brightness<<8; - p->contrast=qcam->contrast<<8; - p->whiteness=qcam->whitebal<<8; - p->depth=qcam->bpp; - p->palette=VIDEO_PALETTE_GREY; + p->colour = 0x8000; + p->hue = 0x8000; + p->brightness = qcam->brightness << 8; + p->contrast = qcam->contrast << 8; + p->whiteness = qcam->whitebal << 8; + p->depth = qcam->bpp; + p->palette = VIDEO_PALETTE_GREY; return 0; } - case VIDIOCSPICT: + case VIDIOCSPICT: { struct video_picture *p = arg; - if(p->palette!=VIDEO_PALETTE_GREY) + if (p->palette != VIDEO_PALETTE_GREY) return -EINVAL; - if(p->depth!=4 && p->depth!=6) + if (p->depth != 4 && p->depth != 6) return -EINVAL; /* * Now load the camera. */ - qcam->brightness = p->brightness>>8; - qcam->contrast = p->contrast>>8; - qcam->whitebal = p->whiteness>>8; + qcam->brightness = p->brightness >> 8; + qcam->contrast = p->contrast >> 8; + qcam->whitebal = p->whiteness >> 8; qcam->bpp = p->depth; mutex_lock(&qcam->lock); @@ -802,28 +769,25 @@ static long qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg) return 0; } - case VIDIOCSWIN: + case VIDIOCSWIN: { struct video_window *vw = arg; - if(vw->flags) + if (vw->flags) return -EINVAL; - if(vw->clipcount) + if (vw->clipcount) return -EINVAL; - if(vw->height<60||vw->height>240) + if (vw->height < 60 || vw->height > 240) return -EINVAL; - if(vw->width<80||vw->width>320) + if (vw->width < 80 || vw->width > 320) return -EINVAL; qcam->width = 320; qcam->height = 240; qcam->transfer_scale = 4; - if(vw->width>=160 && vw->height>=120) - { + if (vw->width >= 160 && vw->height >= 120) qcam->transfer_scale = 2; - } - if(vw->width>=320 && vw->height>=240) - { + if (vw->width >= 320 && vw->height >= 240) { qcam->width = 320; qcam->height = 240; qcam->transfer_scale = 1; @@ -839,41 +803,42 @@ static long qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg) /* Ok we figured out what to use from our wide choice */ return 0; } - case VIDIOCGWIN: + case VIDIOCGWIN: { struct video_window *vw = arg; + memset(vw, 0, sizeof(*vw)); - vw->width=qcam->width/qcam->transfer_scale; - vw->height=qcam->height/qcam->transfer_scale; + vw->width = qcam->width / qcam->transfer_scale; + vw->height = qcam->height / qcam->transfer_scale; return 0; } - case VIDIOCKEY: - return 0; - case VIDIOCCAPTURE: - case VIDIOCGFBUF: - case VIDIOCSFBUF: - case VIDIOCGFREQ: - case VIDIOCSFREQ: - case VIDIOCGAUDIO: - case VIDIOCSAUDIO: - return -EINVAL; - default: - return -ENOIOCTLCMD; + case VIDIOCKEY: + return 0; + case VIDIOCCAPTURE: + case VIDIOCGFBUF: + case VIDIOCSFBUF: + case VIDIOCGFREQ: + case VIDIOCSFREQ: + case VIDIOCGAUDIO: + case VIDIOCSAUDIO: + return -EINVAL; + default: + return -ENOIOCTLCMD; } return 0; } static long qcam_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) + unsigned int cmd, unsigned long arg) { return video_usercopy(file, cmd, arg, qcam_do_ioctl); } static ssize_t qcam_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) + size_t count, loff_t *ppos) { struct video_device *v = video_devdata(file); - struct qcam_device *qcam=(struct qcam_device *)v; + struct qcam_device *qcam = (struct qcam_device *)v; int len; parport_claim_or_block(qcam->pdev); @@ -885,7 +850,7 @@ static ssize_t qcam_read(struct file *file, char __user *buf, if (qcam->status & QC_PARAM_CHANGE) qc_set(qcam); - len=qc_capture(qcam, buf,count); + len = qc_capture(qcam, buf, count); mutex_unlock(&qcam->lock); @@ -917,8 +882,7 @@ static const struct v4l2_file_operations qcam_fops = { .ioctl = qcam_ioctl, .read = qcam_read, }; -static struct video_device qcam_template= -{ +static struct video_device qcam_template = { .name = "Connectix Quickcam", .fops = &qcam_fops, .release = video_device_release_empty, @@ -932,22 +896,20 @@ static int init_bwqcam(struct parport *port) { struct qcam_device *qcam; - if (num_cams == MAX_CAMS) - { + if (num_cams == MAX_CAMS) { printk(KERN_ERR "Too many Quickcams (max %d)\n", MAX_CAMS); return -ENOSPC; } - qcam=qcam_init(port); - if(qcam==NULL) + qcam = qcam_init(port); + if (qcam == NULL) return -ENODEV; parport_claim_or_block(qcam->pdev); qc_reset(qcam); - if(qc_detect(qcam)==0) - { + if (qc_detect(qcam) == 0) { parport_release(qcam->pdev); parport_unregister_device(qcam->pdev); kfree(qcam); @@ -1045,12 +1007,12 @@ static int __init init_bw_qcams(void) #ifdef MODULE /* Do some sanity checks on the module parameters. */ if (maxpoll > 5000) { - printk("Connectix Quickcam max-poll was above 5000. Using 5000.\n"); + printk(KERN_INFO "Connectix Quickcam max-poll was above 5000. Using 5000.\n"); maxpoll = 5000; } if (yieldlines < 1) { - printk("Connectix Quickcam yieldlines was less than 1. Using 1.\n"); + printk(KERN_INFO "Connectix Quickcam yieldlines was less than 1. Using 1.\n"); yieldlines = 1; } #endif -- cgit v1.2.3-70-g09d2 From 88f4423454a23375f07bb4ff3a80d209930560d0 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 22 Mar 2010 04:44:29 -0300 Subject: V4L/DVB: arv: coding style cleanup Clean up the coding style before we convert this driver to V4L2. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/arv.c | 153 +++++++++++++++++++++++----------------------- 1 file changed, 76 insertions(+), 77 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c index a356d6bd313..9f88096a520 100644 --- a/drivers/media/video/arv.c +++ b/drivers/media/video/arv.c @@ -39,7 +39,7 @@ #include #if 0 -#define DEBUG(n, args...) printk(args) +#define DEBUG(n, args...) printk(KERN_INFO args) #define CHECK_LOST 1 #else #define DEBUG(n, args...) @@ -55,7 +55,7 @@ #define VERSION "0.03" #define ar_inl(addr) inl((unsigned long)(addr)) -#define ar_outl(val, addr) outl((unsigned long)(val),(unsigned long)(addr)) +#define ar_outl(val, addr) outl((unsigned long)(val), (unsigned long)(addr)) extern struct cpuinfo_m32r boot_cpu_data; @@ -214,13 +214,12 @@ void init_iic(void) /* I2C CLK */ /* 50MH-100k */ - if (freq == 75) { + if (freq == 75) ar_outl(369, PLDI2CFREQ); /* BCLK = 75MHz */ - } else if (freq == 50) { + else if (freq == 50) ar_outl(244, PLDI2CFREQ); /* BCLK = 50MHz */ - } else { + else ar_outl(244, PLDI2CFREQ); /* default: BCLK = 50MHz */ - } ar_outl(0x1, PLDI2CCR); /* I2CCR Enable */ } @@ -260,7 +259,7 @@ static inline void wait_for_vertical_sync(int exp_line) break; } if (tmout < 0) - printk("arv: lost %d -> %d\n", exp_line, l); + printk(KERN_ERR "arv: lost %d -> %d\n", exp_line, l); #else while (ar_inl(ARVHCOUNT) != exp_line) cpu_relax(); @@ -277,7 +276,7 @@ static ssize_t ar_read(struct file *file, char *buf, size_t count, loff_t *ppos) unsigned char *p; int h, w; unsigned char *py, *pu, *pv; -#if ! USE_INT +#if !USE_INT int l; #endif @@ -313,7 +312,7 @@ static ssize_t ar_read(struct file *file, char *buf, size_t count, loff_t *ppos) /* .... AR interrupts .... */ interruptible_sleep_on(&ar->wait); if (signal_pending(current)) { - printk("arv: interrupted while get frame data.\n"); + printk(KERN_ERR "arv: interrupted while get frame data.\n"); ret = -EINTR; goto out_up; } @@ -386,7 +385,7 @@ static ssize_t ar_read(struct file *file, char *buf, size_t count, loff_t *ppos) } } if (copy_to_user(buf, yuv, ar->frame_bytes)) { - printk("arv: failed while copy_to_user yuv.\n"); + printk(KERN_ERR "arv: failed while copy_to_user yuv.\n"); ret = -EFAULT; goto out_up; } @@ -402,7 +401,7 @@ static long ar_do_ioctl(struct file *file, unsigned int cmd, void *arg) struct ar_device *ar = video_get_drvdata(dev); DEBUG(1, "ar_ioctl()\n"); - switch(cmd) { + switch (cmd) { case VIDIOCGCAP: { struct video_capability *b = arg; @@ -559,11 +558,11 @@ static void ar_interrupt(int irq, void *dev) line_count = ar_inl(ARVHCOUNT); /* line number */ if (ar->mode == AR_MODE_INTERLACE && ar->size == AR_SIZE_VGA) { /* operations for interlace mode */ - if ( line_count < (AR_HEIGHT_VGA/2) ) /* even line */ + if (line_count < (AR_HEIGHT_VGA / 2)) /* even line */ line_number = (line_count << 1); else /* odd line */ line_number = - (((line_count - (AR_HEIGHT_VGA/2)) << 1) + 1); + (((line_count - (AR_HEIGHT_VGA / 2)) << 1) + 1); } else { line_number = line_count; } @@ -627,7 +626,7 @@ static int ar_initialize(struct video_device *dev) { struct ar_device *ar = video_get_drvdata(dev); unsigned long cr = 0; - int i,found=0; + int i, found = 0; DEBUG(1, "ar_initialize:\n"); @@ -666,66 +665,66 @@ static int ar_initialize(struct video_device *dev) if (found == 0) return -ENODEV; - printk("arv: Initializing "); - - iic(2,0x78,0x11,0x01,0x00); /* start */ - iic(3,0x78,0x12,0x00,0x06); - iic(3,0x78,0x12,0x12,0x30); - iic(3,0x78,0x12,0x15,0x58); - iic(3,0x78,0x12,0x17,0x30); - printk("."); - iic(3,0x78,0x12,0x1a,0x97); - iic(3,0x78,0x12,0x1b,0xff); - iic(3,0x78,0x12,0x1c,0xff); - iic(3,0x78,0x12,0x26,0x10); - iic(3,0x78,0x12,0x27,0x00); - printk("."); - iic(2,0x78,0x34,0x02,0x00); - iic(2,0x78,0x7a,0x10,0x00); - iic(2,0x78,0x80,0x39,0x00); - iic(2,0x78,0x81,0xe6,0x00); - iic(2,0x78,0x8d,0x00,0x00); - printk("."); - iic(2,0x78,0x8e,0x0c,0x00); - iic(2,0x78,0x8f,0x00,0x00); + printk(KERN_INFO "arv: Initializing "); + + iic(2, 0x78, 0x11, 0x01, 0x00); /* start */ + iic(3, 0x78, 0x12, 0x00, 0x06); + iic(3, 0x78, 0x12, 0x12, 0x30); + iic(3, 0x78, 0x12, 0x15, 0x58); + iic(3, 0x78, 0x12, 0x17, 0x30); + printk(KERN_CONT "."); + iic(3, 0x78, 0x12, 0x1a, 0x97); + iic(3, 0x78, 0x12, 0x1b, 0xff); + iic(3, 0x78, 0x12, 0x1c, 0xff); + iic(3, 0x78, 0x12, 0x26, 0x10); + iic(3, 0x78, 0x12, 0x27, 0x00); + printk(KERN_CONT "."); + iic(2, 0x78, 0x34, 0x02, 0x00); + iic(2, 0x78, 0x7a, 0x10, 0x00); + iic(2, 0x78, 0x80, 0x39, 0x00); + iic(2, 0x78, 0x81, 0xe6, 0x00); + iic(2, 0x78, 0x8d, 0x00, 0x00); + printk(KERN_CONT "."); + iic(2, 0x78, 0x8e, 0x0c, 0x00); + iic(2, 0x78, 0x8f, 0x00, 0x00); #if 0 - iic(2,0x78,0x90,0x00,0x00); /* AWB on=1 off=0 */ + iic(2, 0x78, 0x90, 0x00, 0x00); /* AWB on=1 off=0 */ #endif - iic(2,0x78,0x93,0x01,0x00); - iic(2,0x78,0x94,0xcd,0x00); - iic(2,0x78,0x95,0x00,0x00); - printk("."); - iic(2,0x78,0x96,0xa0,0x00); - iic(2,0x78,0x97,0x00,0x00); - iic(2,0x78,0x98,0x60,0x00); - iic(2,0x78,0x99,0x01,0x00); - iic(2,0x78,0x9a,0x19,0x00); - printk("."); - iic(2,0x78,0x9b,0x02,0x00); - iic(2,0x78,0x9c,0xe8,0x00); - iic(2,0x78,0x9d,0x02,0x00); - iic(2,0x78,0x9e,0x2e,0x00); - iic(2,0x78,0xb8,0x78,0x00); - iic(2,0x78,0xba,0x05,0x00); + iic(2, 0x78, 0x93, 0x01, 0x00); + iic(2, 0x78, 0x94, 0xcd, 0x00); + iic(2, 0x78, 0x95, 0x00, 0x00); + printk(KERN_CONT "."); + iic(2, 0x78, 0x96, 0xa0, 0x00); + iic(2, 0x78, 0x97, 0x00, 0x00); + iic(2, 0x78, 0x98, 0x60, 0x00); + iic(2, 0x78, 0x99, 0x01, 0x00); + iic(2, 0x78, 0x9a, 0x19, 0x00); + printk(KERN_CONT "."); + iic(2, 0x78, 0x9b, 0x02, 0x00); + iic(2, 0x78, 0x9c, 0xe8, 0x00); + iic(2, 0x78, 0x9d, 0x02, 0x00); + iic(2, 0x78, 0x9e, 0x2e, 0x00); + iic(2, 0x78, 0xb8, 0x78, 0x00); + iic(2, 0x78, 0xba, 0x05, 0x00); #if 0 - iic(2,0x78,0x83,0x8c,0x00); /* brightness */ + iic(2, 0x78, 0x83, 0x8c, 0x00); /* brightness */ #endif - printk("."); + printk(KERN_CONT "."); /* color correction */ - iic(3,0x78,0x49,0x00,0x95); /* a */ - iic(3,0x78,0x49,0x01,0x96); /* b */ - iic(3,0x78,0x49,0x03,0x85); /* c */ - iic(3,0x78,0x49,0x04,0x97); /* d */ - iic(3,0x78,0x49,0x02,0x7e); /* e(Lo) */ - iic(3,0x78,0x49,0x05,0xa4); /* f(Lo) */ - iic(3,0x78,0x49,0x06,0x04); /* e(Hi) */ - iic(3,0x78,0x49,0x07,0x04); /* e(Hi) */ - iic(2,0x78,0x48,0x01,0x00); /* on=1 off=0 */ - - printk("."); - iic(2,0x78,0x11,0x00,0x00); /* end */ - printk(" done\n"); + iic(3, 0x78, 0x49, 0x00, 0x95); /* a */ + iic(3, 0x78, 0x49, 0x01, 0x96); /* b */ + iic(3, 0x78, 0x49, 0x03, 0x85); /* c */ + iic(3, 0x78, 0x49, 0x04, 0x97); /* d */ + iic(3, 0x78, 0x49, 0x02, 0x7e); /* e(Lo) */ + iic(3, 0x78, 0x49, 0x05, 0xa4); /* f(Lo) */ + iic(3, 0x78, 0x49, 0x06, 0x04); /* e(Hi) */ + iic(3, 0x78, 0x49, 0x07, 0x04); /* e(Hi) */ + iic(2, 0x78, 0x48, 0x01, 0x00); /* on=1 off=0 */ + + printk(KERN_CONT "."); + iic(2, 0x78, 0x11, 0x00, 0x00); /* end */ + printk(KERN_CONT " done\n"); return 0; } @@ -787,8 +786,8 @@ static int __init ar_init(void) #if USE_INT /* allocate a DMA buffer for 1 line. */ ar->line_buff = kmalloc(MAX_AR_LINE_BYTES, GFP_KERNEL | GFP_DMA); - if (ar->line_buff == NULL || ! ALIGN4(ar->line_buff)) { - printk("arv: buffer allocation failed for DMA.\n"); + if (ar->line_buff == NULL || !ALIGN4(ar->line_buff)) { + printk(KERN_ERR "arv: buffer allocation failed for DMA.\n"); ret = -ENOMEM; goto out_end; } @@ -796,8 +795,8 @@ static int __init ar_init(void) /* allocate buffers for a frame */ for (i = 0; i < MAX_AR_HEIGHT; i++) { ar->frame[i] = kmalloc(MAX_AR_LINE_BYTES, GFP_KERNEL); - if (ar->frame[i] == NULL || ! ALIGN4(ar->frame[i])) { - printk("arv: buffer allocation failed for frame.\n"); + if (ar->frame[i] == NULL || !ALIGN4(ar->frame[i])) { + printk(KERN_ERR "arv: buffer allocation failed for frame.\n"); ret = -ENOMEM; goto out_line_buff; } @@ -834,14 +833,14 @@ static int __init ar_init(void) #if USE_INT if (request_irq(M32R_IRQ_INT3, ar_interrupt, 0, "arv", ar)) { - printk("arv: request_irq(%d) failed.\n", M32R_IRQ_INT3); + printk(KERN_ERR "arv: request_irq(%d) failed.\n", M32R_IRQ_INT3); ret = -EIO; goto out_irq; } #endif if (ar_initialize(ar->vdev) != 0) { - printk("arv: M64278 not found.\n"); + printk(KERN_ERR "arv: M64278 not found.\n"); ret = -ENODEV; goto out_dev; } @@ -854,12 +853,12 @@ static int __init ar_init(void) */ if (video_register_device(ar->vdev, VFL_TYPE_GRABBER, video_nr) != 0) { /* return -1, -ENFILE(full) or others */ - printk("arv: register video (Colour AR) failed.\n"); + printk(KERN_ERR "arv: register video (Colour AR) failed.\n"); ret = -ENODEV; goto out_dev; } - printk("%s: Found M64278 VGA (IRQ %d, Freq %dMHz).\n", + printk(KERN_INFO "%s: Found M64278 VGA (IRQ %d, Freq %dMHz).\n", video_device_node_name(ar->vdev), M32R_IRQ_INT3, freq); return 0; @@ -886,7 +885,7 @@ out_end: static int __init ar_init_module(void) { freq = (boot_cpu_data.bus_clock / 1000000); - printk("arv: Bus clock %d\n", freq); + printk(KERN_INFO "arv: Bus clock %d\n", freq); if (freq != 50 && freq != 75) freq = DEFAULT_FREQ; return ar_init(); -- cgit v1.2.3-70-g09d2 From 4bfdd58604ead4d49b29630ee8f72c99b7803b7d Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 22 Mar 2010 04:47:27 -0300 Subject: V4L/DVB: w9966: coding style cleanup Clean up the coding style before we convert this driver to V4L2. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/w9966.c | 461 +++++++++++++++++++++----------------------- 1 file changed, 223 insertions(+), 238 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c index bf9bf650a31..25364b8f857 100644 --- a/drivers/media/video/w9966.c +++ b/drivers/media/video/w9966.c @@ -76,12 +76,12 @@ */ #define W9966_DRIVERNAME "W9966CF Webcam" -#define W9966_MAXCAMS 4 // Maximum number of cameras -#define W9966_RBUFFER 2048 // Read buffer (must be an even number) -#define W9966_SRAMSIZE 131072 // 128kb -#define W9966_SRAMID 0x02 // check w9966cf.pdf +#define W9966_MAXCAMS 4 /* Maximum number of cameras */ +#define W9966_RBUFFER 2048 /* Read buffer (must be an even number) */ +#define W9966_SRAMSIZE 131072 /* 128kb */ +#define W9966_SRAMID 0x02 /* check w9966cf.pdf */ -// Empirically determined window limits +/* Empirically determined window limits */ #define W9966_WND_MIN_X 16 #define W9966_WND_MIN_Y 14 #define W9966_WND_MAX_X 705 @@ -89,7 +89,7 @@ #define W9966_WND_MAX_W (W9966_WND_MAX_X - W9966_WND_MIN_X) #define W9966_WND_MAX_H (W9966_WND_MAX_Y - W9966_WND_MIN_Y) -// Keep track of our current state +/* Keep track of our current state */ #define W9966_STATE_PDEV 0x01 #define W9966_STATE_CLAIMED 0x02 #define W9966_STATE_VDEV 0x04 @@ -105,8 +105,8 @@ struct w9966_dev { unsigned char dev_state; unsigned char i2c_state; unsigned short ppmode; - struct parport* pport; - struct pardevice* pdev; + struct parport *pport; + struct pardevice *pdev; struct video_device vdev; unsigned short width; unsigned short height; @@ -127,15 +127,15 @@ MODULE_LICENSE("GPL"); #ifdef MODULE -static const char* pardev[] = {[0 ... W9966_MAXCAMS] = ""}; +static const char *pardev[] = {[0 ... W9966_MAXCAMS] = ""}; #else -static const char* pardev[] = {[0 ... W9966_MAXCAMS] = "aggressive"}; +static const char *pardev[] = {[0 ... W9966_MAXCAMS] = "aggressive"}; #endif module_param_array(pardev, charp, NULL, 0); -MODULE_PARM_DESC(pardev, "pardev: where to search for\n\ -\teach camera. 'aggressive' means brute-force search.\n\ -\tEg: >pardev=parport3,aggressive,parport2,parport1< would assign\n\ -\tcam 1 to parport3 and search every parport for cam 2 etc..."); +MODULE_PARM_DESC(pardev, "pardev: where to search for\n" + "\teach camera. 'aggressive' means brute-force search.\n" + "\tEg: >pardev=parport3,aggressive,parport2,parport1< would assign\n" + "\tcam 1 to parport3 and search every parport for cam 2 etc..."); static int parmode; module_param(parmode, int, 0); @@ -154,31 +154,31 @@ static struct w9966_dev w9966_cams[W9966_MAXCAMS]; * Private function declares */ -static inline void w9966_setState(struct w9966_dev* cam, int mask, int val); -static inline int w9966_getState(struct w9966_dev* cam, int mask, int val); +static inline void w9966_setState(struct w9966_dev *cam, int mask, int val); +static inline int w9966_getState(struct w9966_dev *cam, int mask, int val); static inline void w9966_pdev_claim(struct w9966_dev *vdev); static inline void w9966_pdev_release(struct w9966_dev *vdev); -static int w9966_rReg(struct w9966_dev* cam, int reg); -static int w9966_wReg(struct w9966_dev* cam, int reg, int data); +static int w9966_rReg(struct w9966_dev *cam, int reg); +static int w9966_wReg(struct w9966_dev *cam, int reg, int data); #if 0 -static int w9966_rReg_i2c(struct w9966_dev* cam, int reg); +static int w9966_rReg_i2c(struct w9966_dev *cam, int reg); #endif -static int w9966_wReg_i2c(struct w9966_dev* cam, int reg, int data); +static int w9966_wReg_i2c(struct w9966_dev *cam, int reg, int data); static int w9966_findlen(int near, int size, int maxlen); -static int w9966_calcscale(int size, int min, int max, int* beg, int* end, unsigned char* factor); -static int w9966_setup(struct w9966_dev* cam, int x1, int y1, int x2, int y2, int w, int h); +static int w9966_calcscale(int size, int min, int max, int *beg, int *end, unsigned char *factor); +static int w9966_setup(struct w9966_dev *cam, int x1, int y1, int x2, int y2, int w, int h); -static int w9966_init(struct w9966_dev* cam, struct parport* port); -static void w9966_term(struct w9966_dev* cam); +static int w9966_init(struct w9966_dev *cam, struct parport* port); +static void w9966_term(struct w9966_dev *cam); -static inline void w9966_i2c_setsda(struct w9966_dev* cam, int state); -static inline int w9966_i2c_setscl(struct w9966_dev* cam, int state); -static inline int w9966_i2c_getsda(struct w9966_dev* cam); -static inline int w9966_i2c_getscl(struct w9966_dev* cam); -static int w9966_i2c_wbyte(struct w9966_dev* cam, int data); +static inline void w9966_i2c_setsda(struct w9966_dev *cam, int state); +static inline int w9966_i2c_setscl(struct w9966_dev *cam, int state); +static inline int w9966_i2c_getsda(struct w9966_dev *cam); +static inline int w9966_i2c_getscl(struct w9966_dev *cam); +static int w9966_i2c_wbyte(struct w9966_dev *cam, int data); #if 0 -static int w9966_i2c_rbyte(struct w9966_dev* cam); +static int w9966_i2c_rbyte(struct w9966_dev *cam); #endif static long w9966_v4l_ioctl(struct file *file, @@ -219,20 +219,20 @@ static struct video_device w9966_template = { */ -// Set camera phase flags, so we know what to uninit when terminating -static inline void w9966_setState(struct w9966_dev* cam, int mask, int val) +/* Set camera phase flags, so we know what to uninit when terminating */ +static inline void w9966_setState(struct w9966_dev *cam, int mask, int val) { cam->dev_state = (cam->dev_state & ~mask) ^ val; } -// Get camera phase flags -static inline int w9966_getState(struct w9966_dev* cam, int mask, int val) +/* Get camera phase flags */ +static inline int w9966_getState(struct w9966_dev *cam, int mask, int val) { return ((cam->dev_state & mask) == val); } -// Claim parport for ourself -static inline void w9966_pdev_claim(struct w9966_dev* cam) +/* Claim parport for ourself */ +static inline void w9966_pdev_claim(struct w9966_dev *cam) { if (w9966_getState(cam, W9966_STATE_CLAIMED, W9966_STATE_CLAIMED)) return; @@ -240,8 +240,8 @@ static inline void w9966_pdev_claim(struct w9966_dev* cam) w9966_setState(cam, W9966_STATE_CLAIMED, W9966_STATE_CLAIMED); } -// Release parport for others to use -static inline void w9966_pdev_release(struct w9966_dev* cam) +/* Release parport for others to use */ +static inline void w9966_pdev_release(struct w9966_dev *cam) { if (w9966_getState(cam, W9966_STATE_CLAIMED, 0)) return; @@ -249,12 +249,12 @@ static inline void w9966_pdev_release(struct w9966_dev* cam) w9966_setState(cam, W9966_STATE_CLAIMED, 0); } -// Read register from W9966 interface-chip -// Expects a claimed pdev -// -1 on error, else register data (byte) -static int w9966_rReg(struct w9966_dev* cam, int reg) +/* Read register from W9966 interface-chip + Expects a claimed pdev + -1 on error, else register data (byte) */ +static int w9966_rReg(struct w9966_dev *cam, int reg) { - // ECP, read, regtransfer, REG, REG, REG, REG, REG + /* ECP, read, regtransfer, REG, REG, REG, REG, REG */ const unsigned char addr = 0x80 | (reg & 0x1f); unsigned char val; @@ -270,12 +270,12 @@ static int w9966_rReg(struct w9966_dev* cam, int reg) return val; } -// Write register to W9966 interface-chip -// Expects a claimed pdev -// -1 on error -static int w9966_wReg(struct w9966_dev* cam, int reg, int data) +/* Write register to W9966 interface-chip + Expects a claimed pdev + -1 on error */ +static int w9966_wReg(struct w9966_dev *cam, int reg, int data) { - // ECP, write, regtransfer, REG, REG, REG, REG, REG + /* ECP, write, regtransfer, REG, REG, REG, REG, REG */ const unsigned char addr = 0xc0 | (reg & 0x1f); const unsigned char val = data; @@ -291,11 +291,11 @@ static int w9966_wReg(struct w9966_dev* cam, int reg, int data) return 0; } -// Initialize camera device. Setup all internal flags, set a -// default video mode, setup ccd-chip, register v4l device etc.. -// Also used for 'probing' of hardware. -// -1 on error -static int w9966_init(struct w9966_dev* cam, struct parport* port) +/* Initialize camera device. Setup all internal flags, set a + default video mode, setup ccd-chip, register v4l device etc.. + Also used for 'probing' of hardware. + -1 on error */ +static int w9966_init(struct w9966_dev *cam, struct parport* port) { if (cam->dev_state != 0) return -1; @@ -306,10 +306,9 @@ static int w9966_init(struct w9966_dev* cam, struct parport* port) cam->color = 64; cam->hue = 0; -// Select requested transfer mode - switch(parmode) - { - default: // Auto-detect (priority: hw-ecp, hw-epp, sw-ecp) +/* Select requested transfer mode */ + switch (parmode) { + default: /* Auto-detect (priority: hw-ecp, hw-epp, sw-ecp) */ case 0: if (port->modes & PARPORT_MODE_ECP) cam->ppmode = IEEE1284_MODE_ECP; @@ -318,15 +317,15 @@ static int w9966_init(struct w9966_dev* cam, struct parport* port) else cam->ppmode = IEEE1284_MODE_ECP; break; - case 1: // hw- or sw-ecp + case 1: /* hw- or sw-ecp */ cam->ppmode = IEEE1284_MODE_ECP; break; - case 2: // hw- or sw-epp + case 2: /* hw- or sw-epp */ cam->ppmode = IEEE1284_MODE_EPP; break; } -// Tell the parport driver that we exists +/* Tell the parport driver that we exists */ cam->pdev = parport_register_device(port, "w9966", NULL, NULL, NULL, 0, NULL); if (cam->pdev == NULL) { DPRINTF("parport_register_device() failed\n"); @@ -336,7 +335,7 @@ static int w9966_init(struct w9966_dev* cam, struct parport* port) w9966_pdev_claim(cam); -// Setup a default capture mode +/* Setup a default capture mode */ if (w9966_setup(cam, 0, 0, 1023, 1023, 200, 160) != 0) { DPRINTF("w9966_setup() failed.\n"); return -1; @@ -344,7 +343,7 @@ static int w9966_init(struct w9966_dev* cam, struct parport* port) w9966_pdev_release(cam); -// Fill in the video_device struct and register us to v4l +/* Fill in the video_device struct and register us to v4l */ memcpy(&cam->vdev, &w9966_template, sizeof(struct video_device)); video_set_drvdata(&cam->vdev, cam); @@ -353,32 +352,30 @@ static int w9966_init(struct w9966_dev* cam, struct parport* port) w9966_setState(cam, W9966_STATE_VDEV, W9966_STATE_VDEV); - // All ok - printk( - "w9966cf: Found and initialized a webcam on %s.\n", - cam->pport->name - ); + /* All ok */ + printk(KERN_INFO "w9966cf: Found and initialized a webcam on %s.\n", + cam->pport->name); return 0; } -// Terminate everything gracefully -static void w9966_term(struct w9966_dev* cam) +/* Terminate everything gracefully */ +static void w9966_term(struct w9966_dev *cam) { -// Unregister from v4l +/* Unregister from v4l */ if (w9966_getState(cam, W9966_STATE_VDEV, W9966_STATE_VDEV)) { video_unregister_device(&cam->vdev); w9966_setState(cam, W9966_STATE_VDEV, 0); } -// Terminate from IEEE1284 mode and release pdev block +/* Terminate from IEEE1284 mode and release pdev block */ if (w9966_getState(cam, W9966_STATE_PDEV, W9966_STATE_PDEV)) { w9966_pdev_claim(cam); parport_negotiate(cam->pport, IEEE1284_MODE_COMPAT); w9966_pdev_release(cam); } -// Unregister from parport +/* Unregister from parport */ if (w9966_getState(cam, W9966_STATE_PDEV, W9966_STATE_PDEV)) { parport_unregister_device(cam->pdev); w9966_setState(cam, W9966_STATE_PDEV, 0); @@ -386,24 +383,23 @@ static void w9966_term(struct w9966_dev* cam) } -// Find a good length for capture window (used both for W and H) -// A bit ugly but pretty functional. The capture length -// have to match the downscale +/* Find a good length for capture window (used both for W and H) + A bit ugly but pretty functional. The capture length + have to match the downscale */ static int w9966_findlen(int near, int size, int maxlen) { int bestlen = size; int besterr = abs(near - bestlen); int len; - for(len = size+1;len < maxlen;len++) - { + for (len = size + 1; len < maxlen; len++) { int err; - if ( ((64*size) %len) != 0) + if (((64 * size) % len) != 0) continue; err = abs(near - len); - // Only continue as long as we keep getting better values + /* Only continue as long as we keep getting better values */ if (err > besterr) break; @@ -414,32 +410,32 @@ static int w9966_findlen(int near, int size, int maxlen) return bestlen; } -// Modify capture window (if necessary) -// and calculate downscaling -// Return -1 on error -static int w9966_calcscale(int size, int min, int max, int* beg, int* end, unsigned char* factor) +/* Modify capture window (if necessary) + and calculate downscaling + Return -1 on error */ +static int w9966_calcscale(int size, int min, int max, int *beg, int *end, unsigned char *factor) { int maxlen = max - min; int len = *end - *beg + 1; int newlen = w9966_findlen(len, size, maxlen); int err = newlen - len; - // Check for bad format + /* Check for bad format */ if (newlen > maxlen || newlen < size) return -1; - // Set factor (6 bit fixed) - *factor = (64*size) / newlen; + /* Set factor (6 bit fixed) */ + *factor = (64 * size) / newlen; if (*factor == 64) - *factor = 0x00; // downscale is disabled + *factor = 0x00; /* downscale is disabled */ else - *factor |= 0x80; // set downscale-enable bit + *factor |= 0x80; /* set downscale-enable bit */ - // Modify old beginning and end + /* Modify old beginning and end */ *beg -= err / 2; *end += err - (err / 2); - // Move window if outside borders + /* Move window if outside borders */ if (*beg < min) { *end += min - *beg; *beg += min - *beg; @@ -452,10 +448,10 @@ static int w9966_calcscale(int size, int min, int max, int* beg, int* end, unsig return 0; } -// Setup the cameras capture window etc. -// Expects a claimed pdev -// return -1 on error -static int w9966_setup(struct w9966_dev* cam, int x1, int y1, int x2, int y2, int w, int h) +/* Setup the cameras capture window etc. + Expects a claimed pdev + return -1 on error */ +static int w9966_setup(struct w9966_dev *cam, int x1, int y1, int x2, int y2, int w, int h) { unsigned int i; unsigned int enh_s, enh_e; @@ -469,84 +465,84 @@ static int w9966_setup(struct w9966_dev* cam, int x1, int y1, int x2, int y2, in }; - if (w*h*2 > W9966_SRAMSIZE) - { + if (w * h * 2 > W9966_SRAMSIZE) { DPRINTF("capture window exceeds SRAM size!.\n"); - w = 200; h = 160; // Pick default values + w = 200; h = 160; /* Pick default values */ } w &= ~0x1; - if (w < 2) w = 2; - if (h < 1) h = 1; - if (w > W9966_WND_MAX_W) w = W9966_WND_MAX_W; - if (h > W9966_WND_MAX_H) h = W9966_WND_MAX_H; + if (w < 2) + w = 2; + if (h < 1) + h = 1; + if (w > W9966_WND_MAX_W) + w = W9966_WND_MAX_W; + if (h > W9966_WND_MAX_H) + h = W9966_WND_MAX_H; cam->width = w; cam->height = h; enh_s = 0; - enh_e = w*h*2; - -// Modify capture window if necessary and calculate downscaling - if ( - w9966_calcscale(w, W9966_WND_MIN_X, W9966_WND_MAX_X, &x1, &x2, &scale_x) != 0 || - w9966_calcscale(h, W9966_WND_MIN_Y, W9966_WND_MAX_Y, &y1, &y2, &scale_y) != 0 - ) return -1; - - DPRINTF( - "%dx%d, x: %d<->%d, y: %d<->%d, sx: %d/64, sy: %d/64.\n", - w, h, x1, x2, y1, y2, scale_x&~0x80, scale_y&~0x80 - ); - -// Setup registers - regs[0x00] = 0x00; // Set normal operation - regs[0x01] = 0x18; // Capture mode - regs[0x02] = scale_y; // V-scaling - regs[0x03] = scale_x; // H-scaling - - // Capture window - regs[0x04] = (x1 & 0x0ff); // X-start (8 low bits) - regs[0x05] = (x1 & 0x300)>>8; // X-start (2 high bits) - regs[0x06] = (y1 & 0x0ff); // Y-start (8 low bits) - regs[0x07] = (y1 & 0x300)>>8; // Y-start (2 high bits) - regs[0x08] = (x2 & 0x0ff); // X-end (8 low bits) - regs[0x09] = (x2 & 0x300)>>8; // X-end (2 high bits) - regs[0x0a] = (y2 & 0x0ff); // Y-end (8 low bits) - - regs[0x0c] = W9966_SRAMID; // SRAM-banks (1x 128kb) - - // Enhancement layer - regs[0x0d] = (enh_s& 0x000ff); // Enh. start (0-7) - regs[0x0e] = (enh_s& 0x0ff00)>>8; // Enh. start (8-15) - regs[0x0f] = (enh_s& 0x70000)>>16; // Enh. start (16-17/18??) - regs[0x10] = (enh_e& 0x000ff); // Enh. end (0-7) - regs[0x11] = (enh_e& 0x0ff00)>>8; // Enh. end (8-15) - regs[0x12] = (enh_e& 0x70000)>>16; // Enh. end (16-17/18??) - - // Misc - regs[0x13] = 0x40; // VEE control (raw 4:2:2) - regs[0x17] = 0x00; // ??? - regs[0x18] = cam->i2c_state = 0x00; // Serial bus - regs[0x19] = 0xff; // I/O port direction control - regs[0x1a] = 0xff; // I/O port data register - regs[0x1b] = 0x10; // ??? - - // SAA7111 chip settings + enh_e = w * h * 2; + +/* Modify capture window if necessary and calculate downscaling */ + if (w9966_calcscale(w, W9966_WND_MIN_X, W9966_WND_MAX_X, &x1, &x2, &scale_x) != 0 || + w9966_calcscale(h, W9966_WND_MIN_Y, W9966_WND_MAX_Y, &y1, &y2, &scale_y) != 0) + return -1; + + DPRINTF("%dx%d, x: %d<->%d, y: %d<->%d, sx: %d/64, sy: %d/64.\n", + w, h, x1, x2, y1, y2, scale_x & ~0x80, scale_y & ~0x80); + +/* Setup registers */ + regs[0x00] = 0x00; /* Set normal operation */ + regs[0x01] = 0x18; /* Capture mode */ + regs[0x02] = scale_y; /* V-scaling */ + regs[0x03] = scale_x; /* H-scaling */ + + /* Capture window */ + regs[0x04] = (x1 & 0x0ff); /* X-start (8 low bits) */ + regs[0x05] = (x1 & 0x300)>>8; /* X-start (2 high bits) */ + regs[0x06] = (y1 & 0x0ff); /* Y-start (8 low bits) */ + regs[0x07] = (y1 & 0x300)>>8; /* Y-start (2 high bits) */ + regs[0x08] = (x2 & 0x0ff); /* X-end (8 low bits) */ + regs[0x09] = (x2 & 0x300)>>8; /* X-end (2 high bits) */ + regs[0x0a] = (y2 & 0x0ff); /* Y-end (8 low bits) */ + + regs[0x0c] = W9966_SRAMID; /* SRAM-banks (1x 128kb) */ + + /* Enhancement layer */ + regs[0x0d] = (enh_s & 0x000ff); /* Enh. start (0-7) */ + regs[0x0e] = (enh_s & 0x0ff00) >> 8; /* Enh. start (8-15) */ + regs[0x0f] = (enh_s & 0x70000) >> 16; /* Enh. start (16-17/18??) */ + regs[0x10] = (enh_e & 0x000ff); /* Enh. end (0-7) */ + regs[0x11] = (enh_e & 0x0ff00) >> 8; /* Enh. end (8-15) */ + regs[0x12] = (enh_e & 0x70000) >> 16; /* Enh. end (16-17/18??) */ + + /* Misc */ + regs[0x13] = 0x40; /* VEE control (raw 4:2:2) */ + regs[0x17] = 0x00; /* ??? */ + regs[0x18] = cam->i2c_state = 0x00; /* Serial bus */ + regs[0x19] = 0xff; /* I/O port direction control */ + regs[0x1a] = 0xff; /* I/O port data register */ + regs[0x1b] = 0x10; /* ??? */ + + /* SAA7111 chip settings */ saa7111_regs[0x0a] = cam->brightness; saa7111_regs[0x0b] = cam->contrast; saa7111_regs[0x0c] = cam->color; saa7111_regs[0x0d] = cam->hue; -// Reset (ECP-fifo & serial-bus) +/* Reset (ECP-fifo & serial-bus) */ if (w9966_wReg(cam, 0x00, 0x03) == -1) return -1; -// Write regs to w9966cf chip +/* Write regs to w9966cf chip */ for (i = 0; i < 0x1c; i++) if (w9966_wReg(cam, i, regs[i]) == -1) return -1; -// Write regs to saa7111 chip +/* Write regs to saa7111 chip */ for (i = 0; i < 0x20; i++) if (w9966_wReg_i2c(cam, i, saa7111_regs[i]) == -1) return -1; @@ -558,9 +554,9 @@ static int w9966_setup(struct w9966_dev* cam, int x1, int y1, int x2, int y2, in * Ugly and primitive i2c protocol functions */ -// Sets the data line on the i2c bus. -// Expects a claimed pdev. -static inline void w9966_i2c_setsda(struct w9966_dev* cam, int state) +/* Sets the data line on the i2c bus. + Expects a claimed pdev. */ +static inline void w9966_i2c_setsda(struct w9966_dev *cam, int state) { if (state) cam->i2c_state |= W9966_I2C_W_DATA; @@ -571,17 +567,17 @@ static inline void w9966_i2c_setsda(struct w9966_dev* cam, int state) udelay(5); } -// Get peripheral clock line -// Expects a claimed pdev. -static inline int w9966_i2c_getscl(struct w9966_dev* cam) +/* Get peripheral clock line + Expects a claimed pdev. */ +static inline int w9966_i2c_getscl(struct w9966_dev *cam) { const unsigned char state = w9966_rReg(cam, 0x18); return ((state & W9966_I2C_R_CLOCK) > 0); } -// Sets the clock line on the i2c bus. -// Expects a claimed pdev. -1 on error -static inline int w9966_i2c_setscl(struct w9966_dev* cam, int state) +/* Sets the clock line on the i2c bus. + Expects a claimed pdev. -1 on error */ +static inline int w9966_i2c_setscl(struct w9966_dev *cam, int state) { unsigned long timeout; @@ -593,7 +589,7 @@ static inline int w9966_i2c_setscl(struct w9966_dev* cam, int state) w9966_wReg(cam, 0x18, cam->i2c_state); udelay(5); - // we go to high, we also expect the peripheral to ack. + /* we go to high, we also expect the peripheral to ack. */ if (state) { timeout = jiffies + 100; while (!w9966_i2c_getscl(cam)) { @@ -604,21 +600,21 @@ static inline int w9966_i2c_setscl(struct w9966_dev* cam, int state) return 0; } -// Get peripheral data line -// Expects a claimed pdev. -static inline int w9966_i2c_getsda(struct w9966_dev* cam) +/* Get peripheral data line + Expects a claimed pdev. */ +static inline int w9966_i2c_getsda(struct w9966_dev *cam) { const unsigned char state = w9966_rReg(cam, 0x18); return ((state & W9966_I2C_R_DATA) > 0); } -// Write a byte with ack to the i2c bus. -// Expects a claimed pdev. -1 on error -static int w9966_i2c_wbyte(struct w9966_dev* cam, int data) +/* Write a byte with ack to the i2c bus. + Expects a claimed pdev. -1 on error */ +static int w9966_i2c_wbyte(struct w9966_dev *cam, int data) { int i; - for (i = 7; i >= 0; i--) - { + + for (i = 7; i >= 0; i--) { w9966_i2c_setsda(cam, (data >> i) & 0x01); if (w9966_i2c_setscl(cam, 1) == -1) @@ -635,18 +631,17 @@ static int w9966_i2c_wbyte(struct w9966_dev* cam, int data) return 0; } -// Read a data byte with ack from the i2c-bus -// Expects a claimed pdev. -1 on error +/* Read a data byte with ack from the i2c-bus + Expects a claimed pdev. -1 on error */ #if 0 -static int w9966_i2c_rbyte(struct w9966_dev* cam) +static int w9966_i2c_rbyte(struct w9966_dev *cam) { unsigned char data = 0x00; int i; w9966_i2c_setsda(cam, 1); - for (i = 0; i < 8; i++) - { + for (i = 0; i < 8; i++) { if (w9966_i2c_setscl(cam, 1) == -1) return -1; data = data << 1; @@ -659,20 +654,18 @@ static int w9966_i2c_rbyte(struct w9966_dev* cam) } #endif -// Read a register from the i2c device. -// Expects claimed pdev. -1 on error +/* Read a register from the i2c device. + Expects claimed pdev. -1 on error */ #if 0 -static int w9966_rReg_i2c(struct w9966_dev* cam, int reg) +static int w9966_rReg_i2c(struct w9966_dev *cam, int reg) { int data; w9966_i2c_setsda(cam, 0); w9966_i2c_setscl(cam, 0); - if ( - w9966_i2c_wbyte(cam, W9966_I2C_W_ID) == -1 || - w9966_i2c_wbyte(cam, reg) == -1 - ) + if (w9966_i2c_wbyte(cam, W9966_I2C_W_ID) == -1 || + w9966_i2c_wbyte(cam, reg) == -1) return -1; w9966_i2c_setsda(cam, 1); @@ -681,10 +674,10 @@ static int w9966_rReg_i2c(struct w9966_dev* cam, int reg) w9966_i2c_setsda(cam, 0); w9966_i2c_setscl(cam, 0); - if ( - w9966_i2c_wbyte(cam, W9966_I2C_R_ID) == -1 || - (data = w9966_i2c_rbyte(cam)) == -1 - ) + if (w9966_i2c_wbyte(cam, W9966_I2C_R_ID) == -1) + return -1; + data = w9966_i2c_rbyte(cam); + if (data == -1) return -1; w9966_i2c_setsda(cam, 0); @@ -697,18 +690,16 @@ static int w9966_rReg_i2c(struct w9966_dev* cam, int reg) } #endif -// Write a register to the i2c device. -// Expects claimed pdev. -1 on error -static int w9966_wReg_i2c(struct w9966_dev* cam, int reg, int data) +/* Write a register to the i2c device. + Expects claimed pdev. -1 on error */ +static int w9966_wReg_i2c(struct w9966_dev *cam, int reg, int data) { w9966_i2c_setsda(cam, 0); w9966_i2c_setscl(cam, 0); - if ( - w9966_i2c_wbyte(cam, W9966_I2C_W_ID) == -1 || - w9966_i2c_wbyte(cam, reg) == -1 || - w9966_i2c_wbyte(cam, data) == -1 - ) + if (w9966_i2c_wbyte(cam, W9966_I2C_W_ID) == -1 || + w9966_i2c_wbyte(cam, reg) == -1 || + w9966_i2c_wbyte(cam, data) == -1) return -1; w9966_i2c_setsda(cam, 0); @@ -728,8 +719,7 @@ static long w9966_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct w9966_dev *cam = video_drvdata(file); - switch(cmd) - { + switch (cmd) { case VIDIOCGCAP: { static struct video_capability vcap = { @@ -748,9 +738,9 @@ static long w9966_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg) case VIDIOCGCHAN: { struct video_channel *vch = arg; - if(vch->channel != 0) // We only support one channel (#0) + if (vch->channel != 0) /* We only support one channel (#0) */ return -EINVAL; - memset(vch,0,sizeof(*vch)); + memset(vch, 0, sizeof(*vch)); strcpy(vch->name, "CCD-input"); vch->type = VIDEO_TYPE_CAMERA; return 0; @@ -758,14 +748,14 @@ static long w9966_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg) case VIDIOCSCHAN: { struct video_channel *vch = arg; - if(vch->channel != 0) + if (vch->channel != 0) return -EINVAL; return 0; } case VIDIOCGTUNER: { struct video_tuner *vtune = arg; - if(vtune->tuner != 0) + if (vtune->tuner != 0) return -EINVAL; strcpy(vtune->name, "no tuner"); vtune->rangelow = 0; @@ -787,12 +777,12 @@ static long w9966_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg) case VIDIOCGPICT: { struct video_picture vpic = { - cam->brightness << 8, // brightness - (cam->hue + 128) << 8, // hue - cam->color << 9, // color - cam->contrast << 9, // contrast - 0x8000, // whiteness - 16, VIDEO_PALETTE_YUV422// bpp, palette format + cam->brightness << 8, /* brightness */ + (cam->hue + 128) << 8, /* hue */ + cam->color << 9, /* color */ + cam->contrast << 9, /* contrast */ + 0x8000, /* whiteness */ + 16, VIDEO_PALETTE_YUV422/* bpp, palette format */ }; struct video_picture *pic = arg; *pic = vpic; @@ -838,7 +828,7 @@ static long w9966_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg) if (vwin->height < 1 || vwin->height > W9966_WND_MAX_H) return -EINVAL; - // Update camera regs + /* Update camera regs */ w9966_pdev_claim(cam); ret = w9966_setup(cam, 0, 0, 1023, 1023, vwin->width, vwin->height); w9966_pdev_release(cam); @@ -858,7 +848,7 @@ static long w9966_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg) vwin->height = cam->height; return 0; } - // Unimplemented + /* Unimplemented */ case VIDIOCCAPTURE: case VIDIOCGFBUF: case VIDIOCSFBUF: @@ -880,31 +870,29 @@ static long w9966_v4l_ioctl(struct file *file, return video_usercopy(file, cmd, arg, w9966_v4l_do_ioctl); } -// Capture data +/* Capture data */ static ssize_t w9966_v4l_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { struct w9966_dev *cam = video_drvdata(file); - unsigned char addr = 0xa0; // ECP, read, CCD-transfer, 00000 + unsigned char addr = 0xa0; /* ECP, read, CCD-transfer, 00000 */ unsigned char __user *dest = (unsigned char __user *)buf; unsigned long dleft = count; unsigned char *tbuf; - // Why would anyone want more than this?? + /* Why would anyone want more than this?? */ if (count > cam->width * cam->height * 2) return -EINVAL; w9966_pdev_claim(cam); - w9966_wReg(cam, 0x00, 0x02); // Reset ECP-FIFO buffer - w9966_wReg(cam, 0x00, 0x00); // Return to normal operation - w9966_wReg(cam, 0x01, 0x98); // Enable capture - - // write special capture-addr and negotiate into data transfer - if ( - (parport_negotiate(cam->pport, cam->ppmode|IEEE1284_ADDR) != 0 )|| - (parport_write(cam->pport, &addr, 1) != 1 )|| - (parport_negotiate(cam->pport, cam->ppmode|IEEE1284_DATA) != 0 ) - ) { + w9966_wReg(cam, 0x00, 0x02); /* Reset ECP-FIFO buffer */ + w9966_wReg(cam, 0x00, 0x00); /* Return to normal operation */ + w9966_wReg(cam, 0x01, 0x98); /* Enable capture */ + + /* write special capture-addr and negotiate into data transfer */ + if ((parport_negotiate(cam->pport, cam->ppmode|IEEE1284_ADDR) != 0) || + (parport_write(cam->pport, &addr, 1) != 1) || + (parport_negotiate(cam->pport, cam->ppmode|IEEE1284_DATA) != 0)) { w9966_pdev_release(cam); return -EFAULT; } @@ -915,8 +903,7 @@ static ssize_t w9966_v4l_read(struct file *file, char __user *buf, goto out; } - while(dleft > 0) - { + while (dleft > 0) { unsigned long tsize = (dleft > W9966_RBUFFER) ? W9966_RBUFFER : dleft; if (parport_read(cam->pport, tbuf, tsize) < tsize) { @@ -931,7 +918,7 @@ static ssize_t w9966_v4l_read(struct file *file, char __user *buf, dleft -= tsize; } - w9966_wReg(cam, 0x01, 0x18); // Disable capture + w9966_wReg(cam, 0x01, 0x18); /* Disable capture */ out: kfree(tbuf); @@ -941,33 +928,30 @@ out: } -// Called once for every parport on init +/* Called once for every parport on init */ static void w9966_attach(struct parport *port) { int i; - for (i = 0; i < W9966_MAXCAMS; i++) - { - if (w9966_cams[i].dev_state != 0) // Cam is already assigned + for (i = 0; i < W9966_MAXCAMS; i++) { + if (w9966_cams[i].dev_state != 0) /* Cam is already assigned */ continue; - if ( - strcmp(pardev[i], "aggressive") == 0 || - strcmp(pardev[i], port->name) == 0 - ) { + if (strcmp(pardev[i], "aggressive") == 0 || strcmp(pardev[i], port->name) == 0) { if (w9966_init(&w9966_cams[i], port) != 0) - w9966_term(&w9966_cams[i]); - break; // return + w9966_term(&w9966_cams[i]); + break; /* return */ } } } -// Called once for every parport on termination +/* Called once for every parport on termination */ static void w9966_detach(struct parport *port) { int i; + for (i = 0; i < W9966_MAXCAMS; i++) - if (w9966_cams[i].dev_state != 0 && w9966_cams[i].pport == port) - w9966_term(&w9966_cams[i]); + if (w9966_cams[i].dev_state != 0 && w9966_cams[i].pport == port) + w9966_term(&w9966_cams[i]); } @@ -977,17 +961,18 @@ static struct parport_driver w9966_ppd = { .detach = w9966_detach, }; -// Module entry point +/* Module entry point */ static int __init w9966_mod_init(void) { int i; + for (i = 0; i < W9966_MAXCAMS; i++) w9966_cams[i].dev_state = 0; return parport_register_driver(&w9966_ppd); } -// Module cleanup +/* Module cleanup */ static void __exit w9966_mod_term(void) { parport_unregister_driver(&w9966_ppd); -- cgit v1.2.3-70-g09d2 From 467422678e9e73bff8d175024cdd89ed48483697 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 22 Mar 2010 05:09:07 -0300 Subject: V4L/DVB: pms: remove unnecessary exclusive open/close Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pms.c | 18 ------------------ 1 file changed, 18 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pms.c b/drivers/media/video/pms.c index 0598bbd3f36..7129b50757d 100644 --- a/drivers/media/video/pms.c +++ b/drivers/media/video/pms.c @@ -61,7 +61,6 @@ struct pms { int depth; int input; s32 brightness, saturation, hue, contrast; - unsigned long in_use; struct mutex lock; int i2c_count; struct i2c_info i2cinfo[64]; @@ -931,25 +930,8 @@ static ssize_t pms_read(struct file *file, char __user *buf, return len; } -static int pms_exclusive_open(struct file *file) -{ - struct pms *dev = video_drvdata(file); - - return test_and_set_bit(0, &dev->in_use) ? -EBUSY : 0; -} - -static int pms_exclusive_release(struct file *file) -{ - struct pms *dev = video_drvdata(file); - - clear_bit(0, &dev->in_use); - return 0; -} - static const struct v4l2_file_operations pms_fops = { .owner = THIS_MODULE, - .open = pms_exclusive_open, - .release = pms_exclusive_release, .ioctl = video_ioctl2, .read = pms_read, }; -- cgit v1.2.3-70-g09d2 From 271922c0cee0b086ca2fe9cec39d585a44a2358b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 22 Mar 2010 05:13:17 -0300 Subject: V4L/DVB: w9966: reorganize the order of functions Get rid of completely unnecessary function prototypes. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/w9966.c | 567 +++++++++++++++++++++----------------------- 1 file changed, 265 insertions(+), 302 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c index 25364b8f857..7d5be070041 100644 --- a/drivers/media/video/w9966.c +++ b/drivers/media/video/w9966.c @@ -144,76 +144,8 @@ MODULE_PARM_DESC(parmode, "parmode: transfer mode (0=auto, 1=ecp, 2=epp"); static int video_nr = -1; module_param(video_nr, int, 0); -/* - * Private data - */ - static struct w9966_dev w9966_cams[W9966_MAXCAMS]; -/* - * Private function declares - */ - -static inline void w9966_setState(struct w9966_dev *cam, int mask, int val); -static inline int w9966_getState(struct w9966_dev *cam, int mask, int val); -static inline void w9966_pdev_claim(struct w9966_dev *vdev); -static inline void w9966_pdev_release(struct w9966_dev *vdev); - -static int w9966_rReg(struct w9966_dev *cam, int reg); -static int w9966_wReg(struct w9966_dev *cam, int reg, int data); -#if 0 -static int w9966_rReg_i2c(struct w9966_dev *cam, int reg); -#endif -static int w9966_wReg_i2c(struct w9966_dev *cam, int reg, int data); -static int w9966_findlen(int near, int size, int maxlen); -static int w9966_calcscale(int size, int min, int max, int *beg, int *end, unsigned char *factor); -static int w9966_setup(struct w9966_dev *cam, int x1, int y1, int x2, int y2, int w, int h); - -static int w9966_init(struct w9966_dev *cam, struct parport* port); -static void w9966_term(struct w9966_dev *cam); - -static inline void w9966_i2c_setsda(struct w9966_dev *cam, int state); -static inline int w9966_i2c_setscl(struct w9966_dev *cam, int state); -static inline int w9966_i2c_getsda(struct w9966_dev *cam); -static inline int w9966_i2c_getscl(struct w9966_dev *cam); -static int w9966_i2c_wbyte(struct w9966_dev *cam, int data); -#if 0 -static int w9966_i2c_rbyte(struct w9966_dev *cam); -#endif - -static long w9966_v4l_ioctl(struct file *file, - unsigned int cmd, unsigned long arg); -static ssize_t w9966_v4l_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos); - -static int w9966_exclusive_open(struct file *file) -{ - struct w9966_dev *cam = video_drvdata(file); - - return test_and_set_bit(0, &cam->in_use) ? -EBUSY : 0; -} - -static int w9966_exclusive_release(struct file *file) -{ - struct w9966_dev *cam = video_drvdata(file); - - clear_bit(0, &cam->in_use); - return 0; -} - -static const struct v4l2_file_operations w9966_fops = { - .owner = THIS_MODULE, - .open = w9966_exclusive_open, - .release = w9966_exclusive_release, - .ioctl = w9966_v4l_ioctl, - .read = w9966_v4l_read, -}; -static struct video_device w9966_template = { - .name = W9966_DRIVERNAME, - .fops = &w9966_fops, - .release = video_device_release_empty, -}; - /* * Private function defines */ @@ -232,7 +164,7 @@ static inline int w9966_getState(struct w9966_dev *cam, int mask, int val) } /* Claim parport for ourself */ -static inline void w9966_pdev_claim(struct w9966_dev *cam) +static void w9966_pdev_claim(struct w9966_dev *cam) { if (w9966_getState(cam, W9966_STATE_CLAIMED, W9966_STATE_CLAIMED)) return; @@ -241,7 +173,7 @@ static inline void w9966_pdev_claim(struct w9966_dev *cam) } /* Release parport for others to use */ -static inline void w9966_pdev_release(struct w9966_dev *cam) +static void w9966_pdev_release(struct w9966_dev *cam) { if (w9966_getState(cam, W9966_STATE_CLAIMED, 0)) return; @@ -291,97 +223,168 @@ static int w9966_wReg(struct w9966_dev *cam, int reg, int data) return 0; } -/* Initialize camera device. Setup all internal flags, set a - default video mode, setup ccd-chip, register v4l device etc.. - Also used for 'probing' of hardware. - -1 on error */ -static int w9966_init(struct w9966_dev *cam, struct parport* port) +/* + * Ugly and primitive i2c protocol functions + */ + +/* Sets the data line on the i2c bus. + Expects a claimed pdev. */ +static void w9966_i2c_setsda(struct w9966_dev *cam, int state) { - if (cam->dev_state != 0) - return -1; + if (state) + cam->i2c_state |= W9966_I2C_W_DATA; + else + cam->i2c_state &= ~W9966_I2C_W_DATA; - cam->pport = port; - cam->brightness = 128; - cam->contrast = 64; - cam->color = 64; - cam->hue = 0; + w9966_wReg(cam, 0x18, cam->i2c_state); + udelay(5); +} -/* Select requested transfer mode */ - switch (parmode) { - default: /* Auto-detect (priority: hw-ecp, hw-epp, sw-ecp) */ - case 0: - if (port->modes & PARPORT_MODE_ECP) - cam->ppmode = IEEE1284_MODE_ECP; - else if (port->modes & PARPORT_MODE_EPP) - cam->ppmode = IEEE1284_MODE_EPP; - else - cam->ppmode = IEEE1284_MODE_ECP; - break; - case 1: /* hw- or sw-ecp */ - cam->ppmode = IEEE1284_MODE_ECP; - break; - case 2: /* hw- or sw-epp */ - cam->ppmode = IEEE1284_MODE_EPP; - break; +/* Get peripheral clock line + Expects a claimed pdev. */ +static int w9966_i2c_getscl(struct w9966_dev *cam) +{ + const unsigned char state = w9966_rReg(cam, 0x18); + return ((state & W9966_I2C_R_CLOCK) > 0); +} + +/* Sets the clock line on the i2c bus. + Expects a claimed pdev. -1 on error */ +static int w9966_i2c_setscl(struct w9966_dev *cam, int state) +{ + unsigned long timeout; + + if (state) + cam->i2c_state |= W9966_I2C_W_CLOCK; + else + cam->i2c_state &= ~W9966_I2C_W_CLOCK; + + w9966_wReg(cam, 0x18, cam->i2c_state); + udelay(5); + + /* we go to high, we also expect the peripheral to ack. */ + if (state) { + timeout = jiffies + 100; + while (!w9966_i2c_getscl(cam)) { + if (time_after(jiffies, timeout)) + return -1; + } } + return 0; +} -/* Tell the parport driver that we exists */ - cam->pdev = parport_register_device(port, "w9966", NULL, NULL, NULL, 0, NULL); - if (cam->pdev == NULL) { - DPRINTF("parport_register_device() failed\n"); - return -1; +#if 0 +/* Get peripheral data line + Expects a claimed pdev. */ +static int w9966_i2c_getsda(struct w9966_dev *cam) +{ + const unsigned char state = w9966_rReg(cam, 0x18); + return ((state & W9966_I2C_R_DATA) > 0); +} +#endif + +/* Write a byte with ack to the i2c bus. + Expects a claimed pdev. -1 on error */ +static int w9966_i2c_wbyte(struct w9966_dev *cam, int data) +{ + int i; + + for (i = 7; i >= 0; i--) { + w9966_i2c_setsda(cam, (data >> i) & 0x01); + + if (w9966_i2c_setscl(cam, 1) == -1) + return -1; + w9966_i2c_setscl(cam, 0); } - w9966_setState(cam, W9966_STATE_PDEV, W9966_STATE_PDEV); - w9966_pdev_claim(cam); + w9966_i2c_setsda(cam, 1); -/* Setup a default capture mode */ - if (w9966_setup(cam, 0, 0, 1023, 1023, 200, 160) != 0) { - DPRINTF("w9966_setup() failed.\n"); + if (w9966_i2c_setscl(cam, 1) == -1) return -1; + w9966_i2c_setscl(cam, 0); + + return 0; +} + +/* Read a data byte with ack from the i2c-bus + Expects a claimed pdev. -1 on error */ +#if 0 +static int w9966_i2c_rbyte(struct w9966_dev *cam) +{ + unsigned char data = 0x00; + int i; + + w9966_i2c_setsda(cam, 1); + + for (i = 0; i < 8; i++) { + if (w9966_i2c_setscl(cam, 1) == -1) + return -1; + data = data << 1; + if (w9966_i2c_getsda(cam)) + data |= 0x01; + + w9966_i2c_setscl(cam, 0); } + return data; +} +#endif - w9966_pdev_release(cam); +/* Read a register from the i2c device. + Expects claimed pdev. -1 on error */ +#if 0 +static int w9966_rReg_i2c(struct w9966_dev *cam, int reg) +{ + int data; -/* Fill in the video_device struct and register us to v4l */ - memcpy(&cam->vdev, &w9966_template, sizeof(struct video_device)); - video_set_drvdata(&cam->vdev, cam); + w9966_i2c_setsda(cam, 0); + w9966_i2c_setscl(cam, 0); - if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) + if (w9966_i2c_wbyte(cam, W9966_I2C_W_ID) == -1 || + w9966_i2c_wbyte(cam, reg) == -1) return -1; - w9966_setState(cam, W9966_STATE_VDEV, W9966_STATE_VDEV); + w9966_i2c_setsda(cam, 1); + if (w9966_i2c_setscl(cam, 1) == -1) + return -1; + w9966_i2c_setsda(cam, 0); + w9966_i2c_setscl(cam, 0); - /* All ok */ - printk(KERN_INFO "w9966cf: Found and initialized a webcam on %s.\n", - cam->pport->name); - return 0; -} + if (w9966_i2c_wbyte(cam, W9966_I2C_R_ID) == -1) + return -1; + data = w9966_i2c_rbyte(cam); + if (data == -1) + return -1; + w9966_i2c_setsda(cam, 0); -/* Terminate everything gracefully */ -static void w9966_term(struct w9966_dev *cam) + if (w9966_i2c_setscl(cam, 1) == -1) + return -1; + w9966_i2c_setsda(cam, 1); + + return data; +} +#endif + +/* Write a register to the i2c device. + Expects claimed pdev. -1 on error */ +static int w9966_wReg_i2c(struct w9966_dev *cam, int reg, int data) { -/* Unregister from v4l */ - if (w9966_getState(cam, W9966_STATE_VDEV, W9966_STATE_VDEV)) { - video_unregister_device(&cam->vdev); - w9966_setState(cam, W9966_STATE_VDEV, 0); - } + w9966_i2c_setsda(cam, 0); + w9966_i2c_setscl(cam, 0); -/* Terminate from IEEE1284 mode and release pdev block */ - if (w9966_getState(cam, W9966_STATE_PDEV, W9966_STATE_PDEV)) { - w9966_pdev_claim(cam); - parport_negotiate(cam->pport, IEEE1284_MODE_COMPAT); - w9966_pdev_release(cam); - } + if (w9966_i2c_wbyte(cam, W9966_I2C_W_ID) == -1 || + w9966_i2c_wbyte(cam, reg) == -1 || + w9966_i2c_wbyte(cam, data) == -1) + return -1; -/* Unregister from parport */ - if (w9966_getState(cam, W9966_STATE_PDEV, W9966_STATE_PDEV)) { - parport_unregister_device(cam->pdev); - w9966_setState(cam, W9966_STATE_PDEV, 0); - } -} + w9966_i2c_setsda(cam, 0); + if (w9966_i2c_setscl(cam, 1) == -1) + return -1; + + w9966_i2c_setsda(cam, 1); + return 0; +} /* Find a good length for capture window (used both for W and H) A bit ugly but pretty functional. The capture length @@ -551,171 +554,10 @@ static int w9966_setup(struct w9966_dev *cam, int x1, int y1, int x2, int y2, in } /* - * Ugly and primitive i2c protocol functions + * Video4linux interfacing */ -/* Sets the data line on the i2c bus. - Expects a claimed pdev. */ -static inline void w9966_i2c_setsda(struct w9966_dev *cam, int state) -{ - if (state) - cam->i2c_state |= W9966_I2C_W_DATA; - else - cam->i2c_state &= ~W9966_I2C_W_DATA; - - w9966_wReg(cam, 0x18, cam->i2c_state); - udelay(5); -} - -/* Get peripheral clock line - Expects a claimed pdev. */ -static inline int w9966_i2c_getscl(struct w9966_dev *cam) -{ - const unsigned char state = w9966_rReg(cam, 0x18); - return ((state & W9966_I2C_R_CLOCK) > 0); -} - -/* Sets the clock line on the i2c bus. - Expects a claimed pdev. -1 on error */ -static inline int w9966_i2c_setscl(struct w9966_dev *cam, int state) -{ - unsigned long timeout; - - if (state) - cam->i2c_state |= W9966_I2C_W_CLOCK; - else - cam->i2c_state &= ~W9966_I2C_W_CLOCK; - - w9966_wReg(cam, 0x18, cam->i2c_state); - udelay(5); - - /* we go to high, we also expect the peripheral to ack. */ - if (state) { - timeout = jiffies + 100; - while (!w9966_i2c_getscl(cam)) { - if (time_after(jiffies, timeout)) - return -1; - } - } - return 0; -} - -/* Get peripheral data line - Expects a claimed pdev. */ -static inline int w9966_i2c_getsda(struct w9966_dev *cam) -{ - const unsigned char state = w9966_rReg(cam, 0x18); - return ((state & W9966_I2C_R_DATA) > 0); -} - -/* Write a byte with ack to the i2c bus. - Expects a claimed pdev. -1 on error */ -static int w9966_i2c_wbyte(struct w9966_dev *cam, int data) -{ - int i; - - for (i = 7; i >= 0; i--) { - w9966_i2c_setsda(cam, (data >> i) & 0x01); - - if (w9966_i2c_setscl(cam, 1) == -1) - return -1; - w9966_i2c_setscl(cam, 0); - } - - w9966_i2c_setsda(cam, 1); - - if (w9966_i2c_setscl(cam, 1) == -1) - return -1; - w9966_i2c_setscl(cam, 0); - - return 0; -} - -/* Read a data byte with ack from the i2c-bus - Expects a claimed pdev. -1 on error */ -#if 0 -static int w9966_i2c_rbyte(struct w9966_dev *cam) -{ - unsigned char data = 0x00; - int i; - - w9966_i2c_setsda(cam, 1); - - for (i = 0; i < 8; i++) { - if (w9966_i2c_setscl(cam, 1) == -1) - return -1; - data = data << 1; - if (w9966_i2c_getsda(cam)) - data |= 0x01; - - w9966_i2c_setscl(cam, 0); - } - return data; -} -#endif - -/* Read a register from the i2c device. - Expects claimed pdev. -1 on error */ -#if 0 -static int w9966_rReg_i2c(struct w9966_dev *cam, int reg) -{ - int data; - - w9966_i2c_setsda(cam, 0); - w9966_i2c_setscl(cam, 0); - - if (w9966_i2c_wbyte(cam, W9966_I2C_W_ID) == -1 || - w9966_i2c_wbyte(cam, reg) == -1) - return -1; - - w9966_i2c_setsda(cam, 1); - if (w9966_i2c_setscl(cam, 1) == -1) - return -1; - w9966_i2c_setsda(cam, 0); - w9966_i2c_setscl(cam, 0); - - if (w9966_i2c_wbyte(cam, W9966_I2C_R_ID) == -1) - return -1; - data = w9966_i2c_rbyte(cam); - if (data == -1) - return -1; - - w9966_i2c_setsda(cam, 0); - - if (w9966_i2c_setscl(cam, 1) == -1) - return -1; - w9966_i2c_setsda(cam, 1); - - return data; -} -#endif - -/* Write a register to the i2c device. - Expects claimed pdev. -1 on error */ -static int w9966_wReg_i2c(struct w9966_dev *cam, int reg, int data) -{ - w9966_i2c_setsda(cam, 0); - w9966_i2c_setscl(cam, 0); - - if (w9966_i2c_wbyte(cam, W9966_I2C_W_ID) == -1 || - w9966_i2c_wbyte(cam, reg) == -1 || - w9966_i2c_wbyte(cam, data) == -1) - return -1; - - w9966_i2c_setsda(cam, 0); - if (w9966_i2c_setscl(cam, 1) == -1) - return -1; - - w9966_i2c_setsda(cam, 1); - - return 0; -} - -/* - * Video4linux interfacing - */ - -static long w9966_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg) +static long w9966_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct w9966_dev *cam = video_drvdata(file); @@ -927,6 +769,127 @@ out: return count; } +static int w9966_exclusive_open(struct file *file) +{ + struct w9966_dev *cam = video_drvdata(file); + + return test_and_set_bit(0, &cam->in_use) ? -EBUSY : 0; +} + +static int w9966_exclusive_release(struct file *file) +{ + struct w9966_dev *cam = video_drvdata(file); + + clear_bit(0, &cam->in_use); + return 0; +} + +static const struct v4l2_file_operations w9966_fops = { + .owner = THIS_MODULE, + .open = w9966_exclusive_open, + .release = w9966_exclusive_release, + .ioctl = w9966_v4l_ioctl, + .read = w9966_v4l_read, +}; + +static struct video_device w9966_template = { + .name = W9966_DRIVERNAME, + .fops = &w9966_fops, + .release = video_device_release_empty, +}; + + +/* Initialize camera device. Setup all internal flags, set a + default video mode, setup ccd-chip, register v4l device etc.. + Also used for 'probing' of hardware. + -1 on error */ +static int w9966_init(struct w9966_dev *cam, struct parport* port) +{ + if (cam->dev_state != 0) + return -1; + + cam->pport = port; + cam->brightness = 128; + cam->contrast = 64; + cam->color = 64; + cam->hue = 0; + +/* Select requested transfer mode */ + switch (parmode) { + default: /* Auto-detect (priority: hw-ecp, hw-epp, sw-ecp) */ + case 0: + if (port->modes & PARPORT_MODE_ECP) + cam->ppmode = IEEE1284_MODE_ECP; + else if (port->modes & PARPORT_MODE_EPP) + cam->ppmode = IEEE1284_MODE_EPP; + else + cam->ppmode = IEEE1284_MODE_ECP; + break; + case 1: /* hw- or sw-ecp */ + cam->ppmode = IEEE1284_MODE_ECP; + break; + case 2: /* hw- or sw-epp */ + cam->ppmode = IEEE1284_MODE_EPP; + break; + } + +/* Tell the parport driver that we exists */ + cam->pdev = parport_register_device(port, "w9966", NULL, NULL, NULL, 0, NULL); + if (cam->pdev == NULL) { + DPRINTF("parport_register_device() failed\n"); + return -1; + } + w9966_setState(cam, W9966_STATE_PDEV, W9966_STATE_PDEV); + + w9966_pdev_claim(cam); + +/* Setup a default capture mode */ + if (w9966_setup(cam, 0, 0, 1023, 1023, 200, 160) != 0) { + DPRINTF("w9966_setup() failed.\n"); + return -1; + } + + w9966_pdev_release(cam); + +/* Fill in the video_device struct and register us to v4l */ + memcpy(&cam->vdev, &w9966_template, sizeof(struct video_device)); + video_set_drvdata(&cam->vdev, cam); + + if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) + return -1; + + w9966_setState(cam, W9966_STATE_VDEV, W9966_STATE_VDEV); + + /* All ok */ + printk(KERN_INFO "w9966cf: Found and initialized a webcam on %s.\n", + cam->pport->name); + return 0; +} + + +/* Terminate everything gracefully */ +static void w9966_term(struct w9966_dev *cam) +{ +/* Unregister from v4l */ + if (w9966_getState(cam, W9966_STATE_VDEV, W9966_STATE_VDEV)) { + video_unregister_device(&cam->vdev); + w9966_setState(cam, W9966_STATE_VDEV, 0); + } + +/* Terminate from IEEE1284 mode and release pdev block */ + if (w9966_getState(cam, W9966_STATE_PDEV, W9966_STATE_PDEV)) { + w9966_pdev_claim(cam); + parport_negotiate(cam->pport, IEEE1284_MODE_COMPAT); + w9966_pdev_release(cam); + } + +/* Unregister from parport */ + if (w9966_getState(cam, W9966_STATE_PDEV, W9966_STATE_PDEV)) { + parport_unregister_device(cam->pdev); + w9966_setState(cam, W9966_STATE_PDEV, 0); + } +} + /* Called once for every parport on init */ static void w9966_attach(struct parport *port) -- cgit v1.2.3-70-g09d2 From c1f2b0f29e51cf44eb6addff1b90f99988055a92 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 22 Mar 2010 05:15:14 -0300 Subject: V4L/DVB: w9966: remove camelCase Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/w9966.c | 336 ++++++++++++++++++++++---------------------- 1 file changed, 168 insertions(+), 168 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c index 7d5be070041..b0719976845 100644 --- a/drivers/media/video/w9966.c +++ b/drivers/media/video/w9966.c @@ -133,9 +133,9 @@ static const char *pardev[] = {[0 ... W9966_MAXCAMS] = "aggressive"}; #endif module_param_array(pardev, charp, NULL, 0); MODULE_PARM_DESC(pardev, "pardev: where to search for\n" - "\teach camera. 'aggressive' means brute-force search.\n" - "\tEg: >pardev=parport3,aggressive,parport2,parport1< would assign\n" - "\tcam 1 to parport3 and search every parport for cam 2 etc..."); + "\teach camera. 'aggressive' means brute-force search.\n" + "\tEg: >pardev=parport3,aggressive,parport2,parport1< would assign\n" + "\tcam 1 to parport3 and search every parport for cam 2 etc..."); static int parmode; module_param(parmode, int, 0); @@ -152,13 +152,13 @@ static struct w9966_dev w9966_cams[W9966_MAXCAMS]; /* Set camera phase flags, so we know what to uninit when terminating */ -static inline void w9966_setState(struct w9966_dev *cam, int mask, int val) +static inline void w9966_set_state(struct w9966_dev *cam, int mask, int val) { cam->dev_state = (cam->dev_state & ~mask) ^ val; } /* Get camera phase flags */ -static inline int w9966_getState(struct w9966_dev *cam, int mask, int val) +static inline int w9966_get_state(struct w9966_dev *cam, int mask, int val) { return ((cam->dev_state & mask) == val); } @@ -166,25 +166,25 @@ static inline int w9966_getState(struct w9966_dev *cam, int mask, int val) /* Claim parport for ourself */ static void w9966_pdev_claim(struct w9966_dev *cam) { - if (w9966_getState(cam, W9966_STATE_CLAIMED, W9966_STATE_CLAIMED)) + if (w9966_get_state(cam, W9966_STATE_CLAIMED, W9966_STATE_CLAIMED)) return; parport_claim_or_block(cam->pdev); - w9966_setState(cam, W9966_STATE_CLAIMED, W9966_STATE_CLAIMED); + w9966_set_state(cam, W9966_STATE_CLAIMED, W9966_STATE_CLAIMED); } /* Release parport for others to use */ static void w9966_pdev_release(struct w9966_dev *cam) { - if (w9966_getState(cam, W9966_STATE_CLAIMED, 0)) + if (w9966_get_state(cam, W9966_STATE_CLAIMED, 0)) return; parport_release(cam->pdev); - w9966_setState(cam, W9966_STATE_CLAIMED, 0); + w9966_set_state(cam, W9966_STATE_CLAIMED, 0); } /* Read register from W9966 interface-chip Expects a claimed pdev -1 on error, else register data (byte) */ -static int w9966_rReg(struct w9966_dev *cam, int reg) +static int w9966_read_reg(struct w9966_dev *cam, int reg) { /* ECP, read, regtransfer, REG, REG, REG, REG, REG */ const unsigned char addr = 0x80 | (reg & 0x1f); @@ -205,7 +205,7 @@ static int w9966_rReg(struct w9966_dev *cam, int reg) /* Write register to W9966 interface-chip Expects a claimed pdev -1 on error */ -static int w9966_wReg(struct w9966_dev *cam, int reg, int data) +static int w9966_write_reg(struct w9966_dev *cam, int reg, int data) { /* ECP, write, regtransfer, REG, REG, REG, REG, REG */ const unsigned char addr = 0xc0 | (reg & 0x1f); @@ -236,7 +236,7 @@ static void w9966_i2c_setsda(struct w9966_dev *cam, int state) else cam->i2c_state &= ~W9966_I2C_W_DATA; - w9966_wReg(cam, 0x18, cam->i2c_state); + w9966_write_reg(cam, 0x18, cam->i2c_state); udelay(5); } @@ -244,7 +244,7 @@ static void w9966_i2c_setsda(struct w9966_dev *cam, int state) Expects a claimed pdev. */ static int w9966_i2c_getscl(struct w9966_dev *cam) { - const unsigned char state = w9966_rReg(cam, 0x18); + const unsigned char state = w9966_read_reg(cam, 0x18); return ((state & W9966_I2C_R_CLOCK) > 0); } @@ -259,7 +259,7 @@ static int w9966_i2c_setscl(struct w9966_dev *cam, int state) else cam->i2c_state &= ~W9966_I2C_W_CLOCK; - w9966_wReg(cam, 0x18, cam->i2c_state); + w9966_write_reg(cam, 0x18, cam->i2c_state); udelay(5); /* we go to high, we also expect the peripheral to ack. */ @@ -278,7 +278,7 @@ static int w9966_i2c_setscl(struct w9966_dev *cam, int state) Expects a claimed pdev. */ static int w9966_i2c_getsda(struct w9966_dev *cam) { - const unsigned char state = w9966_rReg(cam, 0x18); + const unsigned char state = w9966_read_reg(cam, 0x18); return ((state & W9966_I2C_R_DATA) > 0); } #endif @@ -332,7 +332,7 @@ static int w9966_i2c_rbyte(struct w9966_dev *cam) /* Read a register from the i2c device. Expects claimed pdev. -1 on error */ #if 0 -static int w9966_rReg_i2c(struct w9966_dev *cam, int reg) +static int w9966_read_reg_i2c(struct w9966_dev *cam, int reg) { int data; @@ -367,14 +367,14 @@ static int w9966_rReg_i2c(struct w9966_dev *cam, int reg) /* Write a register to the i2c device. Expects claimed pdev. -1 on error */ -static int w9966_wReg_i2c(struct w9966_dev *cam, int reg, int data) +static int w9966_write_reg_i2c(struct w9966_dev *cam, int reg, int data) { w9966_i2c_setsda(cam, 0); w9966_i2c_setscl(cam, 0); if (w9966_i2c_wbyte(cam, W9966_I2C_W_ID) == -1 || - w9966_i2c_wbyte(cam, reg) == -1 || - w9966_i2c_wbyte(cam, data) == -1) + w9966_i2c_wbyte(cam, reg) == -1 || + w9966_i2c_wbyte(cam, data) == -1) return -1; w9966_i2c_setsda(cam, 0); @@ -489,15 +489,15 @@ static int w9966_setup(struct w9966_dev *cam, int x1, int y1, int x2, int y2, in enh_s = 0; enh_e = w * h * 2; -/* Modify capture window if necessary and calculate downscaling */ + /* Modify capture window if necessary and calculate downscaling */ if (w9966_calcscale(w, W9966_WND_MIN_X, W9966_WND_MAX_X, &x1, &x2, &scale_x) != 0 || - w9966_calcscale(h, W9966_WND_MIN_Y, W9966_WND_MAX_Y, &y1, &y2, &scale_y) != 0) + w9966_calcscale(h, W9966_WND_MIN_Y, W9966_WND_MAX_Y, &y1, &y2, &scale_y) != 0) return -1; DPRINTF("%dx%d, x: %d<->%d, y: %d<->%d, sx: %d/64, sy: %d/64.\n", - w, h, x1, x2, y1, y2, scale_x & ~0x80, scale_y & ~0x80); + w, h, x1, x2, y1, y2, scale_x & ~0x80, scale_y & ~0x80); -/* Setup registers */ + /* Setup registers */ regs[0x00] = 0x00; /* Set normal operation */ regs[0x01] = 0x18; /* Capture mode */ regs[0x02] = scale_y; /* V-scaling */ @@ -536,18 +536,18 @@ static int w9966_setup(struct w9966_dev *cam, int x1, int y1, int x2, int y2, in saa7111_regs[0x0c] = cam->color; saa7111_regs[0x0d] = cam->hue; -/* Reset (ECP-fifo & serial-bus) */ - if (w9966_wReg(cam, 0x00, 0x03) == -1) + /* Reset (ECP-fifo & serial-bus) */ + if (w9966_write_reg(cam, 0x00, 0x03) == -1) return -1; -/* Write regs to w9966cf chip */ + /* Write regs to w9966cf chip */ for (i = 0; i < 0x1c; i++) - if (w9966_wReg(cam, i, regs[i]) == -1) + if (w9966_write_reg(cam, i, regs[i]) == -1) return -1; -/* Write regs to saa7111 chip */ + /* Write regs to saa7111 chip */ for (i = 0; i < 0x20; i++) - if (w9966_wReg_i2c(cam, i, saa7111_regs[i]) == -1) + if (w9966_write_reg_i2c(cam, i, saa7111_regs[i]) == -1) return -1; return 0; @@ -563,134 +563,134 @@ static long w9966_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg) switch (cmd) { case VIDIOCGCAP: - { - static struct video_capability vcap = { - .name = W9966_DRIVERNAME, - .type = VID_TYPE_CAPTURE | VID_TYPE_SCALES, - .channels = 1, - .maxwidth = W9966_WND_MAX_W, - .maxheight = W9966_WND_MAX_H, - .minwidth = 2, - .minheight = 1, - }; - struct video_capability *cap = arg; - *cap = vcap; - return 0; - } + { + static struct video_capability vcap = { + .name = W9966_DRIVERNAME, + .type = VID_TYPE_CAPTURE | VID_TYPE_SCALES, + .channels = 1, + .maxwidth = W9966_WND_MAX_W, + .maxheight = W9966_WND_MAX_H, + .minwidth = 2, + .minheight = 1, + }; + struct video_capability *cap = arg; + *cap = vcap; + return 0; + } case VIDIOCGCHAN: - { - struct video_channel *vch = arg; - if (vch->channel != 0) /* We only support one channel (#0) */ - return -EINVAL; - memset(vch, 0, sizeof(*vch)); - strcpy(vch->name, "CCD-input"); - vch->type = VIDEO_TYPE_CAMERA; - return 0; - } + { + struct video_channel *vch = arg; + if (vch->channel != 0) /* We only support one channel (#0) */ + return -EINVAL; + memset(vch, 0, sizeof(*vch)); + strcpy(vch->name, "CCD-input"); + vch->type = VIDEO_TYPE_CAMERA; + return 0; + } case VIDIOCSCHAN: - { - struct video_channel *vch = arg; - if (vch->channel != 0) - return -EINVAL; - return 0; - } + { + struct video_channel *vch = arg; + if (vch->channel != 0) + return -EINVAL; + return 0; + } case VIDIOCGTUNER: - { - struct video_tuner *vtune = arg; - if (vtune->tuner != 0) - return -EINVAL; - strcpy(vtune->name, "no tuner"); - vtune->rangelow = 0; - vtune->rangehigh = 0; - vtune->flags = VIDEO_TUNER_NORM; - vtune->mode = VIDEO_MODE_AUTO; - vtune->signal = 0xffff; - return 0; - } + { + struct video_tuner *vtune = arg; + if (vtune->tuner != 0) + return -EINVAL; + strcpy(vtune->name, "no tuner"); + vtune->rangelow = 0; + vtune->rangehigh = 0; + vtune->flags = VIDEO_TUNER_NORM; + vtune->mode = VIDEO_MODE_AUTO; + vtune->signal = 0xffff; + return 0; + } case VIDIOCSTUNER: - { - struct video_tuner *vtune = arg; - if (vtune->tuner != 0) - return -EINVAL; - if (vtune->mode != VIDEO_MODE_AUTO) - return -EINVAL; - return 0; - } + { + struct video_tuner *vtune = arg; + if (vtune->tuner != 0) + return -EINVAL; + if (vtune->mode != VIDEO_MODE_AUTO) + return -EINVAL; + return 0; + } case VIDIOCGPICT: - { - struct video_picture vpic = { - cam->brightness << 8, /* brightness */ - (cam->hue + 128) << 8, /* hue */ - cam->color << 9, /* color */ - cam->contrast << 9, /* contrast */ - 0x8000, /* whiteness */ - 16, VIDEO_PALETTE_YUV422/* bpp, palette format */ - }; - struct video_picture *pic = arg; - *pic = vpic; - return 0; - } + { + struct video_picture vpic = { + cam->brightness << 8, /* brightness */ + (cam->hue + 128) << 8, /* hue */ + cam->color << 9, /* color */ + cam->contrast << 9, /* contrast */ + 0x8000, /* whiteness */ + 16, VIDEO_PALETTE_YUV422/* bpp, palette format */ + }; + struct video_picture *pic = arg; + *pic = vpic; + return 0; + } case VIDIOCSPICT: - { - struct video_picture *vpic = arg; - if (vpic->depth != 16 || (vpic->palette != VIDEO_PALETTE_YUV422 && vpic->palette != VIDEO_PALETTE_YUYV)) - return -EINVAL; - - cam->brightness = vpic->brightness >> 8; - cam->hue = (vpic->hue >> 8) - 128; - cam->color = vpic->colour >> 9; - cam->contrast = vpic->contrast >> 9; + { + struct video_picture *vpic = arg; + if (vpic->depth != 16 || (vpic->palette != VIDEO_PALETTE_YUV422 && vpic->palette != VIDEO_PALETTE_YUYV)) + return -EINVAL; + + cam->brightness = vpic->brightness >> 8; + cam->hue = (vpic->hue >> 8) - 128; + cam->color = vpic->colour >> 9; + cam->contrast = vpic->contrast >> 9; + + w9966_pdev_claim(cam); + + if ( + w9966_write_reg_i2c(cam, 0x0a, cam->brightness) == -1 || + w9966_write_reg_i2c(cam, 0x0b, cam->contrast) == -1 || + w9966_write_reg_i2c(cam, 0x0c, cam->color) == -1 || + w9966_write_reg_i2c(cam, 0x0d, cam->hue) == -1 + ) { + w9966_pdev_release(cam); + return -EIO; + } - w9966_pdev_claim(cam); - - if ( - w9966_wReg_i2c(cam, 0x0a, cam->brightness) == -1 || - w9966_wReg_i2c(cam, 0x0b, cam->contrast) == -1 || - w9966_wReg_i2c(cam, 0x0c, cam->color) == -1 || - w9966_wReg_i2c(cam, 0x0d, cam->hue) == -1 - ) { w9966_pdev_release(cam); - return -EIO; + return 0; } - - w9966_pdev_release(cam); - return 0; - } case VIDIOCSWIN: - { - int ret; - struct video_window *vwin = arg; - - if (vwin->flags != 0) - return -EINVAL; - if (vwin->clipcount != 0) - return -EINVAL; - if (vwin->width < 2 || vwin->width > W9966_WND_MAX_W) - return -EINVAL; - if (vwin->height < 1 || vwin->height > W9966_WND_MAX_H) - return -EINVAL; - - /* Update camera regs */ - w9966_pdev_claim(cam); - ret = w9966_setup(cam, 0, 0, 1023, 1023, vwin->width, vwin->height); - w9966_pdev_release(cam); + { + int ret; + struct video_window *vwin = arg; + + if (vwin->flags != 0) + return -EINVAL; + if (vwin->clipcount != 0) + return -EINVAL; + if (vwin->width < 2 || vwin->width > W9966_WND_MAX_W) + return -EINVAL; + if (vwin->height < 1 || vwin->height > W9966_WND_MAX_H) + return -EINVAL; + + /* Update camera regs */ + w9966_pdev_claim(cam); + ret = w9966_setup(cam, 0, 0, 1023, 1023, vwin->width, vwin->height); + w9966_pdev_release(cam); - if (ret != 0) { - DPRINTF("VIDIOCSWIN: w9966_setup() failed.\n"); - return -EIO; - } + if (ret != 0) { + DPRINTF("VIDIOCSWIN: w9966_setup() failed.\n"); + return -EIO; + } - return 0; - } + return 0; + } case VIDIOCGWIN: - { - struct video_window *vwin = arg; - memset(vwin, 0, sizeof(*vwin)); - vwin->width = cam->width; - vwin->height = cam->height; - return 0; - } - /* Unimplemented */ + { + struct video_window *vwin = arg; + memset(vwin, 0, sizeof(*vwin)); + vwin->width = cam->width; + vwin->height = cam->height; + return 0; + } + /* Unimplemented */ case VIDIOCCAPTURE: case VIDIOCGFBUF: case VIDIOCSFBUF: @@ -707,14 +707,14 @@ static long w9966_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg) } static long w9966_v4l_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) + unsigned int cmd, unsigned long arg) { return video_usercopy(file, cmd, arg, w9966_v4l_do_ioctl); } /* Capture data */ static ssize_t w9966_v4l_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) + size_t count, loff_t *ppos) { struct w9966_dev *cam = video_drvdata(file); unsigned char addr = 0xa0; /* ECP, read, CCD-transfer, 00000 */ @@ -727,14 +727,14 @@ static ssize_t w9966_v4l_read(struct file *file, char __user *buf, return -EINVAL; w9966_pdev_claim(cam); - w9966_wReg(cam, 0x00, 0x02); /* Reset ECP-FIFO buffer */ - w9966_wReg(cam, 0x00, 0x00); /* Return to normal operation */ - w9966_wReg(cam, 0x01, 0x98); /* Enable capture */ + w9966_write_reg(cam, 0x00, 0x02); /* Reset ECP-FIFO buffer */ + w9966_write_reg(cam, 0x00, 0x00); /* Return to normal operation */ + w9966_write_reg(cam, 0x01, 0x98); /* Enable capture */ /* write special capture-addr and negotiate into data transfer */ if ((parport_negotiate(cam->pport, cam->ppmode|IEEE1284_ADDR) != 0) || - (parport_write(cam->pport, &addr, 1) != 1) || - (parport_negotiate(cam->pport, cam->ppmode|IEEE1284_DATA) != 0)) { + (parport_write(cam->pport, &addr, 1) != 1) || + (parport_negotiate(cam->pport, cam->ppmode|IEEE1284_DATA) != 0)) { w9966_pdev_release(cam); return -EFAULT; } @@ -760,7 +760,7 @@ static ssize_t w9966_v4l_read(struct file *file, char __user *buf, dleft -= tsize; } - w9966_wReg(cam, 0x01, 0x18); /* Disable capture */ + w9966_write_reg(cam, 0x01, 0x18); /* Disable capture */ out: kfree(tbuf); @@ -814,7 +814,7 @@ static int w9966_init(struct w9966_dev *cam, struct parport* port) cam->color = 64; cam->hue = 0; -/* Select requested transfer mode */ + /* Select requested transfer mode */ switch (parmode) { default: /* Auto-detect (priority: hw-ecp, hw-epp, sw-ecp) */ case 0: @@ -830,20 +830,20 @@ static int w9966_init(struct w9966_dev *cam, struct parport* port) break; case 2: /* hw- or sw-epp */ cam->ppmode = IEEE1284_MODE_EPP; - break; + break; } -/* Tell the parport driver that we exists */ + /* Tell the parport driver that we exists */ cam->pdev = parport_register_device(port, "w9966", NULL, NULL, NULL, 0, NULL); if (cam->pdev == NULL) { DPRINTF("parport_register_device() failed\n"); return -1; } - w9966_setState(cam, W9966_STATE_PDEV, W9966_STATE_PDEV); + w9966_set_state(cam, W9966_STATE_PDEV, W9966_STATE_PDEV); w9966_pdev_claim(cam); -/* Setup a default capture mode */ + /* Setup a default capture mode */ if (w9966_setup(cam, 0, 0, 1023, 1023, 200, 160) != 0) { DPRINTF("w9966_setup() failed.\n"); return -1; @@ -851,18 +851,18 @@ static int w9966_init(struct w9966_dev *cam, struct parport* port) w9966_pdev_release(cam); -/* Fill in the video_device struct and register us to v4l */ + /* Fill in the video_device struct and register us to v4l */ memcpy(&cam->vdev, &w9966_template, sizeof(struct video_device)); video_set_drvdata(&cam->vdev, cam); if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) return -1; - w9966_setState(cam, W9966_STATE_VDEV, W9966_STATE_VDEV); + w9966_set_state(cam, W9966_STATE_VDEV, W9966_STATE_VDEV); /* All ok */ printk(KERN_INFO "w9966cf: Found and initialized a webcam on %s.\n", - cam->pport->name); + cam->pport->name); return 0; } @@ -870,23 +870,23 @@ static int w9966_init(struct w9966_dev *cam, struct parport* port) /* Terminate everything gracefully */ static void w9966_term(struct w9966_dev *cam) { -/* Unregister from v4l */ - if (w9966_getState(cam, W9966_STATE_VDEV, W9966_STATE_VDEV)) { + /* Unregister from v4l */ + if (w9966_get_state(cam, W9966_STATE_VDEV, W9966_STATE_VDEV)) { video_unregister_device(&cam->vdev); - w9966_setState(cam, W9966_STATE_VDEV, 0); + w9966_set_state(cam, W9966_STATE_VDEV, 0); } -/* Terminate from IEEE1284 mode and release pdev block */ - if (w9966_getState(cam, W9966_STATE_PDEV, W9966_STATE_PDEV)) { + /* Terminate from IEEE1284 mode and release pdev block */ + if (w9966_get_state(cam, W9966_STATE_PDEV, W9966_STATE_PDEV)) { w9966_pdev_claim(cam); parport_negotiate(cam->pport, IEEE1284_MODE_COMPAT); w9966_pdev_release(cam); } -/* Unregister from parport */ - if (w9966_getState(cam, W9966_STATE_PDEV, W9966_STATE_PDEV)) { + /* Unregister from parport */ + if (w9966_get_state(cam, W9966_STATE_PDEV, W9966_STATE_PDEV)) { parport_unregister_device(cam->pdev); - w9966_setState(cam, W9966_STATE_PDEV, 0); + w9966_set_state(cam, W9966_STATE_PDEV, 0); } } -- cgit v1.2.3-70-g09d2 From 51270617a52793c423ef68ddd3f18745e9abd15b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 22 Mar 2010 05:22:34 -0300 Subject: V4L/DVB: meye: remove last V4L1 remnants from the code and add v4l2_device Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 2 +- drivers/media/video/meye.c | 78 ++++++++++++++++++++++++--------------------- drivers/media/video/meye.h | 10 ++++-- include/linux/meye.h | 12 +++---- 4 files changed, 55 insertions(+), 47 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 9644cf760aa..2ed76f97bf6 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -740,7 +740,7 @@ source "drivers/media/video/zoran/Kconfig" config VIDEO_MEYE tristate "Sony Vaio Picturebook Motion Eye Video For Linux" - depends on PCI && SONY_LAPTOP && VIDEO_V4L1 + depends on PCI && SONY_LAPTOP && VIDEO_V4L2 ---help--- This is the video4linux driver for the Motion Eye camera found in the Vaio Picturebook laptops. Please read the material in diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c index 4404e5ef818..2be23bccd3c 100644 --- a/drivers/media/video/meye.c +++ b/drivers/media/video/meye.c @@ -30,9 +30,10 @@ #include #include #include -#include #include +#include #include +#include #include #include #include @@ -1168,22 +1169,22 @@ static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *c) case V4L2_CID_BRIGHTNESS: sony_pic_camera_command( SONY_PIC_COMMAND_SETCAMERABRIGHTNESS, c->value); - meye.picture.brightness = c->value << 10; + meye.brightness = c->value << 10; break; case V4L2_CID_HUE: sony_pic_camera_command( SONY_PIC_COMMAND_SETCAMERAHUE, c->value); - meye.picture.hue = c->value << 10; + meye.hue = c->value << 10; break; case V4L2_CID_CONTRAST: sony_pic_camera_command( SONY_PIC_COMMAND_SETCAMERACONTRAST, c->value); - meye.picture.contrast = c->value << 10; + meye.contrast = c->value << 10; break; case V4L2_CID_SATURATION: sony_pic_camera_command( SONY_PIC_COMMAND_SETCAMERACOLOR, c->value); - meye.picture.colour = c->value << 10; + meye.colour = c->value << 10; break; case V4L2_CID_AGC: sony_pic_camera_command( @@ -1221,16 +1222,16 @@ static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *c) mutex_lock(&meye.lock); switch (c->id) { case V4L2_CID_BRIGHTNESS: - c->value = meye.picture.brightness >> 10; + c->value = meye.brightness >> 10; break; case V4L2_CID_HUE: - c->value = meye.picture.hue >> 10; + c->value = meye.hue >> 10; break; case V4L2_CID_CONTRAST: - c->value = meye.picture.contrast >> 10; + c->value = meye.contrast >> 10; break; case V4L2_CID_SATURATION: - c->value = meye.picture.colour >> 10; + c->value = meye.colour >> 10; break; case V4L2_CID_AGC: c->value = meye.params.agc; @@ -1729,6 +1730,7 @@ static int meye_resume(struct pci_dev *pdev) static int __devinit meye_probe(struct pci_dev *pcidev, const struct pci_device_id *ent) { + struct v4l2_device *v4l2_dev = &meye.v4l2_dev; int ret = -EBUSY; unsigned long mchip_adr; @@ -1737,70 +1739,75 @@ static int __devinit meye_probe(struct pci_dev *pcidev, goto outnotdev; } + ret = v4l2_device_register(&pcidev->dev, v4l2_dev); + if (ret < 0) { + v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); + return ret; + } ret = -ENOMEM; meye.mchip_dev = pcidev; - meye.video_dev = video_device_alloc(); - if (!meye.video_dev) { - printk(KERN_ERR "meye: video_device_alloc() failed!\n"); + meye.vdev = video_device_alloc(); + if (!meye.vdev) { + v4l2_err(v4l2_dev, "video_device_alloc() failed!\n"); goto outnotdev; } meye.grab_temp = vmalloc(MCHIP_NB_PAGES_MJPEG * PAGE_SIZE); if (!meye.grab_temp) { - printk(KERN_ERR "meye: grab buffer allocation failed\n"); + v4l2_err(v4l2_dev, "grab buffer allocation failed\n"); goto outvmalloc; } spin_lock_init(&meye.grabq_lock); if (kfifo_alloc(&meye.grabq, sizeof(int) * MEYE_MAX_BUFNBRS, GFP_KERNEL)) { - printk(KERN_ERR "meye: fifo allocation failed\n"); + v4l2_err(v4l2_dev, "fifo allocation failed\n"); goto outkfifoalloc1; } spin_lock_init(&meye.doneq_lock); if (kfifo_alloc(&meye.doneq, sizeof(int) * MEYE_MAX_BUFNBRS, GFP_KERNEL)) { - printk(KERN_ERR "meye: fifo allocation failed\n"); + v4l2_err(v4l2_dev, "fifo allocation failed\n"); goto outkfifoalloc2; } - memcpy(meye.video_dev, &meye_template, sizeof(meye_template)); - meye.video_dev->parent = &meye.mchip_dev->dev; + memcpy(meye.vdev, &meye_template, sizeof(meye_template)); + meye.vdev->v4l2_dev = &meye.v4l2_dev; ret = -EIO; if ((ret = sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 1))) { - printk(KERN_ERR "meye: unable to power on the camera\n"); - printk(KERN_ERR "meye: did you enable the camera in " + v4l2_err(v4l2_dev, "meye: unable to power on the camera\n"); + v4l2_err(v4l2_dev, "meye: did you enable the camera in " "sonypi using the module options ?\n"); goto outsonypienable; } if ((ret = pci_enable_device(meye.mchip_dev))) { - printk(KERN_ERR "meye: pci_enable_device failed\n"); + v4l2_err(v4l2_dev, "meye: pci_enable_device failed\n"); goto outenabledev; } mchip_adr = pci_resource_start(meye.mchip_dev,0); if (!mchip_adr) { - printk(KERN_ERR "meye: mchip has no device base address\n"); + v4l2_err(v4l2_dev, "meye: mchip has no device base address\n"); goto outregions; } if (!request_mem_region(pci_resource_start(meye.mchip_dev, 0), pci_resource_len(meye.mchip_dev, 0), "meye")) { - printk(KERN_ERR "meye: request_mem_region failed\n"); + v4l2_err(v4l2_dev, "meye: request_mem_region failed\n"); goto outregions; } meye.mchip_mmregs = ioremap(mchip_adr, MCHIP_MM_REGS); if (!meye.mchip_mmregs) { - printk(KERN_ERR "meye: ioremap failed\n"); + v4l2_err(v4l2_dev, "meye: ioremap failed\n"); goto outremap; } meye.mchip_irq = pcidev->irq; if (request_irq(meye.mchip_irq, meye_irq, IRQF_DISABLED | IRQF_SHARED, "meye", meye_irq)) { - printk(KERN_ERR "meye: request_irq failed\n"); + v4l2_err(v4l2_dev, "request_irq failed\n"); goto outreqirq; } @@ -1824,21 +1831,18 @@ static int __devinit meye_probe(struct pci_dev *pcidev, msleep(1); mchip_set(MCHIP_MM_INTA, MCHIP_MM_INTA_HIC_1_MASK); - if (video_register_device(meye.video_dev, VFL_TYPE_GRABBER, + if (video_register_device(meye.vdev, VFL_TYPE_GRABBER, video_nr) < 0) { - printk(KERN_ERR "meye: video_register_device failed\n"); + v4l2_err(v4l2_dev, "video_register_device failed\n"); goto outvideoreg; } mutex_init(&meye.lock); init_waitqueue_head(&meye.proc_list); - meye.picture.depth = 16; - meye.picture.palette = VIDEO_PALETTE_YUV422; - meye.picture.brightness = 32 << 10; - meye.picture.hue = 32 << 10; - meye.picture.colour = 32 << 10; - meye.picture.contrast = 32 << 10; - meye.picture.whiteness = 0; + meye.brightness = 32 << 10; + meye.hue = 32 << 10; + meye.colour = 32 << 10; + meye.contrast = 32 << 10; meye.params.subsample = 0; meye.params.quality = 8; meye.params.sharpness = 32; @@ -1854,9 +1858,9 @@ static int __devinit meye_probe(struct pci_dev *pcidev, sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAPICTURE, 0); sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAAGC, 48); - printk(KERN_INFO "meye: Motion Eye Camera Driver v%s.\n", + v4l2_info(v4l2_dev, "Motion Eye Camera Driver v%s.\n", MEYE_DRIVER_VERSION); - printk(KERN_INFO "meye: mchip KL5A72002 rev. %d, base %lx, irq %d\n", + v4l2_info(v4l2_dev, "mchip KL5A72002 rev. %d, base %lx, irq %d\n", meye.mchip_dev->revision, mchip_adr, meye.mchip_irq); return 0; @@ -1879,14 +1883,14 @@ outkfifoalloc2: outkfifoalloc1: vfree(meye.grab_temp); outvmalloc: - video_device_release(meye.video_dev); + video_device_release(meye.vdev); outnotdev: return ret; } static void __devexit meye_remove(struct pci_dev *pcidev) { - video_unregister_device(meye.video_dev); + video_unregister_device(meye.vdev); mchip_hic_stop(); diff --git a/drivers/media/video/meye.h b/drivers/media/video/meye.h index 1321ad5d659..4bdeb03f164 100644 --- a/drivers/media/video/meye.h +++ b/drivers/media/video/meye.h @@ -31,7 +31,7 @@ #define _MEYE_PRIV_H_ #define MEYE_DRIVER_MAJORVERSION 1 -#define MEYE_DRIVER_MINORVERSION 13 +#define MEYE_DRIVER_MINORVERSION 14 #define MEYE_DRIVER_VERSION __stringify(MEYE_DRIVER_MAJORVERSION) "." \ __stringify(MEYE_DRIVER_MINORVERSION) @@ -289,6 +289,7 @@ struct meye_grab_buffer { /* Motion Eye device structure */ struct meye { + struct v4l2_device v4l2_dev; /* Main v4l2_device struct */ struct pci_dev *mchip_dev; /* pci device */ u8 mchip_irq; /* irq */ u8 mchip_mode; /* actual mchip mode: HIC_MODE... */ @@ -308,8 +309,11 @@ struct meye { struct kfifo doneq; /* queue for grabbed buffers */ spinlock_t doneq_lock; /* lock protecting the queue */ wait_queue_head_t proc_list; /* wait queue */ - struct video_device *video_dev; /* video device parameters */ - struct video_picture picture; /* video picture parameters */ + struct video_device *vdev; /* video device parameters */ + u16 brightness; + u16 hue; + u16 contrast; + u16 colour; struct meye_params params; /* additional parameters */ unsigned long in_use; /* set to 1 if the device is in use */ #ifdef CONFIG_PM diff --git a/include/linux/meye.h b/include/linux/meye.h index 12010ace1f0..0dd49954f74 100644 --- a/include/linux/meye.h +++ b/include/linux/meye.h @@ -44,17 +44,17 @@ struct meye_params { }; /* query the extended parameters */ -#define MEYEIOC_G_PARAMS _IOR ('v', BASE_VIDIOCPRIVATE+0, struct meye_params) +#define MEYEIOC_G_PARAMS _IOR ('v', BASE_VIDIOC_PRIVATE+0, struct meye_params) /* set the extended parameters */ -#define MEYEIOC_S_PARAMS _IOW ('v', BASE_VIDIOCPRIVATE+1, struct meye_params) +#define MEYEIOC_S_PARAMS _IOW ('v', BASE_VIDIOC_PRIVATE+1, struct meye_params) /* queue a buffer for mjpeg capture */ -#define MEYEIOC_QBUF_CAPT _IOW ('v', BASE_VIDIOCPRIVATE+2, int) +#define MEYEIOC_QBUF_CAPT _IOW ('v', BASE_VIDIOC_PRIVATE+2, int) /* sync a previously queued mjpeg buffer */ -#define MEYEIOC_SYNC _IOWR('v', BASE_VIDIOCPRIVATE+3, int) +#define MEYEIOC_SYNC _IOWR('v', BASE_VIDIOC_PRIVATE+3, int) /* get a still uncompressed snapshot */ -#define MEYEIOC_STILLCAPT _IO ('v', BASE_VIDIOCPRIVATE+4) +#define MEYEIOC_STILLCAPT _IO ('v', BASE_VIDIOC_PRIVATE+4) /* get a jpeg compressed snapshot */ -#define MEYEIOC_STILLJCAPT _IOR ('v', BASE_VIDIOCPRIVATE+5, int) +#define MEYEIOC_STILLJCAPT _IOR ('v', BASE_VIDIOC_PRIVATE+5, int) /* V4L2 private controls */ #define V4L2_CID_AGC V4L2_CID_PRIVATE_BASE -- cgit v1.2.3-70-g09d2 From debff5a79595356b1d10063c5f5a7bcdf1b54bec Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 22 Mar 2010 05:25:46 -0300 Subject: V4L/DVB: zoran: remove V4L1 videodev.h include Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/zoran/zoran.h | 24 ++++++++++++++---------- drivers/media/video/zoran/zoran_driver.c | 16 ++++++++-------- 2 files changed, 22 insertions(+), 18 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/zoran/zoran.h b/drivers/media/video/zoran/zoran.h index cb1de7ea197..8997add1248 100644 --- a/drivers/media/video/zoran/zoran.h +++ b/drivers/media/video/zoran/zoran.h @@ -33,6 +33,10 @@ #include +#define ZORAN_VIDMODE_PAL 0 +#define ZORAN_VIDMODE_NTSC 1 +#define ZORAN_VIDMODE_SECAM 2 + struct zoran_requestbuffers { unsigned long count; /* Number of buffers for MJPEG grabbing */ unsigned long size; /* Size PER BUFFER in bytes */ @@ -48,7 +52,7 @@ struct zoran_sync { struct zoran_status { int input; /* Input channel, has to be set prior to BUZIOC_G_STATUS */ int signal; /* Returned: 1 if valid video signal detected */ - int norm; /* Returned: VIDEO_MODE_PAL or VIDEO_MODE_NTSC */ + int norm; /* Returned: ZORAN_VIDMODE_PAL or ZORAN_VIDMODE_NTSC */ int color; /* Returned: 1 if color signal detected */ }; @@ -62,7 +66,7 @@ struct zoran_params { /* Main control parameters */ int input; /* Input channel: 0 = Composite, 1 = S-VHS */ - int norm; /* Norm: VIDEO_MODE_PAL or VIDEO_MODE_NTSC */ + int norm; /* Norm: ZORAN_VIDMODE_PAL or ZORAN_VIDMODE_NTSC */ int decimation; /* decimation of captured video, * enlargement of video played back. * Valid values are 1, 2, 4 or 0. @@ -131,13 +135,13 @@ struct zoran_params { /* Private IOCTL to set up for displaying MJPEG */ -#define BUZIOC_G_PARAMS _IOR ('v', BASE_VIDIOCPRIVATE+0, struct zoran_params) -#define BUZIOC_S_PARAMS _IOWR('v', BASE_VIDIOCPRIVATE+1, struct zoran_params) -#define BUZIOC_REQBUFS _IOWR('v', BASE_VIDIOCPRIVATE+2, struct zoran_requestbuffers) -#define BUZIOC_QBUF_CAPT _IOW ('v', BASE_VIDIOCPRIVATE+3, int) -#define BUZIOC_QBUF_PLAY _IOW ('v', BASE_VIDIOCPRIVATE+4, int) -#define BUZIOC_SYNC _IOR ('v', BASE_VIDIOCPRIVATE+5, struct zoran_sync) -#define BUZIOC_G_STATUS _IOWR('v', BASE_VIDIOCPRIVATE+6, struct zoran_status) +#define BUZIOC_G_PARAMS _IOR ('v', BASE_VIDIOC_PRIVATE+0, struct zoran_params) +#define BUZIOC_S_PARAMS _IOWR('v', BASE_VIDIOC_PRIVATE+1, struct zoran_params) +#define BUZIOC_REQBUFS _IOWR('v', BASE_VIDIOC_PRIVATE+2, struct zoran_requestbuffers) +#define BUZIOC_QBUF_CAPT _IOW ('v', BASE_VIDIOC_PRIVATE+3, int) +#define BUZIOC_QBUF_PLAY _IOW ('v', BASE_VIDIOC_PRIVATE+4, int) +#define BUZIOC_SYNC _IOR ('v', BASE_VIDIOC_PRIVATE+5, struct zoran_sync) +#define BUZIOC_G_STATUS _IOWR('v', BASE_VIDIOC_PRIVATE+6, struct zoran_status) #ifdef __KERNEL__ @@ -401,7 +405,7 @@ struct zoran { spinlock_t spinlock; /* Spinlock */ /* Video for Linux parameters */ - int input; /* card's norm and input - norm=VIDEO_MODE_* */ + int input; /* card's norm and input */ v4l2_std_id norm; /* Current buffer params */ diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index ec41303544e..6f89d0a096e 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c @@ -60,7 +60,7 @@ #include -#include +#include #include #include #include "videocodec.h" @@ -1549,11 +1549,11 @@ static long zoran_default(struct file *file, void *__fh, int cmd, void *arg) mutex_lock(&zr->resource_lock); if (zr->norm & V4L2_STD_NTSC) - bparams->norm = VIDEO_MODE_NTSC; - else if (zr->norm & V4L2_STD_PAL) - bparams->norm = VIDEO_MODE_PAL; + bparams->norm = ZORAN_VIDMODE_NTSC; + else if (zr->norm & V4L2_STD_SECAM) + bparams->norm = ZORAN_VIDMODE_SECAM; else - bparams->norm = VIDEO_MODE_SECAM; + bparams->norm = ZORAN_VIDMODE_PAL; bparams->input = zr->input; @@ -1789,11 +1789,11 @@ gstat_unlock_and_return: bstat->signal = (status & V4L2_IN_ST_NO_SIGNAL) ? 0 : 1; if (norm & V4L2_STD_NTSC) - bstat->norm = VIDEO_MODE_NTSC; + bstat->norm = ZORAN_VIDMODE_NTSC; else if (norm & V4L2_STD_SECAM) - bstat->norm = VIDEO_MODE_SECAM; + bstat->norm = ZORAN_VIDMODE_SECAM; else - bstat->norm = VIDEO_MODE_PAL; + bstat->norm = ZORAN_VIDMODE_PAL; bstat->color = (status & V4L2_IN_ST_NO_COLOR) ? 0 : 1; -- cgit v1.2.3-70-g09d2 From b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 29 Mar 2010 16:05:33 -0300 Subject: V4L/DVB: arv: convert to V4L2 Converted this old V4L1 driver to V4L2. I would like to thank Takeo Takahashi who very kindly tested this driver for me. Much appreciated! Signed-off-by: Hans Verkuil Tested-by: Takeo Takahashi Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 2 +- drivers/media/video/arv.c | 391 ++++++++++++++++++++------------------------ 2 files changed, 179 insertions(+), 214 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 2ed76f97bf6..fe6771271b2 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -807,7 +807,7 @@ source "drivers/media/video/saa7164/Kconfig" config VIDEO_M32R_AR tristate "AR devices" - depends on M32R && VIDEO_V4L1 + depends on M32R && VIDEO_V4L2 ---help--- This is a video4linux driver for the Renesas AR (Artificial Retina) camera module. diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c index 9f88096a520..31e7a123d19 100644 --- a/drivers/media/video/arv.c +++ b/drivers/media/video/arv.c @@ -27,8 +27,10 @@ #include #include #include -#include +#include +#include #include +#include #include #include @@ -52,7 +54,7 @@ */ #define USE_INT 0 /* Don't modify */ -#define VERSION "0.03" +#define VERSION "0.04" #define ar_inl(addr) inl((unsigned long)(addr)) #define ar_outl(val, addr) outl((unsigned long)(val), (unsigned long)(addr)) @@ -79,7 +81,7 @@ extern struct cpuinfo_m32r boot_cpu_data; /* bits & bytes per pixel */ #define AR_BITS_PER_PIXEL 16 -#define AR_BYTES_PER_PIXEL (AR_BITS_PER_PIXEL/8) +#define AR_BYTES_PER_PIXEL (AR_BITS_PER_PIXEL / 8) /* line buffer size */ #define AR_LINE_BYTES_VGA (AR_WIDTH_VGA * AR_BYTES_PER_PIXEL) @@ -104,8 +106,9 @@ extern struct cpuinfo_m32r boot_cpu_data; #define AR_MODE_INTERLACE 0 #define AR_MODE_NORMAL 1 -struct ar_device { - struct video_device *vdev; +struct ar { + struct v4l2_device v4l2_dev; + struct video_device vdev; unsigned int start_capture; /* duaring capture in INT. mode. */ #if USE_INT unsigned char *line_buff; /* DMA line buffer */ @@ -116,12 +119,13 @@ struct ar_device { int width, height; int frame_bytes, line_bytes; wait_queue_head_t wait; - unsigned long in_use; struct mutex lock; }; +static struct ar ardev; + static int video_nr = -1; /* video device number (first free) */ -static unsigned char yuv[MAX_AR_FRAME_BYTES]; +static unsigned char yuv[MAX_AR_FRAME_BYTES]; /* module parameters */ /* default frequency */ @@ -133,9 +137,7 @@ module_param(freq, int, 0); module_param(vga, int, 0); module_param(vga_interlace, int, 0); -static int ar_initialize(struct video_device *dev); - -static inline void wait_for_vsync(void) +static void wait_for_vsync(void) { while (ar_inl(ARVCR0) & ARVCR0_VDS) /* wait for VSYNC */ cpu_relax(); @@ -143,7 +145,7 @@ static inline void wait_for_vsync(void) cpu_relax(); } -static inline void wait_acknowledge(void) +static void wait_acknowledge(void) { int i; @@ -156,7 +158,7 @@ static inline void wait_acknowledge(void) /******************************************************************* * I2C functions *******************************************************************/ -void iic(int n, unsigned long addr, unsigned long data1, unsigned long data2, +static void iic(int n, unsigned long addr, unsigned long data1, unsigned long data2, unsigned long data3) { int i; @@ -200,7 +202,7 @@ void iic(int n, unsigned long addr, unsigned long data1, unsigned long data2, } -void init_iic(void) +static void init_iic(void) { DEBUG(1, "init_iic:\n"); @@ -244,7 +246,7 @@ static inline void clear_dma_status(void) ar_outl(0x8000, M32R_DMAEDET_PORTL); /* clear status */ } -static inline void wait_for_vertical_sync(int exp_line) +static void wait_for_vertical_sync(struct ar *ar, int exp_line) { #if CHECK_LOST int tmout = 10000; /* FIXME */ @@ -259,7 +261,7 @@ static inline void wait_for_vertical_sync(int exp_line) break; } if (tmout < 0) - printk(KERN_ERR "arv: lost %d -> %d\n", exp_line, l); + v4l2_err(&ar->v4l2_dev, "lost %d -> %d\n", exp_line, l); #else while (ar_inl(ARVHCOUNT) != exp_line) cpu_relax(); @@ -268,8 +270,7 @@ static inline void wait_for_vertical_sync(int exp_line) static ssize_t ar_read(struct file *file, char *buf, size_t count, loff_t *ppos) { - struct video_device *v = video_devdata(file); - struct ar_device *ar = video_get_drvdata(v); + struct ar *ar = video_drvdata(file); long ret = ar->frame_bytes; /* return read bytes */ unsigned long arvcr1 = 0; unsigned long flags; @@ -304,7 +305,7 @@ static ssize_t ar_read(struct file *file, char *buf, size_t count, loff_t *ppos) ar_outl(ar->line_bytes, M32R_DMA0RBCUT_PORTL); /* reload count (bytes) */ /* - * Okey , kicks AR LSI to invoke an interrupt + * Okay, kick AR LSI to invoke an interrupt */ ar->start_capture = 0; ar_outl(arvcr1 | ARVCR1_HIEN, ARVCR1); @@ -333,7 +334,7 @@ static ssize_t ar_read(struct file *file, char *buf, size_t count, loff_t *ppos) cpu_relax(); if (ar->mode == AR_MODE_INTERLACE && ar->size == AR_SIZE_VGA) { for (h = 0; h < ar->height; h++) { - wait_for_vertical_sync(h); + wait_for_vertical_sync(ar, h); if (h < (AR_HEIGHT_VGA/2)) l = h << 1; else @@ -348,7 +349,7 @@ static ssize_t ar_read(struct file *file, char *buf, size_t count, loff_t *ppos) } } else { for (h = 0; h < ar->height; h++) { - wait_for_vertical_sync(h); + wait_for_vertical_sync(ar, h); ar_outl(virt_to_phys(ar->frame[h]), M32R_DMA0CDA_PORTL); enable_dma(); while (!(ar_inl(M32R_DMAEDET_PORTL) & 0x8000)) @@ -385,7 +386,7 @@ static ssize_t ar_read(struct file *file, char *buf, size_t count, loff_t *ppos) } } if (copy_to_user(buf, yuv, ar->frame_bytes)) { - printk(KERN_ERR "arv: failed while copy_to_user yuv.\n"); + v4l2_err(&ar->v4l2_dev, "failed while copy_to_user yuv.\n"); ret = -EFAULT; goto out_up; } @@ -395,153 +396,127 @@ out_up: return ret; } -static long ar_do_ioctl(struct file *file, unsigned int cmd, void *arg) +static int ar_querycap(struct file *file, void *priv, + struct v4l2_capability *vcap) { - struct video_device *dev = video_devdata(file); - struct ar_device *ar = video_get_drvdata(dev); - - DEBUG(1, "ar_ioctl()\n"); - switch (cmd) { - case VIDIOCGCAP: - { - struct video_capability *b = arg; - DEBUG(1, "VIDIOCGCAP:\n"); - strcpy(b->name, ar->vdev->name); - b->type = VID_TYPE_CAPTURE; - b->channels = 0; - b->audios = 0; - b->maxwidth = MAX_AR_WIDTH; - b->maxheight = MAX_AR_HEIGHT; - b->minwidth = MIN_AR_WIDTH; - b->minheight = MIN_AR_HEIGHT; - return 0; - } - case VIDIOCGCHAN: - DEBUG(1, "VIDIOCGCHAN:\n"); - return 0; - case VIDIOCSCHAN: - DEBUG(1, "VIDIOCSCHAN:\n"); - return 0; - case VIDIOCGTUNER: - DEBUG(1, "VIDIOCGTUNER:\n"); - return 0; - case VIDIOCSTUNER: - DEBUG(1, "VIDIOCSTUNER:\n"); - return 0; - case VIDIOCGPICT: - DEBUG(1, "VIDIOCGPICT:\n"); - return 0; - case VIDIOCSPICT: - DEBUG(1, "VIDIOCSPICT:\n"); - return 0; - case VIDIOCCAPTURE: - DEBUG(1, "VIDIOCCAPTURE:\n"); + struct ar *ar = video_drvdata(file); + + strlcpy(vcap->driver, ar->vdev.name, sizeof(vcap->driver)); + strlcpy(vcap->card, "Colour AR VGA", sizeof(vcap->card)); + strlcpy(vcap->bus_info, "Platform", sizeof(vcap->bus_info)); + vcap->version = KERNEL_VERSION(0, 0, 4); + vcap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE; + return 0; +} + +static int ar_enum_input(struct file *file, void *fh, struct v4l2_input *vin) +{ + if (vin->index > 0) return -EINVAL; - case VIDIOCGWIN: - { - struct video_window *w = arg; - DEBUG(1, "VIDIOCGWIN:\n"); - memset(w, 0, sizeof(*w)); - w->width = ar->width; - w->height = ar->height; - return 0; + strlcpy(vin->name, "Camera", sizeof(vin->name)); + vin->type = V4L2_INPUT_TYPE_CAMERA; + vin->audioset = 0; + vin->tuner = 0; + vin->std = V4L2_STD_ALL; + vin->status = 0; + return 0; +} + +static int ar_g_input(struct file *file, void *fh, unsigned int *inp) +{ + *inp = 0; + return 0; +} + +static int ar_s_input(struct file *file, void *fh, unsigned int inp) +{ + return inp ? -EINVAL : 0; +} + +static int ar_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) +{ + struct ar *ar = video_drvdata(file); + struct v4l2_pix_format *pix = &fmt->fmt.pix; + + pix->width = ar->width; + pix->height = ar->height; + pix->pixelformat = V4L2_PIX_FMT_YUV422P; + pix->field = (ar->mode == AR_MODE_NORMAL) ? V4L2_FIELD_NONE : V4L2_FIELD_INTERLACED; + pix->bytesperline = ar->width; + pix->sizeimage = 2 * ar->width * ar->height; + /* Just a guess */ + pix->colorspace = V4L2_COLORSPACE_SMPTE170M; + return 0; +} + +static int ar_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) +{ + struct ar *ar = video_drvdata(file); + struct v4l2_pix_format *pix = &fmt->fmt.pix; + + if (pix->height <= AR_HEIGHT_QVGA || pix->width <= AR_WIDTH_QVGA) { + pix->height = AR_HEIGHT_QVGA; + pix->width = AR_WIDTH_QVGA; + pix->field = V4L2_FIELD_INTERLACED; + } else { + pix->height = AR_HEIGHT_VGA; + pix->width = AR_WIDTH_VGA; + pix->field = vga_interlace ? V4L2_FIELD_INTERLACED : V4L2_FIELD_NONE; } - case VIDIOCSWIN: - { - struct video_window *w = arg; - DEBUG(1, "VIDIOCSWIN:\n"); - if ((w->width != AR_WIDTH_VGA || w->height != AR_HEIGHT_VGA) && - (w->width != AR_WIDTH_QVGA || w->height != AR_HEIGHT_QVGA)) - return -EINVAL; - - mutex_lock(&ar->lock); - ar->width = w->width; - ar->height = w->height; - if (ar->width == AR_WIDTH_VGA) { - ar->size = AR_SIZE_VGA; - ar->frame_bytes = AR_FRAME_BYTES_VGA; - ar->line_bytes = AR_LINE_BYTES_VGA; - if (vga_interlace) - ar->mode = AR_MODE_INTERLACE; - else - ar->mode = AR_MODE_NORMAL; - } else { - ar->size = AR_SIZE_QVGA; - ar->frame_bytes = AR_FRAME_BYTES_QVGA; - ar->line_bytes = AR_LINE_BYTES_QVGA; + pix->pixelformat = V4L2_PIX_FMT_YUV422P; + pix->bytesperline = ar->width; + pix->sizeimage = 2 * ar->width * ar->height; + /* Just a guess */ + pix->colorspace = V4L2_COLORSPACE_SMPTE170M; + return 0; +} + +static int ar_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) +{ + struct ar *ar = video_drvdata(file); + struct v4l2_pix_format *pix = &fmt->fmt.pix; + int ret = ar_try_fmt_vid_cap(file, fh, fmt); + + if (ret) + return ret; + mutex_lock(&ar->lock); + ar->width = pix->width; + ar->height = pix->height; + if (ar->width == AR_WIDTH_VGA) { + ar->size = AR_SIZE_VGA; + ar->frame_bytes = AR_FRAME_BYTES_VGA; + ar->line_bytes = AR_LINE_BYTES_VGA; + if (vga_interlace) ar->mode = AR_MODE_INTERLACE; - } - mutex_unlock(&ar->lock); - return 0; - } - case VIDIOCGFBUF: - DEBUG(1, "VIDIOCGFBUF:\n"); - return -EINVAL; - case VIDIOCSFBUF: - DEBUG(1, "VIDIOCSFBUF:\n"); - return -EINVAL; - case VIDIOCKEY: - DEBUG(1, "VIDIOCKEY:\n"); - return 0; - case VIDIOCGFREQ: - DEBUG(1, "VIDIOCGFREQ:\n"); - return -EINVAL; - case VIDIOCSFREQ: - DEBUG(1, "VIDIOCSFREQ:\n"); - return -EINVAL; - case VIDIOCGAUDIO: - DEBUG(1, "VIDIOCGAUDIO:\n"); - return -EINVAL; - case VIDIOCSAUDIO: - DEBUG(1, "VIDIOCSAUDIO:\n"); - return -EINVAL; - case VIDIOCSYNC: - DEBUG(1, "VIDIOCSYNC:\n"); - return -EINVAL; - case VIDIOCMCAPTURE: - DEBUG(1, "VIDIOCMCAPTURE:\n"); - return -EINVAL; - case VIDIOCGMBUF: - DEBUG(1, "VIDIOCGMBUF:\n"); - return -EINVAL; - case VIDIOCGUNIT: - DEBUG(1, "VIDIOCGUNIT:\n"); - return -EINVAL; - case VIDIOCGCAPTURE: - DEBUG(1, "VIDIOCGCAPTURE:\n"); - return -EINVAL; - case VIDIOCSCAPTURE: - DEBUG(1, "VIDIOCSCAPTURE:\n"); - return -EINVAL; - case VIDIOCSPLAYMODE: - DEBUG(1, "VIDIOCSPLAYMODE:\n"); - return -EINVAL; - case VIDIOCSWRITEMODE: - DEBUG(1, "VIDIOCSWRITEMODE:\n"); - return -EINVAL; - case VIDIOCGPLAYINFO: - DEBUG(1, "VIDIOCGPLAYINFO:\n"); - return -EINVAL; - case VIDIOCSMICROCODE: - DEBUG(1, "VIDIOCSMICROCODE:\n"); - return -EINVAL; - case VIDIOCGVBIFMT: - DEBUG(1, "VIDIOCGVBIFMT:\n"); - return -EINVAL; - case VIDIOCSVBIFMT: - DEBUG(1, "VIDIOCSVBIFMT:\n"); - return -EINVAL; - default: - DEBUG(1, "Unknown ioctl(0x%08x)\n", cmd); - return -ENOIOCTLCMD; + else + ar->mode = AR_MODE_NORMAL; + } else { + ar->size = AR_SIZE_QVGA; + ar->frame_bytes = AR_FRAME_BYTES_QVGA; + ar->line_bytes = AR_LINE_BYTES_QVGA; + ar->mode = AR_MODE_INTERLACE; } + /* Ok we figured out what to use from our wide choice */ + mutex_unlock(&ar->lock); return 0; } -static long ar_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) +static int ar_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt) { - return video_usercopy(file, cmd, arg, ar_do_ioctl); + static struct v4l2_fmtdesc formats[] = { + { 0, 0, 0, + "YUV 4:2:2 Planar", V4L2_PIX_FMT_YUV422P, + { 0, 0, 0, 0 } + }, + }; + enum v4l2_buf_type type = fmt->type; + + if (fmt->index > 0) + return -EINVAL; + + *fmt = formats[fmt->index]; + fmt->type = type; + return 0; } #if USE_INT @@ -550,7 +525,7 @@ static long ar_ioctl(struct file *file, unsigned int cmd, */ static void ar_interrupt(int irq, void *dev) { - struct ar_device *ar = dev; + struct ar *ar = dev; unsigned int line_count; unsigned int line_number; unsigned int arvcr1; @@ -622,9 +597,8 @@ static void ar_interrupt(int irq, void *dev) * 0 is returned in success. * */ -static int ar_initialize(struct video_device *dev) +static int ar_initialize(struct ar *ar) { - struct ar_device *ar = video_get_drvdata(dev); unsigned long cr = 0; int i, found = 0; @@ -665,7 +639,7 @@ static int ar_initialize(struct video_device *dev) if (found == 0) return -ENODEV; - printk(KERN_INFO "arv: Initializing "); + v4l2_info(&ar->v4l2_dev, "Initializing "); iic(2, 0x78, 0x11, 0x01, 0x00); /* start */ iic(3, 0x78, 0x12, 0x00, 0x06); @@ -729,65 +703,55 @@ static int ar_initialize(struct video_device *dev) } -void ar_release(struct video_device *vfd) -{ - struct ar_device *ar = video_get_drvdata(vfd); - mutex_lock(&ar->lock); - video_device_release(vfd); -} - /**************************************************************************** * * Video4Linux Module functions * ****************************************************************************/ -static struct ar_device ardev; - -static int ar_exclusive_open(struct file *file) -{ - return test_and_set_bit(0, &ardev.in_use) ? -EBUSY : 0; -} - -static int ar_exclusive_release(struct file *file) -{ - clear_bit(0, &ardev.in_use); - return 0; -} static const struct v4l2_file_operations ar_fops = { .owner = THIS_MODULE, - .open = ar_exclusive_open, - .release = ar_exclusive_release, .read = ar_read, - .ioctl = ar_ioctl, + .ioctl = video_ioctl2, }; -static struct video_device ar_template = { - .name = "Colour AR VGA", - .fops = &ar_fops, - .release = ar_release, +static const struct v4l2_ioctl_ops ar_ioctl_ops = { + .vidioc_querycap = ar_querycap, + .vidioc_g_input = ar_g_input, + .vidioc_s_input = ar_s_input, + .vidioc_enum_input = ar_enum_input, + .vidioc_enum_fmt_vid_cap = ar_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = ar_g_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = ar_s_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = ar_try_fmt_vid_cap, }; #define ALIGN4(x) ((((int)(x)) & 0x3) == 0) static int __init ar_init(void) { - struct ar_device *ar; + struct ar *ar; + struct v4l2_device *v4l2_dev; int ret; int i; - DEBUG(1, "ar_init:\n"); - ret = -EIO; - printk(KERN_INFO "arv: Colour AR VGA driver %s\n", VERSION); - ar = &ardev; - memset(ar, 0, sizeof(struct ar_device)); + v4l2_dev = &ar->v4l2_dev; + strlcpy(v4l2_dev->name, "arv", sizeof(v4l2_dev->name)); + v4l2_info(v4l2_dev, "Colour AR VGA driver %s\n", VERSION); + + ret = v4l2_device_register(NULL, v4l2_dev); + if (ret < 0) { + v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); + return ret; + } + ret = -EIO; #if USE_INT /* allocate a DMA buffer for 1 line. */ ar->line_buff = kmalloc(MAX_AR_LINE_BYTES, GFP_KERNEL | GFP_DMA); if (ar->line_buff == NULL || !ALIGN4(ar->line_buff)) { - printk(KERN_ERR "arv: buffer allocation failed for DMA.\n"); + v4l2_err(v4l2_dev, "buffer allocation failed for DMA.\n"); ret = -ENOMEM; goto out_end; } @@ -796,19 +760,18 @@ static int __init ar_init(void) for (i = 0; i < MAX_AR_HEIGHT; i++) { ar->frame[i] = kmalloc(MAX_AR_LINE_BYTES, GFP_KERNEL); if (ar->frame[i] == NULL || !ALIGN4(ar->frame[i])) { - printk(KERN_ERR "arv: buffer allocation failed for frame.\n"); + v4l2_err(v4l2_dev, "buffer allocation failed for frame.\n"); ret = -ENOMEM; goto out_line_buff; } } - ar->vdev = video_device_alloc(); - if (!ar->vdev) { - printk(KERN_ERR "arv: video_device_alloc() failed\n"); - return -ENOMEM; - } - memcpy(ar->vdev, &ar_template, sizeof(ar_template)); - video_set_drvdata(ar->vdev, ar); + strlcpy(ar->vdev.name, "Colour AR VGA", sizeof(ar->vdev.name)); + ar->vdev.v4l2_dev = v4l2_dev; + ar->vdev.fops = &ar_fops; + ar->vdev.ioctl_ops = &ar_ioctl_ops; + ar->vdev.release = video_device_release_empty; + video_set_drvdata(&ar->vdev, ar); if (vga) { ar->width = AR_WIDTH_VGA; @@ -833,14 +796,14 @@ static int __init ar_init(void) #if USE_INT if (request_irq(M32R_IRQ_INT3, ar_interrupt, 0, "arv", ar)) { - printk(KERN_ERR "arv: request_irq(%d) failed.\n", M32R_IRQ_INT3); + v4l2_err("request_irq(%d) failed.\n", M32R_IRQ_INT3); ret = -EIO; goto out_irq; } #endif - if (ar_initialize(ar->vdev) != 0) { - printk(KERN_ERR "arv: M64278 not found.\n"); + if (ar_initialize(ar) != 0) { + v4l2_err(v4l2_dev, "M64278 not found.\n"); ret = -ENODEV; goto out_dev; } @@ -851,15 +814,15 @@ static int __init ar_init(void) * device is named "video[0-64]". * video_register_device() initializes h/w using ar_initialize(). */ - if (video_register_device(ar->vdev, VFL_TYPE_GRABBER, video_nr) != 0) { + if (video_register_device(&ar->vdev, VFL_TYPE_GRABBER, video_nr) != 0) { /* return -1, -ENFILE(full) or others */ - printk(KERN_ERR "arv: register video (Colour AR) failed.\n"); + v4l2_err(v4l2_dev, "register video (Colour AR) failed.\n"); ret = -ENODEV; goto out_dev; } - printk(KERN_INFO "%s: Found M64278 VGA (IRQ %d, Freq %dMHz).\n", - video_device_node_name(ar->vdev), M32R_IRQ_INT3, freq); + v4l2_info(v4l2_dev, "%s: Found M64278 VGA (IRQ %d, Freq %dMHz).\n", + video_device_node_name(&ar->vdev), M32R_IRQ_INT3, freq); return 0; @@ -878,6 +841,7 @@ out_line_buff: out_end: #endif + v4l2_device_unregister(&ar->v4l2_dev); return ret; } @@ -893,11 +857,11 @@ static int __init ar_init_module(void) static void __exit ar_cleanup_module(void) { - struct ar_device *ar; + struct ar *ar; int i; ar = &ardev; - video_unregister_device(ar->vdev); + video_unregister_device(&ar->vdev); #if USE_INT free_irq(M32R_IRQ_INT3, ar); #endif @@ -906,6 +870,7 @@ static void __exit ar_cleanup_module(void) #if USE_INT kfree(ar->line_buff); #endif + v4l2_device_unregister(&ar->v4l2_dev); } module_init(ar_init_module); -- cgit v1.2.3-70-g09d2 From fcc63274e69f95aee9dbb7c1dc3af3d2961813cc Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Sat, 27 Mar 2010 09:37:03 -0300 Subject: V4L/DVB: V4L: dm644x_ccdc: Debug register read prints removed Signed-off-by: Vaibhav Hiremath Signed-off-by: Muralidharan Karicheri Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/davinci/dm644x_ccdc.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/davinci/dm644x_ccdc.c b/drivers/media/video/davinci/dm644x_ccdc.c index b4cc96dc99e..9876c1d8d59 100644 --- a/drivers/media/video/davinci/dm644x_ccdc.c +++ b/drivers/media/video/davinci/dm644x_ccdc.c @@ -435,7 +435,6 @@ void ccdc_config_ycbcr(void) ccdc_sbl_reset(); dev_dbg(ccdc_cfg.dev, "\nEnd of ccdc_config_ycbcr...\n"); - ccdc_readregs(); } static void ccdc_config_black_clamp(struct ccdc_black_clamp *bclamp) -- cgit v1.2.3-70-g09d2 From 085b54a24fd0c7353cd1b2d462879b7a4a4070fa Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Sat, 27 Mar 2010 09:37:07 -0300 Subject: V4L/DVB: V4L: vpfe_capture: Add call back function for interrupt clear for vpfe_cfg For the devices like AM3517, it is expected that driver clears the interrupt in ISR. Since this is device spcific, callback function added to the platform_data. Signed-off-by: Vaibhav Hiremath Signed-off-by: Muralidharan Karicheri Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/davinci/vpfe_capture.c | 24 ++++++++++++++++++++---- include/media/davinci/vpfe_capture.h | 2 ++ 2 files changed, 22 insertions(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/davinci/vpfe_capture.c b/drivers/media/video/davinci/vpfe_capture.c index 398dbe71cb8..caeac199d15 100644 --- a/drivers/media/video/davinci/vpfe_capture.c +++ b/drivers/media/video/davinci/vpfe_capture.c @@ -475,6 +475,11 @@ static int vpfe_initialize_device(struct vpfe_device *vpfe_dev) ret = ccdc_dev->hw_ops.open(vpfe_dev->pdev); if (!ret) vpfe_dev->initialized = 1; + + /* Clear all VPFE/CCDC interrupts */ + if (vpfe_dev->cfg->clr_intr) + vpfe_dev->cfg->clr_intr(-1); + unlock: mutex_unlock(&ccdc_lock); return ret; @@ -562,7 +567,7 @@ static irqreturn_t vpfe_isr(int irq, void *dev_id) /* if streaming not started, don't do anything */ if (!vpfe_dev->started) - return IRQ_HANDLED; + goto clear_intr; /* only for 6446 this will be applicable */ if (NULL != ccdc_dev->hw_ops.reset) @@ -574,7 +579,7 @@ static irqreturn_t vpfe_isr(int irq, void *dev_id) "frame format is progressive...\n"); if (vpfe_dev->cur_frm != vpfe_dev->next_frm) vpfe_process_buffer_complete(vpfe_dev); - return IRQ_HANDLED; + goto clear_intr; } /* interlaced or TB capture check which field we are in hardware */ @@ -604,7 +609,7 @@ static irqreturn_t vpfe_isr(int irq, void *dev_id) addr += vpfe_dev->field_off; ccdc_dev->hw_ops.setfbaddr(addr); } - return IRQ_HANDLED; + goto clear_intr; } /* * if one field is just being captured configure @@ -624,6 +629,10 @@ static irqreturn_t vpfe_isr(int irq, void *dev_id) */ vpfe_dev->field_id = fid; } +clear_intr: + if (vpfe_dev->cfg->clr_intr) + vpfe_dev->cfg->clr_intr(irq); + return IRQ_HANDLED; } @@ -635,8 +644,11 @@ static irqreturn_t vdint1_isr(int irq, void *dev_id) v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "\nInside vdint1_isr...\n"); /* if streaming not started, don't do anything */ - if (!vpfe_dev->started) + if (!vpfe_dev->started) { + if (vpfe_dev->cfg->clr_intr) + vpfe_dev->cfg->clr_intr(irq); return IRQ_HANDLED; + } spin_lock(&vpfe_dev->dma_queue_lock); if ((vpfe_dev->fmt.fmt.pix.field == V4L2_FIELD_NONE) && @@ -644,6 +656,10 @@ static irqreturn_t vdint1_isr(int irq, void *dev_id) vpfe_dev->cur_frm == vpfe_dev->next_frm) vpfe_schedule_next_buffer(vpfe_dev); spin_unlock(&vpfe_dev->dma_queue_lock); + + if (vpfe_dev->cfg->clr_intr) + vpfe_dev->cfg->clr_intr(irq); + return IRQ_HANDLED; } diff --git a/include/media/davinci/vpfe_capture.h b/include/media/davinci/vpfe_capture.h index 4314a5f6a08..cc973ed845a 100644 --- a/include/media/davinci/vpfe_capture.h +++ b/include/media/davinci/vpfe_capture.h @@ -94,6 +94,8 @@ struct vpfe_config { /* vpfe clock */ struct clk *vpssclk; struct clk *slaveclk; + /* Function for Clearing the interrupt */ + void (*clr_intr)(int vdint); }; struct vpfe_device { -- cgit v1.2.3-70-g09d2 From 21aa300e160f03c237d2153d9938e14a87f38e0d Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Sat, 27 Mar 2010 09:37:12 -0300 Subject: V4L/DVB: V4L: dm644x_ccdc: Add 10bit BT support Signed-off-by: Vaibhav Hiremath Signed-off-by: Muralidharan Karicheri Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/davinci/dm644x_ccdc.c | 16 +++++++++++++--- drivers/media/video/davinci/dm644x_ccdc_regs.h | 8 ++++++++ 2 files changed, 21 insertions(+), 3 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/davinci/dm644x_ccdc.c b/drivers/media/video/davinci/dm644x_ccdc.c index 9876c1d8d59..a1d353125c8 100644 --- a/drivers/media/video/davinci/dm644x_ccdc.c +++ b/drivers/media/video/davinci/dm644x_ccdc.c @@ -400,7 +400,11 @@ void ccdc_config_ycbcr(void) * configure the FID, VD, HD pin polarity, * fld,hd pol positive, vd negative, 8-bit data */ - syn_mode |= CCDC_SYN_MODE_VD_POL_NEGATIVE | CCDC_SYN_MODE_8BITS; + syn_mode |= CCDC_SYN_MODE_VD_POL_NEGATIVE; + if (ccdc_cfg.if_type == VPFE_BT656_10BIT) + syn_mode |= CCDC_SYN_MODE_10BITS; + else + syn_mode |= CCDC_SYN_MODE_8BITS; } else { /* y/c external sync mode */ syn_mode |= (((params->fid_pol & CCDC_FID_POL_MASK) << @@ -419,8 +423,13 @@ void ccdc_config_ycbcr(void) * configure the order of y cb cr in SDRAM, and disable latch * internal register on vsync */ - regw((params->pix_order << CCDC_CCDCFG_Y8POS_SHIFT) | - CCDC_LATCH_ON_VSYNC_DISABLE, CCDC_CCDCFG); + if (ccdc_cfg.if_type == VPFE_BT656_10BIT) + regw((params->pix_order << CCDC_CCDCFG_Y8POS_SHIFT) | + CCDC_LATCH_ON_VSYNC_DISABLE | CCDC_CCDCFG_BW656_10BIT, + CCDC_CCDCFG); + else + regw((params->pix_order << CCDC_CCDCFG_Y8POS_SHIFT) | + CCDC_LATCH_ON_VSYNC_DISABLE, CCDC_CCDCFG); /* * configure the horizontal line offset. This should be a @@ -826,6 +835,7 @@ static int ccdc_set_hw_if_params(struct vpfe_hw_if_param *params) case VPFE_BT656: case VPFE_YCBCR_SYNC_16: case VPFE_YCBCR_SYNC_8: + case VPFE_BT656_10BIT: ccdc_cfg.ycbcr.vd_pol = params->vdpol; ccdc_cfg.ycbcr.hd_pol = params->hdpol; break; diff --git a/drivers/media/video/davinci/dm644x_ccdc_regs.h b/drivers/media/video/davinci/dm644x_ccdc_regs.h index 6e5d0532446..b18d166f181 100644 --- a/drivers/media/video/davinci/dm644x_ccdc_regs.h +++ b/drivers/media/video/davinci/dm644x_ccdc_regs.h @@ -135,11 +135,19 @@ #define CCDC_SYN_MODE_INPMOD_SHIFT 12 #define CCDC_SYN_MODE_INPMOD_MASK 3 #define CCDC_SYN_MODE_8BITS (7 << 8) +#define CCDC_SYN_MODE_10BITS (6 << 8) +#define CCDC_SYN_MODE_11BITS (5 << 8) +#define CCDC_SYN_MODE_12BITS (4 << 8) +#define CCDC_SYN_MODE_13BITS (3 << 8) +#define CCDC_SYN_MODE_14BITS (2 << 8) +#define CCDC_SYN_MODE_15BITS (1 << 8) +#define CCDC_SYN_MODE_16BITS (0 << 8) #define CCDC_SYN_FLDMODE_MASK 1 #define CCDC_SYN_FLDMODE_SHIFT 7 #define CCDC_REC656IF_BT656_EN 3 #define CCDC_SYN_MODE_VD_POL_NEGATIVE (1 << 2) #define CCDC_CCDCFG_Y8POS_SHIFT 11 +#define CCDC_CCDCFG_BW656_10BIT (1 << 5) #define CCDC_SDOFST_FIELD_INTERLEAVED 0x249 #define CCDC_NO_CULLING 0xffff00ff #endif -- cgit v1.2.3-70-g09d2 From aa2dc9034859531206889b6bf07b5f9adae487a6 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Sat, 27 Mar 2010 09:37:16 -0300 Subject: V4L/DVB: V4L: vpfe_capture: Return 0 from suspend/resume Now Suspend/Resume functionality is being handled by respective CCDC code, so return true (0) from bridge suspend/resume function. Signed-off-by: Vaibhav Hiremath Signed-off-by: Muralidharan Karicheri Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/davinci/vpfe_capture.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/davinci/vpfe_capture.c b/drivers/media/video/davinci/vpfe_capture.c index caeac199d15..2b906753f13 100644 --- a/drivers/media/video/davinci/vpfe_capture.c +++ b/drivers/media/video/davinci/vpfe_capture.c @@ -2031,18 +2031,14 @@ static int __devexit vpfe_remove(struct platform_device *pdev) return 0; } -static int -vpfe_suspend(struct device *dev) +static int vpfe_suspend(struct device *dev) { - /* add suspend code here later */ - return -1; + return 0; } -static int -vpfe_resume(struct device *dev) +static int vpfe_resume(struct device *dev) { - /* add resume code here later */ - return -1; + return 0; } static const struct dev_pm_ops vpfe_dev_pm_ops = { -- cgit v1.2.3-70-g09d2 From e333bab73e848d72904f39c7a0f5ba6425ba41f3 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Sat, 27 Mar 2010 09:37:19 -0300 Subject: V4L/DVB: V4L: dm644x_ccdc: Add Suspend/Resume Support Signed-off-by: Vaibhav Hiremath Signed-off-by: Muralidharan Karicheri Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/davinci/dm644x_ccdc.c | 114 +++++++++++++++++++++++++ drivers/media/video/davinci/dm644x_ccdc_regs.h | 2 +- 2 files changed, 115 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/davinci/dm644x_ccdc.c b/drivers/media/video/davinci/dm644x_ccdc.c index a1d353125c8..490aafb34e2 100644 --- a/drivers/media/video/davinci/dm644x_ccdc.c +++ b/drivers/media/video/davinci/dm644x_ccdc.c @@ -101,6 +101,9 @@ static u32 ccdc_raw_bayer_pix_formats[] = static u32 ccdc_raw_yuv_pix_formats[] = {V4L2_PIX_FMT_UYVY, V4L2_PIX_FMT_YUYV}; +/* CCDC Save/Restore context */ +static u32 ccdc_ctx[CCDC_REG_END / sizeof(u32)]; + /* register access routines */ static inline u32 regr(u32 offset) { @@ -846,6 +849,87 @@ static int ccdc_set_hw_if_params(struct vpfe_hw_if_param *params) return 0; } +static void ccdc_save_context(void) +{ + ccdc_ctx[CCDC_PCR >> 2] = regr(CCDC_PCR); + ccdc_ctx[CCDC_SYN_MODE >> 2] = regr(CCDC_SYN_MODE); + ccdc_ctx[CCDC_HD_VD_WID >> 2] = regr(CCDC_HD_VD_WID); + ccdc_ctx[CCDC_PIX_LINES >> 2] = regr(CCDC_PIX_LINES); + ccdc_ctx[CCDC_HORZ_INFO >> 2] = regr(CCDC_HORZ_INFO); + ccdc_ctx[CCDC_VERT_START >> 2] = regr(CCDC_VERT_START); + ccdc_ctx[CCDC_VERT_LINES >> 2] = regr(CCDC_VERT_LINES); + ccdc_ctx[CCDC_CULLING >> 2] = regr(CCDC_CULLING); + ccdc_ctx[CCDC_HSIZE_OFF >> 2] = regr(CCDC_HSIZE_OFF); + ccdc_ctx[CCDC_SDOFST >> 2] = regr(CCDC_SDOFST); + ccdc_ctx[CCDC_SDR_ADDR >> 2] = regr(CCDC_SDR_ADDR); + ccdc_ctx[CCDC_CLAMP >> 2] = regr(CCDC_CLAMP); + ccdc_ctx[CCDC_DCSUB >> 2] = regr(CCDC_DCSUB); + ccdc_ctx[CCDC_COLPTN >> 2] = regr(CCDC_COLPTN); + ccdc_ctx[CCDC_BLKCMP >> 2] = regr(CCDC_BLKCMP); + ccdc_ctx[CCDC_FPC >> 2] = regr(CCDC_FPC); + ccdc_ctx[CCDC_FPC_ADDR >> 2] = regr(CCDC_FPC_ADDR); + ccdc_ctx[CCDC_VDINT >> 2] = regr(CCDC_VDINT); + ccdc_ctx[CCDC_ALAW >> 2] = regr(CCDC_ALAW); + ccdc_ctx[CCDC_REC656IF >> 2] = regr(CCDC_REC656IF); + ccdc_ctx[CCDC_CCDCFG >> 2] = regr(CCDC_CCDCFG); + ccdc_ctx[CCDC_FMTCFG >> 2] = regr(CCDC_FMTCFG); + ccdc_ctx[CCDC_FMT_HORZ >> 2] = regr(CCDC_FMT_HORZ); + ccdc_ctx[CCDC_FMT_VERT >> 2] = regr(CCDC_FMT_VERT); + ccdc_ctx[CCDC_FMT_ADDR0 >> 2] = regr(CCDC_FMT_ADDR0); + ccdc_ctx[CCDC_FMT_ADDR1 >> 2] = regr(CCDC_FMT_ADDR1); + ccdc_ctx[CCDC_FMT_ADDR2 >> 2] = regr(CCDC_FMT_ADDR2); + ccdc_ctx[CCDC_FMT_ADDR3 >> 2] = regr(CCDC_FMT_ADDR3); + ccdc_ctx[CCDC_FMT_ADDR4 >> 2] = regr(CCDC_FMT_ADDR4); + ccdc_ctx[CCDC_FMT_ADDR5 >> 2] = regr(CCDC_FMT_ADDR5); + ccdc_ctx[CCDC_FMT_ADDR6 >> 2] = regr(CCDC_FMT_ADDR6); + ccdc_ctx[CCDC_FMT_ADDR7 >> 2] = regr(CCDC_FMT_ADDR7); + ccdc_ctx[CCDC_PRGEVEN_0 >> 2] = regr(CCDC_PRGEVEN_0); + ccdc_ctx[CCDC_PRGEVEN_1 >> 2] = regr(CCDC_PRGEVEN_1); + ccdc_ctx[CCDC_PRGODD_0 >> 2] = regr(CCDC_PRGODD_0); + ccdc_ctx[CCDC_PRGODD_1 >> 2] = regr(CCDC_PRGODD_1); + ccdc_ctx[CCDC_VP_OUT >> 2] = regr(CCDC_VP_OUT); +} + +static void ccdc_restore_context(void) +{ + regw(ccdc_ctx[CCDC_SYN_MODE >> 2], CCDC_SYN_MODE); + regw(ccdc_ctx[CCDC_HD_VD_WID >> 2], CCDC_HD_VD_WID); + regw(ccdc_ctx[CCDC_PIX_LINES >> 2], CCDC_PIX_LINES); + regw(ccdc_ctx[CCDC_HORZ_INFO >> 2], CCDC_HORZ_INFO); + regw(ccdc_ctx[CCDC_VERT_START >> 2], CCDC_VERT_START); + regw(ccdc_ctx[CCDC_VERT_LINES >> 2], CCDC_VERT_LINES); + regw(ccdc_ctx[CCDC_CULLING >> 2], CCDC_CULLING); + regw(ccdc_ctx[CCDC_HSIZE_OFF >> 2], CCDC_HSIZE_OFF); + regw(ccdc_ctx[CCDC_SDOFST >> 2], CCDC_SDOFST); + regw(ccdc_ctx[CCDC_SDR_ADDR >> 2], CCDC_SDR_ADDR); + regw(ccdc_ctx[CCDC_CLAMP >> 2], CCDC_CLAMP); + regw(ccdc_ctx[CCDC_DCSUB >> 2], CCDC_DCSUB); + regw(ccdc_ctx[CCDC_COLPTN >> 2], CCDC_COLPTN); + regw(ccdc_ctx[CCDC_BLKCMP >> 2], CCDC_BLKCMP); + regw(ccdc_ctx[CCDC_FPC >> 2], CCDC_FPC); + regw(ccdc_ctx[CCDC_FPC_ADDR >> 2], CCDC_FPC_ADDR); + regw(ccdc_ctx[CCDC_VDINT >> 2], CCDC_VDINT); + regw(ccdc_ctx[CCDC_ALAW >> 2], CCDC_ALAW); + regw(ccdc_ctx[CCDC_REC656IF >> 2], CCDC_REC656IF); + regw(ccdc_ctx[CCDC_CCDCFG >> 2], CCDC_CCDCFG); + regw(ccdc_ctx[CCDC_FMTCFG >> 2], CCDC_FMTCFG); + regw(ccdc_ctx[CCDC_FMT_HORZ >> 2], CCDC_FMT_HORZ); + regw(ccdc_ctx[CCDC_FMT_VERT >> 2], CCDC_FMT_VERT); + regw(ccdc_ctx[CCDC_FMT_ADDR0 >> 2], CCDC_FMT_ADDR0); + regw(ccdc_ctx[CCDC_FMT_ADDR1 >> 2], CCDC_FMT_ADDR1); + regw(ccdc_ctx[CCDC_FMT_ADDR2 >> 2], CCDC_FMT_ADDR2); + regw(ccdc_ctx[CCDC_FMT_ADDR3 >> 2], CCDC_FMT_ADDR3); + regw(ccdc_ctx[CCDC_FMT_ADDR4 >> 2], CCDC_FMT_ADDR4); + regw(ccdc_ctx[CCDC_FMT_ADDR5 >> 2], CCDC_FMT_ADDR5); + regw(ccdc_ctx[CCDC_FMT_ADDR6 >> 2], CCDC_FMT_ADDR6); + regw(ccdc_ctx[CCDC_FMT_ADDR7 >> 2], CCDC_FMT_ADDR7); + regw(ccdc_ctx[CCDC_PRGEVEN_0 >> 2], CCDC_PRGEVEN_0); + regw(ccdc_ctx[CCDC_PRGEVEN_1 >> 2], CCDC_PRGEVEN_1); + regw(ccdc_ctx[CCDC_PRGODD_0 >> 2], CCDC_PRGODD_0); + regw(ccdc_ctx[CCDC_PRGODD_1 >> 2], CCDC_PRGODD_1); + regw(ccdc_ctx[CCDC_VP_OUT >> 2], CCDC_VP_OUT); + regw(ccdc_ctx[CCDC_PCR >> 2], CCDC_PCR); +} static struct ccdc_hw_device ccdc_hw_dev = { .name = "DM6446 CCDC", .owner = THIS_MODULE, @@ -954,10 +1038,40 @@ static int dm644x_ccdc_remove(struct platform_device *pdev) return 0; } +static int dm644x_ccdc_suspend(struct device *dev) +{ + /* Save CCDC context */ + ccdc_save_context(); + /* Disable CCDC */ + ccdc_enable(0); + /* Disable both master and slave clock */ + clk_disable(ccdc_cfg.mclk); + clk_disable(ccdc_cfg.sclk); + + return 0; +} + +static int dm644x_ccdc_resume(struct device *dev) +{ + /* Enable both master and slave clock */ + clk_enable(ccdc_cfg.mclk); + clk_enable(ccdc_cfg.sclk); + /* Restore CCDC context */ + ccdc_restore_context(); + + return 0; +} + +static const struct dev_pm_ops dm644x_ccdc_pm_ops = { + .suspend = dm644x_ccdc_suspend, + .resume = dm644x_ccdc_resume, +}; + static struct platform_driver dm644x_ccdc_driver = { .driver = { .name = "dm644x_ccdc", .owner = THIS_MODULE, + .pm = &dm644x_ccdc_pm_ops, }, .remove = __devexit_p(dm644x_ccdc_remove), .probe = dm644x_ccdc_probe, diff --git a/drivers/media/video/davinci/dm644x_ccdc_regs.h b/drivers/media/video/davinci/dm644x_ccdc_regs.h index b18d166f181..90370e414e2 100644 --- a/drivers/media/video/davinci/dm644x_ccdc_regs.h +++ b/drivers/media/video/davinci/dm644x_ccdc_regs.h @@ -59,7 +59,7 @@ #define CCDC_PRGODD_0 0x8c #define CCDC_PRGODD_1 0x90 #define CCDC_VP_OUT 0x94 - +#define CCDC_REG_END 0x98 /*************************************************************** * Define for various register bit mask and shifts for CCDC -- cgit v1.2.3-70-g09d2 From 844cc0dcb588ee7005c70cffd92ee7a0c1270729 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Sat, 27 Mar 2010 09:37:23 -0300 Subject: V4L/DVB: V4L: vpfe_capture: Add support for USERPTR mode of operation Signed-off-by: Vaibhav Hiremath Signed-off-by: Muralidharan Karicheri Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/davinci/vpfe_capture.c | 42 ++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 14 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/davinci/vpfe_capture.c b/drivers/media/video/davinci/vpfe_capture.c index 2b906753f13..d4676ad41f3 100644 --- a/drivers/media/video/davinci/vpfe_capture.c +++ b/drivers/media/video/davinci/vpfe_capture.c @@ -539,6 +539,16 @@ static void vpfe_schedule_next_buffer(struct vpfe_device *vpfe_dev) list_del(&vpfe_dev->next_frm->queue); vpfe_dev->next_frm->state = VIDEOBUF_ACTIVE; addr = videobuf_to_dma_contig(vpfe_dev->next_frm); + + ccdc_dev->hw_ops.setfbaddr(addr); +} + +static void vpfe_schedule_bottom_field(struct vpfe_device *vpfe_dev) +{ + unsigned long addr; + + addr = videobuf_to_dma_contig(vpfe_dev->cur_frm); + addr += vpfe_dev->field_off; ccdc_dev->hw_ops.setfbaddr(addr); } @@ -559,7 +569,6 @@ static irqreturn_t vpfe_isr(int irq, void *dev_id) { struct vpfe_device *vpfe_dev = dev_id; enum v4l2_field field; - unsigned long addr; int fid; v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "\nStarting vpfe_isr...\n"); @@ -604,10 +613,7 @@ static irqreturn_t vpfe_isr(int irq, void *dev_id) * the CCDC memory address */ if (field == V4L2_FIELD_SEQ_TB) { - addr = - videobuf_to_dma_contig(vpfe_dev->cur_frm); - addr += vpfe_dev->field_off; - ccdc_dev->hw_ops.setfbaddr(addr); + vpfe_schedule_bottom_field(vpfe_dev); } goto clear_intr; } @@ -1234,7 +1240,10 @@ static int vpfe_videobuf_setup(struct videobuf_queue *vq, struct vpfe_device *vpfe_dev = fh->vpfe_dev; v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_setup\n"); - *size = config_params.device_bufsize; + *size = vpfe_dev->fmt.fmt.pix.sizeimage; + if (vpfe_dev->memory == V4L2_MEMORY_MMAP && + vpfe_dev->fmt.fmt.pix.sizeimage > config_params.device_bufsize) + *size = config_params.device_bufsize; if (*count < config_params.min_numbuffers) *count = config_params.min_numbuffers; @@ -1249,6 +1258,8 @@ static int vpfe_videobuf_prepare(struct videobuf_queue *vq, { struct vpfe_fh *fh = vq->priv_data; struct vpfe_device *vpfe_dev = fh->vpfe_dev; + unsigned long addr; + int ret; v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_prepare\n"); @@ -1258,8 +1269,18 @@ static int vpfe_videobuf_prepare(struct videobuf_queue *vq, vb->height = vpfe_dev->fmt.fmt.pix.height; vb->size = vpfe_dev->fmt.fmt.pix.sizeimage; vb->field = field; + + ret = videobuf_iolock(vq, vb, NULL);; + if (ret < 0) + return ret; + + addr = videobuf_to_dma_contig(vb); + /* Make sure user addresses are aligned to 32 bytes */ + if (!ALIGN(addr, 32)) + return -EINVAL; + + vb->state = VIDEOBUF_PREPARED; } - vb->state = VIDEOBUF_PREPARED; return 0; } @@ -1327,13 +1348,6 @@ static int vpfe_reqbufs(struct file *file, void *priv, return -EINVAL; } - if (V4L2_MEMORY_USERPTR == req_buf->memory) { - /* we don't support user ptr IO */ - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_reqbufs:" - " USERPTR IO not supported\n"); - return -EINVAL; - } - ret = mutex_lock_interruptible(&vpfe_dev->lock); if (ret) return ret; -- cgit v1.2.3-70-g09d2 From 63b59cecb2fa0a274d1c7240112460816d826988 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Sat, 27 Mar 2010 09:37:54 -0300 Subject: V4L/DVB: V4L: tvp514x: Add Powerup sequence during s_input to lock the signal properly For the sequence streamon -> streamoff and again s_input, it fails to lock the signal, since streamoff puts TVP514x into power off state which leads to failure in sub-sequent s_input. So add powerup sequence in s_routing (if disabled), since it is important to lock the signal at this stage. Signed-off-by: Vaibhav Hiremath Signed-off-by: Sudhakar Rajashekhara Signed-off-by: Muralidharan Karicheri Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvp514x.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/tvp514x.c b/drivers/media/video/tvp514x.c index e4815a1806e..e826114b7fb 100644 --- a/drivers/media/video/tvp514x.c +++ b/drivers/media/video/tvp514x.c @@ -79,6 +79,8 @@ struct tvp514x_std_info { }; static struct tvp514x_reg tvp514x_reg_list_default[0x40]; + +static int tvp514x_s_stream(struct v4l2_subdev *sd, int enable); /** * struct tvp514x_decoder - TVP5146/47 decoder object * @sd: Subdevice Slave handle @@ -644,6 +646,17 @@ static int tvp514x_s_routing(struct v4l2_subdev *sd, /* Index out of bound */ return -EINVAL; + /* + * For the sequence streamon -> streamoff and again s_input + * it fails to lock the signal, since streamoff puts TVP514x + * into power off state which leads to failure in sub-sequent s_input. + * + * So power up the TVP514x device here, since it is important to lock + * the signal at this stage. + */ + if (!decoder->streaming) + tvp514x_s_stream(sd, 1); + input_sel = input; output_sel = output; -- cgit v1.2.3-70-g09d2 From be1da9ee83eb5c27a69b30577232d1ec72876e7a Mon Sep 17 00:00:00 2001 From: Costantino Leandro Date: Tue, 23 Mar 2010 12:31:16 -0300 Subject: V4L/DVB: gspca - t613: Add color controls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Rename controls to fit real behaviour - Add global gain , r/b balance. Signed-off-by: Costantino Leandro Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/t613.c | 159 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 150 insertions(+), 9 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c index 8c7dadef821..63014372adb 100644 --- a/drivers/media/video/gspca/t613.c +++ b/drivers/media/video/gspca/t613.c @@ -44,7 +44,10 @@ struct sd { u8 gamma; u8 sharpness; u8 freq; - u8 whitebalance; + u8 red_balance; /* split balance */ + u8 blue_balance; + u8 global_gain; /* aka gain */ + u8 whitebalance; /* set default r/g/b and activate */ u8 mirror; u8 effect; @@ -70,8 +73,17 @@ static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val); static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); + + static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val); static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val); +static int sd_setblue_balance(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val); +static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val); +static int sd_setglobal_gain(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getglobal_gain(struct gspca_dev *gspca_dev, __s32 *val); + static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val); static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val); static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val); @@ -79,6 +91,7 @@ static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val); static int sd_querymenu(struct gspca_dev *gspca_dev, struct v4l2_querymenu *menu); + static const struct ctrl sd_ctrls[] = { { { @@ -139,7 +152,7 @@ static const struct ctrl sd_ctrls[] = { }, { { - .id = V4L2_CID_GAIN, /* here, i activate only the lowlight, + .id = V4L2_CID_BACKLIGHT_COMPENSATION, /* Activa lowlight, * some apps dont bring up the * backligth_compensation control) */ .type = V4L2_CTRL_TYPE_INTEGER, @@ -183,7 +196,7 @@ static const struct ctrl sd_ctrls[] = { { { - .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE, + .id = V4L2_CID_AUTO_WHITE_BALANCE, .type = V4L2_CTRL_TYPE_INTEGER, .name = "White Balance", .minimum = 0, @@ -223,6 +236,48 @@ static const struct ctrl sd_ctrls[] = { .set = sd_seteffect, .get = sd_geteffect }, + { + { + .id = V4L2_CID_BLUE_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Blue Balance", + .minimum = 0x10, + .maximum = 0x40, + .step = 1, +#define BLUE_BALANCE_DEF 0x20 + .default_value = BLUE_BALANCE_DEF, + }, + .set = sd_setblue_balance, + .get = sd_getblue_balance, + }, + { + { + .id = V4L2_CID_RED_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Red Balance", + .minimum = 0x10, + .maximum = 0x40, + .step = 1, +#define RED_BALANCE_DEF 0x20 + .default_value = RED_BALANCE_DEF, + }, + .set = sd_setred_balance, + .get = sd_getred_balance, + }, + { + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Gain", + .minimum = 0x10, + .maximum = 0x40, + .step = 1, +#define global_gain_DEF 0x20 + .default_value = global_gain_DEF, + }, + .set = sd_setglobal_gain, + .get = sd_getglobal_gain, + }, }; static char *effects_control[] = { @@ -651,6 +706,10 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->whitebalance = WHITE_BALANCE_DEF; sd->sharpness = SHARPNESS_DEF; sd->effect = EFFECTS_DEF; + sd->red_balance = RED_BALANCE_DEF; + sd->blue_balance = BLUE_BALANCE_DEF; + sd->global_gain = global_gain_DEF; + return 0; } @@ -702,18 +761,40 @@ static void setgamma(struct gspca_dev *gspca_dev) reg_w_ixbuf(gspca_dev, 0x90, gamma_table[sd->gamma], sizeof gamma_table[0]); } +static void setglobalgain(struct gspca_dev *gspca_dev) +{ -static void setwhitebalance(struct gspca_dev *gspca_dev) + struct sd *sd = (struct sd *) gspca_dev; + reg_w(gspca_dev, (sd->red_balance << 8) + 0x87); + reg_w(gspca_dev, (sd->blue_balance << 8) + 0x88); + reg_w(gspca_dev, (sd->global_gain << 8) + 0x89); +} + +/* Generic fnc for r/b balance, exposure and whitebalance */ +static void setbalance(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - u8 white_balance[8] = - {0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38}; + /* on whitebalance leave defaults values */ + if (sd->whitebalance) { + reg_w(gspca_dev, 0x3c80); + } else { + reg_w(gspca_dev, 0x3880); + /* shoud we wait here.. */ + /* update and reset 'global gain' with webcam parameters */ + sd->red_balance = reg_r(gspca_dev, 0x0087); + sd->blue_balance = reg_r(gspca_dev, 0x0088); + sd->global_gain = reg_r(gspca_dev, 0x0089); + setglobalgain(gspca_dev); + } + +} - if (sd->whitebalance) - white_balance[7] = 0x3c; - reg_w_buf(gspca_dev, white_balance, sizeof white_balance); + +static void setwhitebalance(struct gspca_dev *gspca_dev) +{ + setbalance(gspca_dev); } static void setsharpness(struct gspca_dev *gspca_dev) @@ -1027,6 +1108,66 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, gspca_frame_add(gspca_dev, INTER_PACKET, data, len); } + +static int sd_setblue_balance(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->blue_balance = val; + if (gspca_dev->streaming) + reg_w(gspca_dev, (val << 8) + 0x88); + return 0; +} + +static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->blue_balance; + return 0; +} + +static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->red_balance = val; + if (gspca_dev->streaming) + reg_w(gspca_dev, (val << 8) + 0x87); + + return 0; +} + +static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->red_balance; + return 0; +} + + + +static int sd_setglobal_gain(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->global_gain = val; + if (gspca_dev->streaming) + setglobalgain(gspca_dev); + + return 0; +} + +static int sd_getglobal_gain(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->global_gain; + return 0; +} + + static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; -- cgit v1.2.3-70-g09d2 From dbad345e6a6159e5d8aec45533d299aa2a138aff Mon Sep 17 00:00:00 2001 From: Jean-François Moine Date: Mon, 29 Mar 2010 03:51:18 -0300 Subject: V4L/DVB: sn9c102 / zc0301: Handle webcams when no gspca subdriver conflict MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some webcams handled by both sn9c102 or zc0301 and some gspca subdrivers (sonixb, sonixj and zc3xx) were not handled when gspca was generated but not the associated subdrivers. Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/sn9c102/sn9c102_devtable.h | 18 +++++++++--------- drivers/media/video/zc0301/zc0301_sensor.h | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/sn9c102/sn9c102_devtable.h b/drivers/media/video/sn9c102/sn9c102_devtable.h index cc40d6ba9f2..522ba3f4c28 100644 --- a/drivers/media/video/sn9c102/sn9c102_devtable.h +++ b/drivers/media/video/sn9c102/sn9c102_devtable.h @@ -40,12 +40,12 @@ struct sn9c102_device; static const struct usb_device_id sn9c102_id_table[] = { /* SN9C101 and SN9C102 */ -#if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE +#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE { SN9C102_USB_DEVICE(0x0c45, 0x6001, BRIDGE_SN9C102), }, { SN9C102_USB_DEVICE(0x0c45, 0x6005, BRIDGE_SN9C102), }, #endif { SN9C102_USB_DEVICE(0x0c45, 0x6007, BRIDGE_SN9C102), }, -#if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE +#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE { SN9C102_USB_DEVICE(0x0c45, 0x6009, BRIDGE_SN9C102), }, { SN9C102_USB_DEVICE(0x0c45, 0x600d, BRIDGE_SN9C102), }, /* { SN9C102_USB_DEVICE(0x0c45, 0x6011, BRIDGE_SN9C102), }, OV6650 */ @@ -53,13 +53,13 @@ static const struct usb_device_id sn9c102_id_table[] = { { SN9C102_USB_DEVICE(0x0c45, 0x6019, BRIDGE_SN9C102), }, { SN9C102_USB_DEVICE(0x0c45, 0x6024, BRIDGE_SN9C102), }, { SN9C102_USB_DEVICE(0x0c45, 0x6025, BRIDGE_SN9C102), }, -#if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE +#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE { SN9C102_USB_DEVICE(0x0c45, 0x6028, BRIDGE_SN9C102), }, { SN9C102_USB_DEVICE(0x0c45, 0x6029, BRIDGE_SN9C102), }, #endif { SN9C102_USB_DEVICE(0x0c45, 0x602a, BRIDGE_SN9C102), }, { SN9C102_USB_DEVICE(0x0c45, 0x602b, BRIDGE_SN9C102), }, -#if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE +#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE { SN9C102_USB_DEVICE(0x0c45, 0x602c, BRIDGE_SN9C102), }, /* { SN9C102_USB_DEVICE(0x0c45, 0x602d, BRIDGE_SN9C102), }, HV7131R */ #endif @@ -74,7 +74,7 @@ static const struct usb_device_id sn9c102_id_table[] = { { SN9C102_USB_DEVICE(0x0c45, 0x608b, BRIDGE_SN9C103), }, { SN9C102_USB_DEVICE(0x0c45, 0x608c, BRIDGE_SN9C103), }, /* { SN9C102_USB_DEVICE(0x0c45, 0x608e, BRIDGE_SN9C103), }, CISVF10 */ -#if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE +#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE { SN9C102_USB_DEVICE(0x0c45, 0x608f, BRIDGE_SN9C103), }, #endif { SN9C102_USB_DEVICE(0x0c45, 0x60a0, BRIDGE_SN9C103), }, @@ -86,7 +86,7 @@ static const struct usb_device_id sn9c102_id_table[] = { { SN9C102_USB_DEVICE(0x0c45, 0x60ac, BRIDGE_SN9C103), }, { SN9C102_USB_DEVICE(0x0c45, 0x60ae, BRIDGE_SN9C103), }, { SN9C102_USB_DEVICE(0x0c45, 0x60af, BRIDGE_SN9C103), }, -#if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE +#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE { SN9C102_USB_DEVICE(0x0c45, 0x60b0, BRIDGE_SN9C103), }, #endif { SN9C102_USB_DEVICE(0x0c45, 0x60b2, BRIDGE_SN9C103), }, @@ -97,7 +97,7 @@ static const struct usb_device_id sn9c102_id_table[] = { { SN9C102_USB_DEVICE(0x0c45, 0x60bc, BRIDGE_SN9C103), }, { SN9C102_USB_DEVICE(0x0c45, 0x60be, BRIDGE_SN9C103), }, /* SN9C105 */ -#if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE +#if !defined CONFIG_USB_GSPCA_SONIXJ && !defined CONFIG_USB_GSPCA_SONIXJ_MODULE { SN9C102_USB_DEVICE(0x045e, 0x00f5, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x045e, 0x00f7, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0471, 0x0327, BRIDGE_SN9C105), }, @@ -121,11 +121,11 @@ static const struct usb_device_id sn9c102_id_table[] = { { SN9C102_USB_DEVICE(0x0c45, 0x610f, BRIDGE_SN9C120), }, { SN9C102_USB_DEVICE(0x0c45, 0x6130, BRIDGE_SN9C120), }, /* { SN9C102_USB_DEVICE(0x0c45, 0x6138, BRIDGE_SN9C120), }, MO8000 */ -#if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE +#if !defined CONFIG_USB_GSPCA_SONIXJ && !defined CONFIG_USB_GSPCA_SONIXJ_MODULE { SN9C102_USB_DEVICE(0x0c45, 0x613a, BRIDGE_SN9C120), }, #endif { SN9C102_USB_DEVICE(0x0c45, 0x613b, BRIDGE_SN9C120), }, -#if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE +#if !defined CONFIG_USB_GSPCA_SONIXJ && !defined CONFIG_USB_GSPCA_SONIXJ_MODULE { SN9C102_USB_DEVICE(0x0c45, 0x613c, BRIDGE_SN9C120), }, { SN9C102_USB_DEVICE(0x0c45, 0x613e, BRIDGE_SN9C120), }, #endif diff --git a/drivers/media/video/zc0301/zc0301_sensor.h b/drivers/media/video/zc0301/zc0301_sensor.h index 3a408de91b9..0be783c203f 100644 --- a/drivers/media/video/zc0301/zc0301_sensor.h +++ b/drivers/media/video/zc0301/zc0301_sensor.h @@ -58,7 +58,7 @@ zc0301_attach_sensor(struct zc0301_device* cam, struct zc0301_sensor* sensor); .idProduct = (prod), \ .bInterfaceClass = (intclass) -#if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE +#if !defined CONFIG_USB_GSPCA_ZC3XX && !defined CONFIG_USB_GSPCA_ZC3XX_MODULE #define ZC0301_ID_TABLE \ static const struct usb_device_id zc0301_id_table[] = { \ { ZC0301_USB_DEVICE(0x046d, 0x08ae, 0xff), }, /* PAS202 */ \ -- cgit v1.2.3-70-g09d2 From 1e4d05bc95a0fe2972c5c91ed45466587d07cd2c Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 4 Mar 2010 07:51:25 -0300 Subject: V4L/DVB: uvcvideo: Add support for unbranded Arkmicro 18ec:3290 webcams The camera requires the PROBE_DEF quirk. Add a corresponding entry in the device IDs list. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_driver.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index 86ff8c12ea5..aa334a33777 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c @@ -2169,6 +2169,15 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, .driver_info = UVC_QUIRK_PROBE_MINMAX }, + /* Arkmicro unbranded */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x18ec, + .idProduct = 0x3290, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_QUIRK_PROBE_DEF }, /* Bodelin ProScopeHR */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_DEV_HI -- cgit v1.2.3-70-g09d2 From f129b03ba272c86c42ad476684caa0d6109cb383 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sat, 13 Mar 2010 18:12:15 -0300 Subject: V4L/DVB: uvcvideo: Add support for Packard Bell EasyNote MX52 integrated webcam The camera requires the STREAM_NO_FID quirk. Add a corresponding entry in the device IDs list. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_driver.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index aa334a33777..72a705802f1 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c @@ -2105,6 +2105,15 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, .driver_info = UVC_QUIRK_STREAM_NO_FID }, + /* Syntek (Packard Bell EasyNote MX52 */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x174f, + .idProduct = 0x8a12, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_QUIRK_STREAM_NO_FID }, /* Syntek (Asus F9SG) */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, -- cgit v1.2.3-70-g09d2 From 48213fe3f981d2cbccd926d6858fa9cf8617beed Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 20 Jan 2010 12:12:57 -0300 Subject: V4L/DVB: v4l: Add V4L2_CID_IRIS_ABSOLUTE and V4L2_CID_IRIS_RELATIVE controls Those control, as their names imply, control the camera aperture settings. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/v4l/compat.xml | 11 +++++++++++ Documentation/DocBook/v4l/controls.xml | 19 +++++++++++++++++++ Documentation/DocBook/v4l/videodev2.h.xml | 3 +++ drivers/media/video/v4l2-common.c | 3 +++ include/linux/videodev2.h | 3 +++ 5 files changed, 39 insertions(+) (limited to 'drivers/media/video') diff --git a/Documentation/DocBook/v4l/compat.xml b/Documentation/DocBook/v4l/compat.xml index b9dbdf9e6d2..854235b5208 100644 --- a/Documentation/DocBook/v4l/compat.xml +++ b/Documentation/DocBook/v4l/compat.xml @@ -2332,6 +2332,17 @@ more information. +
+ V4L2 in Linux 2.6.34 + + + Added +V4L2_CID_IRIS_ABSOLUTE and +V4L2_CID_IRIS_RELATIVE controls to the + Camera controls class. + + +
diff --git a/Documentation/DocBook/v4l/controls.xml b/Documentation/DocBook/v4l/controls.xml index e1bdbb6eff8..7e0c6874713 100644 --- a/Documentation/DocBook/v4l/controls.xml +++ b/Documentation/DocBook/v4l/controls.xml @@ -1830,6 +1830,25 @@ wide-angle direction. The zoom speed unit is driver-specific. + + V4L2_CID_IRIS_ABSOLUTE  + integer + This control sets the +camera's aperture to the specified value. The unit is undefined. +Larger values open the iris wider, smaller values close it. + + + + + V4L2_CID_IRIS_RELATIVE  + integer + This control modifies the +camera's aperture by the specified amount. The unit is undefined. +Positive values open the iris one step further, negative values close +it one step further. This is a write-only control. + + + V4L2_CID_PRIVACY  boolean diff --git a/Documentation/DocBook/v4l/videodev2.h.xml b/Documentation/DocBook/v4l/videodev2.h.xml index 06832594065..c18dfebedef 100644 --- a/Documentation/DocBook/v4l/videodev2.h.xml +++ b/Documentation/DocBook/v4l/videodev2.h.xml @@ -1271,6 +1271,9 @@ enum v4l2_exposure_auto_type { #define V4L2_CID_PRIVACY (V4L2_CID_CAMERA_CLASS_BASE+16) +#define V4L2_CID_IRIS_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+17) +#define V4L2_CID_IRIS_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE+18) + /* FM Modulator class control IDs */ #define V4L2_CID_FM_TX_CLASS_BASE (V4L2_CTRL_CLASS_FM_TX | 0x900) #define V4L2_CID_FM_TX_CLASS (V4L2_CTRL_CLASS_FM_TX | 1) diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index cd1f21d9b07..67944f53a79 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -489,6 +489,8 @@ const char *v4l2_ctrl_get_name(u32 id) case V4L2_CID_FOCUS_ABSOLUTE: return "Focus, Absolute"; case V4L2_CID_FOCUS_RELATIVE: return "Focus, Relative"; case V4L2_CID_FOCUS_AUTO: return "Focus, Automatic"; + case V4L2_CID_IRIS_ABSOLUTE: return "Iris, Absolute"; + case V4L2_CID_IRIS_RELATIVE: return "Iris, Relative"; case V4L2_CID_ZOOM_ABSOLUTE: return "Zoom, Absolute"; case V4L2_CID_ZOOM_RELATIVE: return "Zoom, Relative"; case V4L2_CID_ZOOM_CONTINUOUS: return "Zoom, Continuous"; @@ -643,6 +645,7 @@ int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 ste case V4L2_CID_PAN_RELATIVE: case V4L2_CID_TILT_RELATIVE: case V4L2_CID_FOCUS_RELATIVE: + case V4L2_CID_IRIS_RELATIVE: case V4L2_CID_ZOOM_RELATIVE: qctrl->flags |= V4L2_CTRL_FLAG_WRITE_ONLY; break; diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 6fb0b2daa5b..2559b182b8c 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -1282,6 +1282,9 @@ enum v4l2_exposure_auto_type { #define V4L2_CID_PRIVACY (V4L2_CID_CAMERA_CLASS_BASE+16) +#define V4L2_CID_IRIS_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+17) +#define V4L2_CID_IRIS_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE+18) + /* FM Modulator class control IDs */ #define V4L2_CID_FM_TX_CLASS_BASE (V4L2_CTRL_CLASS_FM_TX | 0x900) #define V4L2_CID_FM_TX_CLASS (V4L2_CTRL_CLASS_FM_TX | 1) -- cgit v1.2.3-70-g09d2 From 35a00c41ea8b280cb629503c735daf20cdf0f9f8 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 20 Jan 2010 12:13:46 -0300 Subject: V4L/DVB: uvcvideo: Support iris absolute and relative controls Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_ctrl.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c index 6d3850b3716..5d6d7bda233 100644 --- a/drivers/media/video/uvc/uvc_ctrl.c +++ b/drivers/media/video/uvc/uvc_ctrl.c @@ -561,6 +561,26 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = { .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN, .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN, }, + { + .id = V4L2_CID_IRIS_ABSOLUTE, + .name = "Iris, Absolute", + .entity = UVC_GUID_UVC_CAMERA, + .selector = UVC_CT_IRIS_ABSOLUTE_CONTROL, + .size = 16, + .offset = 0, + .v4l2_type = V4L2_CTRL_TYPE_INTEGER, + .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, + }, + { + .id = V4L2_CID_IRIS_RELATIVE, + .name = "Iris, Relative", + .entity = UVC_GUID_UVC_CAMERA, + .selector = UVC_CT_IRIS_RELATIVE_CONTROL, + .size = 8, + .offset = 0, + .v4l2_type = V4L2_CTRL_TYPE_INTEGER, + .data_type = UVC_CTRL_DATA_TYPE_SIGNED, + }, { .id = V4L2_CID_ZOOM_ABSOLUTE, .name = "Zoom, Absolute", -- cgit v1.2.3-70-g09d2 From ed3de6015a920c131fbcc770fb95097fde592d86 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 31 Mar 2010 12:29:26 -0300 Subject: V4L/DVB: uvcvideo: Use POLLOUT and POLLWRNORM for output devices The V4L2 specification requires drivers to use the write events in the file operations poll handler for output devices. The uvcvideo driver erroneously used read events for all devices. Fix this. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_queue.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c index 4a925a31b0e..133c78d113a 100644 --- a/drivers/media/video/uvc/uvc_queue.c +++ b/drivers/media/video/uvc/uvc_queue.c @@ -388,8 +388,12 @@ unsigned int uvc_queue_poll(struct uvc_video_queue *queue, struct file *file, poll_wait(file, &buf->wait, wait); if (buf->state == UVC_BUF_STATE_DONE || - buf->state == UVC_BUF_STATE_ERROR) - mask |= POLLIN | POLLRDNORM; + buf->state == UVC_BUF_STATE_ERROR) { + if (queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + mask |= POLLIN | POLLRDNORM; + else + mask |= POLLOUT | POLLWRNORM; + } done: mutex_unlock(&queue->mutex); -- cgit v1.2.3-70-g09d2 From d152b8b62421c441bea4eb5d92e9d1b4883fd201 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 20 Mar 2010 00:23:30 -0300 Subject: V4L/DVB: saa7134: use a full scancode table for M135A Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-keymaps.c | 100 ++++++++++++++-------------- drivers/media/video/saa7134/saa7134-input.c | 4 +- include/media/ir-common.h | 2 +- 3 files changed, 54 insertions(+), 52 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/IR/ir-keymaps.c b/drivers/media/IR/ir-keymaps.c index dfc777b78de..55e7acd7209 100644 --- a/drivers/media/IR/ir-keymaps.c +++ b/drivers/media/IR/ir-keymaps.c @@ -122,55 +122,57 @@ static struct ir_scancode ir_codes_avermedia_dvbt[] = { }; IR_TABLE(avermedia_dvbt, IR_TYPE_UNKNOWN, ir_codes_avermedia_dvbt); -/* Mauro Carvalho Chehab */ -static struct ir_scancode ir_codes_avermedia_m135a[] = { - { 0x00, KEY_POWER2 }, - { 0x2e, KEY_DOT }, /* '.' */ - { 0x01, KEY_MODE }, /* TV/FM */ - - { 0x05, KEY_1 }, - { 0x06, KEY_2 }, - { 0x07, KEY_3 }, - { 0x09, KEY_4 }, - { 0x0a, KEY_5 }, - { 0x0b, KEY_6 }, - { 0x0d, KEY_7 }, - { 0x0e, KEY_8 }, - { 0x0f, KEY_9 }, - { 0x11, KEY_0 }, - - { 0x13, KEY_RIGHT }, /* -> */ - { 0x12, KEY_LEFT }, /* <- */ - - { 0x17, KEY_SLEEP }, /* Capturar Imagem */ - { 0x10, KEY_SHUFFLE }, /* Amostra */ - - /* FIXME: The keys bellow aren't ok */ - - { 0x43, KEY_CHANNELUP }, - { 0x42, KEY_CHANNELDOWN }, - { 0x1f, KEY_VOLUMEUP }, - { 0x1e, KEY_VOLUMEDOWN }, - { 0x0c, KEY_ENTER }, - - { 0x14, KEY_MUTE }, - { 0x08, KEY_AUDIO }, - - { 0x03, KEY_TEXT }, - { 0x04, KEY_EPG }, - { 0x2b, KEY_TV2 }, /* TV2 */ - - { 0x1d, KEY_RED }, - { 0x1c, KEY_YELLOW }, - { 0x41, KEY_GREEN }, - { 0x40, KEY_BLUE }, - - { 0x1a, KEY_PLAYPAUSE }, - { 0x19, KEY_RECORD }, - { 0x18, KEY_PLAY }, - { 0x1b, KEY_STOP }, -}; -IR_TABLE(avermedia_m135a, IR_TYPE_UNKNOWN, ir_codes_avermedia_m135a); +/* + * Avermedia M135A with IR model RM-JX + * The same codes exist on both Positivo (BR) and original IR + * Mauro Carvalho Chehab + */ +static struct ir_scancode ir_codes_avermedia_m135a_rm_jx[] = { + { 0x0200, KEY_POWER2 }, + { 0x022e, KEY_DOT }, /* '.' */ + { 0x0201, KEY_MODE }, /* TV/FM or SOURCE */ + + { 0x0205, KEY_1 }, + { 0x0206, KEY_2 }, + { 0x0207, KEY_3 }, + { 0x0209, KEY_4 }, + { 0x020a, KEY_5 }, + { 0x020b, KEY_6 }, + { 0x020d, KEY_7 }, + { 0x020e, KEY_8 }, + { 0x020f, KEY_9 }, + { 0x0211, KEY_0 }, + + { 0x0213, KEY_RIGHT }, /* -> or L */ + { 0x0212, KEY_LEFT }, /* <- or R */ + + { 0x0217, KEY_SLEEP }, /* Capturar Imagem or Snapshot */ + { 0x0210, KEY_SHUFFLE }, /* Amostra or 16 chan prev */ + + { 0x0303, KEY_CHANNELUP }, + { 0x0302, KEY_CHANNELDOWN }, + { 0x021f, KEY_VOLUMEUP }, + { 0x021e, KEY_VOLUMEDOWN }, + { 0x020c, KEY_ENTER }, /* Full Screen */ + + { 0x0214, KEY_MUTE }, + { 0x0208, KEY_AUDIO }, + + { 0x0203, KEY_TEXT }, /* Teletext */ + { 0x0204, KEY_EPG }, + { 0x022b, KEY_TV2 }, /* TV2 or PIP */ + + { 0x021d, KEY_RED }, + { 0x021c, KEY_YELLOW }, + { 0x0301, KEY_GREEN }, + { 0x0300, KEY_BLUE }, + + { 0x021a, KEY_PLAYPAUSE }, + { 0x0219, KEY_RECORD }, + { 0x0218, KEY_PLAY }, + { 0x021b, KEY_STOP }, +}; +IR_TABLE(aver-m135a-RM-JX, IR_TYPE_NEC, ir_codes_avermedia_m135a_rm_jx); /* Oldrich Jedlicka */ static struct ir_scancode ir_codes_avermedia_cardbus[] = { diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index ac62b77e5ed..241195e8be3 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -525,9 +525,9 @@ int saa7134_input_init1(struct saa7134_dev *dev) saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4); break; case SAA7134_BOARD_AVERMEDIA_M135A: - ir_codes = &ir_codes_avermedia_m135a_table; + ir_codes = &ir_codes_avermedia_m135a_rm_jx_table; mask_keydown = 0x0040000; - mask_keycode = 0x00013f; + mask_keycode = 0xffff; nec_gpio = 1; break; case SAA7134_BOARD_AVERMEDIA_777: diff --git a/include/media/ir-common.h b/include/media/ir-common.h index c66298062d3..c30b28384d8 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -102,7 +102,7 @@ void ir_rc5_timer_keyup(unsigned long data); extern struct ir_scancode_table ir_codes_empty_table; extern struct ir_scancode_table ir_codes_avermedia_table; extern struct ir_scancode_table ir_codes_avermedia_dvbt_table; -extern struct ir_scancode_table ir_codes_avermedia_m135a_table; +extern struct ir_scancode_table ir_codes_avermedia_m135a_rm_jx_table; extern struct ir_scancode_table ir_codes_avermedia_cardbus_table; extern struct ir_scancode_table ir_codes_apac_viewcomp_table; extern struct ir_scancode_table ir_codes_pixelview_table; -- cgit v1.2.3-70-g09d2 From 0210894956cf57d525d56341cc3e0f3d5d2db659 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 20 Mar 2010 00:25:37 -0300 Subject: V4L/DVB: saa7134: add code to allow changing IR protocol Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-input.c | 64 +++++++++++++++++++++++++++-- include/media/ir-common.h | 3 ++ 2 files changed, 63 insertions(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 241195e8be3..7e6f125e4e3 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -421,6 +421,10 @@ static void saa7134_input_timer(unsigned long data) void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir) { + if (ir->running) + return; + + ir->running = 1; if (ir->polling) { setup_timer(&ir->timer, saa7134_input_timer, (unsigned long)dev); @@ -448,8 +452,50 @@ void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir) void saa7134_ir_stop(struct saa7134_dev *dev) { + struct card_ir *ir = dev->remote; + + if (!ir->running) + return; if (dev->remote->polling) del_timer_sync(&dev->remote->timer); + else if (ir->rc5_gpio) + del_timer_sync(&ir->timer_end); + else if (ir->nec_gpio) + tasklet_kill(&ir->tlet); + ir->running = 0; +} + +int saa7134_ir_change_protocol(void *priv, u64 ir_type) +{ + struct saa7134_dev *dev = priv; + struct card_ir *ir = dev->remote; + u32 nec_gpio, rc5_gpio; + + if (ir_type == IR_TYPE_RC5) { + dprintk("Changing protocol to RC5\n"); + nec_gpio = 0; + rc5_gpio = 1; + } else if (ir_type == IR_TYPE_NEC) { + dprintk("Changing protocol to NEC\n"); + nec_gpio = 1; + rc5_gpio = 0; + } else { + dprintk("IR protocol type %ud is not supported\n", + (unsigned)ir_type); + return -EINVAL; + } + + if (ir->running) { + saa7134_ir_stop(dev); + ir->nec_gpio = nec_gpio; + ir->rc5_gpio = rc5_gpio; + saa7134_ir_start(dev, ir); + } else { + ir->nec_gpio = nec_gpio; + ir->rc5_gpio = rc5_gpio; + } + + return 0; } int saa7134_input_init1(struct saa7134_dev *dev) @@ -698,6 +744,9 @@ int saa7134_input_init1(struct saa7134_dev *dev) } ir->dev = input_dev; + dev->remote = ir; + + ir->running = 0; /* init hardware-specific stuff */ ir->mask_keycode = mask_keycode; @@ -713,6 +762,14 @@ int saa7134_input_init1(struct saa7134_dev *dev) snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(dev->pci)); + if (ir_codes->ir_type != IR_TYPE_OTHER) { + ir->props.allowed_protos = IR_TYPE_RC5 | IR_TYPE_NEC; + ir->props.priv = dev; + ir->props.change_protocol = saa7134_ir_change_protocol; + + /* Set IR protocol */ + saa7134_ir_change_protocol(ir->props.priv, ir_codes->ir_type); + } err = ir_input_init(input_dev, &ir->ir, ir_type); if (err < 0) goto err_out_free; @@ -730,13 +787,12 @@ int saa7134_input_init1(struct saa7134_dev *dev) } input_dev->dev.parent = &dev->pci->dev; - dev->remote = ir; - saa7134_ir_start(dev, ir); - - err = ir_input_register(ir->dev, ir_codes, NULL, MODULE_NAME); + err = ir_input_register(ir->dev, ir_codes, &ir->props, MODULE_NAME); if (err) goto err_out_stop; + saa7134_ir_start(dev, ir); + /* the remote isn't as bouncy as a keyboard */ ir->dev->rep[REP_DELAY] = repeat_delay; ir->dev->rep[REP_PERIOD] = repeat_period; diff --git a/include/media/ir-common.h b/include/media/ir-common.h index c30b28384d8..41469b79ad1 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -51,6 +51,9 @@ struct card_ir { char name[32]; char phys[32]; + u32 running:1; + struct ir_dev_props props; + /* Usual gpio signalling */ u32 mask_keycode; -- cgit v1.2.3-70-g09d2 From a3572c34da8dacc78a629211a91cf34e9b408701 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 20 Mar 2010 20:59:44 -0300 Subject: V4L/DVB: ir-core: Add logic to decode IR protocols at the IR core Adds a method to pass IR raw pulse/code events into ir-core. This is needed in order to support LIRC. It also helps to move common code from the drivers into the core. In order to allow testing, it implements a simple NEC protocol decoder at ir-nec-decoder.c file. The logic is about the same used at saa7134 driver that handles Avermedia M135A and Encore FM53 boards. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/Makefile | 2 +- drivers/media/IR/ir-nec-decoder.c | 131 ++++++++++++++++++++++++++++ drivers/media/IR/ir-raw-event.c | 117 +++++++++++++++++++++++++ drivers/media/video/saa7134/saa7134-input.c | 85 +++++++++++++++++- include/media/ir-common.h | 3 + include/media/ir-core.h | 32 +++++++ 6 files changed, 365 insertions(+), 5 deletions(-) create mode 100644 drivers/media/IR/ir-nec-decoder.c create mode 100644 drivers/media/IR/ir-raw-event.c (limited to 'drivers/media/video') diff --git a/drivers/media/IR/Makefile b/drivers/media/IR/Makefile index 171890e7a41..18794c7b0ea 100644 --- a/drivers/media/IR/Makefile +++ b/drivers/media/IR/Makefile @@ -1,5 +1,5 @@ ir-common-objs := ir-functions.o ir-keymaps.o -ir-core-objs := ir-keytable.o ir-sysfs.o +ir-core-objs := ir-keytable.o ir-sysfs.o ir-raw-event.o ir-nec-decoder.o obj-$(CONFIG_IR_CORE) += ir-core.o obj-$(CONFIG_VIDEO_IR) += ir-common.o diff --git a/drivers/media/IR/ir-nec-decoder.c b/drivers/media/IR/ir-nec-decoder.c new file mode 100644 index 00000000000..16360eb4055 --- /dev/null +++ b/drivers/media/IR/ir-nec-decoder.c @@ -0,0 +1,131 @@ +/* ir-raw-event.c - handle IR Pulse/Space event + * + * Copyright (C) 2010 by Mauro Carvalho Chehab + * + * 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 + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include + +/* Start time: 4.5 ms */ +#define MIN_START_TIME 3900000 +#define MAX_START_TIME 5100000 + +/* Pulse time: 560 us */ +#define MIN_PULSE_TIME 460000 +#define MAX_PULSE_TIME 660000 + +/* Bit 1 space time: 2.25ms-560 us */ +#define MIN_BIT1_TIME 1490000 +#define MAX_BIT1_TIME 1890000 + +/* Bit 0 space time: 1.12ms-560 us */ +#define MIN_BIT0_TIME 360000 +#define MAX_BIT0_TIME 760000 + + +/** Decode NEC pulsecode. This code can take up to 76.5 ms to run. + Unfortunately, using IRQ to decode pulse didn't work, since it uses + a pulse train of 38KHz. This means one pulse on each 52 us +*/ + +int ir_nec_decode(struct input_dev *input_dev, + struct ir_raw_event *evs, + int len) +{ + int i, count = -1; + int ircode = 0, not_code = 0; +#if 0 + /* Needed only after porting the event code to the decoder */ + struct ir_input_dev *ir = input_get_drvdata(input_dev); +#endif + + /* Be sure that the first event is an start one and is a pulse */ + for (i = 0; i < len; i++) { + if (evs[i].type & (IR_START_EVENT | IR_PULSE)) + break; + } + i++; /* First event doesn't contain data */ + + if (i >= len) + return 0; + + /* First space should have 4.5 ms otherwise is not NEC protocol */ + if ((evs[i].delta.tv_nsec < MIN_START_TIME) | + (evs[i].delta.tv_nsec > MAX_START_TIME) | + (evs[i].type != IR_SPACE)) + goto err; + + /* + * FIXME: need to implement the repeat sequence + */ + + count = 0; + for (i++; i < len; i++) { + int bit; + + if ((evs[i].delta.tv_nsec < MIN_PULSE_TIME) | + (evs[i].delta.tv_nsec > MAX_PULSE_TIME) | + (evs[i].type != IR_PULSE)) + goto err; + + if (++i >= len) + goto err; + if (evs[i].type != IR_SPACE) + goto err; + + if ((evs[i].delta.tv_nsec > MIN_BIT1_TIME) && + (evs[i].delta.tv_nsec < MAX_BIT1_TIME)) + bit = 1; + else if ((evs[i].delta.tv_nsec > MIN_BIT0_TIME) && + (evs[i].delta.tv_nsec < MAX_BIT0_TIME)) + bit = 0; + else + goto err; + + if (bit) { + int shift = count; + /* Address first, then command */ + if (shift < 8) { + shift += 8; + ircode |= 1 << shift; + } else if (shift < 16) { + not_code |= 1 << shift; + } else if (shift < 24) { + shift -= 16; + ircode |= 1 << shift; + } else { + shift -= 24; + not_code |= 1 << shift; + } + } + if (++count == 32) + break; + } + + /* + * Fixme: may need to accept Extended NEC protocol? + */ + if ((ircode & ~not_code) != ircode) { + IR_dprintk(1, "NEC checksum error: code 0x%04x, not-code 0x%04x\n", + ircode, not_code); + return -EINVAL; + } + + IR_dprintk(1, "NEC scancode 0x%04x\n", ircode); + + return ircode; +err: + IR_dprintk(1, "NEC decoded failed at bit %d while decoding %luus time\n", + count, (evs[i].delta.tv_nsec + 500) / 1000); + + return -EINVAL; +} +EXPORT_SYMBOL_GPL(ir_nec_decode); diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c new file mode 100644 index 00000000000..9c71ac85892 --- /dev/null +++ b/drivers/media/IR/ir-raw-event.c @@ -0,0 +1,117 @@ +/* ir-raw-event.c - handle IR Pulse/Space event + * + * Copyright (C) 2010 by Mauro Carvalho Chehab + * + * 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 + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include + +/* Define the max number of bit transitions per IR keycode */ +#define MAX_IR_EVENT_SIZE 256 + +int ir_raw_event_register(struct input_dev *input_dev) +{ + struct ir_input_dev *ir = input_get_drvdata(input_dev); + int rc, size; + + ir->raw = kzalloc(sizeof(*ir->raw), GFP_KERNEL); + + size = sizeof(struct ir_raw_event) * MAX_IR_EVENT_SIZE * 2; + size = roundup_pow_of_two(size); + + rc = kfifo_alloc(&ir->raw->kfifo, size, GFP_KERNEL); + + return rc; +} +EXPORT_SYMBOL_GPL(ir_raw_event_register); + +void ir_raw_event_unregister(struct input_dev *input_dev) +{ + struct ir_input_dev *ir = input_get_drvdata(input_dev); + + if (!ir->raw) + return; + + kfifo_free(&ir->raw->kfifo); + kfree(ir->raw); + ir->raw = NULL; +} +EXPORT_SYMBOL_GPL(ir_raw_event_unregister); + +int ir_raw_event_store(struct input_dev *input_dev, enum raw_event_type type) +{ + struct ir_input_dev *ir = input_get_drvdata(input_dev); + struct timespec ts; + struct ir_raw_event event; + int rc; + + if (!ir->raw) + return -EINVAL; + + event.type = type; + event.delta.tv_sec = 0; + event.delta.tv_nsec = 0; + + ktime_get_ts(&ts); + + if (timespec_equal(&ir->raw->last_event, &event.delta)) + event.type |= IR_START_EVENT; + else + event.delta = timespec_sub(ts, ir->raw->last_event); + + memcpy(&ir->raw->last_event, &ts, sizeof(ts)); + + if (event.delta.tv_sec) { + event.type |= IR_START_EVENT; + event.delta.tv_sec = 0; + event.delta.tv_nsec = 0; + } + + kfifo_in(&ir->raw->kfifo, &event, sizeof(event)); + + return rc; +} +EXPORT_SYMBOL_GPL(ir_raw_event_store); + +int ir_raw_event_handle(struct input_dev *input_dev) +{ + struct ir_input_dev *ir = input_get_drvdata(input_dev); + int rc; + struct ir_raw_event *evs; + int len, i; + + /* + * Store the events into a temporary buffer. This allows calling more than + * one decoder to deal with the received data + */ + len = kfifo_len(&ir->raw->kfifo) / sizeof(*evs); + if (!len) + return 0; + evs = kmalloc(len * sizeof(*evs), GFP_ATOMIC); + + for (i = 0; i < len; i++) { + rc = kfifo_out(&ir->raw->kfifo, &evs[i], sizeof(*evs)); + if (rc != sizeof(*evs)) { + IR_dprintk(1, "overflow error: received %d instead of %zd\n", + rc, sizeof(*evs)); + return -EINVAL; + } + IR_dprintk(2, "event type %d, time before event: %07luus\n", + evs[i].type, (evs[i].delta.tv_nsec + 500) / 1000); + } + + rc = ir_nec_decode(input_dev, evs, len); + + kfree(evs); + + return rc; +} +EXPORT_SYMBOL_GPL(ir_raw_event_handle); diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 7e6f125e4e3..1a7cf9c8c68 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -68,6 +68,7 @@ MODULE_PARM_DESC(disable_other_ir, "disable full codes of " /* Helper functions for RC5 and NEC decoding at GPIO16 or GPIO18 */ static int saa7134_rc5_irq(struct saa7134_dev *dev); static int saa7134_nec_irq(struct saa7134_dev *dev); +static int saa7134_raw_decode_irq(struct saa7134_dev *dev); static void nec_task(unsigned long data); static void saa7134_nec_timer(unsigned long data); @@ -403,10 +404,12 @@ void saa7134_input_irq(struct saa7134_dev *dev) if (ir->nec_gpio) { saa7134_nec_irq(dev); - } else if (!ir->polling && !ir->rc5_gpio) { + } else if (!ir->polling && !ir->rc5_gpio && !ir->raw_decode) { build_key(dev); } else if (ir->rc5_gpio) { saa7134_rc5_irq(dev); + } else if (ir->raw_decode) { + saa7134_raw_decode_irq(dev); } } @@ -419,6 +422,23 @@ static void saa7134_input_timer(unsigned long data) mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling)); } +void ir_raw_decode_timer_end(unsigned long data) +{ + struct saa7134_dev *dev = (struct saa7134_dev *)data; + struct card_ir *ir = dev->remote; + int rc; + + /* + * FIXME: the IR key handling code should be called by the decoder, + * after implementing the repeat mode + */ + rc = ir_raw_event_handle(dev->remote->dev); + if (rc >= 0) { + ir_input_keydown(ir->dev, &ir->ir, rc); + ir_input_nokey(ir->dev, &ir->ir); + } +} + void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir) { if (ir->running) @@ -447,6 +467,11 @@ void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir) setup_timer(&ir->timer_keyup, saa7134_nec_timer, (unsigned long)dev); tasklet_init(&ir->tlet, nec_task, (unsigned long)dev); + } else if (ir->raw_decode) { + /* set timer_end for code completion */ + init_timer(&ir->timer_end); + ir->timer_end.function = ir_raw_decode_timer_end; + ir->timer_end.data = (unsigned long)dev; } } @@ -462,6 +487,9 @@ void saa7134_ir_stop(struct saa7134_dev *dev) del_timer_sync(&ir->timer_end); else if (ir->nec_gpio) tasklet_kill(&ir->tlet); + else if (ir->raw_decode) + del_timer_sync(&ir->timer_end); + ir->running = 0; } @@ -509,6 +537,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) int polling = 0; int rc5_gpio = 0; int nec_gpio = 0; + int raw_decode = 0; u64 ir_type = IR_TYPE_OTHER; int err; @@ -574,7 +603,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) ir_codes = &ir_codes_avermedia_m135a_rm_jx_table; mask_keydown = 0x0040000; mask_keycode = 0xffff; - nec_gpio = 1; + raw_decode = 1; break; case SAA7134_BOARD_AVERMEDIA_777: case SAA7134_BOARD_AVERMEDIA_A16AR: @@ -755,6 +784,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) ir->polling = polling; ir->rc5_gpio = rc5_gpio; ir->nec_gpio = nec_gpio; + ir->raw_decode = raw_decode; /* init input device */ snprintf(ir->name, sizeof(ir->name), "saa7134 IR (%s)", @@ -762,7 +792,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(dev->pci)); - if (ir_codes->ir_type != IR_TYPE_OTHER) { + if (ir_codes->ir_type != IR_TYPE_OTHER && !raw_decode) { ir->props.allowed_protos = IR_TYPE_RC5 | IR_TYPE_NEC; ir->props.priv = dev; ir->props.change_protocol = saa7134_ir_change_protocol; @@ -790,6 +820,11 @@ int saa7134_input_init1(struct saa7134_dev *dev) err = ir_input_register(ir->dev, ir_codes, &ir->props, MODULE_NAME); if (err) goto err_out_stop; + if (ir_codes->ir_type != IR_TYPE_OTHER) { + err = ir_raw_event_register(ir->dev); + if (err) + goto err_out_stop; + } saa7134_ir_start(dev, ir); @@ -813,6 +848,7 @@ void saa7134_input_fini(struct saa7134_dev *dev) return; saa7134_ir_stop(dev); + ir_raw_event_unregister(dev->remote->dev); ir_input_unregister(dev->remote->dev); kfree(dev->remote); dev->remote = NULL; @@ -919,6 +955,48 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) i2c_new_device(&dev->i2c_adap, &info); } +static int saa7134_raw_decode_irq(struct saa7134_dev *dev) +{ + struct card_ir *ir = dev->remote; + unsigned long timeout; + int count, pulse, oldpulse; + + /* Disable IR IRQ line */ + saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18); + + /* Generate initial event */ + saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); + saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); + pulse = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) & ir->mask_keydown; + ir_raw_event_store(dev->remote->dev, pulse? IR_PULSE : IR_SPACE); + +#if 1 + /* Wait up to 10 ms for event change */ + oldpulse = pulse; + for (count = 0; count < 1000; count++) { + udelay(10); + /* rising SAA7134_GPIO_GPRESCAN reads the status */ + saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); + saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); + pulse = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) + & ir->mask_keydown; + if (pulse != oldpulse) + break; + } + + /* Store final event */ + ir_raw_event_store(dev->remote->dev, pulse? IR_PULSE : IR_SPACE); +#endif + /* Wait 15 ms before deciding to do something else */ + timeout = jiffies + jiffies_to_msecs(15); + mod_timer(&ir->timer_end, timeout); + + /* Enable IR IRQ line */ + saa_setl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18); + + return 1; +} + static int saa7134_rc5_irq(struct saa7134_dev *dev) { struct card_ir *ir = dev->remote; @@ -961,7 +1039,6 @@ static int saa7134_rc5_irq(struct saa7134_dev *dev) return 1; } - /* On NEC protocol, One has 2.25 ms, and zero has 1.125 ms The first pulse (start) has 9 + 4.5 ms */ diff --git a/include/media/ir-common.h b/include/media/ir-common.h index 41469b79ad1..87f2ec78deb 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -82,6 +82,9 @@ struct card_ir { /* NEC decoding */ u32 nec_gpio; struct tasklet_struct tlet; + + /* IR core raw decoding */ + u32 raw_decode; }; /* Routines from ir-functions.c */ diff --git a/include/media/ir-core.h b/include/media/ir-core.h index 1eae72d518e..369969d9077 100644 --- a/include/media/ir-core.h +++ b/include/media/ir-core.h @@ -16,6 +16,8 @@ #include #include +#include +#include extern int ir_core_debug; #define IR_dprintk(level, fmt, arg...) if (ir_core_debug >= level) \ @@ -27,6 +29,13 @@ extern int ir_core_debug; #define IR_TYPE_NEC (1 << 2) #define IR_TYPE_OTHER (((u64)1) << 63l) +enum raw_event_type { + IR_SPACE = (1 << 0), + IR_PULSE = (1 << 1), + IR_START_EVENT = (1 << 2), + IR_STOP_EVENT = (1 << 3), +}; + struct ir_scancode { u16 scancode; u32 keycode; @@ -46,6 +55,15 @@ struct ir_dev_props { int (*change_protocol)(void *priv, u64 ir_type); }; +struct ir_raw_event { + struct timespec delta; /* Time spent before event */ + enum raw_event_type type; /* event type */ +}; + +struct ir_raw_event_ctrl { + struct kfifo kfifo; /* fifo for the pulse/space events */ + struct timespec last_event; /* when last event occurred */ +}; struct ir_input_dev { struct device dev; /* device */ @@ -53,7 +71,9 @@ struct ir_input_dev { struct ir_scancode_table rc_tab; /* scan/key table */ unsigned long devno; /* device number */ const struct ir_dev_props *props; /* Device properties */ + struct ir_raw_event_ctrl *raw; /* for raw pulse/space events */ }; + #define to_ir_input_dev(_attr) container_of(_attr, struct ir_input_dev, attr) /* Routines from ir-keytable.c */ @@ -72,4 +92,16 @@ void ir_input_unregister(struct input_dev *input_dev); int ir_register_class(struct input_dev *input_dev); void ir_unregister_class(struct input_dev *input_dev); +/* Routines from ir-raw-event.c */ +int ir_raw_event_register(struct input_dev *input_dev); +void ir_raw_event_unregister(struct input_dev *input_dev); +int ir_raw_event_store(struct input_dev *input_dev, enum raw_event_type type); +int ir_raw_event_handle(struct input_dev *input_dev); + +/* from ir-nec-decoder.c */ +int ir_nec_decode(struct input_dev *input_dev, + struct ir_raw_event *evs, + int len); + + #endif -- cgit v1.2.3-70-g09d2 From ada39630c758c5c3098f4fc1361103ea2bc1afe0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 21 Mar 2010 12:24:24 -0300 Subject: V4L/DVB: ir-core/saa7134: Move ir keyup/keydown code to the ir-core Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-nec-decoder.c | 90 +++++++++++++++++++---------- drivers/media/video/saa7134/saa7134-input.c | 12 +--- include/media/ir-core.h | 3 +- 3 files changed, 61 insertions(+), 44 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/IR/ir-nec-decoder.c b/drivers/media/IR/ir-nec-decoder.c index 16360eb4055..a58c717ec6b 100644 --- a/drivers/media/IR/ir-nec-decoder.c +++ b/drivers/media/IR/ir-nec-decoder.c @@ -30,37 +30,35 @@ #define MIN_BIT0_TIME 360000 #define MAX_BIT0_TIME 760000 - -/** Decode NEC pulsecode. This code can take up to 76.5 ms to run. - Unfortunately, using IRQ to decode pulse didn't work, since it uses - a pulse train of 38KHz. This means one pulse on each 52 us -*/ - -int ir_nec_decode(struct input_dev *input_dev, - struct ir_raw_event *evs, - int len) +/** + * __ir_nec_decode() - Decode one NEC pulsecode + * @input_dev: the struct input_dev descriptor of the device + * @evs: event array with type/duration of pulse/space + * @len: length of the array + * @pos: position to start seeking for a code + * This function returns the decoded ircode or -EINVAL if no pulse got decoded + */ +static int __ir_nec_decode(struct input_dev *input_dev, + struct ir_raw_event *evs, + int len, int *pos) { - int i, count = -1; + int count = -1; int ircode = 0, not_code = 0; -#if 0 - /* Needed only after porting the event code to the decoder */ - struct ir_input_dev *ir = input_get_drvdata(input_dev); -#endif /* Be sure that the first event is an start one and is a pulse */ - for (i = 0; i < len; i++) { - if (evs[i].type & (IR_START_EVENT | IR_PULSE)) + for (; *pos < len; (*pos)++) { + if (evs[*pos].type & (IR_START_EVENT | IR_PULSE)) break; } - i++; /* First event doesn't contain data */ + (*pos)++; /* First event doesn't contain data */ - if (i >= len) + if (*pos >= len) return 0; /* First space should have 4.5 ms otherwise is not NEC protocol */ - if ((evs[i].delta.tv_nsec < MIN_START_TIME) | - (evs[i].delta.tv_nsec > MAX_START_TIME) | - (evs[i].type != IR_SPACE)) + if ((evs[*pos].delta.tv_nsec < MIN_START_TIME) | + (evs[*pos].delta.tv_nsec > MAX_START_TIME) | + (evs[*pos].type != IR_SPACE)) goto err; /* @@ -68,24 +66,24 @@ int ir_nec_decode(struct input_dev *input_dev, */ count = 0; - for (i++; i < len; i++) { + for ((*pos)++; *pos < len; (*pos)++) { int bit; - if ((evs[i].delta.tv_nsec < MIN_PULSE_TIME) | - (evs[i].delta.tv_nsec > MAX_PULSE_TIME) | - (evs[i].type != IR_PULSE)) + if ((evs[*pos].delta.tv_nsec < MIN_PULSE_TIME) | + (evs[*pos].delta.tv_nsec > MAX_PULSE_TIME) | + (evs[*pos].type != IR_PULSE)) goto err; - if (++i >= len) + if (++*pos >= len) goto err; - if (evs[i].type != IR_SPACE) + if (evs[*pos].type != IR_SPACE) goto err; - if ((evs[i].delta.tv_nsec > MIN_BIT1_TIME) && - (evs[i].delta.tv_nsec < MAX_BIT1_TIME)) + if ((evs[*pos].delta.tv_nsec > MIN_BIT1_TIME) && + (evs[*pos].delta.tv_nsec < MAX_BIT1_TIME)) bit = 1; - else if ((evs[i].delta.tv_nsec > MIN_BIT0_TIME) && - (evs[i].delta.tv_nsec < MAX_BIT0_TIME)) + else if ((evs[*pos].delta.tv_nsec > MIN_BIT0_TIME) && + (evs[*pos].delta.tv_nsec < MAX_BIT0_TIME)) bit = 0; else goto err; @@ -120,12 +118,40 @@ int ir_nec_decode(struct input_dev *input_dev, } IR_dprintk(1, "NEC scancode 0x%04x\n", ircode); + ir_keydown(input_dev, ircode); + ir_keyup(input_dev); return ircode; err: IR_dprintk(1, "NEC decoded failed at bit %d while decoding %luus time\n", - count, (evs[i].delta.tv_nsec + 500) / 1000); + count, (evs[*pos].delta.tv_nsec + 500) / 1000); return -EINVAL; } + +/** + * __ir_nec_decode() - Decodes all NEC pulsecodes on a given array + * @input_dev: the struct input_dev descriptor of the device + * @evs: event array with type/duration of pulse/space + * @len: length of the array + * This function returns the number of decoded pulses or -EINVAL if no + * pulse got decoded + */ +int ir_nec_decode(struct input_dev *input_dev, + struct ir_raw_event *evs, + int len) +{ + int pos = 0; + int rc = 0; + + while (pos < len) { + if (__ir_nec_decode(input_dev, evs, len, &pos) >= 0) + rc++; + } + + if (!rc) + return -EINVAL; + return rc; +} + EXPORT_SYMBOL_GPL(ir_nec_decode); diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 1a7cf9c8c68..dff33279ab3 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -425,18 +425,8 @@ static void saa7134_input_timer(unsigned long data) void ir_raw_decode_timer_end(unsigned long data) { struct saa7134_dev *dev = (struct saa7134_dev *)data; - struct card_ir *ir = dev->remote; - int rc; - /* - * FIXME: the IR key handling code should be called by the decoder, - * after implementing the repeat mode - */ - rc = ir_raw_event_handle(dev->remote->dev); - if (rc >= 0) { - ir_input_keydown(ir->dev, &ir->ir, rc); - ir_input_nokey(ir->dev, &ir->ir); - } + ir_raw_event_handle(dev->remote->dev); } void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir) diff --git a/include/media/ir-core.h b/include/media/ir-core.h index 198fd61f0da..9e03528a767 100644 --- a/include/media/ir-core.h +++ b/include/media/ir-core.h @@ -84,7 +84,8 @@ struct ir_input_dev { u32 ir_g_keycode_from_table(struct input_dev *input_dev, u32 scancode); - +void ir_keyup(struct input_dev *dev); +void ir_keydown(struct input_dev *dev, int scancode); int ir_input_register(struct input_dev *dev, const struct ir_scancode_table *ir_codes, const struct ir_dev_props *props, -- cgit v1.2.3-70-g09d2 From 9f1547829a6f39fe6b2da22653dff40502f3d568 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 21 Mar 2010 13:00:55 -0300 Subject: V4L/DVB: saa7134: don't wait too much to generate an IR event on raw_decode At raw_decode mode, the key is processed after the end of a timer. The previous code resets the timer every time something is received at the IR port. While this works fine with IR's that don't implement repeat, like Avermedia RM-JX IR, it keeps waiting until keydown, on IR's that implement NEC repeat command, like the Terratec yellow. The solution is to change the behaviour to do the timeout after the first received data. The timeout is currently set to 15 ms, as it works fine with NEC protcocol. It may need some adjustments to support other protocols and to better handle spurious detections that may happen with some IR sensors. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-keytable.c | 1 + drivers/media/IR/ir-nec-decoder.c | 122 +++++++++++++++++++--------- drivers/media/IR/ir-raw-event.c | 14 ++++ drivers/media/video/saa7134/saa7134-input.c | 43 ++++------ include/media/ir-core.h | 2 + 5 files changed, 117 insertions(+), 65 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c index e59290febf8..fcb0f0cb1fe 100644 --- a/drivers/media/IR/ir-keytable.c +++ b/drivers/media/IR/ir-keytable.c @@ -405,6 +405,7 @@ void ir_keyup(struct input_dev *dev) if (!ir->keypressed) return; + IR_dprintk(1, "keyup key 0x%04x\n", ir->keycode); input_report_key(dev, ir->keycode, 0); input_sync(dev); ir->keypressed = 0; diff --git a/drivers/media/IR/ir-nec-decoder.c b/drivers/media/IR/ir-nec-decoder.c index a58c717ec6b..104482a6991 100644 --- a/drivers/media/IR/ir-nec-decoder.c +++ b/drivers/media/IR/ir-nec-decoder.c @@ -14,21 +14,51 @@ #include -/* Start time: 4.5 ms */ -#define MIN_START_TIME 3900000 -#define MAX_START_TIME 5100000 +/* Start time: 4.5 ms + 560 us of the next pulse */ +#define MIN_START_TIME (3900000 + 560000) +#define MAX_START_TIME (5100000 + 560000) -/* Pulse time: 560 us */ -#define MIN_PULSE_TIME 460000 -#define MAX_PULSE_TIME 660000 +/* Bit 1 time: 2.25ms us */ +#define MIN_BIT1_TIME 2050000 +#define MAX_BIT1_TIME 2450000 -/* Bit 1 space time: 2.25ms-560 us */ -#define MIN_BIT1_TIME 1490000 -#define MAX_BIT1_TIME 1890000 +/* Bit 0 time: 1.12ms us */ +#define MIN_BIT0_TIME 920000 +#define MAX_BIT0_TIME 1320000 -/* Bit 0 space time: 1.12ms-560 us */ -#define MIN_BIT0_TIME 360000 -#define MAX_BIT0_TIME 760000 +/* Total IR code is 110 ms, including the 9 ms for the start pulse */ +#define MAX_NEC_TIME 4000000 + +/* Total IR code is 110 ms, including the 9 ms for the start pulse */ +#define MIN_REPEAT_TIME 99000000 +#define MAX_REPEAT_TIME 112000000 + +/* Repeat time: 2.25ms us */ +#define MIN_REPEAT_START_TIME 2050000 +#define MAX_REPEAT_START_TIME 3000000 + +#define REPEAT_TIME 240 /* ms */ + +/** is_repeat - Check if it is a NEC repeat event + * @input_dev: the struct input_dev descriptor of the device + * @pos: the position of the first event + * @len: the length of the buffer + */ +static int is_repeat(struct ir_raw_event *evs, int len, int pos) +{ + if ((evs[pos].delta.tv_nsec < MIN_REPEAT_START_TIME) || + (evs[pos].delta.tv_nsec > MAX_REPEAT_START_TIME)) + return 0; + + if (++pos >= len) + return 0; + + if ((evs[pos].delta.tv_nsec < MIN_REPEAT_TIME) || + (evs[pos].delta.tv_nsec > MAX_REPEAT_TIME)) + return 0; + + return 1; +} /** * __ir_nec_decode() - Decode one NEC pulsecode @@ -36,49 +66,59 @@ * @evs: event array with type/duration of pulse/space * @len: length of the array * @pos: position to start seeking for a code - * This function returns the decoded ircode or -EINVAL if no pulse got decoded + * This function returns -EINVAL if no pulse got decoded, + * 0 if buffer is empty and 1 if one keycode were handled. */ static int __ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event *evs, int len, int *pos) { + struct ir_input_dev *ir = input_get_drvdata(input_dev); int count = -1; int ircode = 0, not_code = 0; /* Be sure that the first event is an start one and is a pulse */ for (; *pos < len; (*pos)++) { - if (evs[*pos].type & (IR_START_EVENT | IR_PULSE)) + /* Very long delays are considered as start events */ + if (evs[*pos].delta.tv_nsec > MAX_NEC_TIME) break; - } - (*pos)++; /* First event doesn't contain data */ + if (evs[*pos].type & IR_START_EVENT) + break; + IR_dprintk(1, "%luus: Spurious NEC %s\n", + (evs[*pos].delta.tv_nsec + 500) / 1000, + (evs[*pos].type & IR_SPACE) ? "space" : "pulse"); + } if (*pos >= len) return 0; - /* First space should have 4.5 ms otherwise is not NEC protocol */ - if ((evs[*pos].delta.tv_nsec < MIN_START_TIME) | - (evs[*pos].delta.tv_nsec > MAX_START_TIME) | - (evs[*pos].type != IR_SPACE)) + (*pos)++; /* First event doesn't contain data */ + + if (evs[*pos].type != IR_PULSE) goto err; - /* - * FIXME: need to implement the repeat sequence - */ + /* Check if it is a NEC repeat event */ + if (is_repeat(evs, len, *pos)) { + *pos += 2; + if (ir->keypressed) { + mod_timer(&ir->raw->timer_keyup, + jiffies + msecs_to_jiffies(REPEAT_TIME)); + IR_dprintk(1, "NEC repeat event\n"); + return 1; + } else { + IR_dprintk(1, "missing NEC repeat event\n"); + return 0; + } + } + + /* First space should have 4.5 ms otherwise is not NEC protocol */ + if ((evs[*pos].delta.tv_nsec < MIN_START_TIME) || + (evs[*pos].delta.tv_nsec > MAX_START_TIME)) + goto err; count = 0; for ((*pos)++; *pos < len; (*pos)++) { int bit; - - if ((evs[*pos].delta.tv_nsec < MIN_PULSE_TIME) | - (evs[*pos].delta.tv_nsec > MAX_PULSE_TIME) | - (evs[*pos].type != IR_PULSE)) - goto err; - - if (++*pos >= len) - goto err; - if (evs[*pos].type != IR_SPACE) - goto err; - if ((evs[*pos].delta.tv_nsec > MIN_BIT1_TIME) && (evs[*pos].delta.tv_nsec < MAX_BIT1_TIME)) bit = 1; @@ -107,6 +147,7 @@ static int __ir_nec_decode(struct input_dev *input_dev, if (++count == 32) break; } + *pos++; /* * Fixme: may need to accept Extended NEC protocol? @@ -119,12 +160,15 @@ static int __ir_nec_decode(struct input_dev *input_dev, IR_dprintk(1, "NEC scancode 0x%04x\n", ircode); ir_keydown(input_dev, ircode); - ir_keyup(input_dev); + mod_timer(&ir->raw->timer_keyup, + jiffies + msecs_to_jiffies(REPEAT_TIME)); - return ircode; + return 1; err: - IR_dprintk(1, "NEC decoded failed at bit %d while decoding %luus time\n", - count, (evs[*pos].delta.tv_nsec + 500) / 1000); + IR_dprintk(1, "NEC decoded failed at bit %d (%s) while decoding %luus time\n", + count, + (evs[*pos].type & IR_SPACE) ? "space" : "pulse", + (evs[*pos].delta.tv_nsec + 500) / 1000); return -EINVAL; } @@ -145,7 +189,7 @@ int ir_nec_decode(struct input_dev *input_dev, int rc = 0; while (pos < len) { - if (__ir_nec_decode(input_dev, evs, len, &pos) >= 0) + if (__ir_nec_decode(input_dev, evs, len, &pos) > 0) rc++; } diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c index 9c71ac85892..0ae55433cef 100644 --- a/drivers/media/IR/ir-raw-event.c +++ b/drivers/media/IR/ir-raw-event.c @@ -17,6 +17,13 @@ /* Define the max number of bit transitions per IR keycode */ #define MAX_IR_EVENT_SIZE 256 +static void ir_keyup_timer(unsigned long data) +{ + struct input_dev *input_dev = (struct input_dev *)data; + + ir_keyup(input_dev); +} + int ir_raw_event_register(struct input_dev *input_dev) { struct ir_input_dev *ir = input_get_drvdata(input_dev); @@ -27,6 +34,11 @@ int ir_raw_event_register(struct input_dev *input_dev) size = sizeof(struct ir_raw_event) * MAX_IR_EVENT_SIZE * 2; size = roundup_pow_of_two(size); + init_timer(&ir->raw->timer_keyup); + ir->raw->timer_keyup.function = ir_keyup_timer; + ir->raw->timer_keyup.data = (unsigned long)input_dev; + set_bit(EV_REP, input_dev->evbit); + rc = kfifo_alloc(&ir->raw->kfifo, size, GFP_KERNEL); return rc; @@ -40,6 +52,8 @@ void ir_raw_event_unregister(struct input_dev *input_dev) if (!ir->raw) return; + del_timer_sync(&ir->raw->timer_keyup); + kfifo_free(&ir->raw->kfifo); kfree(ir->raw); ir->raw = NULL; diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index dff33279ab3..32859e549af 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -425,8 +425,11 @@ static void saa7134_input_timer(unsigned long data) void ir_raw_decode_timer_end(unsigned long data) { struct saa7134_dev *dev = (struct saa7134_dev *)data; + struct card_ir *ir = dev->remote; ir_raw_event_handle(dev->remote->dev); + + ir->active = 0; } void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir) @@ -462,6 +465,7 @@ void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir) init_timer(&ir->timer_end); ir->timer_end.function = ir_raw_decode_timer_end; ir->timer_end.data = (unsigned long)dev; + ir->active = 0; } } @@ -477,8 +481,10 @@ void saa7134_ir_stop(struct saa7134_dev *dev) del_timer_sync(&ir->timer_end); else if (ir->nec_gpio) tasklet_kill(&ir->tlet); - else if (ir->raw_decode) + else if (ir->raw_decode) { del_timer_sync(&ir->timer_end); + ir->active = 0; + } ir->running = 0; } @@ -951,38 +957,23 @@ static int saa7134_raw_decode_irq(struct saa7134_dev *dev) unsigned long timeout; int count, pulse, oldpulse; - /* Disable IR IRQ line */ - saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18); - /* Generate initial event */ saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); pulse = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) & ir->mask_keydown; ir_raw_event_store(dev->remote->dev, pulse? IR_PULSE : IR_SPACE); -#if 1 - /* Wait up to 10 ms for event change */ - oldpulse = pulse; - for (count = 0; count < 1000; count++) { - udelay(10); - /* rising SAA7134_GPIO_GPRESCAN reads the status */ - saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); - saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); - pulse = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) - & ir->mask_keydown; - if (pulse != oldpulse) - break; - } - - /* Store final event */ - ir_raw_event_store(dev->remote->dev, pulse? IR_PULSE : IR_SPACE); -#endif - /* Wait 15 ms before deciding to do something else */ - timeout = jiffies + jiffies_to_msecs(15); - mod_timer(&ir->timer_end, timeout); - /* Enable IR IRQ line */ - saa_setl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18); + /* + * Wait 15 ms from the start of the first IR event before processing + * the event. This time is enough for NEC protocol. May need adjustments + * to work with other protocols. + */ + if (!ir->active) { + timeout = jiffies + jiffies_to_msecs(15); + mod_timer(&ir->timer_end, timeout); + ir->active = 1; + } return 1; } diff --git a/include/media/ir-core.h b/include/media/ir-core.h index 9e03528a767..8d8ed7e06cd 100644 --- a/include/media/ir-core.h +++ b/include/media/ir-core.h @@ -18,6 +18,7 @@ #include #include #include +#include extern int ir_core_debug; #define IR_dprintk(level, fmt, arg...) if (ir_core_debug >= level) \ @@ -63,6 +64,7 @@ struct ir_raw_event { struct ir_raw_event_ctrl { struct kfifo kfifo; /* fifo for the pulse/space events */ struct timespec last_event; /* when last event occurred */ + struct timer_list timer_keyup; /* timer for key release */ }; struct ir_input_dev { -- cgit v1.2.3-70-g09d2 From 93c312ff21b0a53e701a45741887208297646a1a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 25 Mar 2010 21:13:43 -0300 Subject: V4L/DVB: ir-core: prepare to add more operations for ir decoders Some decoders and a lirc_dev interface may need some other operations to work. For example: IR device register/unregister and ir_keydown events may need to be tracked. As some operations can occur in interrupt time, and a lock is needed to prevent un-registering a decode while decoding a key, the lock needed to be convert into a spin lock. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-nec-decoder.c | 6 +-- drivers/media/IR/ir-raw-event.c | 71 +++++++++++++++++++++++------ drivers/media/video/saa7134/saa7134-input.c | 2 +- include/media/ir-core.h | 7 +-- 4 files changed, 62 insertions(+), 24 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/IR/ir-nec-decoder.c b/drivers/media/IR/ir-nec-decoder.c index c9a986dd57f..cb57cc28773 100644 --- a/drivers/media/IR/ir-nec-decoder.c +++ b/drivers/media/IR/ir-nec-decoder.c @@ -178,8 +178,7 @@ err: * @input_dev: the struct input_dev descriptor of the device * @evs: event array with type/duration of pulse/space * @len: length of the array - * This function returns the number of decoded pulses or -EINVAL if no - * pulse got decoded + * This function returns the number of decoded pulses */ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event *evs, @@ -192,9 +191,6 @@ static int ir_nec_decode(struct input_dev *input_dev, if (__ir_nec_decode(input_dev, evs, len, &pos) > 0) rc++; } - - if (!rc) - return -EINVAL; return rc; } diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c index 3eae128400e..11f23f4491b 100644 --- a/drivers/media/IR/ir-raw-event.c +++ b/drivers/media/IR/ir-raw-event.c @@ -14,13 +14,41 @@ #include #include +#include /* Define the max number of bit transitions per IR keycode */ #define MAX_IR_EVENT_SIZE 256 /* Used to handle IR raw handler extensions */ static LIST_HEAD(ir_raw_handler_list); -static DEFINE_MUTEX(ir_raw_handler_lock); +static spinlock_t ir_raw_handler_lock; + +/** + * RUN_DECODER() - runs an operation on all IR decoders + * @ops: IR raw handler operation to be called + * @arg: arguments to be passed to the callback + * + * Calls ir_raw_handler::ops for all registered IR handlers. It prevents + * new decode addition/removal while running, by locking ir_raw_handler_lock + * mutex. If an error occurs, it stops the ops. Otherwise, it returns a sum + * of the return codes. + */ +#define RUN_DECODER(ops, ...) ({ \ + struct ir_raw_handler *_ir_raw_handler; \ + int _sumrc = 0, _rc; \ + spin_lock(&ir_raw_handler_lock); \ + list_for_each_entry(_ir_raw_handler, &ir_raw_handler_list, list) { \ + if (_ir_raw_handler->ops) { \ + _rc = _ir_raw_handler->ops(__VA_ARGS__); \ + if (_rc < 0) \ + break; \ + _sumrc += _rc; \ + } \ + } \ + spin_unlock(&ir_raw_handler_lock); \ + _sumrc; \ +}) + /* Used to load the decoders */ static struct work_struct wq_load; @@ -38,6 +66,8 @@ int ir_raw_event_register(struct input_dev *input_dev) int rc, size; ir->raw = kzalloc(sizeof(*ir->raw), GFP_KERNEL); + if (!ir->raw) + return -ENOMEM; size = sizeof(struct ir_raw_event) * MAX_IR_EVENT_SIZE * 2; size = roundup_pow_of_two(size); @@ -48,6 +78,19 @@ int ir_raw_event_register(struct input_dev *input_dev) set_bit(EV_REP, input_dev->evbit); rc = kfifo_alloc(&ir->raw->kfifo, size, GFP_KERNEL); + if (rc < 0) { + kfree(ir->raw); + ir->raw = NULL; + return rc; + } + + rc = RUN_DECODER(raw_register, input_dev); + if (rc < 0) { + kfifo_free(&ir->raw->kfifo); + kfree(ir->raw); + ir->raw = NULL; + return rc; + } return rc; } @@ -62,6 +105,8 @@ void ir_raw_event_unregister(struct input_dev *input_dev) del_timer_sync(&ir->raw->timer_keyup); + RUN_DECODER(raw_unregister, input_dev); + kfifo_free(&ir->raw->kfifo); kfree(ir->raw); ir->raw = NULL; @@ -109,7 +154,6 @@ int ir_raw_event_handle(struct input_dev *input_dev) int rc; struct ir_raw_event *evs; int len, i; - struct ir_raw_handler *ir_raw_handler; /* * Store the events into a temporary buffer. This allows calling more than @@ -133,13 +177,10 @@ int ir_raw_event_handle(struct input_dev *input_dev) /* * Call all ir decoders. This allows decoding the same event with - * more than one protocol handler. - * FIXME: better handle the returned code: does it make sense to use - * other decoders, if the first one already handled the IR? + * more than one protocol handler. It returns the number of keystrokes + * sent to the event interface */ - list_for_each_entry(ir_raw_handler, &ir_raw_handler_list, list) { - rc = ir_raw_handler->decode(input_dev, evs, len); - } + rc = RUN_DECODER(decode, input_dev, evs, len); kfree(evs); @@ -153,18 +194,18 @@ EXPORT_SYMBOL_GPL(ir_raw_event_handle); int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler) { - mutex_lock(&ir_raw_handler_lock); + spin_lock(&ir_raw_handler_lock); list_add_tail(&ir_raw_handler->list, &ir_raw_handler_list); - mutex_unlock(&ir_raw_handler_lock); + spin_unlock(&ir_raw_handler_lock); return 0; } EXPORT_SYMBOL(ir_raw_handler_register); void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler) { - mutex_lock(&ir_raw_handler_lock); + spin_lock(&ir_raw_handler_lock); list_del(&ir_raw_handler->list); - mutex_unlock(&ir_raw_handler_lock); + spin_unlock(&ir_raw_handler_lock); } EXPORT_SYMBOL(ir_raw_handler_unregister); @@ -181,6 +222,10 @@ static void init_decoders(struct work_struct *work) void ir_raw_init(void) { + spin_lock_init(&ir_raw_handler_lock); + +#ifdef MODULE INIT_WORK(&wq_load, init_decoders); schedule_work(&wq_load); -} \ No newline at end of file +#endif +} diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 32859e549af..39564db252f 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -961,7 +961,7 @@ static int saa7134_raw_decode_irq(struct saa7134_dev *dev) saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); pulse = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) & ir->mask_keydown; - ir_raw_event_store(dev->remote->dev, pulse? IR_PULSE : IR_SPACE); + ir_raw_event_store(dev->remote->dev, pulse ? IR_PULSE : IR_SPACE); /* diff --git a/include/media/ir-core.h b/include/media/ir-core.h index c377bf47a05..c704fa7cc11 100644 --- a/include/media/ir-core.h +++ b/include/media/ir-core.h @@ -88,6 +88,8 @@ struct ir_raw_handler { int (*decode)(struct input_dev *input_dev, struct ir_raw_event *evs, int len); + int (*raw_register)(struct input_dev *input_dev); + int (*raw_unregister)(struct input_dev *input_dev); }; #define to_ir_input_dev(_attr) container_of(_attr, struct ir_input_dev, attr) @@ -116,12 +118,7 @@ int ir_raw_event_store(struct input_dev *input_dev, enum raw_event_type type); int ir_raw_event_handle(struct input_dev *input_dev); int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler); void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler); - -#ifdef MODULE void ir_raw_init(void); -#else -#define ir_raw_init() 0 -#endif /* from ir-nec-decoder.c */ #ifdef CONFIG_IR_NEC_DECODER_MODULE -- cgit v1.2.3-70-g09d2 From d89b4bd2b47395339d5b5b6a7e28f91dd0d21b7b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 26 Mar 2010 22:39:29 -0300 Subject: V4L/DVB: saa7134: clear warning noise MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/media/video/saa7134/saa7134-input.c: In function ‘saa7134_raw_decode_irq’: drivers/media/video/saa7134/saa7134-input.c:957: warning: unused variable ‘oldpulse’ drivers/media/video/saa7134/saa7134-input.c:957: warning: unused variable ‘count’ Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 39564db252f..e278d7304b3 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -955,7 +955,7 @@ static int saa7134_raw_decode_irq(struct saa7134_dev *dev) { struct card_ir *ir = dev->remote; unsigned long timeout; - int count, pulse, oldpulse; + int pulse; /* Generate initial event */ saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); -- cgit v1.2.3-70-g09d2 From 716aab44df8bb9bdf16abea9013890274329b61f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 31 Mar 2010 14:40:35 -0300 Subject: V4L/DVB: ir-core: Add callbacks for input/evdev open/close on IR core Especially when IR needs to do polling, it generates lots of wakeups per second. This makes no sense, if the input event device is closed. Adds a callback handler to the IR hardware driver, to allow registering an open/close ops. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-keytable.c | 17 ++++++ drivers/media/video/saa7134/saa7134-core.c | 2 +- drivers/media/video/saa7134/saa7134-input.c | 89 ++++++++++++++++++++++++----- drivers/media/video/saa7134/saa7134.h | 4 +- include/media/ir-common.h | 1 + include/media/ir-core.h | 2 + 6 files changed, 98 insertions(+), 17 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c index fcb0f0cb1fe..99cad829a18 100644 --- a/drivers/media/IR/ir-keytable.c +++ b/drivers/media/IR/ir-keytable.c @@ -446,6 +446,19 @@ void ir_keydown(struct input_dev *dev, int scancode) } EXPORT_SYMBOL_GPL(ir_keydown); +static int ir_open(struct input_dev *input_dev) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + + return ir_dev->props->open(ir_dev->props->priv); +} + +static void ir_close(struct input_dev *input_dev) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + + ir_dev->props->close(ir_dev->props->priv); +} /** * ir_input_register() - sets the IR keycode table and add the handlers @@ -495,6 +508,10 @@ int ir_input_register(struct input_dev *input_dev, ir_copy_table(&ir_dev->rc_tab, rc_tab); ir_dev->props = props; + if (props && props->open) + input_dev->open = ir_open; + if (props && props->close) + input_dev->close = ir_close; /* set the bits for the keys */ IR_dprintk(1, "key map size: %d\n", rc_tab->size); diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index a7ad7810fdd..68cda10e078 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -1227,7 +1227,7 @@ static int saa7134_resume(struct pci_dev *pci_dev) if (card_has_mpeg(dev)) saa7134_ts_init_hw(dev); if (dev->remote) - saa7134_ir_start(dev, dev->remote); + saa7134_ir_start(dev); saa7134_hw_enable1(dev); msleep(100); diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index e278d7304b3..ae17b853f95 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -400,7 +400,14 @@ static int get_key_pinnacle_color(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) void saa7134_input_irq(struct saa7134_dev *dev) { - struct card_ir *ir = dev->remote; + struct card_ir *ir; + + if (!dev || !dev->remote) + return; + + ir = dev->remote; + if (!ir->running) + return; if (ir->nec_gpio) { saa7134_nec_irq(dev); @@ -432,10 +439,20 @@ void ir_raw_decode_timer_end(unsigned long data) ir->active = 0; } -void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir) +static int __saa7134_ir_start(void *priv) { + struct saa7134_dev *dev = priv; + struct card_ir *ir; + + if (!dev) + return -EINVAL; + + ir = dev->remote; + if (!ir) + return -EINVAL; + if (ir->running) - return; + return 0; ir->running = 1; if (ir->polling) { @@ -467,11 +484,21 @@ void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir) ir->timer_end.data = (unsigned long)dev; ir->active = 0; } + + return 0; } -void saa7134_ir_stop(struct saa7134_dev *dev) +static void __saa7134_ir_stop(void *priv) { - struct card_ir *ir = dev->remote; + struct saa7134_dev *dev = priv; + struct card_ir *ir; + + if (!dev) + return; + + ir = dev->remote; + if (!ir) + return; if (!ir->running) return; @@ -487,8 +514,42 @@ void saa7134_ir_stop(struct saa7134_dev *dev) } ir->running = 0; + + return; +} + +int saa7134_ir_start(struct saa7134_dev *dev) +{ + if (dev->remote->users) + return __saa7134_ir_start(dev); + + return 0; +} + +void saa7134_ir_stop(struct saa7134_dev *dev) +{ + if (dev->remote->users) + __saa7134_ir_stop(dev); +} + +static int saa7134_ir_open(void *priv) +{ + struct saa7134_dev *dev = priv; + + dev->remote->users++; + return __saa7134_ir_start(dev); +} + +static void saa7134_ir_close(void *priv) +{ + struct saa7134_dev *dev = priv; + + dev->remote->users--; + if (!dev->remote->users) + __saa7134_ir_stop(dev); } + int saa7134_ir_change_protocol(void *priv, u64 ir_type) { struct saa7134_dev *dev = priv; @@ -513,7 +574,7 @@ int saa7134_ir_change_protocol(void *priv, u64 ir_type) saa7134_ir_stop(dev); ir->nec_gpio = nec_gpio; ir->rc5_gpio = rc5_gpio; - saa7134_ir_start(dev, ir); + saa7134_ir_start(dev); } else { ir->nec_gpio = nec_gpio; ir->rc5_gpio = rc5_gpio; @@ -788,9 +849,13 @@ int saa7134_input_init1(struct saa7134_dev *dev) snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(dev->pci)); + + ir->props.priv = dev; + ir->props.open = saa7134_ir_open; + ir->props.close = saa7134_ir_close; + if (ir_codes->ir_type != IR_TYPE_OTHER && !raw_decode) { ir->props.allowed_protos = IR_TYPE_RC5 | IR_TYPE_NEC; - ir->props.priv = dev; ir->props.change_protocol = saa7134_ir_change_protocol; /* Set IR protocol */ @@ -815,25 +880,21 @@ int saa7134_input_init1(struct saa7134_dev *dev) err = ir_input_register(ir->dev, ir_codes, &ir->props, MODULE_NAME); if (err) - goto err_out_stop; + goto err_out_free; if (ir_codes->ir_type != IR_TYPE_OTHER) { err = ir_raw_event_register(ir->dev); if (err) - goto err_out_stop; + goto err_out_free; } - saa7134_ir_start(dev, ir); - /* the remote isn't as bouncy as a keyboard */ ir->dev->rep[REP_DELAY] = repeat_delay; ir->dev->rep[REP_PERIOD] = repeat_period; return 0; - err_out_stop: - saa7134_ir_stop(dev); +err_out_free: dev->remote = NULL; - err_out_free: kfree(ir); return err; } diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index c3a1ae0adca..cad8aee98e5 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -20,7 +20,7 @@ */ #include -#define SAA7134_VERSION_CODE KERNEL_VERSION(0,2,15) +#define SAA7134_VERSION_CODE KERNEL_VERSION(0, 2, 16) #include #include @@ -810,7 +810,7 @@ int saa7134_input_init1(struct saa7134_dev *dev); void saa7134_input_fini(struct saa7134_dev *dev); void saa7134_input_irq(struct saa7134_dev *dev); void saa7134_probe_i2c_ir(struct saa7134_dev *dev); -void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir); +int saa7134_ir_start(struct saa7134_dev *dev); void saa7134_ir_stop(struct saa7134_dev *dev); diff --git a/include/media/ir-common.h b/include/media/ir-common.h index 87f2ec78deb..e403a9a5281 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -50,6 +50,7 @@ struct card_ir { struct ir_input_state ir; char name[32]; char phys[32]; + int users; u32 running:1; struct ir_dev_props props; diff --git a/include/media/ir-core.h b/include/media/ir-core.h index c704fa7cc11..9a2f3084ffe 100644 --- a/include/media/ir-core.h +++ b/include/media/ir-core.h @@ -56,6 +56,8 @@ struct ir_dev_props { unsigned long allowed_protos; void *priv; int (*change_protocol)(void *priv, u64 ir_type); + int (*open)(void *priv); + void (*close)(void *priv); }; struct ir_raw_event { -- cgit v1.2.3-70-g09d2 From 92f4fc10d7ba01fd84abbfae963d379c73ba5a0f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 31 Mar 2010 16:07:49 -0300 Subject: V4L/DVB: cx88: Only start IR if the input device is opened Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-input.c | 69 ++++++++++++++++++++++++++++++----- drivers/media/video/cx88/cx88-video.c | 6 +-- drivers/media/video/cx88/cx88.h | 6 +-- 3 files changed, 66 insertions(+), 15 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index 8b52546c6e1..8bd95be89e6 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -40,6 +40,10 @@ struct cx88_IR { struct cx88_core *core; struct input_dev *input; struct ir_input_state ir; + struct ir_dev_props props; + + int users; + char name[32]; char phys[32]; @@ -161,8 +165,16 @@ static enum hrtimer_restart cx88_ir_work(struct hrtimer *timer) return HRTIMER_RESTART; } -void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir) +static int __cx88_ir_start(void *priv) { + struct cx88_core *core = priv; + struct cx88_IR *ir; + + if (!core || !core->ir) + return -EINVAL; + + ir = core->ir; + if (ir->polling) { hrtimer_init(&ir->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); ir->timer.function = cx88_ir_work; @@ -175,10 +187,18 @@ void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir) cx_write(MO_DDS_IO, 0xa80a80); /* 4 kHz sample rate */ cx_write(MO_DDSCFG_IO, 0x5); /* enable */ } + return 0; } -void cx88_ir_stop(struct cx88_core *core, struct cx88_IR *ir) +static void __cx88_ir_stop(void *priv) { + struct cx88_core *core = priv; + struct cx88_IR *ir; + + if (!core || !core->ir) + return; + + ir = core->ir; if (ir->sampling) { cx_write(MO_DDSCFG_IO, 0x0); core->pci_irqmask &= ~PCI_INT_IR_SMPINT; @@ -188,6 +208,37 @@ void cx88_ir_stop(struct cx88_core *core, struct cx88_IR *ir) hrtimer_cancel(&ir->timer); } +int cx88_ir_start(struct cx88_core *core) +{ + if (core->ir->users) + return __cx88_ir_start(core); + + return 0; +} + +void cx88_ir_stop(struct cx88_core *core) +{ + if (core->ir->users) + __cx88_ir_stop(core); +} + +static int cx88_ir_open(void *priv) +{ + struct cx88_core *core = priv; + + core->ir->users++; + return __cx88_ir_start(core); +} + +static void cx88_ir_close(void *priv) +{ + struct cx88_core *core = priv; + + core->ir->users--; + if (!core->ir->users) + __cx88_ir_stop(core); +} + /* ---------------------------------------------------------------------- */ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) @@ -383,19 +434,19 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) ir->core = core; core->ir = ir; - cx88_ir_start(core, ir); + ir->props.priv = core; + ir->props.open = cx88_ir_open; + ir->props.close = cx88_ir_close; /* all done */ - err = ir_input_register(ir->input, ir_codes, NULL, MODULE_NAME); + err = ir_input_register(ir->input, ir_codes, &ir->props, MODULE_NAME); if (err) - goto err_out_stop; + goto err_out_free; return 0; - err_out_stop: - cx88_ir_stop(core, ir); - core->ir = NULL; err_out_free: + core->ir = NULL; kfree(ir); return err; } @@ -408,7 +459,7 @@ int cx88_ir_fini(struct cx88_core *core) if (NULL == ir) return 0; - cx88_ir_stop(core, ir); + cx88_ir_stop(core); ir_input_unregister(ir->input); kfree(ir); diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 48c450f4a85..8e414f7aa76 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -1977,7 +1977,7 @@ static void __devexit cx8800_finidev(struct pci_dev *pci_dev) } if (core->ir) - cx88_ir_stop(core, core->ir); + cx88_ir_stop(core); cx88_shutdown(core); /* FIXME */ pci_disable_device(pci_dev); @@ -2015,7 +2015,7 @@ static int cx8800_suspend(struct pci_dev *pci_dev, pm_message_t state) spin_unlock(&dev->slock); if (core->ir) - cx88_ir_stop(core, core->ir); + cx88_ir_stop(core); /* FIXME -- shutdown device */ cx88_shutdown(core); @@ -2056,7 +2056,7 @@ static int cx8800_resume(struct pci_dev *pci_dev) /* FIXME: re-initialize hardware */ cx88_reset(core); if (core->ir) - cx88_ir_start(core, core->ir); + cx88_ir_start(core); cx_set(MO_PCI_INTMSK, core->pci_irqmask); diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index b5f054d124f..bdb03d33653 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -41,7 +41,7 @@ #include #include -#define CX88_VERSION_CODE KERNEL_VERSION(0,0,7) +#define CX88_VERSION_CODE KERNEL_VERSION(0, 0, 8) #define UNSET (-1U) @@ -683,8 +683,8 @@ s32 cx88_dsp_detect_stereo_sap(struct cx88_core *core); int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci); int cx88_ir_fini(struct cx88_core *core); void cx88_ir_irq(struct cx88_core *core); -void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir); -void cx88_ir_stop(struct cx88_core *core, struct cx88_IR *ir); +int cx88_ir_start(struct cx88_core *core); +void cx88_ir_stop(struct cx88_core *core); /* ----------------------------------------------------------- */ /* cx88-mpeg.c */ -- cgit v1.2.3-70-g09d2 From b084307c750cb3de4a366aeced1b69ee768c81aa Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 6 Apr 2010 02:26:48 -0300 Subject: V4L/DVB: cx23885: strcpy() => strlcpy() cap->driver is a 16 char buffer and dev->name is a 32 char buffer. I don't see an actual problem, but we may as well make the static checkers happy. Signed-off-by: Dan Carpenter Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx23885/cx23885-417.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx23885/cx23885-417.c b/drivers/media/video/cx23885/cx23885-417.c index a8ddc227cf8..abd64e89f60 100644 --- a/drivers/media/video/cx23885/cx23885-417.c +++ b/drivers/media/video/cx23885/cx23885-417.c @@ -1356,7 +1356,7 @@ static int vidioc_querycap(struct file *file, void *priv, struct cx23885_dev *dev = fh->dev; struct cx23885_tsport *tsport = &dev->ts1; - strcpy(cap->driver, dev->name); + strlcpy(cap->driver, dev->name, sizeof(cap->driver)); strlcpy(cap->card, cx23885_boards[tsport->dev->board].name, sizeof(cap->card)); sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci)); -- cgit v1.2.3-70-g09d2 From d49f7a240575937703f04d07cf41be1672ce2e25 Mon Sep 17 00:00:00 2001 From: Ricardo Maraschini Date: Tue, 6 Apr 2010 02:40:43 -0300 Subject: V4L/DVB: cx88-dvb: fix on switch identation [dougsland@redhat.com: fixed reject due changes in cx88-dvb.c] Signed-off-by: Ricardo Maraschini Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-dvb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 94ab862f021..faa8e8163a4 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -1231,7 +1231,7 @@ static int dvb_register(struct cx8802_dev *dev) fe->ops.tuner_ops.set_config(fe, &ctl); } break; - case CX88_BOARD_PINNACLE_HYBRID_PCTV: + case CX88_BOARD_PINNACLE_HYBRID_PCTV: case CX88_BOARD_WINFAST_DTV1800H: fe0->dvb.frontend = dvb_attach(zl10353_attach, &cx88_pinnacle_hybrid_pctv, -- cgit v1.2.3-70-g09d2 From e20144770f5a119516f93959eca9818fa5ff065e Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 6 Apr 2010 02:51:04 -0300 Subject: V4L/DVB: drivers/media/video: avoid NULL dereference It seems impossible for ov to be NULL at this point. The semantic match that finds the problem is as follows: (http://coccinelle.lip6.fr/) // @r exists@ expression E, E1; identifier f; statement S1,S3; iterator iter; @@ if ((E == NULL && ...) || ...) { ... when != false ((E == NULL && ...) || ...) when != true ((E != NULL && ...) || ...) when != iter(E,...) S1 when != E = E1 ( sizeof(E->f) | * E->f ) ... when any return ...; } else S3 // Signed-off-by: Julia Lawall Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ov511.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/ov511.c b/drivers/media/video/ov511.c index e0bce8dc74b..dd1b1ac1a0e 100644 --- a/drivers/media/video/ov511.c +++ b/drivers/media/video/ov511.c @@ -5916,11 +5916,6 @@ ov51x_disconnect(struct usb_interface *intf) mutex_lock(&ov->lock); usb_set_intfdata (intf, NULL); - if (!ov) { - mutex_unlock(&ov->lock); - return; - } - /* Free device number */ ov511_devused &= ~(1 << ov->nr); -- cgit v1.2.3-70-g09d2 From e838326312bbacd6c320113711e2662568d4fc6c Mon Sep 17 00:00:00 2001 From: Vladimir Ermakov Date: Wed, 7 Apr 2010 02:23:31 -0300 Subject: V4L/DVB: saa7134: fix GPIO HW-404M7 Signed-off-by: Vladimir Ermakov Reviewed-by: hermann pitton Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-cards.c | 4 ++-- drivers/media/video/saa7134/saa7134-input.c | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 655068f6c49..b937d4da313 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -5364,12 +5364,12 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .gpiomask = 0x01fc00, + .gpiomask = 0x389c00, .inputs = {{ .name = name_comp1, .vmux = 3, .amux = LINE1, - .gpio = 0x389c00, + .gpio = 0x01fc00, } }, }, diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index ae17b853f95..c8c1c9ae6a7 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -607,7 +607,6 @@ int saa7134_input_init1(struct saa7134_dev *dev) switch (dev->board) { case SAA7134_BOARD_FLYVIDEO2000: case SAA7134_BOARD_FLYVIDEO3000: - case SAA7134_BOARD_HAWELL_HW_404M7: case SAA7134_BOARD_FLYTVPLATINUM_FM: case SAA7134_BOARD_FLYTVPLATINUM_MINI2: case SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM: -- cgit v1.2.3-70-g09d2 From 42397ce42cb0a56276abde767e1598af74ca0af2 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 7 Apr 2010 02:59:26 -0300 Subject: V4L/DVB: ov511: Fix continuation lines Signed-off-by: Joe Perches Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ov511.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/ov511.c b/drivers/media/video/ov511.c index dd1b1ac1a0e..6085d558255 100644 --- a/drivers/media/video/ov511.c +++ b/drivers/media/video/ov511.c @@ -57,8 +57,8 @@ #define DRIVER_VERSION "v1.64 for Linux 2.5" #define EMAIL "mark@alpha.dyndns.org" #define DRIVER_AUTHOR "Mark McClelland & Bret Wallach \ - & Orion Sky Lawlor & Kevin Moore & Charl P. Botha \ - & Claudio Matsuoka " +& Orion Sky Lawlor & Kevin Moore & Charl P. Botha \ + & Claudio Matsuoka " #define DRIVER_DESC "ov511 USB Camera Driver" #define OV511_I2C_RETRIES 3 -- cgit v1.2.3-70-g09d2 From d705d2ab7596b4661a2f13172f4f93ad11bd761f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 1 Apr 2010 21:27:04 -0300 Subject: V4L/DVB: ir: use IR_KEYTABLE where an IR table is needed Replaces most of the occurences of IR keytables on V4L drivers by a macro that evaluates to provide the name of the exported symbol. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dm1105/dm1105.c | 2 +- drivers/media/dvb/ttpci/budget-ci.c | 6 +-- drivers/media/video/bt8xx/bttv-input.c | 24 +++++----- drivers/media/video/cx18/cx18-i2c.c | 2 +- drivers/media/video/cx23885/cx23885-input.c | 2 +- drivers/media/video/cx88/cx88-input.c | 38 ++++++++-------- drivers/media/video/em28xx/em28xx-cards.c | 34 +++++++-------- drivers/media/video/ir-kbd-i2c.c | 18 ++++---- drivers/media/video/ivtv/ivtv-i2c.c | 6 +-- drivers/media/video/saa7134/saa7134-input.c | 68 ++++++++++++++--------------- 10 files changed, 100 insertions(+), 100 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c index 3229ff325c5..ff62dc8633c 100644 --- a/drivers/media/dvb/dm1105/dm1105.c +++ b/drivers/media/dvb/dm1105/dm1105.c @@ -596,7 +596,7 @@ static irqreturn_t dm1105_irq(int irq, void *dev_id) int __devinit dm1105_ir_init(struct dm1105_dev *dm1105) { struct input_dev *input_dev; - struct ir_scancode_table *ir_codes = &ir_codes_dm1105_nec_table; + struct ir_scancode_table *ir_codes = &IR_KEYTABLE(dm1105_nec); u64 ir_type = IR_TYPE_OTHER; int err = -ENOMEM; diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index ec89afd3891..75c640e5966 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -232,7 +232,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci) case 0x1011: case 0x1012: /* The hauppauge keymap is a superset of these remotes */ - ir_codes = &ir_codes_hauppauge_new_table; + ir_codes = &IR_KEYTABLE(hauppauge_new); if (rc5_device < 0) budget_ci->ir.rc5_device = 0x1f; @@ -241,11 +241,11 @@ static int msp430_ir_init(struct budget_ci *budget_ci) case 0x1017: case 0x101a: /* for the Technotrend 1500 bundled remote */ - ir_codes = &ir_codes_tt_1500_table; + ir_codes = &IR_KEYTABLE(tt_1500); break; default: /* unknown remote */ - ir_codes = &ir_codes_budget_ci_old_table; + ir_codes = &IR_KEYTABLE(budget_ci_old); break; } diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c index d17a9b7911e..e3d239da1ba 100644 --- a/drivers/media/video/bt8xx/bttv-input.c +++ b/drivers/media/video/bt8xx/bttv-input.c @@ -266,7 +266,7 @@ int bttv_input_init(struct bttv *btv) case BTTV_BOARD_AVERMEDIA: case BTTV_BOARD_AVPHONE98: case BTTV_BOARD_AVERMEDIA98: - ir_codes = &ir_codes_avermedia_table; + ir_codes = &IR_KEYTABLE(avermedia); ir->mask_keycode = 0xf88000; ir->mask_keydown = 0x010000; ir->polling = 50; // ms @@ -274,14 +274,14 @@ int bttv_input_init(struct bttv *btv) case BTTV_BOARD_AVDVBT_761: case BTTV_BOARD_AVDVBT_771: - ir_codes = &ir_codes_avermedia_dvbt_table; + ir_codes = &IR_KEYTABLE(avermedia_dvbt); ir->mask_keycode = 0x0f00c0; ir->mask_keydown = 0x000020; ir->polling = 50; // ms break; case BTTV_BOARD_PXELVWPLTVPAK: - ir_codes = &ir_codes_pixelview_table; + ir_codes = &IR_KEYTABLE(pixelview); ir->mask_keycode = 0x003e00; ir->mask_keyup = 0x010000; ir->polling = 50; // ms @@ -289,24 +289,24 @@ int bttv_input_init(struct bttv *btv) case BTTV_BOARD_PV_M4900: case BTTV_BOARD_PV_BT878P_9B: case BTTV_BOARD_PV_BT878P_PLUS: - ir_codes = &ir_codes_pixelview_table; + ir_codes = &IR_KEYTABLE(pixelview); ir->mask_keycode = 0x001f00; ir->mask_keyup = 0x008000; ir->polling = 50; // ms break; case BTTV_BOARD_WINFAST2000: - ir_codes = &ir_codes_winfast_table; + ir_codes = &IR_KEYTABLE(winfast); ir->mask_keycode = 0x1f8; break; case BTTV_BOARD_MAGICTVIEW061: case BTTV_BOARD_MAGICTVIEW063: - ir_codes = &ir_codes_winfast_table; + ir_codes = &IR_KEYTABLE(winfast); ir->mask_keycode = 0x0008e000; ir->mask_keydown = 0x00200000; break; case BTTV_BOARD_APAC_VIEWCOMP: - ir_codes = &ir_codes_apac_viewcomp_table; + ir_codes = &IR_KEYTABLE(apac_viewcomp); ir->mask_keycode = 0x001f00; ir->mask_keyup = 0x008000; ir->polling = 50; // ms @@ -314,30 +314,30 @@ int bttv_input_init(struct bttv *btv) case BTTV_BOARD_ASKEY_CPH03X: case BTTV_BOARD_CONCEPTRONIC_CTVFMI2: case BTTV_BOARD_CONTVFMI: - ir_codes = &ir_codes_pixelview_table; + ir_codes = &IR_KEYTABLE(pixelview); ir->mask_keycode = 0x001F00; ir->mask_keyup = 0x006000; ir->polling = 50; // ms break; case BTTV_BOARD_NEBULA_DIGITV: - ir_codes = &ir_codes_nebula_table; + ir_codes = &IR_KEYTABLE(nebula); btv->custom_irq = bttv_rc5_irq; ir->rc5_gpio = 1; break; case BTTV_BOARD_MACHTV_MAGICTV: - ir_codes = &ir_codes_apac_viewcomp_table; + ir_codes = &IR_KEYTABLE(apac_viewcomp); ir->mask_keycode = 0x001F00; ir->mask_keyup = 0x004000; ir->polling = 50; /* ms */ break; case BTTV_BOARD_KOZUMI_KTV_01C: - ir_codes = &ir_codes_pctv_sedna_table; + ir_codes = &IR_KEYTABLE(pctv_sedna); ir->mask_keycode = 0x001f00; ir->mask_keyup = 0x006000; ir->polling = 50; /* ms */ break; case BTTV_BOARD_ENLTV_FM_2: - ir_codes = &ir_codes_encore_enltv2_table; + ir_codes = &IR_KEYTABLE(encore_enltv2); ir->mask_keycode = 0x00fd00; ir->mask_keyup = 0x000080; ir->polling = 1; /* ms */ diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c index eecf29af916..476c016e63a 100644 --- a/drivers/media/video/cx18/cx18-i2c.c +++ b/drivers/media/video/cx18/cx18-i2c.c @@ -109,7 +109,7 @@ static int cx18_i2c_new_ir(struct cx18 *cx, struct i2c_adapter *adap, u32 hw, /* Our default information for ir-kbd-i2c.c to use */ switch (hw) { case CX18_HW_Z8F0811_IR_RX_HAUP: - init_data->ir_codes = &ir_codes_hauppauge_new_table; + init_data->ir_codes = &IR_KEYTABLE(hauppauge_new); init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; init_data->type = IR_TYPE_RC5; init_data->name = cx->card_name; diff --git a/drivers/media/video/cx23885/cx23885-input.c b/drivers/media/video/cx23885/cx23885-input.c index ef1db2d9668..66d3e1c64ce 100644 --- a/drivers/media/video/cx23885/cx23885-input.c +++ b/drivers/media/video/cx23885/cx23885-input.c @@ -355,7 +355,7 @@ int cx23885_input_init(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1850: case CX23885_BOARD_HAUPPAUGE_HVR1290: /* Parameters for the grey Hauppauge remote for the HVR-1850 */ - ir_codes = &ir_codes_hauppauge_new_table; + ir_codes = &IR_KEYTABLE(hauppauge_new); ir_type = IR_TYPE_RC5; ir_addr = 0x1e; /* RC-5 system bits emitted by the remote */ ir_start = RC5_START_BITS_NORMAL; /* A basic RC-5 remote */ diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index 8bd95be89e6..48ca9805bb9 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -261,14 +261,14 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) case CX88_BOARD_DNTV_LIVE_DVB_T: case CX88_BOARD_KWORLD_DVB_T: case CX88_BOARD_KWORLD_DVB_T_CX22702: - ir_codes = &ir_codes_dntv_live_dvb_t_table; + ir_codes = &IR_KEYTABLE(dntv_live_dvb_t); ir->gpio_addr = MO_GP1_IO; ir->mask_keycode = 0x1f; ir->mask_keyup = 0x60; ir->polling = 50; /* ms */ break; case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: - ir_codes = &ir_codes_cinergy_1400_table; + ir_codes = &IR_KEYTABLE(cinergy_1400); ir_type = IR_TYPE_PD; ir->sampling = 0xeb04; /* address */ break; @@ -283,14 +283,14 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) case CX88_BOARD_PCHDTV_HD3000: case CX88_BOARD_PCHDTV_HD5500: case CX88_BOARD_HAUPPAUGE_IRONLY: - ir_codes = &ir_codes_hauppauge_new_table; + ir_codes = &IR_KEYTABLE(hauppauge_new); ir_type = IR_TYPE_RC5; ir->sampling = 1; break; case CX88_BOARD_WINFAST_DTV2000H: case CX88_BOARD_WINFAST_DTV2000H_J: case CX88_BOARD_WINFAST_DTV1800H: - ir_codes = &ir_codes_winfast_table; + ir_codes = &IR_KEYTABLE(winfast); ir->gpio_addr = MO_GP0_IO; ir->mask_keycode = 0x8f8; ir->mask_keyup = 0x100; @@ -299,14 +299,14 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) case CX88_BOARD_WINFAST2000XP_EXPERT: case CX88_BOARD_WINFAST_DTV1000: case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: - ir_codes = &ir_codes_winfast_table; + ir_codes = &IR_KEYTABLE(winfast); ir->gpio_addr = MO_GP0_IO; ir->mask_keycode = 0x8f8; ir->mask_keyup = 0x100; ir->polling = 1; /* ms */ break; case CX88_BOARD_IODATA_GVBCTV7E: - ir_codes = &ir_codes_iodata_bctv7e_table; + ir_codes = &IR_KEYTABLE(iodata_bctv7e); ir->gpio_addr = MO_GP0_IO; ir->mask_keycode = 0xfd; ir->mask_keydown = 0x02; @@ -314,7 +314,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) break; case CX88_BOARD_PROLINK_PLAYTVPVR: case CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO: - ir_codes = &ir_codes_pixelview_table; + ir_codes = &IR_KEYTABLE(pixelview); ir->gpio_addr = MO_GP1_IO; ir->mask_keycode = 0x1f; ir->mask_keyup = 0x80; @@ -322,28 +322,28 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) break; case CX88_BOARD_PROLINK_PV_8000GT: case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME: - ir_codes = &ir_codes_pixelview_new_table; + ir_codes = &IR_KEYTABLE(pixelview_new); ir->gpio_addr = MO_GP1_IO; ir->mask_keycode = 0x3f; ir->mask_keyup = 0x80; ir->polling = 1; /* ms */ break; case CX88_BOARD_KWORLD_LTV883: - ir_codes = &ir_codes_pixelview_table; + ir_codes = &IR_KEYTABLE(pixelview); ir->gpio_addr = MO_GP1_IO; ir->mask_keycode = 0x1f; ir->mask_keyup = 0x60; ir->polling = 1; /* ms */ break; case CX88_BOARD_ADSTECH_DVB_T_PCI: - ir_codes = &ir_codes_adstech_dvb_t_pci_table; + ir_codes = &IR_KEYTABLE(adstech_dvb_t_pci); ir->gpio_addr = MO_GP1_IO; ir->mask_keycode = 0xbf; ir->mask_keyup = 0x40; ir->polling = 50; /* ms */ break; case CX88_BOARD_MSI_TVANYWHERE_MASTER: - ir_codes = &ir_codes_msi_tvanywhere_table; + ir_codes = &IR_KEYTABLE(msi_tvanywhere); ir->gpio_addr = MO_GP1_IO; ir->mask_keycode = 0x1f; ir->mask_keyup = 0x40; @@ -351,7 +351,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) break; case CX88_BOARD_AVERTV_303: case CX88_BOARD_AVERTV_STUDIO_303: - ir_codes = &ir_codes_avertv_303_table; + ir_codes = &IR_KEYTABLE(avertv_303); ir->gpio_addr = MO_GP2_IO; ir->mask_keycode = 0xfb; ir->mask_keydown = 0x02; @@ -364,41 +364,41 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) case CX88_BOARD_PROF_7300: case CX88_BOARD_PROF_7301: case CX88_BOARD_PROF_6200: - ir_codes = &ir_codes_tbs_nec_table; + ir_codes = &IR_KEYTABLE(tbs_nec); ir_type = IR_TYPE_PD; ir->sampling = 0xff00; /* address */ break; case CX88_BOARD_TEVII_S460: case CX88_BOARD_TEVII_S420: - ir_codes = &ir_codes_tevii_nec_table; + ir_codes = &IR_KEYTABLE(tevii_nec); ir_type = IR_TYPE_PD; ir->sampling = 0xff00; /* address */ break; case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: - ir_codes = &ir_codes_dntv_live_dvbt_pro_table; + ir_codes = &IR_KEYTABLE(dntv_live_dvbt_pro); ir_type = IR_TYPE_PD; ir->sampling = 0xff00; /* address */ break; case CX88_BOARD_NORWOOD_MICRO: - ir_codes = &ir_codes_norwood_table; + ir_codes = &IR_KEYTABLE(norwood); ir->gpio_addr = MO_GP1_IO; ir->mask_keycode = 0x0e; ir->mask_keyup = 0x80; ir->polling = 50; /* ms */ break; case CX88_BOARD_NPGTECH_REALTV_TOP10FM: - ir_codes = &ir_codes_npgtech_table; + ir_codes = &IR_KEYTABLE(npgtech); ir->gpio_addr = MO_GP0_IO; ir->mask_keycode = 0xfa; ir->polling = 50; /* ms */ break; case CX88_BOARD_PINNACLE_PCTV_HD_800i: - ir_codes = &ir_codes_pinnacle_pctv_hd_table; + ir_codes = &IR_KEYTABLE(pinnacle_pctv_hd); ir_type = IR_TYPE_RC5; ir->sampling = 1; break; case CX88_BOARD_POWERCOLOR_REAL_ANGEL: - ir_codes = &ir_codes_powercolor_real_angel_table; + ir_codes = &IR_KEYTABLE(powercolor_real_angel); ir->gpio_addr = MO_GP2_IO; ir->mask_keycode = 0x7e; ir->polling = 100; /* ms */ diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 7b0ca583de5..29201438b45 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -602,7 +602,7 @@ struct em28xx_board em28xx_boards[] = { .name = "Gadmei UTV330+", .tuner_type = TUNER_TNF_5335MF, .tda9887_conf = TDA9887_PRESENT, - .ir_codes = &ir_codes_gadmei_rm008z_table, + .ir_codes = &IR_KEYTABLE(gadmei_rm008z), .decoder = EM28XX_SAA711X, .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, .input = { { @@ -791,7 +791,7 @@ struct em28xx_board em28xx_boards[] = { .mts_firmware = 1, .has_dvb = 1, .dvb_gpio = hauppauge_wintv_hvr_900_digital, - .ir_codes = &ir_codes_hauppauge_new_table, + .ir_codes = &IR_KEYTABLE(hauppauge_new), .decoder = EM28XX_TVP5150, .input = { { .type = EM28XX_VMUX_TELEVISION, @@ -816,7 +816,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_XC2028, .tuner_gpio = default_tuner_gpio, .mts_firmware = 1, - .ir_codes = &ir_codes_hauppauge_new_table, + .ir_codes = &IR_KEYTABLE(hauppauge_new), .decoder = EM28XX_TVP5150, .input = { { .type = EM28XX_VMUX_TELEVISION, @@ -842,7 +842,7 @@ struct em28xx_board em28xx_boards[] = { .mts_firmware = 1, .has_dvb = 1, .dvb_gpio = hauppauge_wintv_hvr_900_digital, - .ir_codes = &ir_codes_hauppauge_new_table, + .ir_codes = &IR_KEYTABLE(hauppauge_new), .decoder = EM28XX_TVP5150, .input = { { .type = EM28XX_VMUX_TELEVISION, @@ -868,7 +868,7 @@ struct em28xx_board em28xx_boards[] = { .mts_firmware = 1, .has_dvb = 1, .dvb_gpio = hauppauge_wintv_hvr_900_digital, - .ir_codes = &ir_codes_rc5_hauppauge_new_table, + .ir_codes = &IR_KEYTABLE(rc5_hauppauge_new), .decoder = EM28XX_TVP5150, .input = { { .type = EM28XX_VMUX_TELEVISION, @@ -894,7 +894,7 @@ struct em28xx_board em28xx_boards[] = { .mts_firmware = 1, .has_dvb = 1, .dvb_gpio = hauppauge_wintv_hvr_900_digital, - .ir_codes = &ir_codes_pinnacle_pctv_hd_table, + .ir_codes = &IR_KEYTABLE(pinnacle_pctv_hd), .decoder = EM28XX_TVP5150, .input = { { .type = EM28XX_VMUX_TELEVISION, @@ -920,7 +920,7 @@ struct em28xx_board em28xx_boards[] = { .mts_firmware = 1, .has_dvb = 1, .dvb_gpio = hauppauge_wintv_hvr_900_digital, - .ir_codes = &ir_codes_ati_tv_wonder_hd_600_table, + .ir_codes = &IR_KEYTABLE(ati_tv_wonder_hd_600), .decoder = EM28XX_TVP5150, .input = { { .type = EM28XX_VMUX_TELEVISION, @@ -946,7 +946,7 @@ struct em28xx_board em28xx_boards[] = { .decoder = EM28XX_TVP5150, .has_dvb = 1, .dvb_gpio = default_digital, - .ir_codes = &ir_codes_terratec_cinergy_xs_table, + .ir_codes = &IR_KEYTABLE(terratec_cinergy_xs), .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, /* NEC IR */ .input = { { .type = EM28XX_VMUX_TELEVISION, @@ -1296,7 +1296,7 @@ struct em28xx_board em28xx_boards[] = { .decoder = EM28XX_SAA711X, .has_dvb = 1, .dvb_gpio = em2882_kworld_315u_digital, - .ir_codes = &ir_codes_kworld_315u_table, + .ir_codes = &IR_KEYTABLE(kworld_315u), .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE, /* Analog mode - still not ready */ @@ -1425,7 +1425,7 @@ struct em28xx_board em28xx_boards[] = { .has_dvb = 1, .dvb_gpio = kworld_330u_digital, .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, /* NEC IR */ - .ir_codes = &ir_codes_kworld_315u_table, + .ir_codes = &IR_KEYTABLE(kworld_315u), .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, @@ -1448,7 +1448,7 @@ struct em28xx_board em28xx_boards[] = { .decoder = EM28XX_TVP5150, .has_dvb = 1, .dvb_gpio = hauppauge_wintv_hvr_900_digital, - .ir_codes = &ir_codes_terratec_cinergy_xs_table, + .ir_codes = &IR_KEYTABLE(terratec_cinergy_xs), .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, .input = { { .type = EM28XX_VMUX_TELEVISION, @@ -1541,7 +1541,7 @@ struct em28xx_board em28xx_boards[] = { .mts_firmware = 1, .decoder = EM28XX_TVP5150, .tuner_gpio = default_tuner_gpio, - .ir_codes = &ir_codes_kaiomy_table, + .ir_codes = &IR_KEYTABLE(kaiomy), .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, @@ -1641,7 +1641,7 @@ struct em28xx_board em28xx_boards[] = { .mts_firmware = 1, .has_dvb = 1, .dvb_gpio = evga_indtube_digital, - .ir_codes = &ir_codes_evga_indtube_table, + .ir_codes = &IR_KEYTABLE(evga_indtube), .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, @@ -2335,21 +2335,21 @@ void em28xx_register_i2c_ir(struct em28xx *dev) switch (dev->model) { case EM2800_BOARD_TERRATEC_CINERGY_200: case EM2820_BOARD_TERRATEC_CINERGY_250: - dev->init_data.ir_codes = &ir_codes_em_terratec_table; + dev->init_data.ir_codes = &IR_KEYTABLE(em_terratec); dev->init_data.get_key = em28xx_get_key_terratec; dev->init_data.name = "i2c IR (EM28XX Terratec)"; break; case EM2820_BOARD_PINNACLE_USB_2: - dev->init_data.ir_codes = &ir_codes_pinnacle_grey_table; + dev->init_data.ir_codes = &IR_KEYTABLE(pinnacle_grey); dev->init_data.get_key = em28xx_get_key_pinnacle_usb_grey; dev->init_data.name = "i2c IR (EM28XX Pinnacle PCTV)"; break; case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2: - dev->init_data.ir_codes = &ir_codes_rc5_hauppauge_new_table; + dev->init_data.ir_codes = &IR_KEYTABLE(rc5_hauppauge_new); dev->init_data.get_key = em28xx_get_key_em_haup; dev->init_data.name = "i2c IR (EM2840 Hauppauge)"; case EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE: - dev->init_data.ir_codes = &ir_codes_winfast_usbii_deluxe_table;; + dev->init_data.ir_codes = &IR_KEYTABLE(winfast_usbii_deluxe);; dev->init_data.get_key = em28xx_get_key_winfast_usbii_deluxe; dev->init_data.name = "i2c IR (EM2820 Winfast TV USBII Deluxe)"; break; diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index 6af69d5c849..607a0be2ec6 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -322,13 +322,13 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) name = "Pixelview"; ir->get_key = get_key_pixelview; ir_type = IR_TYPE_OTHER; - ir_codes = &ir_codes_empty_table; + ir_codes = &IR_KEYTABLE(empty); break; case 0x4b: name = "PV951"; ir->get_key = get_key_pv951; ir_type = IR_TYPE_OTHER; - ir_codes = &ir_codes_pv951_table; + ir_codes = &IR_KEYTABLE(pv951); break; case 0x18: case 0x1f: @@ -337,22 +337,22 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) ir->get_key = get_key_haup; ir_type = IR_TYPE_RC5; if (hauppauge == 1) { - ir_codes = &ir_codes_hauppauge_new_table; + ir_codes = &IR_KEYTABLE(hauppauge_new); } else { - ir_codes = &ir_codes_rc5_tv_table; + ir_codes = &IR_KEYTABLE(rc5_tv); } break; case 0x30: name = "KNC One"; ir->get_key = get_key_knc1; ir_type = IR_TYPE_OTHER; - ir_codes = &ir_codes_empty_table; + ir_codes = &IR_KEYTABLE(empty); break; case 0x6b: name = "FusionHDTV"; ir->get_key = get_key_fusionhdtv; ir_type = IR_TYPE_RC5; - ir_codes = &ir_codes_fusionhdtv_mce_table; + ir_codes = &IR_KEYTABLE(fusionhdtv_mce); break; case 0x0b: case 0x47: @@ -365,9 +365,9 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) ir_type = IR_TYPE_RC5; ir->get_key = get_key_haup_xvr; if (hauppauge == 1) { - ir_codes = &ir_codes_hauppauge_new_table; + ir_codes = &IR_KEYTABLE(hauppauge_new); } else { - ir_codes = &ir_codes_rc5_tv_table; + ir_codes = &IR_KEYTABLE(rc5_tv); } } else { /* Handled by saa7134-input */ @@ -379,7 +379,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) name = "AVerMedia Cardbus remote"; ir->get_key = get_key_avermedia_cardbus; ir_type = IR_TYPE_OTHER; - ir_codes = &ir_codes_avermedia_cardbus_table; + ir_codes = &IR_KEYTABLE(avermedia_cardbus); break; } diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c index 2ee03c2a1b5..a363e334a50 100644 --- a/drivers/media/video/ivtv/ivtv-i2c.c +++ b/drivers/media/video/ivtv/ivtv-i2c.c @@ -193,7 +193,7 @@ static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr) /* Our default information for ir-kbd-i2c.c to use */ switch (hw) { case IVTV_HW_I2C_IR_RX_AVER: - init_data->ir_codes = &ir_codes_avermedia_cardbus_table; + init_data->ir_codes = &IR_KEYTABLE(avermedia_cardbus); init_data->internal_get_key_func = IR_KBD_GET_KEY_AVERMEDIA_CARDBUS; init_data->type = IR_TYPE_OTHER; @@ -202,14 +202,14 @@ static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr) case IVTV_HW_I2C_IR_RX_HAUP_EXT: case IVTV_HW_I2C_IR_RX_HAUP_INT: /* Default to old black remote */ - init_data->ir_codes = &ir_codes_rc5_tv_table; + init_data->ir_codes = &IR_KEYTABLE(rc5_tv); init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP; init_data->type = IR_TYPE_RC5; init_data->name = itv->card_name; break; case IVTV_HW_Z8F0811_IR_RX_HAUP: /* Default to grey remote */ - init_data->ir_codes = &ir_codes_hauppauge_new_table; + init_data->ir_codes = &IR_KEYTABLE(hauppauge_new); init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; init_data->type = IR_TYPE_RC5; init_data->name = itv->card_name; diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index c8c1c9ae6a7..eaafed181d5 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -610,27 +610,27 @@ int saa7134_input_init1(struct saa7134_dev *dev) case SAA7134_BOARD_FLYTVPLATINUM_FM: case SAA7134_BOARD_FLYTVPLATINUM_MINI2: case SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM: - ir_codes = &ir_codes_flyvideo_table; + ir_codes = &IR_KEYTABLE(flyvideo); mask_keycode = 0xEC00000; mask_keydown = 0x0040000; break; case SAA7134_BOARD_CINERGY400: case SAA7134_BOARD_CINERGY600: case SAA7134_BOARD_CINERGY600_MK3: - ir_codes = &ir_codes_cinergy_table; + ir_codes = &IR_KEYTABLE(cinergy); mask_keycode = 0x00003f; mask_keyup = 0x040000; break; case SAA7134_BOARD_ECS_TVP3XP: case SAA7134_BOARD_ECS_TVP3XP_4CB5: - ir_codes = &ir_codes_eztv_table; + ir_codes = &IR_KEYTABLE(eztv); mask_keycode = 0x00017c; mask_keyup = 0x000002; polling = 50; // ms break; case SAA7134_BOARD_KWORLD_XPERT: case SAA7134_BOARD_AVACSSMARTTV: - ir_codes = &ir_codes_pixelview_table; + ir_codes = &IR_KEYTABLE(pixelview); mask_keycode = 0x00001F; mask_keyup = 0x000020; polling = 50; // ms @@ -647,7 +647,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) case SAA7134_BOARD_AVERMEDIA_GO_007_FM: case SAA7134_BOARD_AVERMEDIA_M102: case SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS: - ir_codes = &ir_codes_avermedia_table; + ir_codes = &IR_KEYTABLE(avermedia); mask_keycode = 0x0007C8; mask_keydown = 0x000010; polling = 50; // ms @@ -656,14 +656,14 @@ int saa7134_input_init1(struct saa7134_dev *dev) saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4); break; case SAA7134_BOARD_AVERMEDIA_M135A: - ir_codes = &ir_codes_avermedia_m135a_rm_jx_table; + ir_codes = &IR_KEYTABLE(avermedia_m135a_rm_jx); mask_keydown = 0x0040000; mask_keycode = 0xffff; raw_decode = 1; break; case SAA7134_BOARD_AVERMEDIA_777: case SAA7134_BOARD_AVERMEDIA_A16AR: - ir_codes = &ir_codes_avermedia_table; + ir_codes = &IR_KEYTABLE(avermedia); mask_keycode = 0x02F200; mask_keydown = 0x000400; polling = 50; // ms @@ -672,7 +672,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) saa_setb(SAA7134_GPIO_GPSTATUS1, 0x1); break; case SAA7134_BOARD_AVERMEDIA_A16D: - ir_codes = &ir_codes_avermedia_a16d_table; + ir_codes = &IR_KEYTABLE(avermedia_a16d); mask_keycode = 0x02F200; mask_keydown = 0x000400; polling = 50; /* ms */ @@ -681,14 +681,14 @@ int saa7134_input_init1(struct saa7134_dev *dev) saa_setb(SAA7134_GPIO_GPSTATUS1, 0x1); break; case SAA7134_BOARD_KWORLD_TERMINATOR: - ir_codes = &ir_codes_pixelview_table; + ir_codes = &IR_KEYTABLE(pixelview); mask_keycode = 0x00001f; mask_keyup = 0x000060; polling = 50; // ms break; case SAA7134_BOARD_MANLI_MTV001: case SAA7134_BOARD_MANLI_MTV002: - ir_codes = &ir_codes_manli_table; + ir_codes = &IR_KEYTABLE(manli); mask_keycode = 0x001f00; mask_keyup = 0x004000; polling = 50; /* ms */ @@ -708,25 +708,25 @@ int saa7134_input_init1(struct saa7134_dev *dev) case SAA7134_BOARD_BEHOLD_507_9FM: case SAA7134_BOARD_BEHOLD_507RDS_MK3: case SAA7134_BOARD_BEHOLD_507RDS_MK5: - ir_codes = &ir_codes_manli_table; + ir_codes = &IR_KEYTABLE(manli); mask_keycode = 0x003f00; mask_keyup = 0x004000; polling = 50; /* ms */ break; case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM: - ir_codes = &ir_codes_behold_columbus_table; + ir_codes = &IR_KEYTABLE(behold_columbus); mask_keycode = 0x003f00; mask_keyup = 0x004000; polling = 50; // ms break; case SAA7134_BOARD_SEDNA_PC_TV_CARDBUS: - ir_codes = &ir_codes_pctv_sedna_table; + ir_codes = &IR_KEYTABLE(pctv_sedna); mask_keycode = 0x001f00; mask_keyup = 0x004000; polling = 50; // ms break; case SAA7134_BOARD_GOTVIEW_7135: - ir_codes = &ir_codes_gotview7135_table; + ir_codes = &IR_KEYTABLE(gotview7135); mask_keycode = 0x0003CC; mask_keydown = 0x000010; polling = 5; /* ms */ @@ -735,80 +735,80 @@ int saa7134_input_init1(struct saa7134_dev *dev) case SAA7134_BOARD_VIDEOMATE_TV_PVR: case SAA7134_BOARD_VIDEOMATE_GOLD_PLUS: case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII: - ir_codes = &ir_codes_videomate_tv_pvr_table; + ir_codes = &IR_KEYTABLE(videomate_tv_pvr); mask_keycode = 0x00003F; mask_keyup = 0x400000; polling = 50; // ms break; case SAA7134_BOARD_PROTEUS_2309: - ir_codes = &ir_codes_proteus_2309_table; + ir_codes = &IR_KEYTABLE(proteus_2309); mask_keycode = 0x00007F; mask_keyup = 0x000080; polling = 50; // ms break; case SAA7134_BOARD_VIDEOMATE_DVBT_300: case SAA7134_BOARD_VIDEOMATE_DVBT_200: - ir_codes = &ir_codes_videomate_tv_pvr_table; + ir_codes = &IR_KEYTABLE(videomate_tv_pvr); mask_keycode = 0x003F00; mask_keyup = 0x040000; break; case SAA7134_BOARD_FLYDVBS_LR300: case SAA7134_BOARD_FLYDVBT_LR301: case SAA7134_BOARD_FLYDVBTDUO: - ir_codes = &ir_codes_flydvb_table; + ir_codes = &IR_KEYTABLE(flydvb); mask_keycode = 0x0001F00; mask_keydown = 0x0040000; break; case SAA7134_BOARD_ASUSTeK_P7131_DUAL: case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA: case SAA7134_BOARD_ASUSTeK_P7131_ANALOG: - ir_codes = &ir_codes_asus_pc39_table; + ir_codes = &IR_KEYTABLE(asus_pc39); mask_keydown = 0x0040000; rc5_gpio = 1; break; case SAA7134_BOARD_ENCORE_ENLTV: case SAA7134_BOARD_ENCORE_ENLTV_FM: - ir_codes = &ir_codes_encore_enltv_table; + ir_codes = &IR_KEYTABLE(encore_enltv); mask_keycode = 0x00007f; mask_keyup = 0x040000; polling = 50; // ms break; case SAA7134_BOARD_ENCORE_ENLTV_FM53: - ir_codes = &ir_codes_encore_enltv_fm53_table; + ir_codes = &IR_KEYTABLE(encore_enltv_fm53); mask_keydown = 0x0040000; mask_keycode = 0x00007f; nec_gpio = 1; break; case SAA7134_BOARD_10MOONSTVMASTER3: - ir_codes = &ir_codes_encore_enltv_table; + ir_codes = &IR_KEYTABLE(encore_enltv); mask_keycode = 0x5f80000; mask_keyup = 0x8000000; polling = 50; //ms break; case SAA7134_BOARD_GENIUS_TVGO_A11MCE: - ir_codes = &ir_codes_genius_tvgo_a11mce_table; + ir_codes = &IR_KEYTABLE(genius_tvgo_a11mce); mask_keycode = 0xff; mask_keydown = 0xf00000; polling = 50; /* ms */ break; case SAA7134_BOARD_REAL_ANGEL_220: - ir_codes = &ir_codes_real_audio_220_32_keys_table; + ir_codes = &IR_KEYTABLE(real_audio_220_32_keys); mask_keycode = 0x3f00; mask_keyup = 0x4000; polling = 50; /* ms */ break; case SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG: - ir_codes = &ir_codes_kworld_plus_tv_analog_table; + ir_codes = &IR_KEYTABLE(kworld_plus_tv_analog); mask_keycode = 0x7f; polling = 40; /* ms */ break; case SAA7134_BOARD_VIDEOMATE_S350: - ir_codes = &ir_codes_videomate_s350_table; + ir_codes = &IR_KEYTABLE(videomate_s350); mask_keycode = 0x003f00; mask_keydown = 0x040000; break; case SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S: - ir_codes = &ir_codes_winfast_table; + ir_codes = &IR_KEYTABLE(winfast); mask_keycode = 0x5f00; mask_keyup = 0x020000; polling = 50; /* ms */ @@ -938,24 +938,24 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) dev->init_data.name = "Pinnacle PCTV"; if (pinnacle_remote == 0) { dev->init_data.get_key = get_key_pinnacle_color; - dev->init_data.ir_codes = &ir_codes_pinnacle_color_table; + dev->init_data.ir_codes = &IR_KEYTABLE(pinnacle_color); info.addr = 0x47; } else { dev->init_data.get_key = get_key_pinnacle_grey; - dev->init_data.ir_codes = &ir_codes_pinnacle_grey_table; + dev->init_data.ir_codes = &IR_KEYTABLE(pinnacle_grey); info.addr = 0x47; } break; case SAA7134_BOARD_UPMOST_PURPLE_TV: dev->init_data.name = "Purple TV"; dev->init_data.get_key = get_key_purpletv; - dev->init_data.ir_codes = &ir_codes_purpletv_table; + dev->init_data.ir_codes = &IR_KEYTABLE(purpletv); info.addr = 0x7a; break; case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS: dev->init_data.name = "MSI TV@nywhere Plus"; dev->init_data.get_key = get_key_msi_tvanywhere_plus; - dev->init_data.ir_codes = &ir_codes_msi_tvanywhere_plus_table; + dev->init_data.ir_codes = &IR_KEYTABLE(msi_tvanywhere_plus); info.addr = 0x30; /* MSI TV@nywhere Plus controller doesn't seem to respond to probes unless we read something from @@ -969,7 +969,7 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) case SAA7134_BOARD_HAUPPAUGE_HVR1110: dev->init_data.name = "HVR 1110"; dev->init_data.get_key = get_key_hvr1110; - dev->init_data.ir_codes = &ir_codes_hauppauge_new_table; + dev->init_data.ir_codes = &IR_KEYTABLE(hauppauge_new); info.addr = 0x71; break; case SAA7134_BOARD_BEHOLD_607FM_MK3: @@ -987,7 +987,7 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) case SAA7134_BOARD_BEHOLD_X7: dev->init_data.name = "BeholdTV"; dev->init_data.get_key = get_key_beholdm6xx; - dev->init_data.ir_codes = &ir_codes_behold_table; + dev->init_data.ir_codes = &IR_KEYTABLE(behold); dev->init_data.type = IR_TYPE_NEC; info.addr = 0x2d; break; @@ -998,7 +998,7 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) case SAA7134_BOARD_FLYDVB_TRIO: dev->init_data.name = "FlyDVB Trio"; dev->init_data.get_key = get_key_flydvb_trio; - dev->init_data.ir_codes = &ir_codes_flydvb_table; + dev->init_data.ir_codes = &IR_KEYTABLE(flydvb); info.addr = 0x0b; break; default: -- cgit v1.2.3-70-g09d2 From b2245ba1644eb1eba400fd04c6e7bb3ab2d4a8fa Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 2 Apr 2010 13:18:42 -0300 Subject: V4L/DVB: ir: prepare IR code for a parameter change at register function A latter patch will reuse the ir_input_register with a different meaning. Before it, change all occurrences to a temporary name. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-keytable.c | 6 +++--- drivers/media/dvb/dm1105/dm1105.c | 2 +- drivers/media/dvb/mantis/mantis_input.c | 2 +- drivers/media/dvb/ttpci/budget-ci.c | 2 +- drivers/media/video/bt8xx/bttv-input.c | 2 +- drivers/media/video/cx231xx/cx231xx-input.c | 2 +- drivers/media/video/cx23885/cx23885-input.c | 2 +- drivers/media/video/cx88/cx88-input.c | 2 +- drivers/media/video/em28xx/em28xx-input.c | 2 +- drivers/media/video/ir-kbd-i2c.c | 2 +- drivers/media/video/saa7134/saa7134-input.c | 2 +- include/media/ir-core.h | 26 ++++++++++++++++++++------ 12 files changed, 33 insertions(+), 19 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c index 99cad829a18..5d4ddc9f4ca 100644 --- a/drivers/media/IR/ir-keytable.c +++ b/drivers/media/IR/ir-keytable.c @@ -461,7 +461,7 @@ static void ir_close(struct input_dev *input_dev) } /** - * ir_input_register() - sets the IR keycode table and add the handlers + * __ir_input_register() - sets the IR keycode table and add the handlers * for keymap table get/set * @input_dev: the struct input_dev descriptor of the device * @rc_tab: the struct ir_scancode_table table of scancode/keymap @@ -471,7 +471,7 @@ static void ir_close(struct input_dev *input_dev) * It will register the input/evdev interface for the device and * register the syfs code for IR class */ -int ir_input_register(struct input_dev *input_dev, +int __ir_input_register(struct input_dev *input_dev, const struct ir_scancode_table *rc_tab, const struct ir_dev_props *props, const char *driver_name) @@ -539,7 +539,7 @@ err: kfree(ir_dev); return rc; } -EXPORT_SYMBOL_GPL(ir_input_register); +EXPORT_SYMBOL_GPL(__ir_input_register); /** * ir_input_unregister() - unregisters IR and frees resources diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c index ff62dc8633c..416c29bf78d 100644 --- a/drivers/media/dvb/dm1105/dm1105.c +++ b/drivers/media/dvb/dm1105/dm1105.c @@ -630,7 +630,7 @@ int __devinit dm1105_ir_init(struct dm1105_dev *dm1105) INIT_WORK(&dm1105->ir.work, dm1105_emit_key); - err = ir_input_register(input_dev, ir_codes, NULL, MODULE_NAME); + err = __ir_input_register(input_dev, ir_codes, NULL, MODULE_NAME); return err; } diff --git a/drivers/media/dvb/mantis/mantis_input.c b/drivers/media/dvb/mantis/mantis_input.c index 6baf3022968..3d4e4663220 100644 --- a/drivers/media/dvb/mantis/mantis_input.c +++ b/drivers/media/dvb/mantis/mantis_input.c @@ -128,7 +128,7 @@ int mantis_input_init(struct mantis_pci *mantis) rc->id.version = 1; rc->dev = mantis->pdev->dev; - err = ir_input_register(rc, &ir_mantis, NULL, MODULE_NAME); + err = __ir_input_register(rc, &ir_mantis, NULL, MODULE_NAME); if (err) { dprintk(MANTIS_ERROR, 1, "IR device registration failed, ret = %d", err); input_free_device(rc); diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index 75c640e5966..ab7479ad592 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -256,7 +256,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci) budget_ci->ir.timer_keyup.function = msp430_ir_keyup; budget_ci->ir.timer_keyup.data = (unsigned long) &budget_ci->ir; budget_ci->ir.last_raw = 0xffff; /* An impossible value */ - error = ir_input_register(input_dev, ir_codes, NULL, MODULE_NAME); + error = __ir_input_register(input_dev, ir_codes, NULL, MODULE_NAME); if (error) { printk(KERN_ERR "budget_ci: could not init driver for IR device (code %d)\n", error); return error; diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c index e3d239da1ba..71a0047ca7b 100644 --- a/drivers/media/video/bt8xx/bttv-input.c +++ b/drivers/media/video/bt8xx/bttv-input.c @@ -392,7 +392,7 @@ int bttv_input_init(struct bttv *btv) bttv_ir_start(btv, ir); /* all done */ - err = ir_input_register(btv->remote->dev, ir_codes, NULL, MODULE_NAME); + err = __ir_input_register(btv->remote->dev, ir_codes, NULL, MODULE_NAME); if (err) goto err_out_stop; diff --git a/drivers/media/video/cx231xx/cx231xx-input.c b/drivers/media/video/cx231xx/cx231xx-input.c index a0e8bb88d67..04ae0839dea 100644 --- a/drivers/media/video/cx231xx/cx231xx-input.c +++ b/drivers/media/video/cx231xx/cx231xx-input.c @@ -219,7 +219,7 @@ int cx231xx_ir_init(struct cx231xx *dev) cx231xx_ir_start(ir); /* all done */ - err = ir_input_register(ir->input, dev->board.ir_codes, + err = __ir_input_register(ir->input, dev->board.ir_codes, NULL, MODULE_NAME); if (err) goto err_out_stop; diff --git a/drivers/media/video/cx23885/cx23885-input.c b/drivers/media/video/cx23885/cx23885-input.c index 66d3e1c64ce..cef36f6b93e 100644 --- a/drivers/media/video/cx23885/cx23885-input.c +++ b/drivers/media/video/cx23885/cx23885-input.c @@ -400,7 +400,7 @@ int cx23885_input_init(struct cx23885_dev *dev) dev->ir_input = ir; cx23885_input_ir_start(dev); - ret = ir_input_register(ir->dev, ir_codes, NULL, MODULE_NAME); + ret = __ir_input_register(ir->dev, ir_codes, NULL, MODULE_NAME); if (ret) goto err_out_stop; diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index 48ca9805bb9..30af956a9ea 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -439,7 +439,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) ir->props.close = cx88_ir_close; /* all done */ - err = ir_input_register(ir->input, ir_codes, &ir->props, MODULE_NAME); + err = __ir_input_register(ir->input, ir_codes, &ir->props, MODULE_NAME); if (err) goto err_out_free; diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index 32f376654c0..6f1fc695c56 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c @@ -475,7 +475,7 @@ int em28xx_ir_init(struct em28xx *dev) em28xx_ir_start(ir); /* all done */ - err = ir_input_register(ir->input, dev->board.ir_codes, + err = __ir_input_register(ir->input, dev->board.ir_codes, &ir->props, MODULE_NAME); if (err) goto err_out_stop; diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index 607a0be2ec6..e6ada5e46df 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -447,7 +447,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) input_dev->name = ir->name; input_dev->phys = ir->phys; - err = ir_input_register(ir->input, ir->ir_codes, NULL, MODULE_NAME); + err = __ir_input_register(ir->input, ir->ir_codes, NULL, MODULE_NAME); if (err) goto err_out_free; diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index eaafed181d5..bf6751c760b 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -877,7 +877,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) } input_dev->dev.parent = &dev->pci->dev; - err = ir_input_register(ir->dev, ir_codes, &ir->props, MODULE_NAME); + err = __ir_input_register(ir->dev, ir_codes, &ir->props, MODULE_NAME); if (err) goto err_out_free; if (ir_codes->ir_type != IR_TYPE_OTHER) { diff --git a/include/media/ir-core.h b/include/media/ir-core.h index 39df3cf9e84..8e975f24dae 100644 --- a/include/media/ir-core.h +++ b/include/media/ir-core.h @@ -119,23 +119,37 @@ EXPORT_SYMBOL_GPL(IR_KEYTABLE(tabname)) #define DEFINE_LEGACY_IR_KEYTABLE(tabname) \ DEFINE_IR_KEYTABLE(tabname, IR_TYPE_UNKNOWN) +/* Routines from rc-map.c */ + +int ir_register_map(struct rc_keymap *map); +void ir_unregister_map(struct rc_keymap *map); +struct ir_scancode_table *get_rc_map(const char *name); + /* Routines from ir-keytable.c */ u32 ir_g_keycode_from_table(struct input_dev *input_dev, u32 scancode); void ir_keyup(struct input_dev *dev); void ir_keydown(struct input_dev *dev, int scancode); -int ir_input_register(struct input_dev *dev, +int __ir_input_register(struct input_dev *dev, const struct ir_scancode_table *ir_codes, const struct ir_dev_props *props, const char *driver_name); -void ir_input_unregister(struct input_dev *input_dev); -/* Routines from rc-map.c */ +static inline int ir_input_register(struct input_dev *dev, + const char *map_name, + const struct ir_dev_props *props, + const char *driver_name) { + struct ir_scancode_table *ir_codes; -int ir_register_map(struct rc_keymap *map); -void ir_unregister_map(struct rc_keymap *map); -struct ir_scancode_table *get_rc_map(const char *name); + ir_codes = get_rc_map(map_name); + if (!ir_codes) + return -EINVAL; + + return __ir_input_register(dev, ir_codes, props, driver_name); +} + + void ir_input_unregister(struct input_dev *input_dev); /* Routines from ir-sysfs.c */ -- cgit v1.2.3-70-g09d2 From 02858eedcb78a664215b918d98cdb753ce432ce6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 2 Apr 2010 20:01:00 -0300 Subject: V4L/DVB: ir-core: Make use of the new IR keymap modules Instead of using the ugly keymap sequences, use the new rc-*.ko keymap files. For now, it is still needed to have one keymap loaded, for the RC code to work. Later patches will remove this depenency. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/Makefile | 2 + drivers/media/IR/ir-sysfs.c | 4 +- drivers/media/IR/rc-map.c | 27 +++++++--- drivers/media/dvb/dm1105/dm1105.c | 4 +- drivers/media/dvb/ttpci/budget-ci.c | 10 ++-- drivers/media/video/bt8xx/bttv-input.c | 28 +++++----- drivers/media/video/cx18/cx18-i2c.c | 2 +- drivers/media/video/cx23885/cx23885-input.c | 6 +-- drivers/media/video/cx88/cx88-input.c | 42 +++++++-------- drivers/media/video/em28xx/em28xx-cards.c | 34 ++++++------ drivers/media/video/em28xx/em28xx-input.c | 6 +-- drivers/media/video/em28xx/em28xx.h | 2 +- drivers/media/video/ir-kbd-i2c.c | 22 ++++---- drivers/media/video/ivtv/ivtv-i2c.c | 6 +-- drivers/media/video/saa7134/saa7134-input.c | 81 ++++++++++++++--------------- include/media/ir-core.h | 21 +++++++- include/media/ir-kbd-i2c.h | 4 +- include/media/rc-map.h | 81 +++++++++++++++++++++++++++++ 18 files changed, 247 insertions(+), 135 deletions(-) create mode 100644 include/media/rc-map.h (limited to 'drivers/media/video') diff --git a/drivers/media/IR/Makefile b/drivers/media/IR/Makefile index 3a4f590d0bb..3d8dd306df4 100644 --- a/drivers/media/IR/Makefile +++ b/drivers/media/IR/Makefile @@ -1,6 +1,8 @@ ir-common-objs := ir-functions.o ir-keymaps.o ir-core-objs := ir-keytable.o ir-sysfs.o ir-raw-event.o rc-map.o +obj-y += keymaps/ + obj-$(CONFIG_IR_CORE) += ir-core.o obj-$(CONFIG_VIDEO_IR) += ir-common.o obj-$(CONFIG_IR_NEC_DECODER) += ir-nec-decoder.o diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c index 36dfe51aad9..58ecca2003a 100644 --- a/drivers/media/IR/ir-sysfs.c +++ b/drivers/media/IR/ir-sysfs.c @@ -251,8 +251,10 @@ static int __init ir_core_init(void) return rc; } - /* Initialize/load the decoders that will be used */ + /* Initialize/load the decoders/keymap code that will be used */ ir_raw_init(); + rc_map_init(); + return 0; } diff --git a/drivers/media/IR/rc-map.c b/drivers/media/IR/rc-map.c index 02c72f086fe..2f6201ce189 100644 --- a/drivers/media/IR/rc-map.c +++ b/drivers/media/IR/rc-map.c @@ -26,12 +26,14 @@ static struct rc_keymap *seek_rc_map(const char *name) spin_lock(&rc_map_lock); list_for_each_entry(map, &rc_map_list, list) { - if (!strcmp(name, map->map.name)) - break; + if (!strcmp(name, map->map.name)) { + spin_unlock(&rc_map_lock); + return map; + } } spin_unlock(&rc_map_lock); - return map; + return NULL; } struct ir_scancode_table *get_rc_map(const char *name) @@ -43,15 +45,22 @@ struct ir_scancode_table *get_rc_map(const char *name) map = seek_rc_map(name); #ifdef MODULE if (!map) { - rc = request_module("name"); - if (rc < 0) + rc = request_module(name); + if (rc < 0) { + printk(KERN_ERR "Couldn't load IR keymap %s\n", name); return NULL; + } + msleep(20); /* Give some time for IR to register */ map = seek_rc_map(name); } #endif - if (!map) + if (!map) { + printk(KERN_ERR "IR keymap %s not found\n", name); return NULL; + } + + printk(KERN_INFO "Registered IR keymap %s\n", map->map.name); return &map->map; } @@ -73,3 +82,9 @@ void ir_unregister_map(struct rc_keymap *map) spin_unlock(&rc_map_lock); } EXPORT_SYMBOL_GPL(ir_unregister_map); + +void rc_map_init(void) +{ + spin_lock_init(&rc_map_lock); + +} diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c index 416c29bf78d..9d389bdaca4 100644 --- a/drivers/media/dvb/dm1105/dm1105.c +++ b/drivers/media/dvb/dm1105/dm1105.c @@ -596,7 +596,7 @@ static irqreturn_t dm1105_irq(int irq, void *dev_id) int __devinit dm1105_ir_init(struct dm1105_dev *dm1105) { struct input_dev *input_dev; - struct ir_scancode_table *ir_codes = &IR_KEYTABLE(dm1105_nec); + char *ir_codes = NULL; u64 ir_type = IR_TYPE_OTHER; int err = -ENOMEM; @@ -630,7 +630,7 @@ int __devinit dm1105_ir_init(struct dm1105_dev *dm1105) INIT_WORK(&dm1105->ir.work, dm1105_emit_key); - err = __ir_input_register(input_dev, ir_codes, NULL, MODULE_NAME); + err = ir_input_register(input_dev, ir_codes, NULL, MODULE_NAME); return err; } diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index ab7479ad592..be2074995a0 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -192,7 +192,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci) struct saa7146_dev *saa = budget_ci->budget.dev; struct input_dev *input_dev = budget_ci->ir.dev; int error; - struct ir_scancode_table *ir_codes; + char *ir_codes = NULL; budget_ci->ir.dev = input_dev = input_allocate_device(); @@ -232,7 +232,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci) case 0x1011: case 0x1012: /* The hauppauge keymap is a superset of these remotes */ - ir_codes = &IR_KEYTABLE(hauppauge_new); + ir_codes = RC_MAP_HAUPPAUGE_NEW; if (rc5_device < 0) budget_ci->ir.rc5_device = 0x1f; @@ -241,11 +241,11 @@ static int msp430_ir_init(struct budget_ci *budget_ci) case 0x1017: case 0x101a: /* for the Technotrend 1500 bundled remote */ - ir_codes = &IR_KEYTABLE(tt_1500); + ir_codes = RC_MAP_TT_1500; break; default: /* unknown remote */ - ir_codes = &IR_KEYTABLE(budget_ci_old); + ir_codes = RC_MAP_BUDGET_CI_OLD; break; } @@ -256,7 +256,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci) budget_ci->ir.timer_keyup.function = msp430_ir_keyup; budget_ci->ir.timer_keyup.data = (unsigned long) &budget_ci->ir; budget_ci->ir.last_raw = 0xffff; /* An impossible value */ - error = __ir_input_register(input_dev, ir_codes, NULL, MODULE_NAME); + error = ir_input_register(input_dev, ir_codes, NULL, MODULE_NAME); if (error) { printk(KERN_ERR "budget_ci: could not init driver for IR device (code %d)\n", error); return error; diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c index 71a0047ca7b..f68717a4bde 100644 --- a/drivers/media/video/bt8xx/bttv-input.c +++ b/drivers/media/video/bt8xx/bttv-input.c @@ -248,7 +248,7 @@ static void bttv_ir_stop(struct bttv *btv) int bttv_input_init(struct bttv *btv) { struct card_ir *ir; - struct ir_scancode_table *ir_codes = NULL; + char *ir_codes = NULL; struct input_dev *input_dev; u64 ir_type = IR_TYPE_OTHER; int err = -ENOMEM; @@ -266,7 +266,7 @@ int bttv_input_init(struct bttv *btv) case BTTV_BOARD_AVERMEDIA: case BTTV_BOARD_AVPHONE98: case BTTV_BOARD_AVERMEDIA98: - ir_codes = &IR_KEYTABLE(avermedia); + ir_codes = RC_MAP_AVERMEDIA; ir->mask_keycode = 0xf88000; ir->mask_keydown = 0x010000; ir->polling = 50; // ms @@ -274,14 +274,14 @@ int bttv_input_init(struct bttv *btv) case BTTV_BOARD_AVDVBT_761: case BTTV_BOARD_AVDVBT_771: - ir_codes = &IR_KEYTABLE(avermedia_dvbt); + ir_codes = RC_MAP_AVERMEDIA_DVBT; ir->mask_keycode = 0x0f00c0; ir->mask_keydown = 0x000020; ir->polling = 50; // ms break; case BTTV_BOARD_PXELVWPLTVPAK: - ir_codes = &IR_KEYTABLE(pixelview); + ir_codes = RC_MAP_PIXELVIEW; ir->mask_keycode = 0x003e00; ir->mask_keyup = 0x010000; ir->polling = 50; // ms @@ -289,24 +289,24 @@ int bttv_input_init(struct bttv *btv) case BTTV_BOARD_PV_M4900: case BTTV_BOARD_PV_BT878P_9B: case BTTV_BOARD_PV_BT878P_PLUS: - ir_codes = &IR_KEYTABLE(pixelview); + ir_codes = RC_MAP_PIXELVIEW; ir->mask_keycode = 0x001f00; ir->mask_keyup = 0x008000; ir->polling = 50; // ms break; case BTTV_BOARD_WINFAST2000: - ir_codes = &IR_KEYTABLE(winfast); + ir_codes = RC_MAP_WINFAST; ir->mask_keycode = 0x1f8; break; case BTTV_BOARD_MAGICTVIEW061: case BTTV_BOARD_MAGICTVIEW063: - ir_codes = &IR_KEYTABLE(winfast); + ir_codes = RC_MAP_WINFAST; ir->mask_keycode = 0x0008e000; ir->mask_keydown = 0x00200000; break; case BTTV_BOARD_APAC_VIEWCOMP: - ir_codes = &IR_KEYTABLE(apac_viewcomp); + ir_codes = RC_MAP_APAC_VIEWCOMP; ir->mask_keycode = 0x001f00; ir->mask_keyup = 0x008000; ir->polling = 50; // ms @@ -314,30 +314,30 @@ int bttv_input_init(struct bttv *btv) case BTTV_BOARD_ASKEY_CPH03X: case BTTV_BOARD_CONCEPTRONIC_CTVFMI2: case BTTV_BOARD_CONTVFMI: - ir_codes = &IR_KEYTABLE(pixelview); + ir_codes = RC_MAP_PIXELVIEW; ir->mask_keycode = 0x001F00; ir->mask_keyup = 0x006000; ir->polling = 50; // ms break; case BTTV_BOARD_NEBULA_DIGITV: - ir_codes = &IR_KEYTABLE(nebula); + ir_codes = RC_MAP_NEBULA; btv->custom_irq = bttv_rc5_irq; ir->rc5_gpio = 1; break; case BTTV_BOARD_MACHTV_MAGICTV: - ir_codes = &IR_KEYTABLE(apac_viewcomp); + ir_codes = RC_MAP_APAC_VIEWCOMP; ir->mask_keycode = 0x001F00; ir->mask_keyup = 0x004000; ir->polling = 50; /* ms */ break; case BTTV_BOARD_KOZUMI_KTV_01C: - ir_codes = &IR_KEYTABLE(pctv_sedna); + ir_codes = RC_MAP_PCTV_SEDNA; ir->mask_keycode = 0x001f00; ir->mask_keyup = 0x006000; ir->polling = 50; /* ms */ break; case BTTV_BOARD_ENLTV_FM_2: - ir_codes = &IR_KEYTABLE(encore_enltv2); + ir_codes = RC_MAP_ENCORE_ENLTV2; ir->mask_keycode = 0x00fd00; ir->mask_keyup = 0x000080; ir->polling = 1; /* ms */ @@ -392,7 +392,7 @@ int bttv_input_init(struct bttv *btv) bttv_ir_start(btv, ir); /* all done */ - err = __ir_input_register(btv->remote->dev, ir_codes, NULL, MODULE_NAME); + err = ir_input_register(btv->remote->dev, ir_codes, NULL, MODULE_NAME); if (err) goto err_out_stop; diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c index 476c016e63a..cfa1f289b0f 100644 --- a/drivers/media/video/cx18/cx18-i2c.c +++ b/drivers/media/video/cx18/cx18-i2c.c @@ -109,7 +109,7 @@ static int cx18_i2c_new_ir(struct cx18 *cx, struct i2c_adapter *adap, u32 hw, /* Our default information for ir-kbd-i2c.c to use */ switch (hw) { case CX18_HW_Z8F0811_IR_RX_HAUP: - init_data->ir_codes = &IR_KEYTABLE(hauppauge_new); + init_data->ir_codes = RC_MAP_HAUPPAUGE_NEW; init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; init_data->type = IR_TYPE_RC5; init_data->name = cx->card_name; diff --git a/drivers/media/video/cx23885/cx23885-input.c b/drivers/media/video/cx23885/cx23885-input.c index cef36f6b93e..8d306d8bb61 100644 --- a/drivers/media/video/cx23885/cx23885-input.c +++ b/drivers/media/video/cx23885/cx23885-input.c @@ -340,7 +340,7 @@ int cx23885_input_init(struct cx23885_dev *dev) { struct card_ir *ir; struct input_dev *input_dev; - struct ir_scancode_table *ir_codes = NULL; + char *ir_codes = NULL; int ir_type, ir_addr, ir_start; int ret; @@ -355,7 +355,7 @@ int cx23885_input_init(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1850: case CX23885_BOARD_HAUPPAUGE_HVR1290: /* Parameters for the grey Hauppauge remote for the HVR-1850 */ - ir_codes = &IR_KEYTABLE(hauppauge_new); + ir_codes = RC_MAP_HAUPPAUGE_NEW; ir_type = IR_TYPE_RC5; ir_addr = 0x1e; /* RC-5 system bits emitted by the remote */ ir_start = RC5_START_BITS_NORMAL; /* A basic RC-5 remote */ @@ -400,7 +400,7 @@ int cx23885_input_init(struct cx23885_dev *dev) dev->ir_input = ir; cx23885_input_ir_start(dev); - ret = __ir_input_register(ir->dev, ir_codes, NULL, MODULE_NAME); + ret = ir_input_register(ir->dev, ir_codes, NULL, MODULE_NAME); if (ret) goto err_out_stop; diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index 30af956a9ea..6efad1da65b 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -245,7 +245,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) { struct cx88_IR *ir; struct input_dev *input_dev; - struct ir_scancode_table *ir_codes = NULL; + char *ir_codes = NULL; u64 ir_type = IR_TYPE_OTHER; int err = -ENOMEM; @@ -261,14 +261,14 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) case CX88_BOARD_DNTV_LIVE_DVB_T: case CX88_BOARD_KWORLD_DVB_T: case CX88_BOARD_KWORLD_DVB_T_CX22702: - ir_codes = &IR_KEYTABLE(dntv_live_dvb_t); + ir_codes = RC_MAP_DNTV_LIVE_DVB_T; ir->gpio_addr = MO_GP1_IO; ir->mask_keycode = 0x1f; ir->mask_keyup = 0x60; ir->polling = 50; /* ms */ break; case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: - ir_codes = &IR_KEYTABLE(cinergy_1400); + ir_codes = RC_MAP_CINERGY_1400; ir_type = IR_TYPE_PD; ir->sampling = 0xeb04; /* address */ break; @@ -283,14 +283,14 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) case CX88_BOARD_PCHDTV_HD3000: case CX88_BOARD_PCHDTV_HD5500: case CX88_BOARD_HAUPPAUGE_IRONLY: - ir_codes = &IR_KEYTABLE(hauppauge_new); + ir_codes = RC_MAP_HAUPPAUGE_NEW; ir_type = IR_TYPE_RC5; ir->sampling = 1; break; case CX88_BOARD_WINFAST_DTV2000H: case CX88_BOARD_WINFAST_DTV2000H_J: case CX88_BOARD_WINFAST_DTV1800H: - ir_codes = &IR_KEYTABLE(winfast); + ir_codes = RC_MAP_WINFAST; ir->gpio_addr = MO_GP0_IO; ir->mask_keycode = 0x8f8; ir->mask_keyup = 0x100; @@ -299,14 +299,14 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) case CX88_BOARD_WINFAST2000XP_EXPERT: case CX88_BOARD_WINFAST_DTV1000: case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: - ir_codes = &IR_KEYTABLE(winfast); + ir_codes = RC_MAP_WINFAST; ir->gpio_addr = MO_GP0_IO; ir->mask_keycode = 0x8f8; ir->mask_keyup = 0x100; ir->polling = 1; /* ms */ break; case CX88_BOARD_IODATA_GVBCTV7E: - ir_codes = &IR_KEYTABLE(iodata_bctv7e); + ir_codes = RC_MAP_IODATA_BCTV7E; ir->gpio_addr = MO_GP0_IO; ir->mask_keycode = 0xfd; ir->mask_keydown = 0x02; @@ -314,7 +314,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) break; case CX88_BOARD_PROLINK_PLAYTVPVR: case CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO: - ir_codes = &IR_KEYTABLE(pixelview); + ir_codes = RC_MAP_PIXELVIEW; ir->gpio_addr = MO_GP1_IO; ir->mask_keycode = 0x1f; ir->mask_keyup = 0x80; @@ -322,28 +322,28 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) break; case CX88_BOARD_PROLINK_PV_8000GT: case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME: - ir_codes = &IR_KEYTABLE(pixelview_new); + ir_codes = RC_MAP_PIXELVIEW_NEW; ir->gpio_addr = MO_GP1_IO; ir->mask_keycode = 0x3f; ir->mask_keyup = 0x80; ir->polling = 1; /* ms */ break; case CX88_BOARD_KWORLD_LTV883: - ir_codes = &IR_KEYTABLE(pixelview); + ir_codes = RC_MAP_PIXELVIEW; ir->gpio_addr = MO_GP1_IO; ir->mask_keycode = 0x1f; ir->mask_keyup = 0x60; ir->polling = 1; /* ms */ break; case CX88_BOARD_ADSTECH_DVB_T_PCI: - ir_codes = &IR_KEYTABLE(adstech_dvb_t_pci); + ir_codes = RC_MAP_ADSTECH_DVB_T_PCI; ir->gpio_addr = MO_GP1_IO; ir->mask_keycode = 0xbf; ir->mask_keyup = 0x40; ir->polling = 50; /* ms */ break; case CX88_BOARD_MSI_TVANYWHERE_MASTER: - ir_codes = &IR_KEYTABLE(msi_tvanywhere); + ir_codes = RC_MAP_MSI_TVANYWHERE; ir->gpio_addr = MO_GP1_IO; ir->mask_keycode = 0x1f; ir->mask_keyup = 0x40; @@ -351,7 +351,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) break; case CX88_BOARD_AVERTV_303: case CX88_BOARD_AVERTV_STUDIO_303: - ir_codes = &IR_KEYTABLE(avertv_303); + ir_codes = RC_MAP_AVERTV_303; ir->gpio_addr = MO_GP2_IO; ir->mask_keycode = 0xfb; ir->mask_keydown = 0x02; @@ -364,41 +364,41 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) case CX88_BOARD_PROF_7300: case CX88_BOARD_PROF_7301: case CX88_BOARD_PROF_6200: - ir_codes = &IR_KEYTABLE(tbs_nec); + ir_codes = RC_MAP_TBS_NEC; ir_type = IR_TYPE_PD; ir->sampling = 0xff00; /* address */ break; case CX88_BOARD_TEVII_S460: case CX88_BOARD_TEVII_S420: - ir_codes = &IR_KEYTABLE(tevii_nec); + ir_codes = RC_MAP_TEVII_NEC; ir_type = IR_TYPE_PD; ir->sampling = 0xff00; /* address */ break; case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: - ir_codes = &IR_KEYTABLE(dntv_live_dvbt_pro); + ir_codes = RC_MAP_DNTV_LIVE_DVBT_PRO; ir_type = IR_TYPE_PD; ir->sampling = 0xff00; /* address */ break; case CX88_BOARD_NORWOOD_MICRO: - ir_codes = &IR_KEYTABLE(norwood); + ir_codes = RC_MAP_NORWOOD; ir->gpio_addr = MO_GP1_IO; ir->mask_keycode = 0x0e; ir->mask_keyup = 0x80; ir->polling = 50; /* ms */ break; case CX88_BOARD_NPGTECH_REALTV_TOP10FM: - ir_codes = &IR_KEYTABLE(npgtech); + ir_codes = RC_MAP_NPGTECH; ir->gpio_addr = MO_GP0_IO; ir->mask_keycode = 0xfa; ir->polling = 50; /* ms */ break; case CX88_BOARD_PINNACLE_PCTV_HD_800i: - ir_codes = &IR_KEYTABLE(pinnacle_pctv_hd); + ir_codes = RC_MAP_PINNACLE_PCTV_HD; ir_type = IR_TYPE_RC5; ir->sampling = 1; break; case CX88_BOARD_POWERCOLOR_REAL_ANGEL: - ir_codes = &IR_KEYTABLE(powercolor_real_angel); + ir_codes = RC_MAP_POWERCOLOR_REAL_ANGEL; ir->gpio_addr = MO_GP2_IO; ir->mask_keycode = 0x7e; ir->polling = 100; /* ms */ @@ -439,7 +439,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) ir->props.close = cx88_ir_close; /* all done */ - err = __ir_input_register(ir->input, ir_codes, &ir->props, MODULE_NAME); + err = ir_input_register(ir->input, ir_codes, &ir->props, MODULE_NAME); if (err) goto err_out_free; diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 29201438b45..3a4fd851451 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -602,7 +602,7 @@ struct em28xx_board em28xx_boards[] = { .name = "Gadmei UTV330+", .tuner_type = TUNER_TNF_5335MF, .tda9887_conf = TDA9887_PRESENT, - .ir_codes = &IR_KEYTABLE(gadmei_rm008z), + .ir_codes = RC_MAP_GADMEI_RM008Z, .decoder = EM28XX_SAA711X, .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, .input = { { @@ -791,7 +791,7 @@ struct em28xx_board em28xx_boards[] = { .mts_firmware = 1, .has_dvb = 1, .dvb_gpio = hauppauge_wintv_hvr_900_digital, - .ir_codes = &IR_KEYTABLE(hauppauge_new), + .ir_codes = RC_MAP_HAUPPAUGE_NEW, .decoder = EM28XX_TVP5150, .input = { { .type = EM28XX_VMUX_TELEVISION, @@ -816,7 +816,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_XC2028, .tuner_gpio = default_tuner_gpio, .mts_firmware = 1, - .ir_codes = &IR_KEYTABLE(hauppauge_new), + .ir_codes = RC_MAP_HAUPPAUGE_NEW, .decoder = EM28XX_TVP5150, .input = { { .type = EM28XX_VMUX_TELEVISION, @@ -842,7 +842,7 @@ struct em28xx_board em28xx_boards[] = { .mts_firmware = 1, .has_dvb = 1, .dvb_gpio = hauppauge_wintv_hvr_900_digital, - .ir_codes = &IR_KEYTABLE(hauppauge_new), + .ir_codes = RC_MAP_HAUPPAUGE_NEW, .decoder = EM28XX_TVP5150, .input = { { .type = EM28XX_VMUX_TELEVISION, @@ -868,7 +868,7 @@ struct em28xx_board em28xx_boards[] = { .mts_firmware = 1, .has_dvb = 1, .dvb_gpio = hauppauge_wintv_hvr_900_digital, - .ir_codes = &IR_KEYTABLE(rc5_hauppauge_new), + .ir_codes = RC_MAP_RC5_HAUPPAUGE_NEW, .decoder = EM28XX_TVP5150, .input = { { .type = EM28XX_VMUX_TELEVISION, @@ -894,7 +894,7 @@ struct em28xx_board em28xx_boards[] = { .mts_firmware = 1, .has_dvb = 1, .dvb_gpio = hauppauge_wintv_hvr_900_digital, - .ir_codes = &IR_KEYTABLE(pinnacle_pctv_hd), + .ir_codes = RC_MAP_PINNACLE_PCTV_HD, .decoder = EM28XX_TVP5150, .input = { { .type = EM28XX_VMUX_TELEVISION, @@ -920,7 +920,7 @@ struct em28xx_board em28xx_boards[] = { .mts_firmware = 1, .has_dvb = 1, .dvb_gpio = hauppauge_wintv_hvr_900_digital, - .ir_codes = &IR_KEYTABLE(ati_tv_wonder_hd_600), + .ir_codes = RC_MAP_ATI_TV_WONDER_HD_600, .decoder = EM28XX_TVP5150, .input = { { .type = EM28XX_VMUX_TELEVISION, @@ -946,7 +946,7 @@ struct em28xx_board em28xx_boards[] = { .decoder = EM28XX_TVP5150, .has_dvb = 1, .dvb_gpio = default_digital, - .ir_codes = &IR_KEYTABLE(terratec_cinergy_xs), + .ir_codes = RC_MAP_TERRATEC_CINERGY_XS, .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, /* NEC IR */ .input = { { .type = EM28XX_VMUX_TELEVISION, @@ -1296,7 +1296,7 @@ struct em28xx_board em28xx_boards[] = { .decoder = EM28XX_SAA711X, .has_dvb = 1, .dvb_gpio = em2882_kworld_315u_digital, - .ir_codes = &IR_KEYTABLE(kworld_315u), + .ir_codes = RC_MAP_KWORLD_315U, .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE, /* Analog mode - still not ready */ @@ -1425,7 +1425,7 @@ struct em28xx_board em28xx_boards[] = { .has_dvb = 1, .dvb_gpio = kworld_330u_digital, .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, /* NEC IR */ - .ir_codes = &IR_KEYTABLE(kworld_315u), + .ir_codes = RC_MAP_KWORLD_315U, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, @@ -1448,7 +1448,7 @@ struct em28xx_board em28xx_boards[] = { .decoder = EM28XX_TVP5150, .has_dvb = 1, .dvb_gpio = hauppauge_wintv_hvr_900_digital, - .ir_codes = &IR_KEYTABLE(terratec_cinergy_xs), + .ir_codes = RC_MAP_TERRATEC_CINERGY_XS, .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, .input = { { .type = EM28XX_VMUX_TELEVISION, @@ -1541,7 +1541,7 @@ struct em28xx_board em28xx_boards[] = { .mts_firmware = 1, .decoder = EM28XX_TVP5150, .tuner_gpio = default_tuner_gpio, - .ir_codes = &IR_KEYTABLE(kaiomy), + .ir_codes = RC_MAP_KAIOMY, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, @@ -1641,7 +1641,7 @@ struct em28xx_board em28xx_boards[] = { .mts_firmware = 1, .has_dvb = 1, .dvb_gpio = evga_indtube_digital, - .ir_codes = &IR_KEYTABLE(evga_indtube), + .ir_codes = RC_MAP_EVGA_INDTUBE, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, @@ -2335,21 +2335,21 @@ void em28xx_register_i2c_ir(struct em28xx *dev) switch (dev->model) { case EM2800_BOARD_TERRATEC_CINERGY_200: case EM2820_BOARD_TERRATEC_CINERGY_250: - dev->init_data.ir_codes = &IR_KEYTABLE(em_terratec); + dev->init_data.ir_codes = RC_MAP_EM_TERRATEC; dev->init_data.get_key = em28xx_get_key_terratec; dev->init_data.name = "i2c IR (EM28XX Terratec)"; break; case EM2820_BOARD_PINNACLE_USB_2: - dev->init_data.ir_codes = &IR_KEYTABLE(pinnacle_grey); + dev->init_data.ir_codes = RC_MAP_PINNACLE_GREY; dev->init_data.get_key = em28xx_get_key_pinnacle_usb_grey; dev->init_data.name = "i2c IR (EM28XX Pinnacle PCTV)"; break; case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2: - dev->init_data.ir_codes = &IR_KEYTABLE(rc5_hauppauge_new); + dev->init_data.ir_codes = RC_MAP_RC5_HAUPPAUGE_NEW; dev->init_data.get_key = em28xx_get_key_em_haup; dev->init_data.name = "i2c IR (EM2840 Hauppauge)"; case EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE: - dev->init_data.ir_codes = &IR_KEYTABLE(winfast_usbii_deluxe);; + dev->init_data.ir_codes = RC_MAP_WINFAST_USBII_DELUXE;; dev->init_data.get_key = em28xx_get_key_winfast_usbii_deluxe; dev->init_data.name = "i2c IR (EM2820 Winfast TV USBII Deluxe)"; break; diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index 6f1fc695c56..e2772a1470c 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c @@ -382,7 +382,6 @@ int em28xx_ir_change_protocol(void *priv, u64 ir_type) /* Adjust xclk based o IR table for RC5/NEC tables */ - dev->board.ir_codes->ir_type = IR_TYPE_OTHER; if (ir_type == IR_TYPE_RC5) { dev->board.xclk |= EM28XX_XCLK_IR_RC5_MODE; ir->full_code = 1; @@ -393,8 +392,6 @@ int em28xx_ir_change_protocol(void *priv, u64 ir_type) } else rc = -EINVAL; - dev->board.ir_codes->ir_type = ir_type; - em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, dev->board.xclk, EM28XX_XCLK_IR_RC5_MODE); @@ -457,7 +454,6 @@ int em28xx_ir_init(struct em28xx *dev) strlcat(ir->phys, "/input0", sizeof(ir->phys)); /* Set IR protocol */ - em28xx_ir_change_protocol(ir, dev->board.ir_codes->ir_type); err = ir_input_init(input_dev, &ir->ir, IR_TYPE_OTHER); if (err < 0) goto err_out_free; @@ -475,7 +471,7 @@ int em28xx_ir_init(struct em28xx *dev) em28xx_ir_start(ir); /* all done */ - err = __ir_input_register(ir->input, dev->board.ir_codes, + err = ir_input_register(ir->input, dev->board.ir_codes, &ir->props, MODULE_NAME); if (err) goto err_out_stop; diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index eec12910c8c..b252d1b1b2a 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -412,7 +412,7 @@ struct em28xx_board { struct em28xx_input input[MAX_EM28XX_INPUT]; struct em28xx_input radio; - struct ir_scancode_table *ir_codes; + char *ir_codes; }; struct em28xx_eeprom { diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index e6ada5e46df..29d43974265 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -297,7 +297,7 @@ static void ir_work(struct work_struct *work) static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) { - struct ir_scancode_table *ir_codes = NULL; + char *ir_codes = NULL; const char *name = NULL; u64 ir_type = 0; struct IR_i2c *ir; @@ -322,13 +322,13 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) name = "Pixelview"; ir->get_key = get_key_pixelview; ir_type = IR_TYPE_OTHER; - ir_codes = &IR_KEYTABLE(empty); + ir_codes = RC_MAP_EMPTY; break; case 0x4b: name = "PV951"; ir->get_key = get_key_pv951; ir_type = IR_TYPE_OTHER; - ir_codes = &IR_KEYTABLE(pv951); + ir_codes = RC_MAP_PV951; break; case 0x18: case 0x1f: @@ -337,22 +337,22 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) ir->get_key = get_key_haup; ir_type = IR_TYPE_RC5; if (hauppauge == 1) { - ir_codes = &IR_KEYTABLE(hauppauge_new); + ir_codes = RC_MAP_HAUPPAUGE_NEW; } else { - ir_codes = &IR_KEYTABLE(rc5_tv); + ir_codes = RC_MAP_RC5_TV; } break; case 0x30: name = "KNC One"; ir->get_key = get_key_knc1; ir_type = IR_TYPE_OTHER; - ir_codes = &IR_KEYTABLE(empty); + ir_codes = RC_MAP_EMPTY; break; case 0x6b: name = "FusionHDTV"; ir->get_key = get_key_fusionhdtv; ir_type = IR_TYPE_RC5; - ir_codes = &IR_KEYTABLE(fusionhdtv_mce); + ir_codes = RC_MAP_FUSIONHDTV_MCE; break; case 0x0b: case 0x47: @@ -365,9 +365,9 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) ir_type = IR_TYPE_RC5; ir->get_key = get_key_haup_xvr; if (hauppauge == 1) { - ir_codes = &IR_KEYTABLE(hauppauge_new); + ir_codes = RC_MAP_HAUPPAUGE_NEW; } else { - ir_codes = &IR_KEYTABLE(rc5_tv); + ir_codes = RC_MAP_RC5_TV; } } else { /* Handled by saa7134-input */ @@ -379,7 +379,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) name = "AVerMedia Cardbus remote"; ir->get_key = get_key_avermedia_cardbus; ir_type = IR_TYPE_OTHER; - ir_codes = &IR_KEYTABLE(avermedia_cardbus); + ir_codes = RC_MAP_AVERMEDIA_CARDBUS; break; } @@ -447,7 +447,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) input_dev->name = ir->name; input_dev->phys = ir->phys; - err = __ir_input_register(ir->input, ir->ir_codes, NULL, MODULE_NAME); + err = ir_input_register(ir->input, ir->ir_codes, NULL, MODULE_NAME); if (err) goto err_out_free; diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c index a363e334a50..a5b92d109c6 100644 --- a/drivers/media/video/ivtv/ivtv-i2c.c +++ b/drivers/media/video/ivtv/ivtv-i2c.c @@ -193,7 +193,7 @@ static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr) /* Our default information for ir-kbd-i2c.c to use */ switch (hw) { case IVTV_HW_I2C_IR_RX_AVER: - init_data->ir_codes = &IR_KEYTABLE(avermedia_cardbus); + init_data->ir_codes = RC_MAP_AVERMEDIA_CARDBUS; init_data->internal_get_key_func = IR_KBD_GET_KEY_AVERMEDIA_CARDBUS; init_data->type = IR_TYPE_OTHER; @@ -202,14 +202,14 @@ static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr) case IVTV_HW_I2C_IR_RX_HAUP_EXT: case IVTV_HW_I2C_IR_RX_HAUP_INT: /* Default to old black remote */ - init_data->ir_codes = &IR_KEYTABLE(rc5_tv); + init_data->ir_codes = RC_MAP_RC5_TV; init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP; init_data->type = IR_TYPE_RC5; init_data->name = itv->card_name; break; case IVTV_HW_Z8F0811_IR_RX_HAUP: /* Default to grey remote */ - init_data->ir_codes = &IR_KEYTABLE(hauppauge_new); + init_data->ir_codes = RC_MAP_HAUPPAUGE_NEW; init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; init_data->type = IR_TYPE_RC5; init_data->name = itv->card_name; diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index bf6751c760b..f46dca3ccf7 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -587,7 +587,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) { struct card_ir *ir; struct input_dev *input_dev; - struct ir_scancode_table *ir_codes = NULL; + char *ir_codes = NULL; u32 mask_keycode = 0; u32 mask_keydown = 0; u32 mask_keyup = 0; @@ -595,6 +595,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) int rc5_gpio = 0; int nec_gpio = 0; int raw_decode = 0; + int allow_protocol_change = 0; u64 ir_type = IR_TYPE_OTHER; int err; @@ -610,27 +611,27 @@ int saa7134_input_init1(struct saa7134_dev *dev) case SAA7134_BOARD_FLYTVPLATINUM_FM: case SAA7134_BOARD_FLYTVPLATINUM_MINI2: case SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM: - ir_codes = &IR_KEYTABLE(flyvideo); + ir_codes = RC_MAP_FLYVIDEO; mask_keycode = 0xEC00000; mask_keydown = 0x0040000; break; case SAA7134_BOARD_CINERGY400: case SAA7134_BOARD_CINERGY600: case SAA7134_BOARD_CINERGY600_MK3: - ir_codes = &IR_KEYTABLE(cinergy); + ir_codes = RC_MAP_CINERGY; mask_keycode = 0x00003f; mask_keyup = 0x040000; break; case SAA7134_BOARD_ECS_TVP3XP: case SAA7134_BOARD_ECS_TVP3XP_4CB5: - ir_codes = &IR_KEYTABLE(eztv); + ir_codes = RC_MAP_EZTV; mask_keycode = 0x00017c; mask_keyup = 0x000002; polling = 50; // ms break; case SAA7134_BOARD_KWORLD_XPERT: case SAA7134_BOARD_AVACSSMARTTV: - ir_codes = &IR_KEYTABLE(pixelview); + ir_codes = RC_MAP_PIXELVIEW; mask_keycode = 0x00001F; mask_keyup = 0x000020; polling = 50; // ms @@ -647,7 +648,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) case SAA7134_BOARD_AVERMEDIA_GO_007_FM: case SAA7134_BOARD_AVERMEDIA_M102: case SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS: - ir_codes = &IR_KEYTABLE(avermedia); + ir_codes = RC_MAP_AVERMEDIA; mask_keycode = 0x0007C8; mask_keydown = 0x000010; polling = 50; // ms @@ -656,14 +657,14 @@ int saa7134_input_init1(struct saa7134_dev *dev) saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4); break; case SAA7134_BOARD_AVERMEDIA_M135A: - ir_codes = &IR_KEYTABLE(avermedia_m135a_rm_jx); + ir_codes = RC_MAP_AVERMEDIA_M135A_RM_JX; mask_keydown = 0x0040000; mask_keycode = 0xffff; raw_decode = 1; break; case SAA7134_BOARD_AVERMEDIA_777: case SAA7134_BOARD_AVERMEDIA_A16AR: - ir_codes = &IR_KEYTABLE(avermedia); + ir_codes = RC_MAP_AVERMEDIA; mask_keycode = 0x02F200; mask_keydown = 0x000400; polling = 50; // ms @@ -672,7 +673,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) saa_setb(SAA7134_GPIO_GPSTATUS1, 0x1); break; case SAA7134_BOARD_AVERMEDIA_A16D: - ir_codes = &IR_KEYTABLE(avermedia_a16d); + ir_codes = RC_MAP_AVERMEDIA_A16D; mask_keycode = 0x02F200; mask_keydown = 0x000400; polling = 50; /* ms */ @@ -681,14 +682,14 @@ int saa7134_input_init1(struct saa7134_dev *dev) saa_setb(SAA7134_GPIO_GPSTATUS1, 0x1); break; case SAA7134_BOARD_KWORLD_TERMINATOR: - ir_codes = &IR_KEYTABLE(pixelview); + ir_codes = RC_MAP_PIXELVIEW; mask_keycode = 0x00001f; mask_keyup = 0x000060; polling = 50; // ms break; case SAA7134_BOARD_MANLI_MTV001: case SAA7134_BOARD_MANLI_MTV002: - ir_codes = &IR_KEYTABLE(manli); + ir_codes = RC_MAP_MANLI; mask_keycode = 0x001f00; mask_keyup = 0x004000; polling = 50; /* ms */ @@ -708,25 +709,25 @@ int saa7134_input_init1(struct saa7134_dev *dev) case SAA7134_BOARD_BEHOLD_507_9FM: case SAA7134_BOARD_BEHOLD_507RDS_MK3: case SAA7134_BOARD_BEHOLD_507RDS_MK5: - ir_codes = &IR_KEYTABLE(manli); + ir_codes = RC_MAP_MANLI; mask_keycode = 0x003f00; mask_keyup = 0x004000; polling = 50; /* ms */ break; case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM: - ir_codes = &IR_KEYTABLE(behold_columbus); + ir_codes = RC_MAP_BEHOLD_COLUMBUS; mask_keycode = 0x003f00; mask_keyup = 0x004000; polling = 50; // ms break; case SAA7134_BOARD_SEDNA_PC_TV_CARDBUS: - ir_codes = &IR_KEYTABLE(pctv_sedna); + ir_codes = RC_MAP_PCTV_SEDNA; mask_keycode = 0x001f00; mask_keyup = 0x004000; polling = 50; // ms break; case SAA7134_BOARD_GOTVIEW_7135: - ir_codes = &IR_KEYTABLE(gotview7135); + ir_codes = RC_MAP_GOTVIEW7135; mask_keycode = 0x0003CC; mask_keydown = 0x000010; polling = 5; /* ms */ @@ -735,80 +736,80 @@ int saa7134_input_init1(struct saa7134_dev *dev) case SAA7134_BOARD_VIDEOMATE_TV_PVR: case SAA7134_BOARD_VIDEOMATE_GOLD_PLUS: case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII: - ir_codes = &IR_KEYTABLE(videomate_tv_pvr); + ir_codes = RC_MAP_VIDEOMATE_TV_PVR; mask_keycode = 0x00003F; mask_keyup = 0x400000; polling = 50; // ms break; case SAA7134_BOARD_PROTEUS_2309: - ir_codes = &IR_KEYTABLE(proteus_2309); + ir_codes = RC_MAP_PROTEUS_2309; mask_keycode = 0x00007F; mask_keyup = 0x000080; polling = 50; // ms break; case SAA7134_BOARD_VIDEOMATE_DVBT_300: case SAA7134_BOARD_VIDEOMATE_DVBT_200: - ir_codes = &IR_KEYTABLE(videomate_tv_pvr); + ir_codes = RC_MAP_VIDEOMATE_TV_PVR; mask_keycode = 0x003F00; mask_keyup = 0x040000; break; case SAA7134_BOARD_FLYDVBS_LR300: case SAA7134_BOARD_FLYDVBT_LR301: case SAA7134_BOARD_FLYDVBTDUO: - ir_codes = &IR_KEYTABLE(flydvb); + ir_codes = RC_MAP_FLYDVB; mask_keycode = 0x0001F00; mask_keydown = 0x0040000; break; case SAA7134_BOARD_ASUSTeK_P7131_DUAL: case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA: case SAA7134_BOARD_ASUSTeK_P7131_ANALOG: - ir_codes = &IR_KEYTABLE(asus_pc39); + ir_codes = RC_MAP_ASUS_PC39; mask_keydown = 0x0040000; rc5_gpio = 1; break; case SAA7134_BOARD_ENCORE_ENLTV: case SAA7134_BOARD_ENCORE_ENLTV_FM: - ir_codes = &IR_KEYTABLE(encore_enltv); + ir_codes = RC_MAP_ENCORE_ENLTV; mask_keycode = 0x00007f; mask_keyup = 0x040000; polling = 50; // ms break; case SAA7134_BOARD_ENCORE_ENLTV_FM53: - ir_codes = &IR_KEYTABLE(encore_enltv_fm53); + ir_codes = RC_MAP_ENCORE_ENLTV_FM53; mask_keydown = 0x0040000; mask_keycode = 0x00007f; nec_gpio = 1; break; case SAA7134_BOARD_10MOONSTVMASTER3: - ir_codes = &IR_KEYTABLE(encore_enltv); + ir_codes = RC_MAP_ENCORE_ENLTV; mask_keycode = 0x5f80000; mask_keyup = 0x8000000; polling = 50; //ms break; case SAA7134_BOARD_GENIUS_TVGO_A11MCE: - ir_codes = &IR_KEYTABLE(genius_tvgo_a11mce); + ir_codes = RC_MAP_GENIUS_TVGO_A11MCE; mask_keycode = 0xff; mask_keydown = 0xf00000; polling = 50; /* ms */ break; case SAA7134_BOARD_REAL_ANGEL_220: - ir_codes = &IR_KEYTABLE(real_audio_220_32_keys); + ir_codes = RC_MAP_REAL_AUDIO_220_32_KEYS; mask_keycode = 0x3f00; mask_keyup = 0x4000; polling = 50; /* ms */ break; case SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG: - ir_codes = &IR_KEYTABLE(kworld_plus_tv_analog); + ir_codes = RC_MAP_KWORLD_PLUS_TV_ANALOG; mask_keycode = 0x7f; polling = 40; /* ms */ break; case SAA7134_BOARD_VIDEOMATE_S350: - ir_codes = &IR_KEYTABLE(videomate_s350); + ir_codes = RC_MAP_VIDEOMATE_S350; mask_keycode = 0x003f00; mask_keydown = 0x040000; break; case SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S: - ir_codes = &IR_KEYTABLE(winfast); + ir_codes = RC_MAP_WINFAST; mask_keycode = 0x5f00; mask_keyup = 0x020000; polling = 50; /* ms */ @@ -853,13 +854,11 @@ int saa7134_input_init1(struct saa7134_dev *dev) ir->props.open = saa7134_ir_open; ir->props.close = saa7134_ir_close; - if (ir_codes->ir_type != IR_TYPE_OTHER && !raw_decode) { + if (!raw_decode && allow_protocol_change) { ir->props.allowed_protos = IR_TYPE_RC5 | IR_TYPE_NEC; ir->props.change_protocol = saa7134_ir_change_protocol; - - /* Set IR protocol */ - saa7134_ir_change_protocol(ir->props.priv, ir_codes->ir_type); } + err = ir_input_init(input_dev, &ir->ir, ir_type); if (err < 0) goto err_out_free; @@ -877,10 +876,10 @@ int saa7134_input_init1(struct saa7134_dev *dev) } input_dev->dev.parent = &dev->pci->dev; - err = __ir_input_register(ir->dev, ir_codes, &ir->props, MODULE_NAME); + err = ir_input_register(ir->dev, ir_codes, &ir->props, MODULE_NAME); if (err) goto err_out_free; - if (ir_codes->ir_type != IR_TYPE_OTHER) { + if (raw_decode) { err = ir_raw_event_register(ir->dev); if (err) goto err_out_free; @@ -938,24 +937,24 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) dev->init_data.name = "Pinnacle PCTV"; if (pinnacle_remote == 0) { dev->init_data.get_key = get_key_pinnacle_color; - dev->init_data.ir_codes = &IR_KEYTABLE(pinnacle_color); + dev->init_data.ir_codes = RC_MAP_PINNACLE_COLOR; info.addr = 0x47; } else { dev->init_data.get_key = get_key_pinnacle_grey; - dev->init_data.ir_codes = &IR_KEYTABLE(pinnacle_grey); + dev->init_data.ir_codes = RC_MAP_PINNACLE_GREY; info.addr = 0x47; } break; case SAA7134_BOARD_UPMOST_PURPLE_TV: dev->init_data.name = "Purple TV"; dev->init_data.get_key = get_key_purpletv; - dev->init_data.ir_codes = &IR_KEYTABLE(purpletv); + dev->init_data.ir_codes = RC_MAP_PURPLETV; info.addr = 0x7a; break; case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS: dev->init_data.name = "MSI TV@nywhere Plus"; dev->init_data.get_key = get_key_msi_tvanywhere_plus; - dev->init_data.ir_codes = &IR_KEYTABLE(msi_tvanywhere_plus); + dev->init_data.ir_codes = RC_MAP_MSI_TVANYWHERE_PLUS; info.addr = 0x30; /* MSI TV@nywhere Plus controller doesn't seem to respond to probes unless we read something from @@ -969,7 +968,7 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) case SAA7134_BOARD_HAUPPAUGE_HVR1110: dev->init_data.name = "HVR 1110"; dev->init_data.get_key = get_key_hvr1110; - dev->init_data.ir_codes = &IR_KEYTABLE(hauppauge_new); + dev->init_data.ir_codes = RC_MAP_HAUPPAUGE_NEW; info.addr = 0x71; break; case SAA7134_BOARD_BEHOLD_607FM_MK3: @@ -987,7 +986,7 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) case SAA7134_BOARD_BEHOLD_X7: dev->init_data.name = "BeholdTV"; dev->init_data.get_key = get_key_beholdm6xx; - dev->init_data.ir_codes = &IR_KEYTABLE(behold); + dev->init_data.ir_codes = RC_MAP_BEHOLD; dev->init_data.type = IR_TYPE_NEC; info.addr = 0x2d; break; @@ -998,7 +997,7 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) case SAA7134_BOARD_FLYDVB_TRIO: dev->init_data.name = "FlyDVB Trio"; dev->init_data.get_key = get_key_flydvb_trio; - dev->init_data.ir_codes = &IR_KEYTABLE(flydvb); + dev->init_data.ir_codes = RC_MAP_FLYDVB; info.addr = 0x0b; break; default: diff --git a/include/media/ir-core.h b/include/media/ir-core.h index 8e975f24dae..e1772b8230c 100644 --- a/include/media/ir-core.h +++ b/include/media/ir-core.h @@ -21,6 +21,7 @@ #include #include #include +#include extern int ir_core_debug; #define IR_dprintk(level, fmt, arg...) if (ir_core_debug >= level) \ @@ -124,6 +125,7 @@ EXPORT_SYMBOL_GPL(IR_KEYTABLE(tabname)) int ir_register_map(struct rc_keymap *map); void ir_unregister_map(struct rc_keymap *map); struct ir_scancode_table *get_rc_map(const char *name); +void rc_map_init(void); /* Routines from ir-keytable.c */ @@ -141,15 +143,30 @@ static inline int ir_input_register(struct input_dev *dev, const struct ir_dev_props *props, const char *driver_name) { struct ir_scancode_table *ir_codes; + struct ir_input_dev *ir_dev; + int rc; + + if (!map_name) + return -EINVAL; ir_codes = get_rc_map(map_name); if (!ir_codes) return -EINVAL; - return __ir_input_register(dev, ir_codes, props, driver_name); + rc = __ir_input_register(dev, ir_codes, props, driver_name); + if (rc < 0) + return -EINVAL; + + ir_dev = input_get_drvdata(dev); + + if (!rc && ir_dev->props && ir_dev->props->change_protocol) + rc = ir_dev->props->change_protocol(ir_dev->props->priv, + ir_codes->ir_type); + + return rc; } - void ir_input_unregister(struct input_dev *input_dev); +void ir_input_unregister(struct input_dev *input_dev); /* Routines from ir-sysfs.c */ diff --git a/include/media/ir-kbd-i2c.h b/include/media/ir-kbd-i2c.h index 9142936603c..057ff64f349 100644 --- a/include/media/ir-kbd-i2c.h +++ b/include/media/ir-kbd-i2c.h @@ -6,7 +6,7 @@ struct IR_i2c; struct IR_i2c { - struct ir_scancode_table *ir_codes; + char *ir_codes; struct i2c_client *c; struct input_dev *input; @@ -34,7 +34,7 @@ enum ir_kbd_get_key_fn { /* Can be passed when instantiating an ir_video i2c device */ struct IR_i2c_init_data { - struct ir_scancode_table *ir_codes; + char *ir_codes; const char *name; u64 type; /* IR_TYPE_RC5, IR_TYPE_PD, etc */ /* diff --git a/include/media/rc-map.h b/include/media/rc-map.h new file mode 100644 index 00000000000..9ea0033fa3c --- /dev/null +++ b/include/media/rc-map.h @@ -0,0 +1,81 @@ +/* + * rc-map.h - define RC map names used by RC drivers + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +#define RC_MAP_ADSTECH_DVB_T_PCI "rc-adstech-dvb-t-pci" +#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" +#define RC_MAP_AVERMEDIA_A16D "rc-avermedia-a16d" +#define RC_MAP_AVERMEDIA_CARDBUS "rc-avermedia-cardbus" +#define RC_MAP_AVERMEDIA_DVBT "rc-avermedia-dvbt" +#define RC_MAP_AVERMEDIA_M135A_RM_JX "rc-avermedia-m135a-rm-jx" +#define RC_MAP_AVERMEDIA "rc-avermedia" +#define RC_MAP_AVERTV_303 "rc-avertv-303" +#define RC_MAP_BEHOLD_COLUMBUS "rc-behold-columbus" +#define RC_MAP_BEHOLD "rc-behold" +#define RC_MAP_BUDGET_CI_OLD "rc-budget-ci-old" +#define RC_MAP_CINERGY_1400 "rc-cinergy-1400" +#define RC_MAP_CINERGY "rc-cinergy" +#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" +#define RC_MAP_EMPTY "rc-empty" +#define RC_MAP_EM_TERRATEC "rc-em-terratec" +#define RC_MAP_ENCORE_ENLTV2 "rc-encore-enltv2" +#define RC_MAP_ENCORE_ENLTV_FM53 "rc-encore-enltv-fm53" +#define RC_MAP_ENCORE_ENLTV "rc-encore-enltv" +#define RC_MAP_EVGA_INDTUBE "rc-evga-indtube" +#define RC_MAP_EZTV "rc-eztv" +#define RC_MAP_FLYDVB "rc-flydvb" +#define RC_MAP_FLYVIDEO "rc-flyvideo" +#define RC_MAP_FUSIONHDTV_MCE "rc-fusionhdtv-mce" +#define RC_MAP_GADMEI_RM008Z "rc-gadmei-rm008z" +#define RC_MAP_GENIUS_TVGO_A11MCE "rc-genius-tvgo-a11mce" +#define RC_MAP_GOTVIEW7135 "rc-gotview7135" +#define RC_MAP_HAUPPAUGE_NEW "rc-hauppauge-new" +#define RC_MAP_IODATA_BCTV7E "rc-iodata-bctv7e" +#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_MANLI "rc-manli" +#define RC_MAP_MSI_TVANYWHERE_PLUS "rc-msi-tvanywhere-plus" +#define RC_MAP_MSI_TVANYWHERE "rc-msi-tvanywhere" +#define RC_MAP_NEBULA "rc-nebula" +#define RC_MAP_NEC_TERRATEC_CINERGY_XS "rc-nec-terratec-cinergy-xs" +#define RC_MAP_NORWOOD "rc-norwood" +#define RC_MAP_NPGTECH "rc-npgtech" +#define RC_MAP_PCTV_SEDNA "rc-pctv-sedna" +#define RC_MAP_PINNACLE_COLOR "rc-pinnacle-color" +#define RC_MAP_PINNACLE_GREY "rc-pinnacle-grey" +#define RC_MAP_PINNACLE_PCTV_HD "rc-pinnacle-pctv-hd" +#define RC_MAP_PIXELVIEW_NEW "rc-pixelview-new" +#define RC_MAP_PIXELVIEW "rc-pixelview" +#define RC_MAP_POWERCOLOR_REAL_ANGEL "rc-powercolor-real-angel" +#define RC_MAP_PROTEUS_2309 "rc-proteus-2309" +#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_TV "rc-rc5-tv" +#define RC_MAP_REAL_AUDIO_220_32_KEYS "rc-real-audio-220-32-keys" +#define RC_MAP_TBS_NEC "rc-tbs-nec" +#define RC_MAP_TERRATEC_CINERGY_XS "rc-terratec-cinergy-xs" +#define RC_MAP_TEVII_NEC "rc-tevii-nec" +#define RC_MAP_TT_1500 "rc-tt-1500" +#define RC_MAP_VIDEOMATE_S350 "rc-videomate-s350" +#define RC_MAP_VIDEOMATE_TV_PVR "rc-videomate-tv-pvr" +#define RC_MAP_WINFAST "rc-winfast" +#define RC_MAP_WINFAST_USBII_DELUXE "rc-winfast-usbii-deluxe" +/* + * Please, do not just append newer Remote Controller names at the end. + * The names should be ordered in alphabetical order + */ -- cgit v1.2.3-70-g09d2 From 3629e1dadff88d22f35f88d53edbac14fd8931de Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 3 Apr 2010 01:43:36 -0300 Subject: V4L/DVB: saa7134: Fix IRQ2 bit names for the register map There's an error at the IRQ2 bit map registers. Also, it doesn't show what bits are needed for positive and for negative edge. In the case of IR raw decoding, for some protocols, it is important to detect both positive and negative edges. So, a latter patch will need to use the other values. Also, the code that detects problems on IRQ handling is incomplete, as it disables only one of the IRQ bits for GPIO16 and GPIO18. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-core.c | 14 ++++++++------ drivers/media/video/saa7134/saa7134-input.c | 4 ++-- drivers/media/video/saa7134/saa7134-reg.h | 24 ++++++++++++------------ 3 files changed, 22 insertions(+), 20 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 68cda10e078..0612fffdd1f 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -471,7 +471,7 @@ static char *irqbits[] = { "DONE_RA0", "DONE_RA1", "DONE_RA2", "DONE_RA3", "AR", "PE", "PWR_ON", "RDCAP", "INTL", "FIDT", "MMC", "TRIG_ERR", "CONF_ERR", "LOAD_ERR", - "GPIO16?", "GPIO18", "GPIO22", "GPIO23" + "GPIO16", "GPIO18", "GPIO22", "GPIO23" }; #define IRQBITS ARRAY_SIZE(irqbits) @@ -601,12 +601,14 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id) /* disable gpio16 IRQ */ printk(KERN_WARNING "%s/irq: looping -- " "clearing GPIO16 enable bit\n",dev->name); - saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO16); + saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO16_P); + saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO16_N); } else if (report & SAA7134_IRQ_REPORT_GPIO18) { /* disable gpio18 IRQs */ printk(KERN_WARNING "%s/irq: looping -- " "clearing GPIO18 enable bit\n",dev->name); - saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18); + saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18_P); + saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18_N); } else { /* disable all irqs */ printk(KERN_WARNING "%s/irq: looping -- " @@ -698,11 +700,11 @@ static int saa7134_hw_enable2(struct saa7134_dev *dev) if (dev->has_remote == SAA7134_REMOTE_GPIO && dev->remote) { if (dev->remote->mask_keydown & 0x10000) - irq2_mask |= SAA7134_IRQ2_INTE_GPIO16; + irq2_mask |= SAA7134_IRQ2_INTE_GPIO16_N; else if (dev->remote->mask_keydown & 0x40000) - irq2_mask |= SAA7134_IRQ2_INTE_GPIO18; + irq2_mask |= SAA7134_IRQ2_INTE_GPIO18_P; else if (dev->remote->mask_keyup & 0x40000) - irq2_mask |= SAA7134_IRQ2_INTE_GPIO18A; + irq2_mask |= SAA7134_IRQ2_INTE_GPIO18_N; } if (dev->has_remote == SAA7134_REMOTE_I2C) { diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index f46dca3ccf7..a51ba83fb6c 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -1188,14 +1188,14 @@ static void nec_task(unsigned long data) /* Keep repeating the last key */ mod_timer(&ir->timer_keyup, jiffies + msecs_to_jiffies(150)); - saa_setl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18); + saa_setl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18_P); } static int saa7134_nec_irq(struct saa7134_dev *dev) { struct card_ir *ir = dev->remote; - saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18); + saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18_P); tasklet_schedule(&ir->tlet); return 1; diff --git a/drivers/media/video/saa7134/saa7134-reg.h b/drivers/media/video/saa7134/saa7134-reg.h index cf89d96d729..e7e0af101fa 100644 --- a/drivers/media/video/saa7134/saa7134-reg.h +++ b/drivers/media/video/saa7134/saa7134-reg.h @@ -112,17 +112,17 @@ #define SAA7134_IRQ1_INTE_RA0_0 (1 << 0) #define SAA7134_IRQ2 (0x2c8 >> 2) -#define SAA7134_IRQ2_INTE_GPIO23A (1 << 17) -#define SAA7134_IRQ2_INTE_GPIO23 (1 << 16) -#define SAA7134_IRQ2_INTE_GPIO22A (1 << 15) -#define SAA7134_IRQ2_INTE_GPIO22 (1 << 14) -#define SAA7134_IRQ2_INTE_GPIO18A (1 << 13) -#define SAA7134_IRQ2_INTE_GPIO18 (1 << 12) -#define SAA7134_IRQ2_INTE_GPIO16 (1 << 11) /* not certain */ -#define SAA7134_IRQ2_INTE_SC2 (1 << 10) -#define SAA7134_IRQ2_INTE_SC1 (1 << 9) -#define SAA7134_IRQ2_INTE_SC0 (1 << 8) -#define SAA7134_IRQ2_INTE_DEC5 (1 << 7) +#define SAA7134_IRQ2_INTE_GPIO23_N (1 << 17) /* negative edge */ +#define SAA7134_IRQ2_INTE_GPIO23_P (1 << 16) /* positive edge */ +#define SAA7134_IRQ2_INTE_GPIO22_N (1 << 15) /* negative edge */ +#define SAA7134_IRQ2_INTE_GPIO22_P (1 << 14) /* positive edge */ +#define SAA7134_IRQ2_INTE_GPIO18_N (1 << 13) /* negative edge */ +#define SAA7134_IRQ2_INTE_GPIO18_P (1 << 12) /* positive edge */ +#define SAA7134_IRQ2_INTE_GPIO16_N (1 << 11) /* negative edge */ +#define SAA7134_IRQ2_INTE_GPIO16_P (1 << 10) /* positive edge */ +#define SAA7134_IRQ2_INTE_SC2 (1 << 9) +#define SAA7134_IRQ2_INTE_SC1 (1 << 8) +#define SAA7134_IRQ2_INTE_SC0 (1 << 7) #define SAA7134_IRQ2_INTE_DEC4 (1 << 6) #define SAA7134_IRQ2_INTE_DEC3 (1 << 5) #define SAA7134_IRQ2_INTE_DEC2 (1 << 4) @@ -135,7 +135,7 @@ #define SAA7134_IRQ_REPORT_GPIO23 (1 << 17) #define SAA7134_IRQ_REPORT_GPIO22 (1 << 16) #define SAA7134_IRQ_REPORT_GPIO18 (1 << 15) -#define SAA7134_IRQ_REPORT_GPIO16 (1 << 14) /* not certain */ +#define SAA7134_IRQ_REPORT_GPIO16 (1 << 14) #define SAA7134_IRQ_REPORT_LOAD_ERR (1 << 13) #define SAA7134_IRQ_REPORT_CONF_ERR (1 << 12) #define SAA7134_IRQ_REPORT_TRIG_ERR (1 << 11) -- cgit v1.2.3-70-g09d2 From bdf1c98e4205832c07d6dedbfd0ec6eab83df358 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 3 Apr 2010 11:26:01 -0300 Subject: V4L/DVB: saa7134: Add support for both positive and negative edge IRQ The code that enables IRQ for the Remote Controller on saa7134 is a little messy: it is outside saa7134-input, it checks if RC is GPIO based, and it mixes both serial raw decode with parallel reads from a hardware-based IR decoder. Also, currently, it doesn't allow to trigger both transition edges at GPIO16 and GPIO18 lines. A rework on the code is needed to provide a better way to specify what saa7134-input needs, maybe even moving part of the code from saa7134-core and saa7134-cards into saa7134-input. Yet, as a large rework is happening at RC core, it is better to wait until the core changes stablize, in order to rework saa7134 RC internals.While this don't happen, let's just change the logic a little bit to allow enabling IRQ to be generated on both edge transitions, in order to better support pulse/space raw decoders. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-core.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 0612fffdd1f..90f23188129 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -701,10 +701,12 @@ static int saa7134_hw_enable2(struct saa7134_dev *dev) if (dev->has_remote == SAA7134_REMOTE_GPIO && dev->remote) { if (dev->remote->mask_keydown & 0x10000) irq2_mask |= SAA7134_IRQ2_INTE_GPIO16_N; - else if (dev->remote->mask_keydown & 0x40000) - irq2_mask |= SAA7134_IRQ2_INTE_GPIO18_P; - else if (dev->remote->mask_keyup & 0x40000) - irq2_mask |= SAA7134_IRQ2_INTE_GPIO18_N; + else { /* Allow enabling both IRQ edge triggers */ + if (dev->remote->mask_keydown & 0x40000) + irq2_mask |= SAA7134_IRQ2_INTE_GPIO18_P; + if (dev->remote->mask_keyup & 0x40000) + irq2_mask |= SAA7134_IRQ2_INTE_GPIO18_N; + } } if (dev->has_remote == SAA7134_REMOTE_I2C) { -- cgit v1.2.3-70-g09d2 From 2f16f6315f583964732bc23c873d4024281d763c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 3 Apr 2010 18:51:50 -0300 Subject: V4L/DVB: ir-nec-decoder: Reimplement the entire decoder Thanks to Andy Walls for pointing me his code, that gave me some ideas to better implement it. After some work with saa7134 bits, I found a way to catch both IRQ edge pulses. By enabling it, the NEC decoder can now take both pulse and spaces into account, making it more precise. Instead of the old strategy of handling the events all at once, this code implements a state machine. Due to that, it handles individual pulse or space events, validating them against the protocol, producing a much more reliable decoding. With the new implementation, the protocol trailer bits are properly handled, making possible for the repeat key to work. Also, the code is now capable of handling both NEC and NEC extended IR devices. With NEC, it produces a 16 bits code, while with NEC extended, a 24 bits code is returned. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-nec-decoder.c | 271 +++++++++++++++++----------- drivers/media/video/saa7134/saa7134-input.c | 9 +- 2 files changed, 172 insertions(+), 108 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/IR/ir-nec-decoder.c b/drivers/media/IR/ir-nec-decoder.c index 0b50060ffba..33b260f517f 100644 --- a/drivers/media/IR/ir-nec-decoder.c +++ b/drivers/media/IR/ir-nec-decoder.c @@ -14,6 +14,14 @@ #include +#define NEC_UNIT 559979 /* ns */ +#define NEC_HEADER_MARK (16 * NEC_UNIT) +#define NEC_HEADER_SPACE (8 * NEC_UNIT) +#define NEC_REPEAT_SPACE (4 * NEC_UNIT) +#define NEC_MARK (NEC_UNIT) +#define NEC_0_SYMBOL (NEC_UNIT) +#define NEC_1_SYMBOL (3 * NEC_UNIT) + /* Start time: 4.5 ms + 560 us of the next pulse */ #define MIN_START_TIME (3900000 + 560000) #define MAX_START_TIME (5100000 + 560000) @@ -43,10 +51,32 @@ static LIST_HEAD(decoder_list); static spinlock_t decoder_lock; +enum nec_state { + STATE_INACTIVE, + STATE_HEADER_MARK, + STATE_HEADER_SPACE, + STATE_MARK, + STATE_SPACE, + STATE_TRAILER_MARK, + STATE_TRAILER_SPACE, +}; + +struct nec_code { + u8 address; + u8 not_address; + u8 command; + u8 not_command; +}; + struct decoder_data { struct list_head list; struct ir_input_dev *ir_dev; int enabled:1; + + /* State machine control */ + enum nec_state state; + struct nec_code nec_code; + unsigned count; }; @@ -118,139 +148,173 @@ static struct attribute_group decoder_attribute_group = { }; -/** is_repeat - Check if it is a NEC repeat event +/** + * handle_event() - Decode one NEC pulse or space * @input_dev: the struct input_dev descriptor of the device - * @pos: the position of the first event - * @len: the length of the buffer + * @ev: event array with type/duration of pulse/space + * + * This function returns -EINVAL if the pulse violates the state machine */ -static int is_repeat(struct ir_raw_event *evs, int len, int pos) +static int handle_event(struct input_dev *input_dev, + struct ir_raw_event *ev) { - if ((evs[pos].delta.tv_nsec < MIN_REPEAT_START_TIME) || - (evs[pos].delta.tv_nsec > MAX_REPEAT_START_TIME)) - return 0; + struct decoder_data *data; + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + int bit, last_bit; - if (++pos >= len) - return 0; + data = get_decoder_data(ir_dev); + if (!data) + return -EINVAL; - if ((evs[pos].delta.tv_nsec < MIN_REPEAT_TIME) || - (evs[pos].delta.tv_nsec > MAX_REPEAT_TIME)) - return 0; + /* Except for the initial event, what matters is the previous bit */ + bit = (ev->type & IR_PULSE) ? 1 : 0; - return 1; -} + last_bit = !bit; -/** - * __ir_nec_decode() - Decode one NEC pulsecode - * @input_dev: the struct input_dev descriptor of the device - * @evs: event array with type/duration of pulse/space - * @len: length of the array - * @pos: position to start seeking for a code - * This function returns -EINVAL if no pulse got decoded, - * 0 if buffer is empty and 1 if one keycode were handled. - */ -static int __ir_nec_decode(struct input_dev *input_dev, - struct ir_raw_event *evs, - int len, int *pos) -{ - struct ir_input_dev *ir = input_get_drvdata(input_dev); - int count = -1; - int ircode = 0, not_code = 0; - - /* Be sure that the first event is an start one and is a pulse */ - for (; *pos < len; (*pos)++) { - /* Very long delays are considered as start events */ - if (evs[*pos].delta.tv_nsec > MAX_NEC_TIME) - break; - if (evs[*pos].type & IR_START_EVENT) - break; - IR_dprintk(1, "%luus: Spurious NEC %s\n", - (evs[*pos].delta.tv_nsec + 500) / 1000, - (evs[*pos].type & IR_SPACE) ? "space" : "pulse"); + /* Discards spurious space last_bits when inactive */ - } - if (*pos >= len) - return 0; + /* Very long delays are considered as start events */ + if (ev->delta.tv_nsec > NEC_HEADER_MARK + NEC_HEADER_SPACE - NEC_UNIT / 2) + data->state = STATE_INACTIVE; - (*pos)++; /* First event doesn't contain data */ + if (ev->type & IR_START_EVENT) + data->state = STATE_INACTIVE; - if (evs[*pos].type != IR_PULSE) - goto err; + switch (data->state) { + case STATE_INACTIVE: + if (!bit) /* PULSE marks the start event */ + return 0; - /* Check if it is a NEC repeat event */ - if (is_repeat(evs, len, *pos)) { - *pos += 2; - if (ir->keypressed) { - ir_repeat(input_dev); - IR_dprintk(1, "NEC repeat event\n"); - return 1; - } else { - IR_dprintk(1, "missing NEC repeat event\n"); + data->count = 0; + data->state = STATE_HEADER_MARK; + memset (&data->nec_code, 0, sizeof(data->nec_code)); + return 0; + case STATE_HEADER_MARK: + if (!last_bit) + goto err; + if (ev->delta.tv_nsec < NEC_HEADER_MARK - 6 * NEC_UNIT) + goto err; + data->state = STATE_HEADER_SPACE; + return 0; + case STATE_HEADER_SPACE: + if (last_bit) + goto err; + if (ev->delta.tv_nsec >= NEC_HEADER_SPACE - NEC_UNIT / 2) { + data->state = STATE_MARK; return 0; } - } - /* First space should have 4.5 ms otherwise is not NEC protocol */ - if ((evs[*pos].delta.tv_nsec < MIN_START_TIME) || - (evs[*pos].delta.tv_nsec > MAX_START_TIME)) + if (ev->delta.tv_nsec >= NEC_REPEAT_SPACE - NEC_UNIT / 2) { + ir_repeat(input_dev); + IR_dprintk(1, "Repeat last key\n"); + data->state = STATE_TRAILER_MARK; + return 0; + } goto err; + case STATE_MARK: + if (!last_bit) + goto err; + if ((ev->delta.tv_nsec > NEC_MARK + NEC_UNIT / 2) || + (ev->delta.tv_nsec < NEC_MARK - NEC_UNIT / 2)) + goto err; + data->state = STATE_SPACE; + return 0; + case STATE_SPACE: + if (last_bit) + goto err; - count = 0; - for ((*pos)++; *pos < len; (*pos)++) { - int bit; - if ((evs[*pos].delta.tv_nsec > MIN_BIT1_TIME) && - (evs[*pos].delta.tv_nsec < MAX_BIT1_TIME)) - bit = 1; - else if ((evs[*pos].delta.tv_nsec > MIN_BIT0_TIME) && - (evs[*pos].delta.tv_nsec < MAX_BIT0_TIME)) + if ((ev->delta.tv_nsec >= NEC_0_SYMBOL - NEC_UNIT / 2) && + (ev->delta.tv_nsec < NEC_0_SYMBOL + NEC_UNIT / 2)) bit = 0; - else - goto err; + else if ((ev->delta.tv_nsec >= NEC_1_SYMBOL - NEC_UNIT / 2) && + (ev->delta.tv_nsec < NEC_1_SYMBOL + NEC_UNIT / 2)) + bit = 1; + else { + IR_dprintk(1, "Decode failed at %d-th bit (%s) @%luus\n", + data->count, + last_bit ? "pulse" : "space", + (ev->delta.tv_nsec + 500) / 1000); + + goto err2; + } + /* Ok, we've got a valid bit. proccess it */ if (bit) { - int shift = count; - /* Address first, then command */ + int shift = data->count; + + /* + * NEC transmit bytes on this temporal order: + * address | not address | command | not command + */ if (shift < 8) { - shift += 8; - ircode |= 1 << shift; + data->nec_code.address |= 1 << shift; } else if (shift < 16) { - not_code |= 1 << shift; + data->nec_code.not_address |= 1 << (shift - 8); } else if (shift < 24) { - shift -= 16; - ircode |= 1 << shift; + data->nec_code.command |= 1 << (shift - 16); } else { - shift -= 24; - not_code |= 1 << shift; + data->nec_code.not_command |= 1 << (shift - 24); } } - if (++count == 32) - break; - } - (*pos)++; - - /* - * Fixme: may need to accept Extended NEC protocol? - */ - if ((ircode & ~not_code) != ircode) { - IR_dprintk(1, "NEC checksum error: code 0x%04x, not-code 0x%04x\n", - ircode, not_code); - return -EINVAL; - } + if (++data->count == 32) { + u32 scancode; + /* + * Fixme: may need to accept Extended NEC protocol? + */ + if ((data->nec_code.command ^ data->nec_code.not_command) != 0xff) + goto checksum_err; + + if ((data->nec_code.address ^ data->nec_code.not_address) != 0xff) { + /* Extended NEC */ + scancode = data->nec_code.address << 16 | + data->nec_code.not_address << 8 | + data->nec_code.command; + IR_dprintk(1, "NEC scancode 0x%06x\n", scancode); + } else { + /* normal NEC */ + scancode = data->nec_code.address << 8 | + data->nec_code.command; + IR_dprintk(1, "NEC scancode 0x%04x\n", scancode); + } + ir_keydown(input_dev, scancode, 0); - IR_dprintk(1, "NEC scancode 0x%04x\n", ircode); - ir_keydown(input_dev, ircode, 0); + data->state = STATE_TRAILER_MARK; + } else + data->state = STATE_MARK; + return 0; + case STATE_TRAILER_MARK: + if (!last_bit) + goto err; + data->state = STATE_TRAILER_SPACE; + return 0; + case STATE_TRAILER_SPACE: + if (last_bit) + goto err; + data->state = STATE_INACTIVE; + return 0; + } - return 1; err: - IR_dprintk(1, "NEC decoded failed at bit %d (%s) while decoding %luus time\n", - count, - (evs[*pos].type & IR_SPACE) ? "space" : "pulse", - (evs[*pos].delta.tv_nsec + 500) / 1000); + IR_dprintk(1, "NEC decoded failed at state %d (%s) @ %luus\n", + data->state, + bit ? "pulse" : "space", + (ev->delta.tv_nsec + 500) / 1000); +err2: + data->state = STATE_INACTIVE; + return -EINVAL; +checksum_err: + data->state = STATE_INACTIVE; + IR_dprintk(1, "NEC checksum error: received 0x%02x%02x%02x%02x\n", + data->nec_code.address, + data->nec_code.not_address, + data->nec_code.command, + data->nec_code.not_command); return -EINVAL; } /** - * __ir_nec_decode() - Decodes all NEC pulsecodes on a given array + * ir_nec_decode() - Decodes all NEC pulsecodes on a given array * @input_dev: the struct input_dev descriptor of the device * @evs: event array with type/duration of pulse/space * @len: length of the array @@ -269,10 +333,9 @@ static int ir_nec_decode(struct input_dev *input_dev, if (!data || !data->enabled) return 0; - while (pos < len) { - if (__ir_nec_decode(input_dev, evs, len, &pos) > 0) - rc++; - } + for (pos = 0; pos < len; pos++) + handle_event(input_dev, &evs[pos]); + return rc; } diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index a51ba83fb6c..867f027c3fe 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -658,7 +658,8 @@ int saa7134_input_init1(struct saa7134_dev *dev) break; case SAA7134_BOARD_AVERMEDIA_M135A: ir_codes = RC_MAP_AVERMEDIA_M135A_RM_JX; - mask_keydown = 0x0040000; + mask_keydown = 0x0040000; /* Enable GPIO18 line on both edges */ + mask_keyup = 0x0040000; mask_keycode = 0xffff; raw_decode = 1; break; @@ -1014,13 +1015,13 @@ static int saa7134_raw_decode_irq(struct saa7134_dev *dev) { struct card_ir *ir = dev->remote; unsigned long timeout; - int pulse; + int space; /* Generate initial event */ saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); - pulse = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) & ir->mask_keydown; - ir_raw_event_store(dev->remote->dev, pulse ? IR_PULSE : IR_SPACE); + space = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) & ir->mask_keydown; + ir_raw_event_store(dev->remote->dev, space ? IR_SPACE : IR_PULSE); /* -- cgit v1.2.3-70-g09d2 From 26d5683d36729f11f5764909ae37c69488596d36 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 4 Apr 2010 10:32:04 -0300 Subject: V4L/DVB: cx88: don't handle IR on Pixelview too fast Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-input.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index 6efad1da65b..7ddc8bb463f 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -316,9 +316,9 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) case CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO: ir_codes = RC_MAP_PIXELVIEW; ir->gpio_addr = MO_GP1_IO; - ir->mask_keycode = 0x1f; + ir->mask_keycode = 0x1f; /* Only command is retrieved */ ir->mask_keyup = 0x80; - ir->polling = 1; /* ms */ + ir->polling = 10; /* ms */ break; case CX88_BOARD_PROLINK_PV_8000GT: case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME: -- cgit v1.2.3-70-g09d2 From 9dfe4e8339499bfe8e9a362fefc290b4cb9c3803 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 4 Apr 2010 14:06:55 -0300 Subject: V4L/DVB: ir-core: Add support for badly-implemented hardware decoders A few hardware Remote Controller decoders, even using a standard protocol, aren't able to provide the entire scancode. Due to that, the capability of using other IR's are limited on those hardware. Adds a way to indicate to ir-core what are the bits that the hardware provides, from a scancode, allowing the addition of a complete IR table to the kernel and allowing a limited support for changing the Remote Controller on those devices. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-keytable.c | 25 +++++++-- drivers/media/IR/keymaps/Makefile | 1 + drivers/media/IR/keymaps/rc-pixelview-mk12.c | 83 ++++++++++++++++++++++++++++ drivers/media/video/cx88/cx88-input.c | 30 +++++++++- include/media/ir-core.h | 24 ++++++-- include/media/rc-map.h | 3 +- 6 files changed, 153 insertions(+), 13 deletions(-) create mode 100644 drivers/media/IR/keymaps/rc-pixelview-mk12.c (limited to 'drivers/media/video') diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c index a89456932f7..af7400bc906 100644 --- a/drivers/media/IR/ir-keytable.c +++ b/drivers/media/IR/ir-keytable.c @@ -89,6 +89,18 @@ static int ir_do_setkeycode(struct input_dev *dev, { 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 + * all bits for the complete IR code. In general, they provide only + * the command part of the IR code. Yet, as it is possible to replace + * 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) { + 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++) { @@ -448,6 +460,13 @@ int __ir_input_register(struct input_dev *input_dev, 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) + input_dev->open = ir_open; + if (props->close) + input_dev->close = ir_close; + } if (!ir_dev->rc_tab.scan) { rc = -ENOMEM; @@ -465,12 +484,6 @@ int __ir_input_register(struct input_dev *input_dev, goto out_table; } - ir_dev->props = props; - if (props && props->open) - input_dev->open = ir_open; - if (props && props->close) - input_dev->close = ir_close; - rc = ir_register_class(input_dev); if (rc < 0) goto out_table; diff --git a/drivers/media/IR/keymaps/Makefile b/drivers/media/IR/keymaps/Makefile index 937b7db9c9d..c4d891d7949 100644 --- a/drivers/media/IR/keymaps/Makefile +++ b/drivers/media/IR/keymaps/Makefile @@ -46,6 +46,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ rc-pinnacle-grey.o \ rc-pinnacle-pctv-hd.o \ rc-pixelview.o \ + rc-pixelview-mk12.o \ rc-pixelview-new.o \ rc-powercolor-real-angel.o \ rc-proteus-2309.o \ diff --git a/drivers/media/IR/keymaps/rc-pixelview-mk12.c b/drivers/media/IR/keymaps/rc-pixelview-mk12.c new file mode 100644 index 00000000000..5a735d569a8 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-pixelview-mk12.c @@ -0,0 +1,83 @@ +/* rc-pixelview-mk12.h - Keytable for pixelview Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* + * Keytable for MK-F12 IR remote provided together with Pixelview + * Ultra Pro Remote Controller. Uses NEC extended format. + */ +static struct ir_scancode pixelview_mk12[] = { + { 0x866b03, KEY_TUNER }, /* Timeshift */ + { 0x866b1e, KEY_POWER2 }, /* power */ + + { 0x866b01, KEY_1 }, + { 0x866b0b, KEY_2 }, + { 0x866b1b, KEY_3 }, + { 0x866b05, KEY_4 }, + { 0x866b09, KEY_5 }, + { 0x866b15, KEY_6 }, + { 0x866b06, KEY_7 }, + { 0x866b0a, KEY_8 }, + { 0x866b12, KEY_9 }, + { 0x866b02, KEY_0 }, + + { 0x866b13, KEY_AGAIN }, /* loop */ + { 0x866b10, KEY_DIGITS }, /* +100 */ + + { 0x866b00, KEY_MEDIA }, /* source */ + { 0x866b18, KEY_MUTE }, /* mute */ + { 0x866b19, KEY_CAMERA }, /* snapshot */ + { 0x866b1a, KEY_SEARCH }, /* scan */ + + { 0x866b16, KEY_CHANNELUP }, /* chn + */ + { 0x866b14, KEY_CHANNELDOWN }, /* chn - */ + { 0x866b1f, KEY_VOLUMEUP }, /* vol + */ + { 0x866b17, KEY_VOLUMEDOWN }, /* vol - */ + { 0x866b1c, KEY_ZOOM }, /* zoom */ + + { 0x866b04, KEY_REWIND }, + { 0x866b0e, KEY_RECORD }, + { 0x866b0c, KEY_FORWARD }, + + { 0x866b1d, KEY_STOP }, + { 0x866b08, KEY_PLAY }, + { 0x866b0f, KEY_PAUSE }, + + { 0x866b0d, KEY_TV }, + { 0x866b07, KEY_RADIO }, /* FM */ +}; + +static struct rc_keymap pixelview_map = { + .map = { + .scan = pixelview_mk12, + .size = ARRAY_SIZE(pixelview_mk12), + .ir_type = IR_TYPE_NEC, + .name = RC_MAP_PIXELVIEW_MK12, + } +}; + +static int __init init_rc_map_pixelview(void) +{ + return ir_register_map(&pixelview_map); +} + +static void __exit exit_rc_map_pixelview(void) +{ + ir_unregister_map(&pixelview_map); +} + +module_init(init_rc_map_pixelview) +module_exit(exit_rc_map_pixelview) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index 7ddc8bb463f..76733349c6c 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -248,6 +248,9 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) char *ir_codes = NULL; u64 ir_type = IR_TYPE_OTHER; int err = -ENOMEM; + u32 hardware_mask = 0; /* For devices with a hardware mask, when + * used with a full-code IR table + */ ir = kzalloc(sizeof(*ir), GFP_KERNEL); input_dev = input_allocate_device(); @@ -314,11 +317,18 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) break; case CX88_BOARD_PROLINK_PLAYTVPVR: case CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO: - ir_codes = RC_MAP_PIXELVIEW; + /* + * It seems that this hardware is paired with NEC extended + * address 0x866b. So, unfortunately, its usage with other + * IR's with different address won't work. Still, there are + * other IR's from the same manufacturer that works, like the + * 002-T mini RC, provided with newer PV hardware + */ + ir_codes = RC_MAP_PIXELVIEW_MK12; ir->gpio_addr = MO_GP1_IO; - ir->mask_keycode = 0x1f; /* Only command is retrieved */ ir->mask_keyup = 0x80; ir->polling = 10; /* ms */ + hardware_mask = 0x3f; /* Hardware returns only 6 bits from command part */ break; case CX88_BOARD_PROLINK_PV_8000GT: case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME: @@ -410,6 +420,21 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) goto err_out_free; } + /* + * The usage of mask_keycode were very convenient, due to several + * reasons. Among others, the scancode tables were using the scancode + * as the index elements. So, the less bits it was used, the smaller + * the table were stored. After the input changes, the better is to use + * the full scancodes, since it allows replacing the IR remote by + * another one. Unfortunately, there are still some hardware, like + * Pixelview Ultra Pro, where only part of the scancode is sent via + * GPIO. So, there's no way to get the full scancode. Due to that, + * hardware_mask were introduced here: it represents those hardware + * that has such limits. + */ + if (hardware_mask && !ir->mask_keycode) + ir->mask_keycode = hardware_mask; + /* init input device */ snprintf(ir->name, sizeof(ir->name), "cx88 IR (%s)", core->board.name); snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(pci)); @@ -437,6 +462,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) ir->props.priv = core; ir->props.open = cx88_ir_open; ir->props.close = cx88_ir_close; + ir->props.scanmask = hardware_mask; /* all done */ err = ir_input_register(ir->input, ir_codes, &ir->props, MODULE_NAME); diff --git a/include/media/ir-core.h b/include/media/ir-core.h index 0f64b48ecd9..4397ea3d975 100644 --- a/include/media/ir-core.h +++ b/include/media/ir-core.h @@ -33,12 +33,28 @@ enum raw_event_type { IR_STOP_EVENT = (1 << 3), }; +/** + * struct ir_dev_props - Allow caller drivers to set special properties + * @allowed_protos: bitmask with the supported IR_TYPE_* protocols + * @scanmask: some hardware decoders are not capable of providing the full + * scancode to the application. As this is a hardware limit, we can't do + * anything with it. Yet, as the same keycode table can be used with other + * devices, a mask is provided to allow its usage. Drivers should generally + * leave this field in blank + * @priv: driver-specific data, to be used on the callbacks + * @change_protocol: allow changing the protocol used on hardware decoders + * @open: callback to allow drivers to enable polling/irq when IR input device + * is opened. + * @close: callback to allow drivers to disable polling/irq when IR input device + * is opened. + */ struct ir_dev_props { - unsigned long allowed_protos; + unsigned long allowed_protos; + u32 scanmask; void *priv; - int (*change_protocol)(void *priv, u64 ir_type); - int (*open)(void *priv); - void (*close)(void *priv); + int (*change_protocol)(void *priv, u64 ir_type); + int (*open)(void *priv); + void (*close)(void *priv); }; struct ir_raw_event { diff --git a/include/media/rc-map.h b/include/media/rc-map.h index b10990d1749..3b7fe5a0dc7 100644 --- a/include/media/rc-map.h +++ b/include/media/rc-map.h @@ -18,7 +18,7 @@ #define IR_TYPE_OTHER (1u << 31) struct ir_scancode { - u16 scancode; + u32 scancode; u32 keycode; }; @@ -95,6 +95,7 @@ void rc_map_init(void); #define RC_MAP_PINNACLE_PCTV_HD "rc-pinnacle-pctv-hd" #define RC_MAP_PIXELVIEW_NEW "rc-pixelview-new" #define RC_MAP_PIXELVIEW "rc-pixelview" +#define RC_MAP_PIXELVIEW_MK12 "rc-pixelview-mk12" #define RC_MAP_POWERCOLOR_REAL_ANGEL "rc-powercolor-real-angel" #define RC_MAP_PROTEUS_2309 "rc-proteus-2309" #define RC_MAP_PURPLETV "rc-purpletv" -- cgit v1.2.3-70-g09d2 From c373cabfbbb7631526003f17d470c0d1e5915a4c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 7 Apr 2010 22:57:04 -0300 Subject: V4L/DVB: em28xx: fix a regression caused by the rc-map changes The patch that adds the rc-map changes didn't take into account that an a table with IR_TYPE_UNKNOWN would make change_protocol to return -EINVAL. As this function is fundamental to initialize some data, including a callback to the getkey function, this caused the driver to stop working, hanging the machine most of the times. The fix were simply to add a handler for the IR type, but, to avoid further issues, explicitly call change_protocol and handle the error before initializing the IR. Also, let input_dev to start/stop IR handling, after the opening of the input device. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-input.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index e2772a1470c..5c3fd9411b1 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c @@ -362,14 +362,20 @@ static void em28xx_ir_work(struct work_struct *work) schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling)); } -static void em28xx_ir_start(struct em28xx_IR *ir) +static int em28xx_ir_start(void *priv) { + struct em28xx_IR *ir = priv; + INIT_DELAYED_WORK(&ir->work, em28xx_ir_work); schedule_delayed_work(&ir->work, 0); + + return 0; } -static void em28xx_ir_stop(struct em28xx_IR *ir) +static void em28xx_ir_stop(void *priv) { + struct em28xx_IR *ir = priv; + cancel_delayed_work_sync(&ir->work); } @@ -389,7 +395,7 @@ int em28xx_ir_change_protocol(void *priv, u64 ir_type) dev->board.xclk &= ~EM28XX_XCLK_IR_RC5_MODE; ir_config = EM2874_IR_NEC; ir->full_code = 1; - } else + } else if (ir_type != IR_TYPE_UNKNOWN) rc = -EINVAL; em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, dev->board.xclk, @@ -442,6 +448,13 @@ int em28xx_ir_init(struct em28xx *dev) ir->props.allowed_protos = IR_TYPE_RC5 | IR_TYPE_NEC; ir->props.priv = ir; ir->props.change_protocol = em28xx_ir_change_protocol; + ir->props.open = em28xx_ir_start; + ir->props.close = em28xx_ir_stop; + + /* By default, keep protocol field untouched */ + err = em28xx_ir_change_protocol(ir, IR_TYPE_UNKNOWN); + if (err) + goto err_out_free; /* This is how often we ask the chip for IR information */ ir->polling = 100; /* ms */ @@ -468,7 +481,6 @@ int em28xx_ir_init(struct em28xx *dev) input_dev->dev.parent = &dev->udev->dev; - em28xx_ir_start(ir); /* all done */ err = ir_input_register(ir->input, dev->board.ir_codes, @@ -478,7 +490,6 @@ int em28xx_ir_init(struct em28xx *dev) return 0; err_out_stop: - em28xx_ir_stop(ir); dev->ir = NULL; err_out_free: kfree(ir); -- cgit v1.2.3-70-g09d2 From 626cf6979e99bf2c642456308bed7bb25a37569b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 6 Apr 2010 23:21:46 -0300 Subject: V4L/DVB: ir-core: Distinguish sysfs attributes for in-hardware and raw decoders Some devices have in-hardware Remote Controller decoder, while others need a software decoder to get the IR code. As each software decoder can be enabled/disabled individually, allowing multiple protocol decoding capability. On the other hand, hardware decoders have a limited protocol support, often being able of decoding just one protocol each time. So, each type needs a different set of capabilities to control the supported protocol(s). Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-keytable.c | 17 ++++++++++++++--- drivers/media/IR/ir-raw-event.c | 2 -- drivers/media/IR/ir-sysfs.c | 25 ++++++++++++++++--------- drivers/media/video/saa7134/saa7134-input.c | 9 +++------ include/media/ir-core.h | 20 ++++++++++++++------ 5 files changed, 47 insertions(+), 26 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c index af7400bc906..1fdb528737f 100644 --- a/drivers/media/IR/ir-keytable.c +++ b/drivers/media/IR/ir-keytable.c @@ -488,11 +488,19 @@ int __ir_input_register(struct input_dev *input_dev, if (rc < 0) goto out_table; + if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW) { + rc = ir_raw_event_register(input_dev); + if (rc < 0) + goto out_event; + } + IR_dprintk(1, "Registered input device on %s for %s remote.\n", driver_name, rc_tab->name); return 0; +out_event: + ir_unregister_class(input_dev); out_table: kfree(ir_dev->rc_tab.scan); out_name: @@ -509,22 +517,25 @@ EXPORT_SYMBOL_GPL(__ir_input_register); * This routine is used to free memory and de-register interfaces. */ -void ir_input_unregister(struct input_dev *dev) +void ir_input_unregister(struct input_dev *input_dev) { - struct ir_input_dev *ir_dev = input_get_drvdata(dev); + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); struct ir_scancode_table *rc_tab; if (!ir_dev) return; IR_dprintk(1, "Freed keycode table\n"); + del_timer_sync(&ir_dev->timer_keyup); + 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_unregister_class(dev); + ir_unregister_class(input_dev); kfree(ir_dev->driver_name); kfree(ir_dev); diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c index ddb3365adc8..bc4ca08adf4 100644 --- a/drivers/media/IR/ir-raw-event.c +++ b/drivers/media/IR/ir-raw-event.c @@ -82,7 +82,6 @@ int ir_raw_event_register(struct input_dev *input_dev) return rc; } -EXPORT_SYMBOL_GPL(ir_raw_event_register); void ir_raw_event_unregister(struct input_dev *input_dev) { @@ -97,7 +96,6 @@ void ir_raw_event_unregister(struct input_dev *input_dev) kfree(ir->raw); ir->raw = NULL; } -EXPORT_SYMBOL_GPL(ir_raw_event_unregister); int ir_raw_event_store(struct input_dev *input_dev, enum raw_event_type type) { diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c index c33333f1f60..81eebd8eae5 100644 --- a/drivers/media/IR/ir-sysfs.c +++ b/drivers/media/IR/ir-sysfs.c @@ -152,22 +152,26 @@ static int ir_dev_uevent(struct device *device, struct kobj_uevent_env *env) static DEVICE_ATTR(current_protocol, S_IRUGO | S_IWUSR, show_protocol, store_protocol); -static struct attribute *ir_dev_attrs[] = { +static struct attribute *ir_hw_dev_attrs[] = { &dev_attr_current_protocol.attr, NULL, }; -static struct attribute_group ir_dev_attr_grp = { - .attrs = ir_dev_attrs, +static struct attribute_group ir_hw_dev_attr_grp = { + .attrs = ir_hw_dev_attrs, }; -static const struct attribute_group *ir_dev_attr_groups[] = { - &ir_dev_attr_grp, +static const struct attribute_group *ir_hw_dev_attr_groups[] = { + &ir_hw_dev_attr_grp, NULL }; -static struct device_type ir_dev_type = { - .groups = ir_dev_attr_groups, +static struct device_type rc_dev_type = { + .groups = ir_hw_dev_attr_groups, + .uevent = ir_dev_uevent, +}; + +static struct device_type ir_raw_dev_type = { .uevent = ir_dev_uevent, }; @@ -181,7 +185,6 @@ int ir_register_class(struct input_dev *input_dev) { int rc; const char *path; - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); int devno = find_first_zero_bit(&ir_core_dev_number, IRRCV_NUM_DEVICES); @@ -189,7 +192,11 @@ int ir_register_class(struct input_dev *input_dev) if (unlikely(devno < 0)) return devno; - ir_dev->dev.type = &ir_dev_type; + if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE) + ir_dev->dev.type = &rc_dev_type; + else + ir_dev->dev.type = &ir_raw_dev_type; + ir_dev->dev.class = &ir_input_class; ir_dev->dev.parent = input_dev->dev.parent; dev_set_name(&ir_dev->dev, "rc%d", devno); diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 867f027c3fe..6d5fe596245 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -855,6 +855,9 @@ int saa7134_input_init1(struct saa7134_dev *dev) ir->props.open = saa7134_ir_open; ir->props.close = saa7134_ir_close; + if (raw_decode) + ir->props.driver_type = RC_DRIVER_IR_RAW; + if (!raw_decode && allow_protocol_change) { ir->props.allowed_protos = IR_TYPE_RC5 | IR_TYPE_NEC; ir->props.change_protocol = saa7134_ir_change_protocol; @@ -880,11 +883,6 @@ int saa7134_input_init1(struct saa7134_dev *dev) err = ir_input_register(ir->dev, ir_codes, &ir->props, MODULE_NAME); if (err) goto err_out_free; - if (raw_decode) { - err = ir_raw_event_register(ir->dev); - if (err) - goto err_out_free; - } /* the remote isn't as bouncy as a keyboard */ ir->dev->rep[REP_DELAY] = repeat_delay; @@ -904,7 +902,6 @@ void saa7134_input_fini(struct saa7134_dev *dev) return; saa7134_ir_stop(dev); - ir_raw_event_unregister(dev->remote->dev); ir_input_unregister(dev->remote->dev); kfree(dev->remote); dev->remote = NULL; diff --git a/include/media/ir-core.h b/include/media/ir-core.h index 4397ea3d975..e9fa94fe2ef 100644 --- a/include/media/ir-core.h +++ b/include/media/ir-core.h @@ -26,6 +26,11 @@ extern int ir_core_debug; #define IR_dprintk(level, fmt, arg...) if (ir_core_debug >= level) \ printk(KERN_DEBUG "%s: " fmt , __func__, ## arg) +enum rc_driver_type { + RC_DRIVER_SCANCODE = 0, /* Driver or hardware generates a scancode */ + RC_DRIVER_IR_RAW, /* Needs a Infra-Red pulse/space decoder */ +}; + enum raw_event_type { IR_SPACE = (1 << 0), IR_PULSE = (1 << 1), @@ -35,6 +40,8 @@ enum raw_event_type { /** * struct ir_dev_props - Allow caller drivers to set special properties + * @driver_type: specifies if the driver or hardware have already a decoder, + * or if it needs to use the IR raw event decoders to produce a scancode * @allowed_protos: bitmask with the supported IR_TYPE_* protocols * @scanmask: some hardware decoders are not capable of providing the full * scancode to the application. As this is a hardware limit, we can't do @@ -49,12 +56,13 @@ enum raw_event_type { * is opened. */ struct ir_dev_props { - unsigned long allowed_protos; - u32 scanmask; - void *priv; - int (*change_protocol)(void *priv, u64 ir_type); - int (*open)(void *priv); - void (*close)(void *priv); + enum rc_driver_type driver_type; + unsigned long allowed_protos; + u32 scanmask; + void *priv; + int (*change_protocol)(void *priv, u64 ir_type); + int (*open)(void *priv); + void (*close)(void *priv); }; struct ir_raw_event { -- cgit v1.2.3-70-g09d2 From 724e2495502a98aaa3f93c404472a991da8ff857 Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Thu, 8 Apr 2010 13:10:00 -0300 Subject: V4L/DVB: Teach drivers/media/IR/ir-raw-event.c to use durations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/media/IR/ir-raw-event.c is currently written with the assumption that all "raw" hardware will generate events only on state change (i.e. when a pulse or space starts). However, some hardware (like mceusb, probably the most popular IR receiver out there) only generates duration data (and that data is buffered so using any kind of timing on the data is futile). Furthermore, using signed int's to represent pulse/space durations is a well-known approach when writing ir decoders. With this patch: - s64 int's are used to represent pulse/space durations in ns - a workqueue is used to decode the ir protocols outside of interrupt context - #defines are added to make decoders clearer - decoder reset is implemented by passing a zero duration to the kfifo queue and decoders are updated accordingly Signed-off-by: David Härdeman Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-nec-decoder.c | 247 +++++++++++----------------- drivers/media/IR/ir-raw-event.c | 143 +++++++++------- drivers/media/IR/ir-rc5-decoder.c | 150 ++++++++--------- drivers/media/video/saa7134/saa7134-input.c | 2 +- include/media/ir-core.h | 47 ++++-- 5 files changed, 296 insertions(+), 293 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/IR/ir-nec-decoder.c b/drivers/media/IR/ir-nec-decoder.c index 18918e52c0c..02682e617fa 100644 --- a/drivers/media/IR/ir-nec-decoder.c +++ b/drivers/media/IR/ir-nec-decoder.c @@ -13,15 +13,16 @@ */ #include +#include #define NEC_NBITS 32 -#define NEC_UNIT 559979 /* ns */ -#define NEC_HEADER_MARK (16 * NEC_UNIT) -#define NEC_HEADER_SPACE (8 * NEC_UNIT) -#define NEC_REPEAT_SPACE (4 * NEC_UNIT) -#define NEC_MARK (NEC_UNIT) -#define NEC_0_SPACE (NEC_UNIT) -#define NEC_1_SPACE (3 * NEC_UNIT) +#define NEC_UNIT 562500 /* ns */ +#define NEC_HEADER_PULSE PULSE(16) +#define NEC_HEADER_SPACE SPACE(8) +#define NEC_REPEAT_SPACE SPACE(4) +#define NEC_BIT_PULSE PULSE(1) +#define NEC_BIT_0_SPACE SPACE(1) +#define NEC_BIT_1_SPACE SPACE(3) /* Used to register nec_decoder clients */ static LIST_HEAD(decoder_list); @@ -29,21 +30,13 @@ static DEFINE_SPINLOCK(decoder_lock); enum nec_state { STATE_INACTIVE, - STATE_HEADER_MARK, STATE_HEADER_SPACE, - STATE_MARK, - STATE_SPACE, - STATE_TRAILER_MARK, + STATE_BIT_PULSE, + STATE_BIT_SPACE, + STATE_TRAILER_PULSE, STATE_TRAILER_SPACE, }; -struct nec_code { - u8 address; - u8 not_address; - u8 command; - u8 not_command; -}; - struct decoder_data { struct list_head list; struct ir_input_dev *ir_dev; @@ -51,7 +44,7 @@ struct decoder_data { /* State machine control */ enum nec_state state; - struct nec_code nec_code; + u32 nec_bits; unsigned count; }; @@ -62,7 +55,6 @@ struct decoder_data { * * Returns the struct decoder_data that corresponds to a device */ - static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev) { struct decoder_data *data = NULL; @@ -123,20 +115,20 @@ static struct attribute_group decoder_attribute_group = { .attrs = decoder_attributes, }; - /** * ir_nec_decode() - Decode one NEC pulse or space * @input_dev: the struct input_dev descriptor of the device - * @ev: event array with type/duration of pulse/space + * @duration: duration in ns of pulse/space * * This function returns -EINVAL if the pulse violates the state machine */ -static int ir_nec_decode(struct input_dev *input_dev, - struct ir_raw_event *ev) +static int ir_nec_decode(struct input_dev *input_dev, s64 duration) { struct decoder_data *data; struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - int bit, last_bit; + int u; + u32 scancode; + u8 address, not_address, command, not_command; data = get_decoder_data(ir_dev); if (!data) @@ -145,150 +137,107 @@ static int ir_nec_decode(struct input_dev *input_dev, if (!data->enabled) return 0; - /* Except for the initial event, what matters is the previous bit */ - bit = (ev->type & IR_PULSE) ? 1 : 0; - - last_bit = !bit; - - /* Discards spurious space last_bits when inactive */ - - /* Very long delays are considered as start events */ - if (ev->delta.tv_nsec > NEC_HEADER_MARK + NEC_HEADER_SPACE - NEC_UNIT / 2) + if (IS_RESET(duration)) { data->state = STATE_INACTIVE; + return 0; + } - if (ev->type & IR_START_EVENT) - data->state = STATE_INACTIVE; + u = TO_UNITS(duration, NEC_UNIT); + if (DURATION(u) == 0) + goto out; + + IR_dprintk(2, "NEC decode started at state %d (%i units, %ius)\n", + data->state, u, TO_US(duration)); switch (data->state) { - case STATE_INACTIVE: - if (!bit) /* PULSE marks the start event */ - return 0; - data->count = 0; - data->state = STATE_HEADER_MARK; - memset (&data->nec_code, 0, sizeof(data->nec_code)); - return 0; - case STATE_HEADER_MARK: - if (!last_bit) - goto err; - if (ev->delta.tv_nsec < NEC_HEADER_MARK - 6 * NEC_UNIT) - goto err; - data->state = STATE_HEADER_SPACE; + case STATE_INACTIVE: + if (u == NEC_HEADER_PULSE) { + data->count = 0; + data->state = STATE_HEADER_SPACE; + } return 0; + case STATE_HEADER_SPACE: - if (last_bit) - goto err; - if (ev->delta.tv_nsec >= NEC_HEADER_SPACE - NEC_UNIT / 2) { - data->state = STATE_MARK; + if (u == NEC_HEADER_SPACE) { + data->state = STATE_BIT_PULSE; return 0; - } - - if (ev->delta.tv_nsec >= NEC_REPEAT_SPACE - NEC_UNIT / 2) { + } else if (u == NEC_REPEAT_SPACE) { ir_repeat(input_dev); IR_dprintk(1, "Repeat last key\n"); - data->state = STATE_TRAILER_MARK; + data->state = STATE_TRAILER_PULSE; return 0; } - goto err; - case STATE_MARK: - if (!last_bit) - goto err; - if ((ev->delta.tv_nsec > NEC_MARK + NEC_UNIT / 2) || - (ev->delta.tv_nsec < NEC_MARK - NEC_UNIT / 2)) - goto err; - data->state = STATE_SPACE; - return 0; - case STATE_SPACE: - if (last_bit) - goto err; - - if ((ev->delta.tv_nsec >= NEC_0_SPACE - NEC_UNIT / 2) && - (ev->delta.tv_nsec < NEC_0_SPACE + NEC_UNIT / 2)) - bit = 0; - else if ((ev->delta.tv_nsec >= NEC_1_SPACE - NEC_UNIT / 2) && - (ev->delta.tv_nsec < NEC_1_SPACE + NEC_UNIT / 2)) - bit = 1; - else { - IR_dprintk(1, "Decode failed at %d-th bit (%s) @%luus\n", - data->count, - last_bit ? "pulse" : "space", - (ev->delta.tv_nsec + 500) / 1000); - - goto err2; + break; + + case STATE_BIT_PULSE: + if (u == NEC_BIT_PULSE) { + data->state = STATE_BIT_SPACE; + return 0; + } + break; + + case STATE_BIT_SPACE: + if (u != NEC_BIT_0_SPACE && u != NEC_BIT_1_SPACE) + break; + + data->nec_bits <<= 1; + if (u == NEC_BIT_1_SPACE) + data->nec_bits |= 1; + data->count++; + + if (data->count != NEC_NBITS) { + data->state = STATE_BIT_PULSE; + return 0; + } + + address = bitrev8((data->nec_bits >> 24) & 0xff); + not_address = bitrev8((data->nec_bits >> 16) & 0xff); + command = bitrev8((data->nec_bits >> 8) & 0xff); + not_command = bitrev8((data->nec_bits >> 0) & 0xff); + + if ((command ^ not_command) != 0xff) { + IR_dprintk(1, "NEC checksum error: received 0x%08x\n", + data->nec_bits); + break; } - /* Ok, we've got a valid bit. proccess it */ - if (bit) { - int shift = data->count; - - /* - * NEC transmit bytes on this temporal order: - * address | not address | command | not command - */ - if (shift < 8) { - data->nec_code.address |= 1 << shift; - } else if (shift < 16) { - data->nec_code.not_address |= 1 << (shift - 8); - } else if (shift < 24) { - data->nec_code.command |= 1 << (shift - 16); - } else { - data->nec_code.not_command |= 1 << (shift - 24); - } + if ((address ^ not_address) != 0xff) { + /* Extended NEC */ + scancode = address << 16 | + not_address << 8 | + command; + IR_dprintk(1, "NEC (Ext) scancode 0x%06x\n", scancode); + } else { + /* normal NEC */ + scancode = address << 8 | command; + IR_dprintk(1, "NEC scancode 0x%04x\n", scancode); } - if (++data->count == NEC_NBITS) { - u32 scancode; - /* - * Fixme: may need to accept Extended NEC protocol? - */ - if ((data->nec_code.command ^ data->nec_code.not_command) != 0xff) - goto checksum_err; - - if ((data->nec_code.address ^ data->nec_code.not_address) != 0xff) { - /* Extended NEC */ - scancode = data->nec_code.address << 16 | - data->nec_code.not_address << 8 | - data->nec_code.command; - IR_dprintk(1, "NEC scancode 0x%06x\n", scancode); - } else { - /* normal NEC */ - scancode = data->nec_code.address << 8 | - data->nec_code.command; - IR_dprintk(1, "NEC scancode 0x%04x\n", scancode); - } - ir_keydown(input_dev, scancode, 0); - - data->state = STATE_TRAILER_MARK; - } else - data->state = STATE_MARK; - return 0; - case STATE_TRAILER_MARK: - if (!last_bit) - goto err; - data->state = STATE_TRAILER_SPACE; + + ir_keydown(input_dev, scancode, 0); + data->state = STATE_TRAILER_PULSE; return 0; + + case STATE_TRAILER_PULSE: + if (u > 0) { + data->state = STATE_TRAILER_SPACE; + return 0; + } + break; + case STATE_TRAILER_SPACE: - if (last_bit) - goto err; - data->state = STATE_INACTIVE; - return 0; - } + if (u < 0) { + data->state = STATE_INACTIVE; + return 0; + } -err: - IR_dprintk(1, "NEC decoded failed at state %d (%s) @ %luus\n", - data->state, - bit ? "pulse" : "space", - (ev->delta.tv_nsec + 500) / 1000); -err2: - data->state = STATE_INACTIVE; - return -EINVAL; + break; + } -checksum_err: +out: + IR_dprintk(1, "NEC decode failed at state %d (%i units, %ius)\n", + data->state, u, TO_US(duration)); data->state = STATE_INACTIVE; - IR_dprintk(1, "NEC checksum error: received 0x%02x%02x%02x%02x\n", - data->nec_code.address, - data->nec_code.not_address, - data->nec_code.command, - data->nec_code.not_command); return -EINVAL; } diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c index bc4ca08adf4..e144f152296 100644 --- a/drivers/media/IR/ir-raw-event.c +++ b/drivers/media/IR/ir-raw-event.c @@ -15,9 +15,10 @@ #include #include #include +#include -/* Define the max number of bit transitions per IR keycode */ -#define MAX_IR_EVENT_SIZE 256 +/* Define the max number of pulse/space transitions to buffer */ +#define MAX_IR_EVENT_SIZE 512 /* Used to handle IR raw handler extensions */ static LIST_HEAD(ir_raw_handler_list); @@ -53,19 +54,30 @@ static DEFINE_SPINLOCK(ir_raw_handler_lock); /* Used to load the decoders */ static struct work_struct wq_load; +static void ir_raw_event_work(struct work_struct *work) +{ + s64 d; + struct ir_raw_event_ctrl *raw = + container_of(work, struct ir_raw_event_ctrl, rx_work); + + while (kfifo_out(&raw->kfifo, &d, sizeof(d)) == sizeof(d)) + RUN_DECODER(decode, raw->input_dev, d); +} + int ir_raw_event_register(struct input_dev *input_dev) { struct ir_input_dev *ir = input_get_drvdata(input_dev); - int rc, size; + int rc; ir->raw = kzalloc(sizeof(*ir->raw), GFP_KERNEL); if (!ir->raw) return -ENOMEM; - size = sizeof(struct ir_raw_event) * MAX_IR_EVENT_SIZE * 2; - size = roundup_pow_of_two(size); + ir->raw->input_dev = input_dev; + INIT_WORK(&ir->raw->rx_work, ir_raw_event_work); - rc = kfifo_alloc(&ir->raw->kfifo, size, GFP_KERNEL); + rc = kfifo_alloc(&ir->raw->kfifo, sizeof(s64) * MAX_IR_EVENT_SIZE, + GFP_KERNEL); if (rc < 0) { kfree(ir->raw); ir->raw = NULL; @@ -90,6 +102,7 @@ void ir_raw_event_unregister(struct input_dev *input_dev) if (!ir->raw) return; + cancel_work_sync(&ir->raw->rx_work); RUN_DECODER(raw_unregister, input_dev); kfifo_free(&ir->raw->kfifo); @@ -97,74 +110,90 @@ void ir_raw_event_unregister(struct input_dev *input_dev) ir->raw = NULL; } -int ir_raw_event_store(struct input_dev *input_dev, enum raw_event_type type) +/** + * ir_raw_event_store() - pass a pulse/space duration to the raw ir decoders + * @input_dev: the struct input_dev device descriptor + * @duration: duration of the pulse or space in ns + * + * This routine (which may be called from an interrupt context) stores a + * pulse/space duration for the raw ir decoding state machines. Pulses are + * signalled as positive values and spaces as negative values. A zero value + * will reset the decoding state machines. + */ +int ir_raw_event_store(struct input_dev *input_dev, s64 duration) { - struct ir_input_dev *ir = input_get_drvdata(input_dev); - struct timespec ts; - struct ir_raw_event event; - int rc; + struct ir_input_dev *ir = input_get_drvdata(input_dev); if (!ir->raw) return -EINVAL; - event.type = type; - event.delta.tv_sec = 0; - event.delta.tv_nsec = 0; + if (kfifo_in(&ir->raw->kfifo, &duration, sizeof(duration)) != sizeof(duration)) + return -ENOMEM; - ktime_get_ts(&ts); + return 0; +} +EXPORT_SYMBOL_GPL(ir_raw_event_store); - if (timespec_equal(&ir->raw->last_event, &event.delta)) - event.type |= IR_START_EVENT; - else - event.delta = timespec_sub(ts, ir->raw->last_event); +/** + * ir_raw_event_store_edge() - notify raw ir decoders of the start of a pulse/space + * @input_dev: the struct input_dev device descriptor + * @type: the type of the event that has occurred + * + * This routine (which may be called from an interrupt context) is used to + * store the beginning of an ir pulse or space (or the start/end of ir + * reception) for the raw ir decoding state machines. This is used by + * hardware which does not provide durations directly but only interrupts + * (or similar events) on state change. + */ +int ir_raw_event_store_edge(struct input_dev *input_dev, enum raw_event_type type) +{ + struct ir_input_dev *ir = input_get_drvdata(input_dev); + ktime_t now; + s64 delta; /* ns */ + int rc = 0; - memcpy(&ir->raw->last_event, &ts, sizeof(ts)); + if (!ir->raw) + return -EINVAL; - if (event.delta.tv_sec) { - event.type |= IR_START_EVENT; - event.delta.tv_sec = 0; - event.delta.tv_nsec = 0; - } + now = ktime_get(); + delta = ktime_to_ns(ktime_sub(now, ir->raw->last_event)); - kfifo_in(&ir->raw->kfifo, &event, sizeof(event)); + /* Check for a long duration since last event or if we're + * being called for the first time, note that delta can't + * possibly be negative. + */ + if (delta > NSEC_PER_SEC || !ir->raw->last_type) + type |= IR_START_EVENT; + + if (type & IR_START_EVENT) + ir_raw_event_reset(input_dev); + else if (ir->raw->last_type & IR_SPACE) + rc = ir_raw_event_store(input_dev, -delta); + else if (ir->raw->last_type & IR_PULSE) + rc = ir_raw_event_store(input_dev, delta); + else + return 0; + ir->raw->last_event = now; + ir->raw->last_type = type; return rc; } -EXPORT_SYMBOL_GPL(ir_raw_event_store); +EXPORT_SYMBOL_GPL(ir_raw_event_store_edge); -int ir_raw_event_handle(struct input_dev *input_dev) +/** + * ir_raw_event_handle() - schedules the decoding of stored ir data + * @input_dev: the struct input_dev device descriptor + * + * This routine will signal the workqueue to start decoding stored ir data. + */ +void ir_raw_event_handle(struct input_dev *input_dev) { - struct ir_input_dev *ir = input_get_drvdata(input_dev); - int rc; - struct ir_raw_event ev; - int len, i; - - /* - * Store the events into a temporary buffer. This allows calling more than - * one decoder to deal with the received data - */ - len = kfifo_len(&ir->raw->kfifo) / sizeof(ev); - if (!len) - return 0; - - for (i = 0; i < len; i++) { - rc = kfifo_out(&ir->raw->kfifo, &ev, sizeof(ev)); - if (rc != sizeof(ev)) { - IR_dprintk(1, "overflow error: received %d instead of %zd\n", - rc, sizeof(ev)); - return -EINVAL; - } - IR_dprintk(2, "event type %d, time before event: %07luus\n", - ev.type, (ev.delta.tv_nsec + 500) / 1000); - rc = RUN_DECODER(decode, input_dev, &ev); - } + struct ir_input_dev *ir = input_get_drvdata(input_dev); - /* - * Call all ir decoders. This allows decoding the same event with - * more than one protocol handler. - */ + if (!ir->raw) + return; - return rc; + schedule_work(&ir->raw->rx_work); } EXPORT_SYMBOL_GPL(ir_raw_event_handle); diff --git a/drivers/media/IR/ir-rc5-decoder.c b/drivers/media/IR/ir-rc5-decoder.c index 6323066438b..1d0857b6908 100644 --- a/drivers/media/IR/ir-rc5-decoder.c +++ b/drivers/media/IR/ir-rc5-decoder.c @@ -21,11 +21,8 @@ #include -static unsigned int ir_rc5_remote_gap = 888888; - #define RC5_NBITS 14 -#define RC5_BIT (ir_rc5_remote_gap * 2) -#define RC5_DURATION (ir_rc5_remote_gap * RC5_NBITS) +#define RC5_UNIT 888888 /* ns */ /* Used to register rc5_decoder clients */ static LIST_HEAD(decoder_list); @@ -33,13 +30,9 @@ static DEFINE_SPINLOCK(decoder_lock); enum rc5_state { STATE_INACTIVE, - STATE_MARKSPACE, - STATE_TRAILER, -}; - -struct rc5_code { - u8 address; - u8 command; + STATE_BIT_START, + STATE_BIT_END, + STATE_FINISHED, }; struct decoder_data { @@ -49,8 +42,9 @@ struct decoder_data { /* State machine control */ enum rc5_state state; - struct rc5_code rc5_code; - unsigned code, elapsed, last_bit, last_code; + u32 rc5_bits; + int last_unit; + unsigned count; }; @@ -122,18 +116,19 @@ static struct attribute_group decoder_attribute_group = { }; /** - * handle_event() - Decode one RC-5 pulse or space + * ir_rc5_decode() - Decode one RC-5 pulse or space * @input_dev: the struct input_dev descriptor of the device - * @ev: event array with type/duration of pulse/space + * @duration: duration of pulse/space in ns * * This function returns -EINVAL if the pulse violates the state machine */ -static int ir_rc5_decode(struct input_dev *input_dev, - struct ir_raw_event *ev) +static int ir_rc5_decode(struct input_dev *input_dev, s64 duration) { struct decoder_data *data; struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - int is_pulse, scancode, delta, toggle; + u8 command, system, toggle; + u32 scancode; + int u; data = get_decoder_data(ir_dev); if (!data) @@ -142,79 +137,84 @@ static int ir_rc5_decode(struct input_dev *input_dev, if (!data->enabled) return 0; - delta = DIV_ROUND_CLOSEST(ev->delta.tv_nsec, ir_rc5_remote_gap); - - /* The duration time refers to the last bit time */ - is_pulse = (ev->type & IR_PULSE) ? 1 : 0; - - /* Very long delays are considered as start events */ - if (delta > RC5_DURATION || (ev->type & IR_START_EVENT)) + if (IS_RESET(duration)) { data->state = STATE_INACTIVE; - - switch (data->state) { - case STATE_INACTIVE: - IR_dprintk(2, "currently inative. Start bit (%s) @%uus\n", - is_pulse ? "pulse" : "space", - (unsigned)(ev->delta.tv_nsec + 500) / 1000); - - /* Discards the initial start space */ - if (!is_pulse) - goto err; - data->code = 1; - data->last_bit = 1; - data->elapsed = 0; - memset(&data->rc5_code, 0, sizeof(data->rc5_code)); - data->state = STATE_MARKSPACE; return 0; - case STATE_MARKSPACE: - if (delta != 1) - data->last_bit = data->last_bit ? 0 : 1; + } - data->elapsed += delta; + u = TO_UNITS(duration, RC5_UNIT); + if (DURATION(u) == 0) + goto out; - if ((data->elapsed % 2) == 1) - return 0; +again: + IR_dprintk(2, "RC5 decode started at state %i (%i units, %ius)\n", + data->state, u, TO_US(duration)); - data->code <<= 1; - data->code |= data->last_bit; - - /* Fill the 2 unused bits at the command with 0 */ - if (data->elapsed / 2 == 6) - data->code <<= 2; + if (DURATION(u) == 0 && data->state != STATE_FINISHED) + return 0; - if (data->elapsed >= (RC5_NBITS - 1) * 2) { - scancode = data->code; + switch (data->state) { - /* Check for the start bits */ - if ((scancode & 0xc000) != 0xc000) { - IR_dprintk(1, "Code 0x%04x doesn't have two start bits. It is not RC-5\n", scancode); - goto err; + case STATE_INACTIVE: + if (IS_PULSE(u)) { + data->state = STATE_BIT_START; + data->count = 1; + DECREASE_DURATION(u, 1); + goto again; + } + break; + + case STATE_BIT_START: + if (DURATION(u) == 1) { + data->rc5_bits <<= 1; + if (IS_SPACE(u)) + data->rc5_bits |= 1; + data->count++; + data->last_unit = u; + + /* + * If the last bit is zero, a space will merge + * with the silence after the command. + */ + if (IS_PULSE(u) && data->count == RC5_NBITS) { + data->state = STATE_FINISHED; + goto again; } - toggle = (scancode & 0x2000) ? 1 : 0; + data->state = STATE_BIT_END; + return 0; + } + break; - if (scancode == data->last_code) { - IR_dprintk(1, "RC-5 repeat\n"); - ir_repeat(input_dev); - } else { - data->last_code = scancode; - scancode &= 0x1fff; - IR_dprintk(1, "RC-5 scancode 0x%04x\n", scancode); + case STATE_BIT_END: + if (IS_TRANSITION(u, data->last_unit)) { + if (data->count == RC5_NBITS) + data->state = STATE_FINISHED; + else + data->state = STATE_BIT_START; - ir_keydown(input_dev, scancode, 0); - } - data->state = STATE_TRAILER; + DECREASE_DURATION(u, 1); + goto again; } - return 0; - case STATE_TRAILER: + break; + + case STATE_FINISHED: + command = (data->rc5_bits & 0x0003F) >> 0; + system = (data->rc5_bits & 0x007C0) >> 6; + toggle = (data->rc5_bits & 0x00800) ? 1 : 0; + command += (data->rc5_bits & 0x01000) ? 0 : 0x40; + scancode = system << 8 | command; + + IR_dprintk(1, "RC5 scancode 0x%04x (toggle: %u)\n", + scancode, toggle); + ir_keydown(input_dev, scancode, toggle); data->state = STATE_INACTIVE; return 0; } -err: - IR_dprintk(1, "RC-5 decoded failed at %s @ %luus\n", - is_pulse ? "pulse" : "space", - (ev->delta.tv_nsec + 500) / 1000); +out: + IR_dprintk(1, "RC5 decode failed at state %i (%i units, %ius)\n", + data->state, u, TO_US(duration)); data->state = STATE_INACTIVE; return -EINVAL; } diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 6d5fe596245..e4681eda01f 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -1018,7 +1018,7 @@ static int saa7134_raw_decode_irq(struct saa7134_dev *dev) saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); space = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) & ir->mask_keydown; - ir_raw_event_store(dev->remote->dev, space ? IR_SPACE : IR_PULSE); + ir_raw_event_store_edge(dev->remote->dev, space ? IR_SPACE : IR_PULSE); /* diff --git a/include/media/ir-core.h b/include/media/ir-core.h index e9fa94fe2ef..e9a0cbf67ff 100644 --- a/include/media/ir-core.h +++ b/include/media/ir-core.h @@ -65,14 +65,12 @@ struct ir_dev_props { void (*close)(void *priv); }; -struct ir_raw_event { - struct timespec delta; /* Time spent before event */ - enum raw_event_type type; /* event type */ -}; - struct ir_raw_event_ctrl { - struct kfifo kfifo; /* fifo for the pulse/space events */ - struct timespec last_event; /* when last event occurred */ + struct work_struct rx_work; /* for the rx decoding workqueue */ + struct kfifo kfifo; /* fifo for the pulse/space durations */ + ktime_t last_event; /* when last event occurred */ + enum raw_event_type last_type; /* last event type */ + struct input_dev *input_dev; /* pointer to the parent input_dev */ }; struct ir_input_dev { @@ -97,8 +95,7 @@ struct ir_input_dev { struct ir_raw_handler { struct list_head list; - int (*decode)(struct input_dev *input_dev, - struct ir_raw_event *ev); + int (*decode)(struct input_dev *input_dev, s64 duration); int (*raw_register)(struct input_dev *input_dev); int (*raw_unregister)(struct input_dev *input_dev); }; @@ -154,8 +151,14 @@ void ir_unregister_class(struct input_dev *input_dev); /* Routines from ir-raw-event.c */ int ir_raw_event_register(struct input_dev *input_dev); void ir_raw_event_unregister(struct input_dev *input_dev); -int ir_raw_event_store(struct input_dev *input_dev, enum raw_event_type type); -int ir_raw_event_handle(struct input_dev *input_dev); +void ir_raw_event_handle(struct input_dev *input_dev); +int ir_raw_event_store(struct input_dev *input_dev, s64 duration); +int ir_raw_event_store_edge(struct input_dev *input_dev, enum raw_event_type type); +static inline void ir_raw_event_reset(struct input_dev *input_dev) +{ + ir_raw_event_store(input_dev, 0); + ir_raw_event_handle(input_dev); +} int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler); void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler); void ir_raw_init(void); @@ -174,4 +177,26 @@ void ir_raw_init(void); #define load_rc5_decode() 0 #endif +/* macros for ir decoders */ +#define PULSE(units) ((units)) +#define SPACE(units) (-(units)) +#define IS_RESET(duration) ((duration) == 0) +#define IS_PULSE(duration) ((duration) > 0) +#define IS_SPACE(duration) ((duration) < 0) +#define DURATION(duration) (abs((duration))) +#define IS_TRANSITION(x, y) ((x) * (y) < 0) +#define DECREASE_DURATION(duration, amount) \ + do { \ + if (IS_SPACE(duration)) \ + duration += (amount); \ + else if (IS_PULSE(duration)) \ + duration -= (amount); \ + } while (0) + +#define TO_UNITS(duration, unit_len) \ + ((int)((duration) > 0 ? \ + DIV_ROUND_CLOSEST(abs((duration)), (unit_len)) :\ + -DIV_ROUND_CLOSEST(abs((duration)), (unit_len)))) +#define TO_US(duration) ((int)TO_UNITS(duration, 1000)) + #endif /* _IR_CORE */ -- cgit v1.2.3-70-g09d2 From 2b080c5df00e431baec09222aa8d623f0cd77314 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 7 Apr 2010 06:21:05 -0300 Subject: V4L/DVB: davinci: don't return under lock on error path If the kmalloc() failed for "ccdc_cfg = kmalloc(...);" then we would exit with the lock held. I moved the mutex_lock() below the allocation because it isn't protecting anything in that block and allocations are allocations are sometimes slow. Signed-off-by: Dan Carpenter Acked-by: Vaibhav Hiremath Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/davinci/vpfe_capture.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/davinci/vpfe_capture.c b/drivers/media/video/davinci/vpfe_capture.c index d4676ad41f3..f6648f6ba2f 100644 --- a/drivers/media/video/davinci/vpfe_capture.c +++ b/drivers/media/video/davinci/vpfe_capture.c @@ -1861,7 +1861,6 @@ static __init int vpfe_probe(struct platform_device *pdev) goto probe_free_dev_mem; } - mutex_lock(&ccdc_lock); /* Allocate memory for ccdc configuration */ ccdc_cfg = kmalloc(sizeof(struct ccdc_config), GFP_KERNEL); if (NULL == ccdc_cfg) { @@ -1870,6 +1869,8 @@ static __init int vpfe_probe(struct platform_device *pdev) goto probe_free_lock; } + mutex_lock(&ccdc_lock); + strncpy(ccdc_cfg->name, vpfe_cfg->ccdc, 32); /* Get VINT0 irq resource */ res1 = platform_get_resource(pdev, IORESOURCE_IRQ, 0); -- cgit v1.2.3-70-g09d2 From 1d94aa369da073acff26fa98ad6b2168cb028ab1 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 6 Apr 2010 08:12:21 -0300 Subject: V4L/DVB: video_ioctl2: do not replace arg with NULL for _IO() ioctls If the ioctl was defined without direction (e.g. _IO('o', 25)), then the arg as passed to vidioc_default was NULL instead of the original argument. Several ioctls in e.g. include/linux/dvb/video.h and audio.h use this type of ioctl to pass simple numerical values to the driver. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-ioctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 7d59c107f13..d6975f9c372 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -2006,7 +2006,7 @@ long video_ioctl2(struct file *file, { char sbuf[128]; void *mbuf = NULL; - void *parg = NULL; + void *parg = (void *)arg; long err = -EINVAL; int is_ext_ctrl; size_t ctrls_size = 0; -- cgit v1.2.3-70-g09d2 From 3f5e18249ce0d71a900bfdb8df327269483e730d Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 6 Apr 2010 08:14:11 -0300 Subject: V4L/DVB: video_ioctl2: don't return, use break You want to be able to reach the debug code at the end of this function, so don't use return, use break. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-ioctl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index d6975f9c372..571f0c6e7c8 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -1072,7 +1072,7 @@ static long __video_do_ioctl(struct file *file, id &= ~curr_id; } if (i <= index) - return -EINVAL; + break; v4l2_video_std_construct(p, curr_id, descr); @@ -1597,7 +1597,7 @@ static long __video_do_ioctl(struct file *file, v4l2_std_id std = vfd->current_norm; if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; + break; ret = 0; if (ops->vidioc_g_std) -- cgit v1.2.3-70-g09d2 From fa0290eaee03c3205cb6d344db25580fb3e5e53e Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 6 Apr 2010 08:20:56 -0300 Subject: V4L/DVB: usbvision: remove non-working vbi device The usbvision driver created vbi device nodes but the actual implementation was just stubs and only returned errors to userspace. In addition it used video_usercopy() and we want to remove that eventually. So remove all the vbi code except for the vbi flag in the card definition should someone ever be mad enough to work on a proper implementation for this driver. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/usbvision/usbvision-video.c | 77 ------------------------- drivers/media/video/usbvision/usbvision.h | 1 - 2 files changed, 78 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index 7c17ec63c5d..d91f0166807 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c @@ -137,8 +137,6 @@ static int PowerOnAtOpen = 1; static int video_nr = -1; /* Sequential Number of Radio Device */ static int radio_nr = -1; -/* Sequential Number of VBI Device */ -static int vbi_nr = -1; /* Grab parameters for the device driver */ @@ -148,14 +146,12 @@ module_param(video_debug, int, 0444); module_param(PowerOnAtOpen, int, 0444); module_param(video_nr, int, 0444); module_param(radio_nr, int, 0444); -module_param(vbi_nr, int, 0444); MODULE_PARM_DESC(isocMode, " Set the default format for ISOC endpoint. Default: 0x60 (Compression On)"); MODULE_PARM_DESC(video_debug, " Set the default Debug Mode of the device driver. Default: 0 (Off)"); MODULE_PARM_DESC(PowerOnAtOpen, " Set the default device to power on when device is opened. Default: 1 (On)"); MODULE_PARM_DESC(video_nr, "Set video device number (/dev/videoX). Default: -1 (autodetect)"); MODULE_PARM_DESC(radio_nr, "Set radio device number (/dev/radioX). Default: -1 (autodetect)"); -MODULE_PARM_DESC(vbi_nr, "Set vbi device number (/dev/vbiX). Default: -1 (autodetect)"); // Misc stuff @@ -1244,36 +1240,6 @@ static int usbvision_radio_close(struct file *file) return errCode; } -/* - * Here comes the stuff for vbi on usbvision based devices - * - */ -static int usbvision_vbi_open(struct file *file) -{ - /* TODO */ - return -ENODEV; -} - -static int usbvision_vbi_close(struct file *file) -{ - /* TODO */ - return -ENODEV; -} - -static long usbvision_do_vbi_ioctl(struct file *file, - unsigned int cmd, void *arg) -{ - /* TODO */ - return -ENOIOCTLCMD; -} - -static long usbvision_vbi_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) -{ - return video_usercopy(file, cmd, arg, usbvision_do_vbi_ioctl); -} - - // // Video registration stuff // @@ -1367,21 +1333,6 @@ static struct video_device usbvision_radio_template = { .current_norm = V4L2_STD_PAL }; -// vbi template -static const struct v4l2_file_operations usbvision_vbi_fops = { - .owner = THIS_MODULE, - .open = usbvision_vbi_open, - .release = usbvision_vbi_close, - .ioctl = usbvision_vbi_ioctl, -}; - -static struct video_device usbvision_vbi_template= -{ - .fops = &usbvision_vbi_fops, - .release = video_device_release, - .name = "usbvision-vbi", -}; - static struct video_device *usbvision_vdev_init(struct usb_usbvision *usbvision, struct video_device *vdev_template, @@ -1410,18 +1361,6 @@ static struct video_device *usbvision_vdev_init(struct usb_usbvision *usbvision, // unregister video4linux devices static void usbvision_unregister_video(struct usb_usbvision *usbvision) { - // vbi Device: - if (usbvision->vbi) { - PDEBUG(DBG_PROBE, "unregister %s [v4l2]", - video_device_node_name(usbvision->vbi)); - if (video_is_registered(usbvision->vbi)) { - video_unregister_device(usbvision->vbi); - } else { - video_device_release(usbvision->vbi); - } - usbvision->vbi = NULL; - } - // Radio Device: if (usbvision->rdev) { PDEBUG(DBG_PROBE, "unregister %s [v4l2]", @@ -1482,22 +1421,6 @@ static int __devinit usbvision_register_video(struct usb_usbvision *usbvision) printk(KERN_INFO "USBVision[%d]: registered USBVision Radio device %s [v4l2]\n", usbvision->nr, video_device_node_name(usbvision->rdev)); } - // vbi Device: - if (usbvision_device_data[usbvision->DevModel].vbi) { - usbvision->vbi = usbvision_vdev_init(usbvision, - &usbvision_vbi_template, - "USBVision VBI"); - if (usbvision->vbi == NULL) { - goto err_exit; - } - if (video_register_device(usbvision->vbi, - VFL_TYPE_VBI, - vbi_nr)<0) { - goto err_exit; - } - printk(KERN_INFO "USBVision[%d]: registered USBVision VBI device %s [v4l2] (Not Working Yet!)\n", - usbvision->nr, video_device_node_name(usbvision->vbi)); - } // all done return 0; diff --git a/drivers/media/video/usbvision/usbvision.h b/drivers/media/video/usbvision/usbvision.h index f8d7458daf3..5ab936e252f 100644 --- a/drivers/media/video/usbvision/usbvision.h +++ b/drivers/media/video/usbvision/usbvision.h @@ -360,7 +360,6 @@ struct usb_usbvision { struct v4l2_device v4l2_dev; struct video_device *vdev; /* Video Device */ struct video_device *rdev; /* Radio Device */ - struct video_device *vbi; /* VBI Device */ /* i2c Declaration Section*/ struct i2c_adapter i2c_adap; -- cgit v1.2.3-70-g09d2 From 626e2acfdce76b5a6a1daa4bc8ef556d507f5941 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 6 Apr 2010 11:36:39 -0300 Subject: V4L/DVB: w9966: convert to V4L2 Note that I have not been able to find anyone with this hardware. I tried contacting the author without success, searched on eBay and similar places without luck either. So this conversion is untested. That said, it was pretty straightforward so it is time to have this driver join the V4L2 world at last. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 2 +- drivers/media/video/w9966.c | 435 ++++++++++++++++++++++++-------------------- 2 files changed, 243 insertions(+), 194 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index fe6771271b2..67d31f6cc60 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -647,7 +647,7 @@ config VIDEO_CQCAM config VIDEO_W9966 tristate "W9966CF Webcam (FlyCam Supra and others) Video For Linux" - depends on PARPORT_1284 && PARPORT && VIDEO_V4L1 + depends on PARPORT_1284 && PARPORT && VIDEO_V4L2 help Video4linux driver for Winbond's w9966 based Webcams. Currently tested with the LifeView FlyCam Supra. diff --git a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c index b0719976845..635420d8d84 100644 --- a/drivers/media/video/w9966.c +++ b/drivers/media/video/w9966.c @@ -1,7 +1,7 @@ /* Winbond w9966cf Webcam parport driver. - Version 0.32 + Version 0.33 Copyright (C) 2001 Jakob Kemi @@ -57,10 +57,12 @@ #include #include #include -#include +#include +#include #include #include #include +#include #include /*#define DEBUG*/ /* Undef me for production */ @@ -101,7 +103,8 @@ #define W9966_I2C_W_DATA 0x02 #define W9966_I2C_W_CLOCK 0x01 -struct w9966_dev { +struct w9966 { + struct v4l2_device v4l2_dev; unsigned char dev_state; unsigned char i2c_state; unsigned short ppmode; @@ -114,7 +117,7 @@ struct w9966_dev { signed char contrast; signed char color; signed char hue; - unsigned long in_use; + struct mutex lock; }; /* @@ -144,7 +147,7 @@ MODULE_PARM_DESC(parmode, "parmode: transfer mode (0=auto, 1=ecp, 2=epp"); static int video_nr = -1; module_param(video_nr, int, 0); -static struct w9966_dev w9966_cams[W9966_MAXCAMS]; +static struct w9966 w9966_cams[W9966_MAXCAMS]; /* * Private function defines @@ -152,19 +155,19 @@ static struct w9966_dev w9966_cams[W9966_MAXCAMS]; /* Set camera phase flags, so we know what to uninit when terminating */ -static inline void w9966_set_state(struct w9966_dev *cam, int mask, int val) +static inline void w9966_set_state(struct w9966 *cam, int mask, int val) { cam->dev_state = (cam->dev_state & ~mask) ^ val; } /* Get camera phase flags */ -static inline int w9966_get_state(struct w9966_dev *cam, int mask, int val) +static inline int w9966_get_state(struct w9966 *cam, int mask, int val) { return ((cam->dev_state & mask) == val); } /* Claim parport for ourself */ -static void w9966_pdev_claim(struct w9966_dev *cam) +static void w9966_pdev_claim(struct w9966 *cam) { if (w9966_get_state(cam, W9966_STATE_CLAIMED, W9966_STATE_CLAIMED)) return; @@ -173,7 +176,7 @@ static void w9966_pdev_claim(struct w9966_dev *cam) } /* Release parport for others to use */ -static void w9966_pdev_release(struct w9966_dev *cam) +static void w9966_pdev_release(struct w9966 *cam) { if (w9966_get_state(cam, W9966_STATE_CLAIMED, 0)) return; @@ -184,7 +187,7 @@ static void w9966_pdev_release(struct w9966_dev *cam) /* Read register from W9966 interface-chip Expects a claimed pdev -1 on error, else register data (byte) */ -static int w9966_read_reg(struct w9966_dev *cam, int reg) +static int w9966_read_reg(struct w9966 *cam, int reg) { /* ECP, read, regtransfer, REG, REG, REG, REG, REG */ const unsigned char addr = 0x80 | (reg & 0x1f); @@ -205,7 +208,7 @@ static int w9966_read_reg(struct w9966_dev *cam, int reg) /* Write register to W9966 interface-chip Expects a claimed pdev -1 on error */ -static int w9966_write_reg(struct w9966_dev *cam, int reg, int data) +static int w9966_write_reg(struct w9966 *cam, int reg, int data) { /* ECP, write, regtransfer, REG, REG, REG, REG, REG */ const unsigned char addr = 0xc0 | (reg & 0x1f); @@ -229,7 +232,7 @@ static int w9966_write_reg(struct w9966_dev *cam, int reg, int data) /* Sets the data line on the i2c bus. Expects a claimed pdev. */ -static void w9966_i2c_setsda(struct w9966_dev *cam, int state) +static void w9966_i2c_setsda(struct w9966 *cam, int state) { if (state) cam->i2c_state |= W9966_I2C_W_DATA; @@ -242,7 +245,7 @@ static void w9966_i2c_setsda(struct w9966_dev *cam, int state) /* Get peripheral clock line Expects a claimed pdev. */ -static int w9966_i2c_getscl(struct w9966_dev *cam) +static int w9966_i2c_getscl(struct w9966 *cam) { const unsigned char state = w9966_read_reg(cam, 0x18); return ((state & W9966_I2C_R_CLOCK) > 0); @@ -250,7 +253,7 @@ static int w9966_i2c_getscl(struct w9966_dev *cam) /* Sets the clock line on the i2c bus. Expects a claimed pdev. -1 on error */ -static int w9966_i2c_setscl(struct w9966_dev *cam, int state) +static int w9966_i2c_setscl(struct w9966 *cam, int state) { unsigned long timeout; @@ -276,7 +279,7 @@ static int w9966_i2c_setscl(struct w9966_dev *cam, int state) #if 0 /* Get peripheral data line Expects a claimed pdev. */ -static int w9966_i2c_getsda(struct w9966_dev *cam) +static int w9966_i2c_getsda(struct w9966 *cam) { const unsigned char state = w9966_read_reg(cam, 0x18); return ((state & W9966_I2C_R_DATA) > 0); @@ -285,7 +288,7 @@ static int w9966_i2c_getsda(struct w9966_dev *cam) /* Write a byte with ack to the i2c bus. Expects a claimed pdev. -1 on error */ -static int w9966_i2c_wbyte(struct w9966_dev *cam, int data) +static int w9966_i2c_wbyte(struct w9966 *cam, int data) { int i; @@ -309,7 +312,7 @@ static int w9966_i2c_wbyte(struct w9966_dev *cam, int data) /* Read a data byte with ack from the i2c-bus Expects a claimed pdev. -1 on error */ #if 0 -static int w9966_i2c_rbyte(struct w9966_dev *cam) +static int w9966_i2c_rbyte(struct w9966 *cam) { unsigned char data = 0x00; int i; @@ -332,7 +335,7 @@ static int w9966_i2c_rbyte(struct w9966_dev *cam) /* Read a register from the i2c device. Expects claimed pdev. -1 on error */ #if 0 -static int w9966_read_reg_i2c(struct w9966_dev *cam, int reg) +static int w9966_read_reg_i2c(struct w9966 *cam, int reg) { int data; @@ -367,7 +370,7 @@ static int w9966_read_reg_i2c(struct w9966_dev *cam, int reg) /* Write a register to the i2c device. Expects claimed pdev. -1 on error */ -static int w9966_write_reg_i2c(struct w9966_dev *cam, int reg, int data) +static int w9966_write_reg_i2c(struct w9966 *cam, int reg, int data) { w9966_i2c_setsda(cam, 0); w9966_i2c_setscl(cam, 0); @@ -454,7 +457,7 @@ static int w9966_calcscale(int size, int min, int max, int *beg, int *end, unsig /* Setup the cameras capture window etc. Expects a claimed pdev return -1 on error */ -static int w9966_setup(struct w9966_dev *cam, int x1, int y1, int x2, int y2, int w, int h) +static int w9966_setup(struct w9966 *cam, int x1, int y1, int x2, int y2, int w, int h) { unsigned int i; unsigned int enh_s, enh_e; @@ -557,166 +560,204 @@ static int w9966_setup(struct w9966_dev *cam, int x1, int y1, int x2, int y2, in * Video4linux interfacing */ -static long w9966_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg) -{ - struct w9966_dev *cam = video_drvdata(file); - - switch (cmd) { - case VIDIOCGCAP: - { - static struct video_capability vcap = { - .name = W9966_DRIVERNAME, - .type = VID_TYPE_CAPTURE | VID_TYPE_SCALES, - .channels = 1, - .maxwidth = W9966_WND_MAX_W, - .maxheight = W9966_WND_MAX_H, - .minwidth = 2, - .minheight = 1, - }; - struct video_capability *cap = arg; - *cap = vcap; - return 0; - } - case VIDIOCGCHAN: - { - struct video_channel *vch = arg; - if (vch->channel != 0) /* We only support one channel (#0) */ - return -EINVAL; - memset(vch, 0, sizeof(*vch)); - strcpy(vch->name, "CCD-input"); - vch->type = VIDEO_TYPE_CAMERA; - return 0; - } - case VIDIOCSCHAN: - { - struct video_channel *vch = arg; - if (vch->channel != 0) - return -EINVAL; - return 0; - } - case VIDIOCGTUNER: - { - struct video_tuner *vtune = arg; - if (vtune->tuner != 0) - return -EINVAL; - strcpy(vtune->name, "no tuner"); - vtune->rangelow = 0; - vtune->rangehigh = 0; - vtune->flags = VIDEO_TUNER_NORM; - vtune->mode = VIDEO_MODE_AUTO; - vtune->signal = 0xffff; - return 0; - } - case VIDIOCSTUNER: - { - struct video_tuner *vtune = arg; - if (vtune->tuner != 0) - return -EINVAL; - if (vtune->mode != VIDEO_MODE_AUTO) - return -EINVAL; - return 0; - } - case VIDIOCGPICT: - { - struct video_picture vpic = { - cam->brightness << 8, /* brightness */ - (cam->hue + 128) << 8, /* hue */ - cam->color << 9, /* color */ - cam->contrast << 9, /* contrast */ - 0x8000, /* whiteness */ - 16, VIDEO_PALETTE_YUV422/* bpp, palette format */ - }; - struct video_picture *pic = arg; - *pic = vpic; - return 0; - } - case VIDIOCSPICT: - { - struct video_picture *vpic = arg; - if (vpic->depth != 16 || (vpic->palette != VIDEO_PALETTE_YUV422 && vpic->palette != VIDEO_PALETTE_YUYV)) - return -EINVAL; - - cam->brightness = vpic->brightness >> 8; - cam->hue = (vpic->hue >> 8) - 128; - cam->color = vpic->colour >> 9; - cam->contrast = vpic->contrast >> 9; - - w9966_pdev_claim(cam); - - if ( - w9966_write_reg_i2c(cam, 0x0a, cam->brightness) == -1 || - w9966_write_reg_i2c(cam, 0x0b, cam->contrast) == -1 || - w9966_write_reg_i2c(cam, 0x0c, cam->color) == -1 || - w9966_write_reg_i2c(cam, 0x0d, cam->hue) == -1 - ) { - w9966_pdev_release(cam); - return -EIO; - } - - w9966_pdev_release(cam); - return 0; - } - case VIDIOCSWIN: - { - int ret; - struct video_window *vwin = arg; - - if (vwin->flags != 0) - return -EINVAL; - if (vwin->clipcount != 0) - return -EINVAL; - if (vwin->width < 2 || vwin->width > W9966_WND_MAX_W) - return -EINVAL; - if (vwin->height < 1 || vwin->height > W9966_WND_MAX_H) - return -EINVAL; - - /* Update camera regs */ - w9966_pdev_claim(cam); - ret = w9966_setup(cam, 0, 0, 1023, 1023, vwin->width, vwin->height); - w9966_pdev_release(cam); - - if (ret != 0) { - DPRINTF("VIDIOCSWIN: w9966_setup() failed.\n"); - return -EIO; - } - - return 0; - } - case VIDIOCGWIN: - { - struct video_window *vwin = arg; - memset(vwin, 0, sizeof(*vwin)); - vwin->width = cam->width; - vwin->height = cam->height; - return 0; - } - /* Unimplemented */ - case VIDIOCCAPTURE: - case VIDIOCGFBUF: - case VIDIOCSFBUF: - case VIDIOCKEY: - case VIDIOCGFREQ: - case VIDIOCSFREQ: - case VIDIOCGAUDIO: - case VIDIOCSAUDIO: +static int cam_querycap(struct file *file, void *priv, + struct v4l2_capability *vcap) +{ + struct w9966 *cam = video_drvdata(file); + + strlcpy(vcap->driver, cam->v4l2_dev.name, sizeof(vcap->driver)); + strlcpy(vcap->card, W9966_DRIVERNAME, sizeof(vcap->card)); + strlcpy(vcap->bus_info, "parport", sizeof(vcap->bus_info)); + vcap->version = KERNEL_VERSION(0, 33, 0); + vcap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE; + return 0; +} + +static int cam_enum_input(struct file *file, void *fh, struct v4l2_input *vin) +{ + if (vin->index > 0) return -EINVAL; + strlcpy(vin->name, "Camera", sizeof(vin->name)); + vin->type = V4L2_INPUT_TYPE_CAMERA; + vin->audioset = 0; + vin->tuner = 0; + vin->std = 0; + vin->status = 0; + return 0; +} + +static int cam_g_input(struct file *file, void *fh, unsigned int *inp) +{ + *inp = 0; + return 0; +} + +static int cam_s_input(struct file *file, void *fh, unsigned int inp) +{ + return (inp > 0) ? -EINVAL : 0; +} + +static int cam_queryctrl(struct file *file, void *priv, + struct v4l2_queryctrl *qc) +{ + switch (qc->id) { + case V4L2_CID_BRIGHTNESS: + return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128); + case V4L2_CID_CONTRAST: + return v4l2_ctrl_query_fill(qc, -64, 64, 1, 64); + case V4L2_CID_SATURATION: + return v4l2_ctrl_query_fill(qc, -64, 64, 1, 64); + case V4L2_CID_HUE: + return v4l2_ctrl_query_fill(qc, -128, 127, 1, 0); + } + return -EINVAL; +} + +static int cam_g_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct w9966 *cam = video_drvdata(file); + int ret = 0; + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + ctrl->value = cam->brightness; + break; + case V4L2_CID_CONTRAST: + ctrl->value = cam->contrast; + break; + case V4L2_CID_SATURATION: + ctrl->value = cam->color; + break; + case V4L2_CID_HUE: + ctrl->value = cam->hue; + break; default: - return -ENOIOCTLCMD; + ret = -EINVAL; + break; } + return ret; +} + +static int cam_s_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct w9966 *cam = video_drvdata(file); + int ret = 0; + + mutex_lock(&cam->lock); + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + cam->brightness = ctrl->value; + break; + case V4L2_CID_CONTRAST: + cam->contrast = ctrl->value; + break; + case V4L2_CID_SATURATION: + cam->color = ctrl->value; + break; + case V4L2_CID_HUE: + cam->hue = ctrl->value; + break; + default: + ret = -EINVAL; + break; + } + + if (ret == 0) { + w9966_pdev_claim(cam); + + if (w9966_write_reg_i2c(cam, 0x0a, cam->brightness) == -1 || + w9966_write_reg_i2c(cam, 0x0b, cam->contrast) == -1 || + w9966_write_reg_i2c(cam, 0x0c, cam->color) == -1 || + w9966_write_reg_i2c(cam, 0x0d, cam->hue) == -1) { + ret = -EIO; + } + + w9966_pdev_release(cam); + } + mutex_unlock(&cam->lock); + return ret; +} + +static int cam_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) +{ + struct w9966 *cam = video_drvdata(file); + struct v4l2_pix_format *pix = &fmt->fmt.pix; + + pix->width = cam->width; + pix->height = cam->height; + pix->pixelformat = V4L2_PIX_FMT_YUYV; + pix->field = V4L2_FIELD_NONE; + pix->bytesperline = 2 * cam->width; + pix->sizeimage = 2 * cam->width * cam->height; + /* Just a guess */ + pix->colorspace = V4L2_COLORSPACE_SMPTE170M; return 0; } -static long w9966_v4l_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) +static int cam_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) { - return video_usercopy(file, cmd, arg, w9966_v4l_do_ioctl); + struct v4l2_pix_format *pix = &fmt->fmt.pix; + + if (pix->width < 2) + pix->width = 2; + if (pix->height < 1) + pix->height = 1; + if (pix->width > W9966_WND_MAX_W) + pix->width = W9966_WND_MAX_W; + if (pix->height > W9966_WND_MAX_H) + pix->height = W9966_WND_MAX_H; + pix->pixelformat = V4L2_PIX_FMT_YUYV; + pix->field = V4L2_FIELD_NONE; + pix->bytesperline = 2 * pix->width; + pix->sizeimage = 2 * pix->width * pix->height; + /* Just a guess */ + pix->colorspace = V4L2_COLORSPACE_SMPTE170M; + return 0; +} + +static int cam_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) +{ + struct w9966 *cam = video_drvdata(file); + struct v4l2_pix_format *pix = &fmt->fmt.pix; + int ret = cam_try_fmt_vid_cap(file, fh, fmt); + + if (ret) + return ret; + + mutex_lock(&cam->lock); + /* Update camera regs */ + w9966_pdev_claim(cam); + ret = w9966_setup(cam, 0, 0, 1023, 1023, pix->width, pix->height); + w9966_pdev_release(cam); + mutex_unlock(&cam->lock); + return ret; +} + +static int cam_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt) +{ + static struct v4l2_fmtdesc formats[] = { + { 0, 0, 0, + "YUV 4:2:2", V4L2_PIX_FMT_YUYV, + { 0, 0, 0, 0 } + }, + }; + enum v4l2_buf_type type = fmt->type; + + if (fmt->index > 0) + return -EINVAL; + + *fmt = formats[fmt->index]; + fmt->type = type; + return 0; } /* Capture data */ static ssize_t w9966_v4l_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - struct w9966_dev *cam = video_drvdata(file); + struct w9966 *cam = video_drvdata(file); unsigned char addr = 0xa0; /* ECP, read, CCD-transfer, 00000 */ unsigned char __user *dest = (unsigned char __user *)buf; unsigned long dleft = count; @@ -726,6 +767,7 @@ static ssize_t w9966_v4l_read(struct file *file, char __user *buf, if (count > cam->width * cam->height * 2) return -EINVAL; + mutex_lock(&cam->lock); w9966_pdev_claim(cam); w9966_write_reg(cam, 0x00, 0x02); /* Reset ECP-FIFO buffer */ w9966_write_reg(cam, 0x00, 0x00); /* Return to normal operation */ @@ -736,6 +778,7 @@ static ssize_t w9966_v4l_read(struct file *file, char __user *buf, (parport_write(cam->pport, &addr, 1) != 1) || (parport_negotiate(cam->pport, cam->ppmode|IEEE1284_DATA) != 0)) { w9966_pdev_release(cam); + mutex_unlock(&cam->lock); return -EFAULT; } @@ -765,37 +808,29 @@ static ssize_t w9966_v4l_read(struct file *file, char __user *buf, out: kfree(tbuf); w9966_pdev_release(cam); + mutex_unlock(&cam->lock); return count; } -static int w9966_exclusive_open(struct file *file) -{ - struct w9966_dev *cam = video_drvdata(file); - - return test_and_set_bit(0, &cam->in_use) ? -EBUSY : 0; -} - -static int w9966_exclusive_release(struct file *file) -{ - struct w9966_dev *cam = video_drvdata(file); - - clear_bit(0, &cam->in_use); - return 0; -} - static const struct v4l2_file_operations w9966_fops = { .owner = THIS_MODULE, - .open = w9966_exclusive_open, - .release = w9966_exclusive_release, - .ioctl = w9966_v4l_ioctl, + .ioctl = video_ioctl2, .read = w9966_v4l_read, }; -static struct video_device w9966_template = { - .name = W9966_DRIVERNAME, - .fops = &w9966_fops, - .release = video_device_release_empty, +static const struct v4l2_ioctl_ops w9966_ioctl_ops = { + .vidioc_querycap = cam_querycap, + .vidioc_g_input = cam_g_input, + .vidioc_s_input = cam_s_input, + .vidioc_enum_input = cam_enum_input, + .vidioc_queryctrl = cam_queryctrl, + .vidioc_g_ctrl = cam_g_ctrl, + .vidioc_s_ctrl = cam_s_ctrl, + .vidioc_enum_fmt_vid_cap = cam_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = cam_g_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = cam_s_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = cam_try_fmt_vid_cap, }; @@ -803,11 +838,19 @@ static struct video_device w9966_template = { default video mode, setup ccd-chip, register v4l device etc.. Also used for 'probing' of hardware. -1 on error */ -static int w9966_init(struct w9966_dev *cam, struct parport* port) +static int w9966_init(struct w9966 *cam, struct parport *port) { + struct v4l2_device *v4l2_dev = &cam->v4l2_dev; + if (cam->dev_state != 0) return -1; + strlcpy(v4l2_dev->name, "w9966", sizeof(v4l2_dev->name)); + + if (v4l2_device_register(NULL, v4l2_dev) < 0) { + v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); + return -1; + } cam->pport = port; cam->brightness = 128; cam->contrast = 64; @@ -852,23 +895,29 @@ static int w9966_init(struct w9966_dev *cam, struct parport* port) w9966_pdev_release(cam); /* Fill in the video_device struct and register us to v4l */ - memcpy(&cam->vdev, &w9966_template, sizeof(struct video_device)); + strlcpy(cam->vdev.name, W9966_DRIVERNAME, sizeof(cam->vdev.name)); + cam->vdev.v4l2_dev = v4l2_dev; + cam->vdev.fops = &w9966_fops; + cam->vdev.ioctl_ops = &w9966_ioctl_ops; + cam->vdev.release = video_device_release_empty; video_set_drvdata(&cam->vdev, cam); + mutex_init(&cam->lock); + if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) return -1; w9966_set_state(cam, W9966_STATE_VDEV, W9966_STATE_VDEV); /* All ok */ - printk(KERN_INFO "w9966cf: Found and initialized a webcam on %s.\n", + v4l2_info(v4l2_dev, "Found and initialized a webcam on %s.\n", cam->pport->name); return 0; } /* Terminate everything gracefully */ -static void w9966_term(struct w9966_dev *cam) +static void w9966_term(struct w9966 *cam) { /* Unregister from v4l */ if (w9966_get_state(cam, W9966_STATE_VDEV, W9966_STATE_VDEV)) { -- cgit v1.2.3-70-g09d2 From 6a717883e720f75dec252c8af2a2d6dd049af254 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 6 Apr 2010 15:56:08 -0300 Subject: V4L/DVB: video_ioctl2: handle the v4l1 compat bit first and move VIDIOCGMBUF into the switch Try to make a more sensible sequence of events in __video_do_ioctl: first check for a valid ops pointer, then get the compat part done. The VIDIOCGMBUF command is now part of the big switch. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-ioctl.c | 44 +++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 19 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 571f0c6e7c8..3da8d8f041d 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -610,17 +610,33 @@ static long __video_do_ioctl(struct file *file, void *fh = file->private_data; long ret = -EINVAL; + if (ops == NULL) { + printk(KERN_WARNING "videodev: \"%s\" has no ioctl_ops.\n", + vfd->name); + return -EINVAL; + } + +#ifdef CONFIG_VIDEO_V4L1_COMPAT + /******************************************************** + All other V4L1 calls are handled by v4l1_compat module. + Those calls will be translated into V4L2 calls, and + __video_do_ioctl will be called again, with one or more + V4L2 ioctls. + ********************************************************/ + if (_IOC_TYPE(cmd) == 'v' && cmd != VIDIOCGMBUF && + _IOC_NR(cmd) < BASE_VIDIOCPRIVATE) { + return v4l_compat_translate_ioctl(file, cmd, arg, + __video_do_ioctl); + } +#endif + if ((vfd->debug & V4L2_DEBUG_IOCTL) && !(vfd->debug & V4L2_DEBUG_IOCTL_ARG)) { v4l_print_ioctl(vfd->name, cmd); printk(KERN_CONT "\n"); } - if (ops == NULL) { - printk(KERN_WARNING "videodev: \"%s\" has no ioctl_ops.\n", - vfd->name); - return -EINVAL; - } + switch (cmd) { #ifdef CONFIG_VIDEO_V4L1_COMPAT /*********************************************************** @@ -630,31 +646,21 @@ static long __video_do_ioctl(struct file *file, ***********************************************************/ /* --- streaming capture ------------------------------------- */ - if (cmd == VIDIOCGMBUF) { + case VIDIOCGMBUF: + { struct video_mbuf *p = arg; if (!ops->vidiocgmbuf) - return ret; + break; ret = ops->vidiocgmbuf(file, fh, p); if (!ret) dbgarg(cmd, "size=%d, frames=%d, offsets=0x%08lx\n", p->size, p->frames, (unsigned long)p->offsets); - return ret; + break; } - - /******************************************************** - All other V4L1 calls are handled by v4l1_compat module. - Those calls will be translated into V4L2 calls, and - __video_do_ioctl will be called again, with one or more - V4L2 ioctls. - ********************************************************/ - if (_IOC_TYPE(cmd) == 'v' && _IOC_NR(cmd) < BASE_VIDIOCPRIVATE) - return v4l_compat_translate_ioctl(file, cmd, arg, - __video_do_ioctl); #endif - switch (cmd) { /* --- capabilities ------------------------------------------ */ case VIDIOC_QUERYCAP: { -- cgit v1.2.3-70-g09d2 From ce68025e9f10481b9104c5bdf88b0dac52790757 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 6 Apr 2010 15:58:53 -0300 Subject: V4L/DVB: ivtv: move the _IO() decoder ioctls into vidioc_default Now that video_ioctl2 no longer clobbers the argument for _IO() ioctls we can move these into vidioc_default where they really belong. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtv-ioctl.c | 65 +++++++++++++++++------------------ 1 file changed, 32 insertions(+), 33 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index c29ff983d43..6422cf8f189 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c @@ -1564,6 +1564,7 @@ static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg) struct ivtv *itv = id->itv; int nonblocking = filp->f_flags & O_NONBLOCK; struct ivtv_stream *s = &itv->streams[id->type]; + unsigned long iarg = (unsigned long)arg; switch (cmd) { case IVTV_IOC_DMA_FRAME: { @@ -1745,6 +1746,33 @@ static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg) break; } + case VIDEO_SELECT_SOURCE: + IVTV_DEBUG_IOCTL("VIDEO_SELECT_SOURCE\n"); + if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) + return -EINVAL; + return ivtv_passthrough_mode(itv, iarg == VIDEO_SOURCE_DEMUX); + + case AUDIO_SET_MUTE: + IVTV_DEBUG_IOCTL("AUDIO_SET_MUTE\n"); + itv->speed_mute_audio = iarg; + return 0; + + case AUDIO_CHANNEL_SELECT: + IVTV_DEBUG_IOCTL("AUDIO_CHANNEL_SELECT\n"); + if (iarg > AUDIO_STEREO_SWAPPED) + return -EINVAL; + itv->audio_stereo_mode = iarg; + ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); + return 0; + + case AUDIO_BILINGUAL_CHANNEL_SELECT: + IVTV_DEBUG_IOCTL("AUDIO_BILINGUAL_CHANNEL_SELECT\n"); + if (iarg > AUDIO_STEREO_SWAPPED) + return -EINVAL; + itv->audio_bilingual_mode = iarg; + ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); + return 0; + default: return -EINVAL; } @@ -1776,6 +1804,10 @@ static long ivtv_default(struct file *file, void *fh, int cmd, void *arg) case VIDEO_CONTINUE: case VIDEO_COMMAND: case VIDEO_TRY_COMMAND: + case VIDEO_SELECT_SOURCE: + case AUDIO_SET_MUTE: + case AUDIO_CHANNEL_SELECT: + case AUDIO_BILINGUAL_CHANNEL_SELECT: return ivtv_decoder_ioctls(file, cmd, (void *)arg); default: @@ -1791,39 +1823,6 @@ static long ivtv_serialized_ioctl(struct ivtv *itv, struct file *filp, struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data; long ret; - /* Filter dvb ioctls that cannot be handled by the v4l ioctl framework */ - switch (cmd) { - case VIDEO_SELECT_SOURCE: - IVTV_DEBUG_IOCTL("VIDEO_SELECT_SOURCE\n"); - if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) - return -EINVAL; - return ivtv_passthrough_mode(itv, arg == VIDEO_SOURCE_DEMUX); - - case AUDIO_SET_MUTE: - IVTV_DEBUG_IOCTL("AUDIO_SET_MUTE\n"); - itv->speed_mute_audio = arg; - return 0; - - case AUDIO_CHANNEL_SELECT: - IVTV_DEBUG_IOCTL("AUDIO_CHANNEL_SELECT\n"); - if (arg > AUDIO_STEREO_SWAPPED) - return -EINVAL; - itv->audio_stereo_mode = arg; - ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); - return 0; - - case AUDIO_BILINGUAL_CHANNEL_SELECT: - IVTV_DEBUG_IOCTL("AUDIO_BILINGUAL_CHANNEL_SELECT\n"); - if (arg > AUDIO_STEREO_SWAPPED) - return -EINVAL; - itv->audio_bilingual_mode = arg; - ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); - return 0; - - default: - break; - } - /* check priority */ switch (cmd) { case VIDIOC_S_CTRL: -- cgit v1.2.3-70-g09d2 From 0a062033f727dc041691bfd768f4cf0598f559a1 Mon Sep 17 00:00:00 2001 From: Herton Ronaldo Krzesinski Date: Fri, 19 Mar 2010 14:58:23 -0300 Subject: Revert "V4L/DVB (11906): saa7134: Use v4l bounding/alignment function" This reverts commit bc52d6eb44de8f19934768d4d10d19fdbdc99950. On newer kernels, a saa7134 board stopped to display TV video output properly. After a bisect, I found it as the commit causing the issue. Turns out that v4l_bound_align_image isn't doing the same bounding calculation as manually done previously in saa7134_try_fmt_vid_cap. What isn't equal is the calculation done in clamp align, while previously it did "f->fmt.pix.width &= ~0x03", clamp_align function does "Round to nearest aligned value" as stated in the comment, which yields a different result. If I comment the round calculation in clamp_align like this: "x = (x /*+ (1 << (align - 1))*/) & mask", I get it fixed too, because this way the calculation is the same then. Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-video.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index 31138d3e51b..7806fb17e74 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -1632,8 +1632,15 @@ static int saa7134_try_fmt_vid_cap(struct file *file, void *priv, } f->fmt.pix.field = field; - v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2, - &f->fmt.pix.height, 32, maxh, 0, 0); + if (f->fmt.pix.width < 48) + f->fmt.pix.width = 48; + if (f->fmt.pix.height < 32) + f->fmt.pix.height = 32; + if (f->fmt.pix.width > maxw) + f->fmt.pix.width = maxw; + if (f->fmt.pix.height > maxh) + f->fmt.pix.height = maxh; + f->fmt.pix.width &= ~0x03; f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3; f->fmt.pix.sizeimage = -- cgit v1.2.3-70-g09d2 From dab7e3106ddd6cbc3b55301228407b9d17ce7773 Mon Sep 17 00:00:00 2001 From: Andreas Bombe Date: Sun, 21 Mar 2010 16:02:45 -0300 Subject: V4L/DVB: V4L2: Replace loops for finding max buffers in VIDIOC_REQBUFS callbacks Due to obvious copy and paste coding a number of video capture drivers which implement a limit on the buffer memory decremented the user supplied buffer count in a while loop until it reaches an acceptable value. This is a silly thing to do when the maximum value can be directly computed. Signed-off-by: Andreas Bombe Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/bttv-driver.c | 4 ++-- drivers/media/video/cx23885/cx23885-video.c | 4 ++-- drivers/media/video/cx88/cx88-video.c | 4 ++-- drivers/media/video/mx1_camera.c | 4 ++-- drivers/media/video/omap24xxcam.c | 4 ++-- drivers/media/video/pxa_camera.c | 4 ++-- drivers/media/video/s2255drv.c | 4 ++-- drivers/media/video/sh_mobile_ceu_camera.c | 4 ++-- drivers/media/video/vivi.c | 4 ++-- drivers/media/video/zr364xx.c | 4 ++-- drivers/staging/cx25821/cx25821-video.c | 4 ++-- 11 files changed, 22 insertions(+), 22 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index f4860f03dfc..350e7af7588 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -1806,8 +1806,8 @@ buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) *size = fh->fmt->depth*fh->width*fh->height >> 3; if (0 == *count) *count = gbuffers; - while (*size * *count > gbuffers * gbufsize) - (*count)--; + if (*size * *count > gbuffers * gbufsize) + *count = (gbuffers * gbufsize) / *size; return 0; } diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c index 2d3ac8b83dc..543b854f6a6 100644 --- a/drivers/media/video/cx23885/cx23885-video.c +++ b/drivers/media/video/cx23885/cx23885-video.c @@ -514,8 +514,8 @@ static int buffer_setup(struct videobuf_queue *q, unsigned int *count, *size = fh->fmt->depth*fh->width*fh->height >> 3; if (0 == *count) *count = 32; - while (*size * *count > vid_limit * 1024 * 1024) - (*count)--; + if (*size * *count > vid_limit * 1024 * 1024) + *count = (vid_limit * 1024 * 1024) / *size; return 0; } diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 8e414f7aa76..0a3849c710f 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -561,8 +561,8 @@ buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) *size = fh->fmt->depth*fh->width*fh->height >> 3; if (0 == *count) *count = 32; - while (*size * *count > vid_limit * 1024 * 1024) - (*count)--; + if (*size * *count > vid_limit * 1024 * 1024) + *count = (vid_limit * 1024 * 1024) / *size; return 0; } diff --git a/drivers/media/video/mx1_camera.c b/drivers/media/video/mx1_camera.c index 34a66019190..5c17f9ec3d7 100644 --- a/drivers/media/video/mx1_camera.c +++ b/drivers/media/video/mx1_camera.c @@ -139,8 +139,8 @@ static int mx1_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, if (!*count) *count = 32; - while (*size * *count > MAX_VIDEO_MEM * 1024 * 1024) - (*count)--; + if (*size * *count > MAX_VIDEO_MEM * 1024 * 1024) + *count = (MAX_VIDEO_MEM * 1024 * 1024) / *size; dev_dbg(icd->dev.parent, "count=%d, size=%d\n", *count, *size); diff --git a/drivers/media/video/omap24xxcam.c b/drivers/media/video/omap24xxcam.c index ce76d952e16..f85b2ed8a2d 100644 --- a/drivers/media/video/omap24xxcam.c +++ b/drivers/media/video/omap24xxcam.c @@ -452,8 +452,8 @@ static int omap24xxcam_vbq_setup(struct videobuf_queue *vbq, unsigned int *cnt, *size = fh->pix.sizeimage; /* accessing fh->cam->capture_mem is ok, it's constant */ - while (*size * *cnt > fh->cam->capture_mem) - (*cnt)--; + if (*size * *cnt > fh->cam->capture_mem) + *cnt = fh->cam->capture_mem / *size; return 0; } diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index 04bf5c11308..7fe70e71865 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c @@ -253,8 +253,8 @@ static int pxa_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, if (0 == *count) *count = 32; - while (*size * *count > vid_limit * 1024 * 1024) - (*count)--; + if (*size * *count > vid_limit * 1024 * 1024) + *count = (vid_limit * 1024 * 1024) / *size; return 0; } diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index 0092ff52bb2..5ecd41b3bf3 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c @@ -702,8 +702,8 @@ static int buffer_setup(struct videobuf_queue *vq, unsigned int *count, if (0 == *count) *count = S2255_DEF_BUFS; - while (*size * (*count) > vid_limit * 1024 * 1024) - (*count)--; + if (*size * *count > vid_limit * 1024 * 1024) + *count = (vid_limit * 1024 * 1024) / *size; return 0; } diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index 7a229ebe692..9a46f0a0c1b 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c @@ -213,8 +213,8 @@ static int sh_mobile_ceu_videobuf_setup(struct videobuf_queue *vq, *count = 2; if (pcdev->video_limit) { - while (PAGE_ALIGN(*size) * *count > pcdev->video_limit) - (*count)--; + if (PAGE_ALIGN(*size) * *count > pcdev->video_limit) + *count = pcdev->video_limit / PAGE_ALIGN(*size); } dev_dbg(icd->dev.parent, "count=%d, size=%d\n", *count, *size); diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index cdbe70385c1..5a736b8a5a3 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -749,8 +749,8 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) if (0 == *count) *count = 32; - while (*size * *count > vid_limit * 1024 * 1024) - (*count)--; + if (*size * *count > vid_limit * 1024 * 1024) + *count = (vid_limit * 1024 * 1024) / *size; dprintk(dev, 1, "%s, count=%d, size=%d\n", __func__, *count, *size); diff --git a/drivers/media/video/zr364xx.c b/drivers/media/video/zr364xx.c index 3d4bac25290..a82b5bd18d2 100644 --- a/drivers/media/video/zr364xx.c +++ b/drivers/media/video/zr364xx.c @@ -376,8 +376,8 @@ static int buffer_setup(struct videobuf_queue *vq, unsigned int *count, if (*count == 0) *count = ZR364XX_DEF_BUFS; - while (*size * (*count) > ZR364XX_DEF_BUFS * 1024 * 1024) - (*count)--; + if (*size * *count > ZR364XX_DEF_BUFS * 1024 * 1024) + *count = (ZR364XX_DEF_BUFS * 1024 * 1024) / *size; return 0; } diff --git a/drivers/staging/cx25821/cx25821-video.c b/drivers/staging/cx25821/cx25821-video.c index 91e0db2e37f..a3bea2739ce 100644 --- a/drivers/staging/cx25821/cx25821-video.c +++ b/drivers/staging/cx25821/cx25821-video.c @@ -516,8 +516,8 @@ int cx25821_buffer_setup(struct videobuf_queue *q, unsigned int *count, if (0 == *count) *count = 32; - while (*size * *count > vid_limit * 1024 * 1024) - (*count)--; + if (*size * *count > vid_limit * 1024 * 1024) + *count = (vid_limit * 1024 * 1024) / *size; return 0; } -- cgit v1.2.3-70-g09d2 From b4bc3dcbefc0a359744ab13bc8b67c6cb5cd0086 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 8 Apr 2010 19:09:13 -0300 Subject: V4L/DVB: cpia1: comment unused command_setlights() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/media/video/gspca/cpia1.c:1063: warning: ‘command_setlights’ defined but not used Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/cpia1.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/cpia1.c b/drivers/media/video/gspca/cpia1.c index 92879c072e9..58b696f455b 100644 --- a/drivers/media/video/gspca/cpia1.c +++ b/drivers/media/video/gspca/cpia1.c @@ -1059,6 +1059,7 @@ static int command_resume(struct gspca_dev *gspca_dev) 0, sd->params.streamStartLine, 0, 0); } +#if 0 /* Currently unused */ static int command_setlights(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -1078,6 +1079,7 @@ static int command_setlights(struct gspca_dev *gspca_dev) return do_command(gspca_dev, CPIA_COMMAND_WriteMCPort, 2, 0, p1 | p2 | 0xE0, 0); } +#endif static int set_flicker(struct gspca_dev *gspca_dev, int on, int apply) { -- cgit v1.2.3-70-g09d2 From 10f1a6e8eda5cccc2753955ae81fa217d75bf68d Mon Sep 17 00:00:00 2001 From: Christoph Fritz Date: Wed, 24 Mar 2010 22:40:41 -0300 Subject: V4L/DVB: pwc Kconfig dependency fix makes USB_PWC_INPUT_EVDEV to depend also on USB_PWC Signed-off-by: Christoph Fritz Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pwc/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pwc/Kconfig b/drivers/media/video/pwc/Kconfig index 340f954aba3..11980db22d3 100644 --- a/drivers/media/video/pwc/Kconfig +++ b/drivers/media/video/pwc/Kconfig @@ -39,7 +39,7 @@ config USB_PWC_DEBUG config USB_PWC_INPUT_EVDEV bool "USB Philips Cameras input events device support" default y - depends on USB_PWC=INPUT || INPUT=y + depends on USB_PWC && (USB_PWC=INPUT || INPUT=y) ---help--- This option makes USB Philips cameras register the snapshot button as an input device to report button events. -- cgit v1.2.3-70-g09d2 From 6e1f4df7da6edd21a184daff023a8eef67f005dc Mon Sep 17 00:00:00 2001 From: "istvan_v@mailbox.hu" Date: Sat, 27 Mar 2010 09:31:32 -0300 Subject: V4L/DVB: cx88: fix checks for analog TV inputs The following patch fixes code that checks for CX88_VMUX_TELEVISION, but not CX88_VMUX_CABLE. This prevented for example the audio standard from being set when using the cable input. Signed-off-by: Istvan Varga Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-core.c | 3 ++- drivers/media/video/cx88/cx88-video.c | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index b35411160f0..8b21457111b 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c @@ -847,7 +847,8 @@ static int set_tvaudio(struct cx88_core *core) { v4l2_std_id norm = core->tvnorm; - if (CX88_VMUX_TELEVISION != INPUT(core->input).type) + if (CX88_VMUX_TELEVISION != INPUT(core->input).type && + CX88_VMUX_CABLE != INPUT(core->input).type) return 0; if (V4L2_STD_PAL_BG & norm) { diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 0a3849c710f..f5d1d89bdc2 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -426,12 +426,13 @@ int cx88_video_mux(struct cx88_core *core, unsigned int input) if (core->board.audio_chip && core->board.audio_chip == V4L2_IDENT_WM8775) { call_all(core, audio, s_routing, - INPUT(input).audioroute, 0, 0); + INPUT(input).audioroute, 0, 0); } /* cx2388's C-ADC is connected to the tuner only. When used with S-Video, that ADC is busy dealing with chroma, so an external must be used for baseband audio */ - if (INPUT(input).type != CX88_VMUX_TELEVISION ) { + if (INPUT(input).type != CX88_VMUX_TELEVISION && + INPUT(input).type != CX88_VMUX_CABLE) { /* "I2S ADC mode" */ core->tvaudio = WW_I2SADC; cx88_set_tvaudio(core); -- cgit v1.2.3-70-g09d2 From f5e20c34e9c1bcf9e92f2634411bffd98511fc48 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sun, 28 Mar 2010 08:21:18 -0300 Subject: V4L/DVB: video/au0828: off by one bug The "AUVI_INPUT(tmp)" macro uses "tmp" as an index of an array with AU0828_MAX_INPUT elements. Signed-off-by: Dan Carpenter Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/au0828/au0828-video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c index 8c140c01c5e..66150216f97 100644 --- a/drivers/media/video/au0828/au0828-video.c +++ b/drivers/media/video/au0828/au0828-video.c @@ -1105,7 +1105,7 @@ static int vidioc_enum_input(struct file *file, void *priv, tmp = input->index; - if (tmp > AU0828_MAX_INPUT) + if (tmp >= AU0828_MAX_INPUT) return -EINVAL; if (AUVI_INPUT(tmp).type == 0) return -EINVAL; -- cgit v1.2.3-70-g09d2 From ff7e22dfa1b8c291f154db990ff686adbe334448 Mon Sep 17 00:00:00 2001 From: Dean Anderson Date: Thu, 8 Apr 2010 23:38:07 -0300 Subject: V4L/DVB: s2255drv: cleanup of driver disconnect code simplifies use of kref in driver Signed-off-by: Dean Anderson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s2255drv.c | 266 +++++++++++++++++------------------------ 1 file changed, 109 insertions(+), 157 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index 5ecd41b3bf3..1d8c6b4364d 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c @@ -226,7 +226,6 @@ struct s2255_fmt; /*forward declaration */ struct s2255_dev { int frames; - int users[MAX_CHANNELS]; struct mutex lock; struct mutex open_lock; int resources[MAX_CHANNELS]; @@ -367,7 +366,6 @@ static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf, static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn, struct s2255_mode *mode); static int s2255_board_shutdown(struct s2255_dev *dev); -static void s2255_exit_v4l(struct s2255_dev *dev); static void s2255_fwload_start(struct s2255_dev *dev, int reset); static void s2255_destroy(struct kref *kref); static long s2255_vendor_req(struct s2255_dev *dev, unsigned char req, @@ -606,7 +604,6 @@ unlock: return 0; } - static const struct s2255_fmt *format_by_fourcc(int fourcc) { unsigned int i; @@ -620,9 +617,6 @@ static const struct s2255_fmt *format_by_fourcc(int fourcc) return NULL; } - - - /* video buffer vmalloc implementation based partly on VIVI driver which is * Copyright (c) 2006 by * Mauro Carvalho Chehab @@ -849,7 +843,6 @@ static int vidioc_querymenu(struct file *file, void *priv, return v4l2_ctrl_query_menu(qmenu, NULL, NULL); } - static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { @@ -1759,31 +1752,26 @@ static int s2255_open(struct file *file) int i = 0; int cur_channel = -1; int state; - dprintk(1, "s2255: open called (dev=%s)\n", video_device_node_name(vdev)); - lock_kernel(); - - for (i = 0; i < MAX_CHANNELS; i++) { + for (i = 0; i < MAX_CHANNELS; i++) if (dev->vdev[i] == vdev) { cur_channel = i; break; } - } - - if (atomic_read(&dev->fw_data->fw_state) == S2255_FW_DISCONNECTING) { + /* + * open lock necessary to prevent multiple instances + * of v4l-conf (or other programs) from simultaneously + * reloading firmware. + */ + mutex_lock(&dev->open_lock); + state = atomic_read(&dev->fw_data->fw_state); + switch (state) { + case S2255_FW_DISCONNECTING: + mutex_unlock(&dev->open_lock); unlock_kernel(); - printk(KERN_INFO "disconnecting\n"); return -ENODEV; - } - kref_get(&dev->kref); - mutex_lock(&dev->open_lock); - - dev->users[cur_channel]++; - dprintk(4, "s2255: open_handles %d\n", dev->users[cur_channel]); - - switch (atomic_read(&dev->fw_data->fw_state)) { case S2255_FW_FAILED: s2255_dev_err(&dev->udev->dev, "firmware load failed. retrying.\n"); @@ -1794,6 +1782,8 @@ static int s2255_open(struct file *file) (atomic_read(&dev->fw_data->fw_state) == S2255_FW_DISCONNECTING)), msecs_to_jiffies(S2255_LOAD_TIMEOUT)); + /* state may have changed, re-read */ + state = atomic_read(&dev->fw_data->fw_state); break; case S2255_FW_NOTLOADED: case S2255_FW_LOADED_DSPWAIT: @@ -1806,52 +1796,44 @@ static int s2255_open(struct file *file) (atomic_read(&dev->fw_data->fw_state) == S2255_FW_DISCONNECTING)), msecs_to_jiffies(S2255_LOAD_TIMEOUT)); + /* state may have changed, re-read */ + state = atomic_read(&dev->fw_data->fw_state); break; case S2255_FW_SUCCESS: default: break; } - state = atomic_read(&dev->fw_data->fw_state); - if (state != S2255_FW_SUCCESS) { - int rc; - switch (state) { - case S2255_FW_FAILED: - printk(KERN_INFO "2255 FW load failed. %d\n", state); - rc = -ENODEV; - break; - case S2255_FW_DISCONNECTING: - printk(KERN_INFO "%s: disconnecting\n", __func__); - rc = -ENODEV; - break; - case S2255_FW_LOADED_DSPWAIT: - case S2255_FW_NOTLOADED: - printk(KERN_INFO "%s: firmware not loaded yet" - "please try again later\n", - __func__); - rc = -EAGAIN; - break; - default: - printk(KERN_INFO "%s: unknown state\n", __func__); - rc = -EFAULT; - break; - } - dev->users[cur_channel]--; - mutex_unlock(&dev->open_lock); - kref_put(&dev->kref, s2255_destroy); + mutex_unlock(&dev->open_lock); + /* state may have changed in above switch statement */ + switch (state) { + case S2255_FW_SUCCESS: + break; + case S2255_FW_FAILED: + printk(KERN_INFO "2255 firmware load failed.\n"); + unlock_kernel(); + return -ENODEV; + case S2255_FW_DISCONNECTING: + printk(KERN_INFO "%s: disconnecting\n", __func__); + unlock_kernel(); + return -ENODEV; + case S2255_FW_LOADED_DSPWAIT: + case S2255_FW_NOTLOADED: + printk(KERN_INFO "%s: firmware not loaded yet" + "please try again later\n", + __func__); + unlock_kernel(); + return -EAGAIN; + default: + printk(KERN_INFO "%s: unknown state\n", __func__); unlock_kernel(); - return rc; + return -EFAULT; } - /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); if (NULL == fh) { - dev->users[cur_channel]--; - mutex_unlock(&dev->open_lock); - kref_put(&dev->kref, s2255_destroy); unlock_kernel(); return -ENOMEM; } - file->private_data = fh; fh->dev = dev; fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; @@ -1866,9 +1848,8 @@ static int s2255_open(struct file *file) s2255_set_mode(dev, cur_channel, &fh->mode); dev->chn_configured[cur_channel] = 1; } - dprintk(1, "s2255drv: open dev=%s type=%s users=%d\n", - video_device_node_name(vdev), v4l2_type_names[type], - dev->users[cur_channel]); + dprintk(1, "s2255drv: open dev=%s type=%s\n", + video_device_node_name(vdev), v4l2_type_names[type]); dprintk(2, "s2255drv: open: fh=0x%08lx, dev=0x%08lx, vidq=0x%08lx\n", (unsigned long)fh, (unsigned long)dev, (unsigned long)&dev->vidq[cur_channel]); @@ -1880,8 +1861,6 @@ static int s2255_open(struct file *file) fh->type, V4L2_FIELD_INTERLACED, sizeof(struct s2255_buffer), fh); - - mutex_unlock(&dev->open_lock); unlock_kernel(); return 0; } @@ -1904,28 +1883,10 @@ static unsigned int s2255_poll(struct file *file, static void s2255_destroy(struct kref *kref) { struct s2255_dev *dev = to_s2255_dev(kref); - int i; - if (!dev) { - printk(KERN_ERR "s2255drv: kref problem\n"); - return; - } - atomic_set(&dev->fw_data->fw_state, S2255_FW_DISCONNECTING); - wake_up(&dev->fw_data->wait_fw); - for (i = 0; i < MAX_CHANNELS; i++) { - dev->setmode_ready[i] = 1; - wake_up(&dev->wait_setmode[i]); - dev->vidstatus_ready[i] = 1; - wake_up(&dev->wait_vidstatus[i]); - } - mutex_lock(&dev->open_lock); - /* reset the DSP so firmware can be reload next time */ - s2255_reset_dsppower(dev); - s2255_exit_v4l(dev); /* board shutdown stops the read pipe if it is running */ s2255_board_shutdown(dev); /* make sure firmware still not trying to load */ del_timer(&dev->timer); /* only started in .probe and .open */ - if (dev->fw_data->fw_urb) { dprintk(2, "kill fw_urb\n"); usb_kill_urb(dev->fw_data->fw_urb); @@ -1936,24 +1897,22 @@ static void s2255_destroy(struct kref *kref) release_firmware(dev->fw_data->fw); kfree(dev->fw_data->pfw_data); kfree(dev->fw_data); + /* reset the DSP so firmware can be reloaded next time */ + s2255_reset_dsppower(dev); + mutex_destroy(&dev->open_lock); + mutex_destroy(&dev->lock); usb_put_dev(dev->udev); dprintk(1, "%s", __func__); - - mutex_unlock(&dev->open_lock); kfree(dev); } -static int s2255_close(struct file *file) +static int s2255_release(struct file *file) { struct s2255_fh *fh = file->private_data; struct s2255_dev *dev = fh->dev; struct video_device *vdev = video_devdata(file); - if (!dev) return -ENODEV; - - mutex_lock(&dev->open_lock); - /* turn off stream */ if (res_check(fh)) { if (dev->b_acquire[fh->channel]) @@ -1961,15 +1920,8 @@ static int s2255_close(struct file *file) videobuf_streamoff(&fh->vb_vidq); res_free(dev, fh); } - videobuf_mmap_free(&fh->vb_vidq); - dev->users[fh->channel]--; - - mutex_unlock(&dev->open_lock); - - kref_put(&dev->kref, s2255_destroy); - dprintk(1, "s2255: close called (dev=%s, users=%d)\n", - video_device_node_name(vdev), dev->users[fh->channel]); + dprintk(1, "%s (dev=%s)\n", __func__, video_device_node_name(vdev)); kfree(fh); return 0; } @@ -1995,7 +1947,7 @@ static int s2255_mmap_v4l(struct file *file, struct vm_area_struct *vma) static const struct v4l2_file_operations s2255_fops_v4l = { .owner = THIS_MODULE, .open = s2255_open, - .release = s2255_close, + .release = s2255_release, .poll = s2255_poll, .ioctl = video_ioctl2, /* V4L2 ioctl handler */ .mmap = s2255_mmap_v4l, @@ -2031,11 +1983,19 @@ static const struct v4l2_ioctl_ops s2255_ioctl_ops = { .vidioc_enum_frameintervals = vidioc_enum_frameintervals, }; +static void s2255_video_device_release(struct video_device *vdev) +{ + struct s2255_dev *dev = video_get_drvdata(vdev); + video_device_release(vdev); + kref_put(&dev->kref, s2255_destroy); + return; +} + static struct video_device template = { .name = "s2255v", .fops = &s2255_fops_v4l, .ioctl_ops = &s2255_ioctl_ops, - .release = video_device_release, + .release = s2255_video_device_release, .tvnorms = S2255_NORMS, .current_norm = V4L2_STD_NTSC_M, }; @@ -2079,21 +2039,6 @@ static int s2255_probe_v4l(struct s2255_dev *dev) return ret; } -static void s2255_exit_v4l(struct s2255_dev *dev) -{ - - int i; - for (i = 0; i < MAX_CHANNELS; i++) { - if (video_is_registered(dev->vdev[i])) { - video_unregister_device(dev->vdev[i]); - printk(KERN_INFO "s2255 unregistered\n"); - } else { - video_device_release(dev->vdev[i]); - printk(KERN_INFO "s2255 released\n"); - } - } -} - /* this function moves the usb stream read pipe data * into the system buffers. * returns 0 on success, EAGAIN if more data to process( call this @@ -2408,9 +2353,7 @@ static int s2255_board_init(struct s2255_dev *dev) dprintk(1, "out of memory!\n"); return -ENOMEM; } - } - /* query the firmware */ fw_ver = s2255_get_fx2fw(dev); @@ -2447,7 +2390,6 @@ static int s2255_board_init(struct s2255_dev *dev) static int s2255_board_shutdown(struct s2255_dev *dev) { u32 i; - dprintk(1, "S2255: board shutdown: %p", dev); for (i = 0; i < MAX_CHANNELS; i++) { @@ -2640,7 +2582,6 @@ static int s2255_stop_acquire(struct s2255_dev *dev, unsigned long chn) static void s2255_stop_readpipe(struct s2255_dev *dev) { int j; - if (dev == NULL) { s2255_dev_err(&dev->udev->dev, "invalid device\n"); return; @@ -2654,7 +2595,6 @@ static void s2255_stop_readpipe(struct s2255_dev *dev) pipe_info->state = 0; } } - for (j = 0; j < MAX_PIPE_BUFFERS; j++) { struct s2255_pipeinfo *pipe_info = &dev->pipes[j]; if (pipe_info->stream_urb) { @@ -2703,24 +2643,22 @@ static int s2255_probe(struct usb_interface *interface, dev = kzalloc(sizeof(struct s2255_dev), GFP_KERNEL); if (dev == NULL) { s2255_dev_err(&interface->dev, "out of memory\n"); - goto error; + return -ENOMEM; } + kref_init(&dev->kref); dev->pid = id->idProduct; dev->fw_data = kzalloc(sizeof(struct s2255_fw), GFP_KERNEL); if (!dev->fw_data) - goto error; - + goto errorFWDATA1; mutex_init(&dev->lock); mutex_init(&dev->open_lock); - /* grab usb_device and save it */ dev->udev = usb_get_dev(interface_to_usbdev(interface)); if (dev->udev == NULL) { dev_err(&interface->dev, "null usb device\n"); retval = -ENODEV; - goto error; + goto errorUDEV; } - kref_init(&dev->kref); dprintk(1, "dev: %p, kref: %p udev %p interface %p\n", dev, &dev->kref, dev->udev, interface); dev->interface = interface; @@ -2737,14 +2675,11 @@ static int s2255_probe(struct usb_interface *interface, if (!dev->read_endpoint) { dev_err(&interface->dev, "Could not find bulk-in endpoint\n"); - goto error; + goto errorEP; } - /* set intfdata */ usb_set_intfdata(interface, dev); - dprintk(100, "after intfdata %p\n", dev); - init_timer(&dev->timer); dev->timer.function = s2255_timer; dev->timer.data = (unsigned long)dev->fw_data; @@ -2756,21 +2691,21 @@ static int s2255_probe(struct usb_interface *interface, } dev->fw_data->fw_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!dev->fw_data->fw_urb) { dev_err(&interface->dev, "out of memory!\n"); - goto error; + goto errorFWURB; } + dev->fw_data->pfw_data = kzalloc(CHUNK_SIZE, GFP_KERNEL); if (!dev->fw_data->pfw_data) { dev_err(&interface->dev, "out of memory!\n"); - goto error; + goto errorFWDATA2; } /* load the first chunk */ if (request_firmware(&dev->fw_data->fw, FIRMWARE_FILE_NAME, &dev->udev->dev)) { printk(KERN_ERR "sensoray 2255 failed to get firmware\n"); - goto error; + goto errorREQFW; } /* check the firmware is valid */ fw_size = dev->fw_data->fw->size; @@ -2779,7 +2714,7 @@ static int s2255_probe(struct usb_interface *interface, if (*pdata != S2255_FW_MARKER) { printk(KERN_INFO "Firmware invalid.\n"); retval = -ENODEV; - goto error; + goto errorFWMARKER; } else { /* make sure firmware is the latest */ __le32 *pRel; @@ -2789,26 +2724,53 @@ static int s2255_probe(struct usb_interface *interface, if (*pRel < S2255_CUR_DSP_FWVER) printk(KERN_INFO "s2255: f2255usb.bin out of date.\n"); if (dev->pid == 0x2257 && *pRel < S2255_MIN_DSP_COLORFILTER) - printk(KERN_WARNING "s2255: 2257 requires firmware 8 or above.\n"); + printk(KERN_WARNING "s2255: 2257 requires firmware %d" + "or above.\n", S2255_MIN_DSP_COLORFILTER); } - /* loads v4l specific */ - s2255_probe_v4l(dev); usb_reset_device(dev->udev); /* load 2255 board specific */ retval = s2255_board_init(dev); if (retval) - goto error; - + goto errorBOARDINIT; dprintk(4, "before probe done %p\n", dev); spin_lock_init(&dev->slock); - s2255_fwload_start(dev, 0); + /* kref for each vdev. Released on video_device_release callback */ + for (i = 0; i < MAX_CHANNELS; i++) + kref_get(&dev->kref); + /* loads v4l specific */ + retval = s2255_probe_v4l(dev); + if (retval) + goto errorV4L; dev_info(&interface->dev, "Sensoray 2255 detected\n"); return 0; -error: +errorV4L: + for (i = 0; i < MAX_CHANNELS; i++) + if (dev->vdev[i] && video_is_registered(dev->vdev[i])) + video_unregister_device(dev->vdev[i]); +errorBOARDINIT: + s2255_board_shutdown(dev); +errorFWMARKER: + release_firmware(dev->fw_data->fw); +errorREQFW: + kfree(dev->fw_data->pfw_data); +errorFWDATA2: + usb_free_urb(dev->fw_data->fw_urb); +errorFWURB: + del_timer(&dev->timer); +errorEP: + usb_put_dev(dev->udev); +errorUDEV: + kfree(dev->fw_data); + mutex_destroy(&dev->open_lock); + mutex_destroy(&dev->lock); +errorFWDATA1: + kfree(dev); + printk(KERN_WARNING "Sensoray 2255 driver load failed: 0x%x\n", retval); return retval; } + /* disconnect routine. when board is removed physically or with rmmod */ static void s2255_disconnect(struct usb_interface *interface) { @@ -2816,11 +2778,11 @@ static void s2255_disconnect(struct usb_interface *interface) int i; dprintk(1, "s2255: disconnect interface %p\n", interface); dev = usb_get_intfdata(interface); - - /* - * wake up any of the timers to allow open_lock to be - * acquired sooner - */ + /* unregister each video device. */ + for (i = 0; i < MAX_CHANNELS; i++) + if (video_is_registered(dev->vdev[i])) + video_unregister_device(dev->vdev[i]); + /* wake up any of our timers */ atomic_set(&dev->fw_data->fw_state, S2255_FW_DISCONNECTING); wake_up(&dev->fw_data->wait_fw); for (i = 0; i < MAX_CHANNELS; i++) { @@ -2829,16 +2791,9 @@ static void s2255_disconnect(struct usb_interface *interface) dev->vidstatus_ready[i] = 1; wake_up(&dev->wait_vidstatus[i]); } - - mutex_lock(&dev->open_lock); usb_set_intfdata(interface, NULL); - mutex_unlock(&dev->open_lock); - - if (dev) { - kref_put(&dev->kref, s2255_destroy); - dprintk(1, "s2255drv: disconnect\n"); - dev_info(&interface->dev, "s2255usb now disconnected\n"); - } + kref_put(&dev->kref, s2255_destroy); + dev_info(&interface->dev, "%s\n", __func__); } static struct usb_driver s2255_driver = { @@ -2851,15 +2806,12 @@ static struct usb_driver s2255_driver = { static int __init usb_s2255_init(void) { int result; - /* register this driver with the USB subsystem */ result = usb_register(&s2255_driver); - if (result) pr_err(KBUILD_MODNAME - ": usb_register failed. Error number %d\n", result); - - dprintk(2, "s2255_init: done\n"); + ": usb_register failed. Error number %d\n", result); + dprintk(2, "%s\n", __func__); return result; } -- cgit v1.2.3-70-g09d2 From ab85c6a33c7168cc42ce12ac3335c2f12d5a8d22 Mon Sep 17 00:00:00 2001 From: Dean Anderson Date: Thu, 8 Apr 2010 23:39:12 -0300 Subject: V4L/DVB: s2255drv: code cleanup removal of unused pipe array (of size one). Signed-off-by: Dean Anderson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s2255drv.c | 113 ++++++++++++++++------------------------- 1 file changed, 44 insertions(+), 69 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index 1d8c6b4364d..91f7e9538f6 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c @@ -85,7 +85,6 @@ #define S2255_RESPONSE_STATUS cpu_to_le32(0x20) #define S2255_USB_XFER_SIZE (16 * 1024) #define MAX_CHANNELS 4 -#define MAX_PIPE_BUFFERS 1 #define SYS_FRAMES 4 /* maximum size is PAL full size plus room for the marker header(s) */ #define SYS_FRAMES_MAXSIZE (720*288*2*2 + 4096) @@ -237,8 +236,8 @@ struct s2255_dev { struct video_device *vdev[MAX_CHANNELS]; struct timer_list timer; struct s2255_fw *fw_data; - struct s2255_pipeinfo pipes[MAX_PIPE_BUFFERS]; - struct s2255_bufferi buffer[MAX_CHANNELS]; + struct s2255_pipeinfo pipe; + struct s2255_bufferi buffer[MAX_CHANNELS]; struct s2255_mode mode[MAX_CHANNELS]; /* jpeg compression */ struct v4l2_jpegcompression jc[MAX_CHANNELS]; @@ -2334,25 +2333,21 @@ static int s2255_release_sys_buffers(struct s2255_dev *dev, static int s2255_board_init(struct s2255_dev *dev) { - int j; struct s2255_mode mode_def = DEF_MODEI_NTSC_CONT; int fw_ver; + int j; + struct s2255_pipeinfo *pipe = &dev->pipe; dprintk(4, "board init: %p", dev); - - for (j = 0; j < MAX_PIPE_BUFFERS; j++) { - struct s2255_pipeinfo *pipe = &dev->pipes[j]; - - memset(pipe, 0, sizeof(*pipe)); - pipe->dev = dev; - pipe->cur_transfer_size = S2255_USB_XFER_SIZE; - pipe->max_transfer_size = S2255_USB_XFER_SIZE; - - pipe->transfer_buffer = kzalloc(pipe->max_transfer_size, - GFP_KERNEL); - if (pipe->transfer_buffer == NULL) { - dprintk(1, "out of memory!\n"); - return -ENOMEM; - } + memset(pipe, 0, sizeof(*pipe)); + pipe->dev = dev; + pipe->cur_transfer_size = S2255_USB_XFER_SIZE; + pipe->max_transfer_size = S2255_USB_XFER_SIZE; + + pipe->transfer_buffer = kzalloc(pipe->max_transfer_size, + GFP_KERNEL); + if (pipe->transfer_buffer == NULL) { + dprintk(1, "out of memory!\n"); + return -ENOMEM; } /* query the firmware */ fw_ver = s2255_get_fx2fw(dev); @@ -2401,12 +2396,8 @@ static int s2255_board_shutdown(struct s2255_dev *dev) for (i = 0; i < MAX_CHANNELS; i++) s2255_release_sys_buffers(dev, i); - - /* release transfer buffers */ - for (i = 0; i < MAX_PIPE_BUFFERS; i++) { - struct s2255_pipeinfo *pipe = &dev->pipes[i]; - kfree(pipe->transfer_buffer); - } + /* release transfer buffer */ + kfree(dev->pipe.transfer_buffer); return 0; } @@ -2472,35 +2463,30 @@ static int s2255_start_readpipe(struct s2255_dev *dev) { int pipe; int retval; - int i; - struct s2255_pipeinfo *pipe_info = dev->pipes; + struct s2255_pipeinfo *pipe_info = &dev->pipe; pipe = usb_rcvbulkpipe(dev->udev, dev->read_endpoint); dprintk(2, "start pipe IN %d\n", dev->read_endpoint); - - for (i = 0; i < MAX_PIPE_BUFFERS; i++) { - pipe_info->state = 1; - pipe_info->err_count = 0; - pipe_info->stream_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!pipe_info->stream_urb) { - dev_err(&dev->udev->dev, - "ReadStream: Unable to alloc URB\n"); - return -ENOMEM; - } - /* transfer buffer allocated in board_init */ - usb_fill_bulk_urb(pipe_info->stream_urb, dev->udev, - pipe, - pipe_info->transfer_buffer, - pipe_info->cur_transfer_size, - read_pipe_completion, pipe_info); - - dprintk(4, "submitting URB %p\n", pipe_info->stream_urb); - retval = usb_submit_urb(pipe_info->stream_urb, GFP_KERNEL); - if (retval) { - printk(KERN_ERR "s2255: start read pipe failed\n"); - return retval; - } + pipe_info->state = 1; + pipe_info->err_count = 0; + pipe_info->stream_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!pipe_info->stream_urb) { + dev_err(&dev->udev->dev, + "ReadStream: Unable to alloc URB\n"); + return -ENOMEM; } + /* transfer buffer allocated in board_init */ + usb_fill_bulk_urb(pipe_info->stream_urb, dev->udev, + pipe, + pipe_info->transfer_buffer, + pipe_info->cur_transfer_size, + read_pipe_completion, pipe_info); + dprintk(4, "submitting URB %p\n", pipe_info->stream_urb); + retval = usb_submit_urb(pipe_info->stream_urb, GFP_KERNEL); + if (retval) { + printk(KERN_ERR "s2255: start read pipe failed\n"); + return retval; + } return 0; } @@ -2581,30 +2567,19 @@ static int s2255_stop_acquire(struct s2255_dev *dev, unsigned long chn) static void s2255_stop_readpipe(struct s2255_dev *dev) { - int j; + struct s2255_pipeinfo *pipe = &dev->pipe; if (dev == NULL) { s2255_dev_err(&dev->udev->dev, "invalid device\n"); return; } - dprintk(4, "stop read pipe\n"); - for (j = 0; j < MAX_PIPE_BUFFERS; j++) { - struct s2255_pipeinfo *pipe_info = &dev->pipes[j]; - if (pipe_info) { - if (pipe_info->state == 0) - continue; - pipe_info->state = 0; - } - } - for (j = 0; j < MAX_PIPE_BUFFERS; j++) { - struct s2255_pipeinfo *pipe_info = &dev->pipes[j]; - if (pipe_info->stream_urb) { - /* cancel urb */ - usb_kill_urb(pipe_info->stream_urb); - usb_free_urb(pipe_info->stream_urb); - pipe_info->stream_urb = NULL; - } + pipe->state = 0; + if (pipe->stream_urb) { + /* cancel urb */ + usb_kill_urb(pipe->stream_urb); + usb_free_urb(pipe->stream_urb); + pipe->stream_urb = NULL; } - dprintk(2, "s2255 stop read pipe: %d\n", j); + dprintk(4, "%s", __func__); return; } -- cgit v1.2.3-70-g09d2 From c0a2ec956d6e61081b6f98b839b0e28979941687 Mon Sep 17 00:00:00 2001 From: Dean Anderson Date: Thu, 8 Apr 2010 23:40:31 -0300 Subject: V4L/DVB: s2255drv: video_device_alloc call not checked fix call to video_device_alloc was not being checked in probe function. code simplified and uses video_device inside device structure. Signed-off-by: Dean Anderson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s2255drv.c | 42 ++++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 22 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index 91f7e9538f6..4c5d3672e2d 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c @@ -224,6 +224,7 @@ struct s2255_pipeinfo { struct s2255_fmt; /*forward declaration */ struct s2255_dev { + struct video_device vdev[MAX_CHANNELS]; int frames; struct mutex lock; struct mutex open_lock; @@ -233,7 +234,6 @@ struct s2255_dev { u8 read_endpoint; struct s2255_dmaqueue vidq[MAX_CHANNELS]; - struct video_device *vdev[MAX_CHANNELS]; struct timer_list timer; struct s2255_fw *fw_data; struct s2255_pipeinfo pipe; @@ -719,10 +719,10 @@ static int buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, if (fh->fmt == NULL) return -EINVAL; - if ((fh->width < norm_minw(fh->dev->vdev[fh->channel])) || - (fh->width > norm_maxw(fh->dev->vdev[fh->channel])) || - (fh->height < norm_minh(fh->dev->vdev[fh->channel])) || - (fh->height > norm_maxh(fh->dev->vdev[fh->channel]))) { + if ((fh->width < norm_minw(&fh->dev->vdev[fh->channel])) || + (fh->width > norm_maxw(&fh->dev->vdev[fh->channel])) || + (fh->height < norm_minh(&fh->dev->vdev[fh->channel])) || + (fh->height > norm_maxh(&fh->dev->vdev[fh->channel]))) { dprintk(4, "invalid buffer prepare\n"); return -EINVAL; } @@ -896,7 +896,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, int is_ntsc; is_ntsc = - (dev->vdev[fh->channel]->current_norm & V4L2_STD_NTSC) ? 1 : 0; + (dev->vdev[fh->channel].current_norm & V4L2_STD_NTSC) ? 1 : 0; fmt = format_by_fourcc(f->fmt.pix.pixelformat); @@ -1029,9 +1029,9 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, fh->height = f->fmt.pix.height; fh->vb_vidq.field = f->fmt.pix.field; fh->type = f->type; - norm = norm_minw(fh->dev->vdev[fh->channel]); - if (fh->width > norm_minw(fh->dev->vdev[fh->channel])) { - if (fh->height > norm_minh(fh->dev->vdev[fh->channel])) { + norm = norm_minw(&fh->dev->vdev[fh->channel]); + if (fh->width > norm_minw(&fh->dev->vdev[fh->channel])) { + if (fh->height > norm_minh(&fh->dev->vdev[fh->channel])) { if (fh->dev->cap_parm[fh->channel].capturemode & V4L2_MODE_HIGHQUALITY) { fh->mode.scale = SCALE_4CIFSI; @@ -1755,7 +1755,7 @@ static int s2255_open(struct file *file) video_device_node_name(vdev)); lock_kernel(); for (i = 0; i < MAX_CHANNELS; i++) - if (dev->vdev[i] == vdev) { + if (&dev->vdev[i] == vdev) { cur_channel = i; break; } @@ -1985,7 +1985,6 @@ static const struct v4l2_ioctl_ops s2255_ioctl_ops = { static void s2255_video_device_release(struct video_device *vdev) { struct s2255_dev *dev = video_get_drvdata(vdev); - video_device_release(vdev); kref_put(&dev->kref, s2255_destroy); return; } @@ -2012,19 +2011,18 @@ static int s2255_probe_v4l(struct s2255_dev *dev) dev->vidq[i].dev = dev; dev->vidq[i].channel = i; /* register 4 video devices */ - dev->vdev[i] = video_device_alloc(); - memcpy(dev->vdev[i], &template, sizeof(struct video_device)); - dev->vdev[i]->parent = &dev->interface->dev; - video_set_drvdata(dev->vdev[i], dev); + memcpy(&dev->vdev[i], &template, sizeof(struct video_device)); + dev->vdev[i].parent = &dev->interface->dev; + video_set_drvdata(&dev->vdev[i], dev); if (video_nr == -1) - ret = video_register_device(dev->vdev[i], + ret = video_register_device(&dev->vdev[i], VFL_TYPE_GRABBER, video_nr); else - ret = video_register_device(dev->vdev[i], + ret = video_register_device(&dev->vdev[i], VFL_TYPE_GRABBER, cur_nr + i); - video_set_drvdata(dev->vdev[i], dev); + video_set_drvdata(&dev->vdev[i], dev); if (ret != 0) { dev_err(&dev->udev->dev, @@ -2721,8 +2719,8 @@ static int s2255_probe(struct usb_interface *interface, return 0; errorV4L: for (i = 0; i < MAX_CHANNELS; i++) - if (dev->vdev[i] && video_is_registered(dev->vdev[i])) - video_unregister_device(dev->vdev[i]); + if (video_is_registered(&dev->vdev[i])) + video_unregister_device(&dev->vdev[i]); errorBOARDINIT: s2255_board_shutdown(dev); errorFWMARKER: @@ -2755,8 +2753,8 @@ static void s2255_disconnect(struct usb_interface *interface) dev = usb_get_intfdata(interface); /* unregister each video device. */ for (i = 0; i < MAX_CHANNELS; i++) - if (video_is_registered(dev->vdev[i])) - video_unregister_device(dev->vdev[i]); + if (video_is_registered(&dev->vdev[i])) + video_unregister_device(&dev->vdev[i]); /* wake up any of our timers */ atomic_set(&dev->fw_data->fw_state, S2255_FW_DISCONNECTING); wake_up(&dev->fw_data->wait_fw); -- cgit v1.2.3-70-g09d2 From a5ef91c9a55c89e8c57e628d371107cdfe2d0bd9 Mon Sep 17 00:00:00 2001 From: Dean Anderson Date: Thu, 8 Apr 2010 23:46:08 -0300 Subject: V4L/DVB: s2255drv: removal of big kernel lock big kernel lock removed from open function. v4l2 code does not require locking the open function except to check asynchronous firmware load state, which is protected by a mutex Signed-off-by: Dean Anderson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s2255drv.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index 4c5d3672e2d..83ee93d4ad1 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c @@ -1753,7 +1753,6 @@ static int s2255_open(struct file *file) int state; dprintk(1, "s2255: open called (dev=%s)\n", video_device_node_name(vdev)); - lock_kernel(); for (i = 0; i < MAX_CHANNELS; i++) if (&dev->vdev[i] == vdev) { cur_channel = i; @@ -1769,7 +1768,6 @@ static int s2255_open(struct file *file) switch (state) { case S2255_FW_DISCONNECTING: mutex_unlock(&dev->open_lock); - unlock_kernel(); return -ENODEV; case S2255_FW_FAILED: s2255_dev_err(&dev->udev->dev, @@ -1809,30 +1807,24 @@ static int s2255_open(struct file *file) break; case S2255_FW_FAILED: printk(KERN_INFO "2255 firmware load failed.\n"); - unlock_kernel(); return -ENODEV; case S2255_FW_DISCONNECTING: printk(KERN_INFO "%s: disconnecting\n", __func__); - unlock_kernel(); return -ENODEV; case S2255_FW_LOADED_DSPWAIT: case S2255_FW_NOTLOADED: printk(KERN_INFO "%s: firmware not loaded yet" "please try again later\n", __func__); - unlock_kernel(); return -EAGAIN; default: printk(KERN_INFO "%s: unknown state\n", __func__); - unlock_kernel(); return -EFAULT; } /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) { - unlock_kernel(); + if (NULL == fh) return -ENOMEM; - } file->private_data = fh; fh->dev = dev; fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; @@ -1860,7 +1852,6 @@ static int s2255_open(struct file *file) fh->type, V4L2_FIELD_INTERLACED, sizeof(struct s2255_buffer), fh); - unlock_kernel(); return 0; } -- cgit v1.2.3-70-g09d2 From 85b85482c243398839564d5f95d75f479bed591c Mon Sep 17 00:00:00 2001 From: Dean Anderson Date: Thu, 8 Apr 2010 23:51:17 -0300 Subject: V4L/DVB: s2255drv: cleanup of debug messages Signed-off-by: Dean Anderson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s2255drv.c | 153 +++++++++++------------------------------ 1 file changed, 42 insertions(+), 111 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index 83ee93d4ad1..aba7a72f355 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c @@ -56,10 +56,14 @@ #include #include +#define S2255_MAJOR_VERSION 1 +#define S2255_MINOR_VERSION 19 +#define S2255_RELEASE 0 +#define S2255_VERSION KERNEL_VERSION(S2255_MAJOR_VERSION, \ + S2255_MINOR_VERSION, \ + S2255_RELEASE) #define FIRMWARE_FILE_NAME "f2255usb.bin" - - /* default JPEG quality */ #define S2255_DEF_JPEG_QUAL 50 /* vendor request in */ @@ -308,13 +312,6 @@ struct s2255_fh { /* Need DSP version 5+ for video status feature */ #define S2255_MIN_DSP_STATUS 5 #define S2255_MIN_DSP_COLORFILTER 8 -#define S2255_MAJOR_VERSION 1 -#define S2255_MINOR_VERSION 18 -#define S2255_RELEASE 0 -#define S2255_VERSION KERNEL_VERSION(S2255_MAJOR_VERSION, \ - S2255_MINOR_VERSION, \ - S2255_RELEASE) - #define S2255_NORMS (V4L2_STD_PAL | V4L2_STD_NTSC) /* private V4L2 controls */ @@ -501,7 +498,7 @@ static void s2255_reset_dsppower(struct s2255_dev *dev) static void s2255_timer(unsigned long user_data) { struct s2255_fw *data = (struct s2255_fw *)user_data; - dprintk(100, "s2255 timer\n"); + dprintk(100, "%s\n", __func__); if (usb_submit_urb(data->fw_urb, GFP_ATOMIC) < 0) { printk(KERN_ERR "s2255: can't submit urb\n"); atomic_set(&data->fw_state, S2255_FW_FAILED); @@ -523,7 +520,7 @@ static void s2255_fwchunk_complete(struct urb *urb) struct s2255_fw *data = urb->context; struct usb_device *udev = urb->dev; int len; - dprintk(100, "udev %p urb %p", udev, urb); + dprintk(100, "%s: udev %p urb %p", __func__, udev, urb); if (urb->status) { dev_err(&udev->dev, "URB failed with status %d\n", urb->status); atomic_set(&data->fw_state, S2255_FW_FAILED); @@ -569,8 +566,8 @@ static void s2255_fwchunk_complete(struct urb *urb) data->fw_loaded += len; } else { atomic_set(&data->fw_state, S2255_FW_LOADED_DSPWAIT); + dprintk(100, "%s: firmware upload complete\n", __func__); } - dprintk(100, "2255 complete done\n"); return; } @@ -581,9 +578,7 @@ static int s2255_got_frame(struct s2255_dev *dev, int chn, int jpgsize) struct s2255_buffer *buf; unsigned long flags = 0; int rc = 0; - dprintk(2, "wakeup: %p channel: %d\n", &dma_q, chn); spin_lock_irqsave(&dev->slock, flags); - if (list_empty(&dma_q->active)) { dprintk(1, "No active queue to serve\n"); rc = -1; @@ -591,13 +586,11 @@ static int s2255_got_frame(struct s2255_dev *dev, int chn, int jpgsize) } buf = list_entry(dma_q->active.next, struct s2255_buffer, vb.queue); - list_del(&buf->vb.queue); do_gettimeofday(&buf->vb.ts); - dprintk(100, "[%p/%d] wakeup\n", buf, buf->vb.i); s2255_fillbuff(dev, buf, dma_q->channel, jpgsize); wake_up(&buf->vb.done); - dprintk(2, "wakeup [buf/i] [%p/%d]\n", buf, buf->vb.i); + dprintk(2, "%s: [buf/i] [%p/%d]\n", __func__, buf, buf->vb.i); unlock: spin_unlock_irqrestore(&dev->slock, flags); return 0; @@ -606,7 +599,6 @@ unlock: static const struct s2255_fmt *format_by_fourcc(int fourcc) { unsigned int i; - for (i = 0; i < ARRAY_SIZE(formats); i++) { if (-1 == formats[i].fourcc) continue; @@ -739,7 +731,6 @@ static int buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, buf->vb.height = fh->height; buf->vb.field = field; - if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { rc = videobuf_iolock(vq, &buf->vb, NULL); if (rc < 0) @@ -759,9 +750,7 @@ static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) struct s2255_fh *fh = vq->priv_data; struct s2255_dev *dev = fh->dev; struct s2255_dmaqueue *vidq = &dev->vidq[fh->channel]; - dprintk(1, "%s\n", __func__); - buf->vb.state = VIDEOBUF_QUEUED; list_add_tail(&buf->vb.queue, &vidq->active); } @@ -907,10 +896,8 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, if (field == V4L2_FIELD_ANY) b_any_field = 1; - dprintk(4, "try format %d \n", is_ntsc); - /* supports 3 sizes. see s2255drv.h */ - dprintk(50, "width test %d, height %d\n", - f->fmt.pix.width, f->fmt.pix.height); + dprintk(50, "%s NTSC: %d suggested width: %d, height: %d\n", + __func__, is_ntsc, f->fmt.pix.width, f->fmt.pix.height); if (is_ntsc) { /* NTSC */ if (f->fmt.pix.height >= NUM_LINES_1CIFS_NTSC * 2) { @@ -965,29 +952,24 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, } } if (f->fmt.pix.width >= LINE_SZ_4CIFS_PAL) { - dprintk(50, "pal 704\n"); f->fmt.pix.width = LINE_SZ_4CIFS_PAL; field = V4L2_FIELD_SEQ_TB; } else if (f->fmt.pix.width >= LINE_SZ_2CIFS_PAL) { - dprintk(50, "pal 352A\n"); f->fmt.pix.width = LINE_SZ_2CIFS_PAL; field = V4L2_FIELD_TOP; } else if (f->fmt.pix.width >= LINE_SZ_1CIFS_PAL) { - dprintk(50, "pal 352B\n"); f->fmt.pix.width = LINE_SZ_1CIFS_PAL; field = V4L2_FIELD_TOP; } else { - dprintk(50, "pal 352C\n"); f->fmt.pix.width = LINE_SZ_1CIFS_PAL; field = V4L2_FIELD_TOP; } } - - dprintk(50, "width %d height %d field %d \n", f->fmt.pix.width, - f->fmt.pix.height, f->fmt.pix.field); f->fmt.pix.field = field; f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3; f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; + dprintk(50, "%s: set width %d height %d field %d\n", __func__, + f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field); return 0; } @@ -1019,7 +1001,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, } if (res_locked(fh->dev, fh)) { - dprintk(1, "can't change format after started\n"); + dprintk(1, "%s: channel busy\n", __func__); ret = -EBUSY; goto out_s_fmt; } @@ -1033,13 +1015,10 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, if (fh->width > norm_minw(&fh->dev->vdev[fh->channel])) { if (fh->height > norm_minh(&fh->dev->vdev[fh->channel])) { if (fh->dev->cap_parm[fh->channel].capturemode & - V4L2_MODE_HIGHQUALITY) { + V4L2_MODE_HIGHQUALITY) fh->mode.scale = SCALE_4CIFSI; - dprintk(2, "scale 4CIFSI\n"); - } else { + else fh->mode.scale = SCALE_4CIFS; - dprintk(2, "scale 4CIFS\n"); - } } else fh->mode.scale = SCALE_2CIFS; @@ -1195,19 +1174,13 @@ static u32 get_transfer_size(struct s2255_mode *mode) return usbInSize; } -static void dump_verify_mode(struct s2255_dev *sdev, struct s2255_mode *mode) +static void s2255_print_cfg(struct s2255_dev *sdev, struct s2255_mode *mode) { struct device *dev = &sdev->udev->dev; dev_info(dev, "------------------------------------------------\n"); - dev_info(dev, "verify mode\n"); - dev_info(dev, "format: %d\n", mode->format); - dev_info(dev, "scale: %d\n", mode->scale); - dev_info(dev, "fdec: %d\n", mode->fdec); - dev_info(dev, "color: %d\n", mode->color); + dev_info(dev, "format: %d\nscale %d\n", mode->format, mode->scale); + dev_info(dev, "fdec: %d\ncolor %d\n", mode->fdec, mode->color); dev_info(dev, "bright: 0x%x\n", mode->bright); - dev_info(dev, "restart: 0x%x\n", mode->restart); - dev_info(dev, "usb_block: 0x%x\n", mode->usb_block); - dev_info(dev, "single: 0x%x\n", mode->single); dev_info(dev, "------------------------------------------------\n"); } @@ -1227,11 +1200,7 @@ static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn, unsigned long chn_rev; mutex_lock(&dev->lock); chn_rev = G_chnmap[chn]; - dprintk(3, "mode scale [%ld] %p %d\n", chn, mode, mode->scale); - dprintk(3, "mode scale [%ld] %p %d\n", chn, &dev->mode[chn], - dev->mode[chn].scale); - dprintk(2, "mode contrast %x\n", mode->contrast); - + dprintk(3, "%s channel %lu\n", __func__, chn); /* if JPEG, set the quality */ if ((mode->color & MASK_COLOR) == COLOR_JPG) { mode->color &= ~MASK_COLOR; @@ -1239,19 +1208,16 @@ static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn, mode->color &= ~MASK_JPG_QUALITY; mode->color |= (dev->jc[chn].quality << 8); } - /* save the mode */ dev->mode[chn] = *mode; dev->req_image_size[chn] = get_transfer_size(mode); - dprintk(1, "transfer size %ld\n", dev->req_image_size[chn]); - + dprintk(1, "%s: reqsize %ld\n", __func__, dev->req_image_size[chn]); buffer = kzalloc(512, GFP_KERNEL); if (buffer == NULL) { dev_err(&dev->udev->dev, "out of mem\n"); mutex_unlock(&dev->lock); return -ENOMEM; } - /* set the mode */ buffer[0] = IN_DATA_TOKEN; buffer[1] = (__le32) cpu_to_le32(chn_rev); @@ -1260,10 +1226,8 @@ static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn, dev->setmode_ready[chn] = 0; res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512); if (debug) - dump_verify_mode(dev, mode); + s2255_print_cfg(dev, mode); kfree(buffer); - dprintk(1, "set mode done chn %lu, %d\n", chn, res); - /* wait at least 3 frames before continuing */ if (mode->restart) { wait_event_timeout(dev->wait_setmode[chn], @@ -1274,10 +1238,10 @@ static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn, res = -EFAULT; } } - /* clear the restart flag */ dev->mode[chn].restart = 0; mutex_unlock(&dev->lock); + dprintk(1, "%s chn %lu, result: %d\n", __func__, chn, res); return res; } @@ -1289,7 +1253,7 @@ static int s2255_cmd_status(struct s2255_dev *dev, unsigned long chn, u32 chn_rev; mutex_lock(&dev->lock); chn_rev = G_chnmap[chn]; - dprintk(4, "%s chan %d\n", __func__, chn_rev); + dprintk(4, "%s chan %lu\n", __func__, chn); buffer = kzalloc(512, GFP_KERNEL); if (buffer == NULL) { dev_err(&dev->udev->dev, "out of mem\n"); @@ -1358,7 +1322,6 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) new_mode->restart = 0; *old_mode = *new_mode; dev->cur_fmt[chn] = fh->fmt; - dprintk(1, "%s[%d]\n", __func__, chn); dev->last_frame[chn] = -1; dev->bad_payload[chn] = 0; dev->cur_frame[chn] = 0; @@ -1381,7 +1344,6 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) { struct s2255_fh *fh = priv; struct s2255_dev *dev = fh->dev; - dprintk(4, "%s\n, channel: %d", __func__, fh->channel); if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { printk(KERN_ERR "invalid fh type0\n"); @@ -1403,15 +1365,12 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i) struct s2255_mode *mode; struct videobuf_queue *q = &fh->vb_vidq; int ret = 0; - mutex_lock(&q->vb_lock); - if (videobuf_queue_is_busy(q)) { dprintk(1, "queue busy\n"); ret = -EBUSY; goto out_s_std; } - if (res_locked(fh->dev, fh)) { dprintk(1, "can't change standard after started\n"); ret = -EBUSY; @@ -1453,10 +1412,8 @@ static int vidioc_enum_input(struct file *file, void *priv, struct s2255_fh *fh = priv; struct s2255_dev *dev = fh->dev; u32 status = 0; - if (inp->index != 0) return -EINVAL; - inp->type = V4L2_INPUT_TYPE_CAMERA; inp->std = S2255_NORMS; inp->status = 0; @@ -1612,7 +1569,7 @@ static int vidioc_g_jpegcomp(struct file *file, void *priv, struct s2255_fh *fh = priv; struct s2255_dev *dev = fh->dev; *jc = dev->jc[fh->channel]; - dprintk(2, "getting jpegcompression, quality %d\n", jc->quality); + dprintk(2, "%s: quality %d\n", __func__, jc->quality); return 0; } @@ -1624,7 +1581,7 @@ static int vidioc_s_jpegcomp(struct file *file, void *priv, if (jc->quality < 0 || jc->quality > 100) return -EINVAL; dev->jc[fh->channel].quality = jc->quality; - dprintk(2, "setting jpeg quality %d\n", jc->quality); + dprintk(2, "%s: quality %d\n", __func__, jc->quality); return 0; } @@ -1839,14 +1796,13 @@ static int s2255_open(struct file *file) s2255_set_mode(dev, cur_channel, &fh->mode); dev->chn_configured[cur_channel] = 1; } - dprintk(1, "s2255drv: open dev=%s type=%s\n", + dprintk(1, "%s: dev=%s type=%s\n", __func__, video_device_node_name(vdev), v4l2_type_names[type]); - dprintk(2, "s2255drv: open: fh=0x%08lx, dev=0x%08lx, vidq=0x%08lx\n", + dprintk(2, "%s: fh=0x%08lx, dev=0x%08lx, vidq=0x%08lx\n", __func__, (unsigned long)fh, (unsigned long)dev, (unsigned long)&dev->vidq[cur_channel]); - dprintk(4, "s2255drv: open: list_empty active=%d\n", + dprintk(4, "%s: list_empty active=%d\n", __func__, list_empty(&dev->vidq[cur_channel].active)); - videobuf_queue_vmalloc_init(&fh->vb_vidq, &s2255_video_qops, NULL, &dev->slock, fh->type, @@ -1862,10 +1818,8 @@ static unsigned int s2255_poll(struct file *file, struct s2255_fh *fh = file->private_data; int rc; dprintk(100, "%s\n", __func__); - if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type) return POLLERR; - rc = videobuf_poll_stream(file, &fh->vb_vidq, wait); return rc; } @@ -1878,7 +1832,6 @@ static void s2255_destroy(struct kref *kref) /* make sure firmware still not trying to load */ del_timer(&dev->timer); /* only started in .probe and .open */ if (dev->fw_data->fw_urb) { - dprintk(2, "kill fw_urb\n"); usb_kill_urb(dev->fw_data->fw_urb); usb_free_urb(dev->fw_data->fw_urb); dev->fw_data->fw_urb = NULL; @@ -1923,14 +1876,11 @@ static int s2255_mmap_v4l(struct file *file, struct vm_area_struct *vma) if (!fh) return -ENODEV; - dprintk(4, "mmap called, vma=0x%08lx\n", (unsigned long)vma); - + dprintk(4, "%s, vma=0x%08lx\n", __func__, (unsigned long)vma); ret = videobuf_mmap_mapper(&fh->vb_vidq, vma); - - dprintk(4, "vma start=0x%08lx, size=%ld, ret=%d\n", + dprintk(4, "%s vma start=0x%08lx, size=%ld, ret=%d\n", __func__, (unsigned long)vma->vm_start, (unsigned long)vma->vm_end - (unsigned long)vma->vm_start, ret); - return ret; } @@ -2004,7 +1954,6 @@ static int s2255_probe_v4l(struct s2255_dev *dev) /* register 4 video devices */ memcpy(&dev->vdev[i], &template, sizeof(struct video_device)); dev->vdev[i].parent = &dev->interface->dev; - video_set_drvdata(&dev->vdev[i], dev); if (video_nr == -1) ret = video_register_device(&dev->vdev[i], VFL_TYPE_GRABBER, @@ -2366,15 +2315,14 @@ static int s2255_board_init(struct s2255_dev *dev) } /* start read pipe */ s2255_start_readpipe(dev); - - dprintk(1, "S2255: board initialized\n"); + dprintk(1, "%s: success\n", __func__); return 0; } static int s2255_board_shutdown(struct s2255_dev *dev) { u32 i; - dprintk(1, "S2255: board shutdown: %p", dev); + dprintk(1, "%s: dev: %p", __func__, dev); for (i = 0; i < MAX_CHANNELS; i++) { if (dev->b_acquire[i]) @@ -2396,9 +2344,8 @@ static void read_pipe_completion(struct urb *purb) struct s2255_dev *dev; int status; int pipe; - pipe_info = purb->context; - dprintk(100, "read pipe completion %p, status %d\n", purb, + dprintk(100, "%s: urb:%p, status %d\n", __func__, purb, purb->status); if (pipe_info == NULL) { dev_err(&purb->dev->dev, "no context!\n"); @@ -2413,13 +2360,13 @@ static void read_pipe_completion(struct urb *purb) status = purb->status; /* if shutting down, do not resubmit, exit immediately */ if (status == -ESHUTDOWN) { - dprintk(2, "read_pipe_completion: err shutdown\n"); + dprintk(2, "%s: err shutdown\n", __func__); pipe_info->err_count++; return; } if (pipe_info->state == 0) { - dprintk(2, "exiting USB pipe"); + dprintk(2, "%s: exiting USB pipe", __func__); return; } @@ -2427,7 +2374,7 @@ static void read_pipe_completion(struct urb *purb) s2255_read_video_callback(dev, pipe_info); else { pipe_info->err_count++; - dprintk(1, "s2255drv: failed URB %d\n", status); + dprintk(1, "%s: failed URB %d\n", __func__, status); } pipe = usb_rcvbulkpipe(dev->udev, dev->read_endpoint); @@ -2443,7 +2390,7 @@ static void read_pipe_completion(struct urb *purb) dev_err(&dev->udev->dev, "error submitting urb\n"); } } else { - dprintk(2, "read pipe complete state 0\n"); + dprintk(2, "%s :complete state 0\n", __func__); } return; } @@ -2454,7 +2401,7 @@ static int s2255_start_readpipe(struct s2255_dev *dev) int retval; struct s2255_pipeinfo *pipe_info = &dev->pipe; pipe = usb_rcvbulkpipe(dev->udev, dev->read_endpoint); - dprintk(2, "start pipe IN %d\n", dev->read_endpoint); + dprintk(2, "%s: IN %d\n", __func__, dev->read_endpoint); pipe_info->state = 1; pipe_info->err_count = 0; pipe_info->stream_urb = usb_alloc_urb(0, GFP_KERNEL); @@ -2469,8 +2416,6 @@ static int s2255_start_readpipe(struct s2255_dev *dev) pipe_info->transfer_buffer, pipe_info->cur_transfer_size, read_pipe_completion, pipe_info); - - dprintk(4, "submitting URB %p\n", pipe_info->stream_urb); retval = usb_submit_urb(pipe_info->stream_urb, GFP_KERNEL); if (retval) { printk(KERN_ERR "s2255: start read pipe failed\n"); @@ -2490,10 +2435,7 @@ static int s2255_start_acquire(struct s2255_dev *dev, unsigned long chn) dprintk(2, "start acquire failed, bad channel %lu\n", chn); return -1; } - chn_rev = G_chnmap[chn]; - dprintk(1, "S2255: start acquire %lu \n", chn); - buffer = kzalloc(512, GFP_KERNEL); if (buffer == NULL) { dev_err(&dev->udev->dev, "out of mem\n"); @@ -2537,20 +2479,15 @@ static int s2255_stop_acquire(struct s2255_dev *dev, unsigned long chn) return -ENOMEM; } /* send the stop command */ - dprintk(4, "stop acquire %lu\n", chn); *(__le32 *) buffer = IN_DATA_TOKEN; *((__le32 *) buffer + 1) = (__le32) cpu_to_le32(chn_rev); *((__le32 *) buffer + 2) = CMD_STOP; res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512); - if (res != 0) dev_err(&dev->udev->dev, "CMD_STOP error\n"); - - dprintk(4, "stop acquire: releasing states \n"); - kfree(buffer); dev->b_acquire[chn] = 0; - + dprintk(4, "%s: chn %lu, res %d\n", __func__, chn, res); return res; } @@ -2600,9 +2537,7 @@ static int s2255_probe(struct usb_interface *interface, int retval = -ENOMEM; __le32 *pdata; int fw_size; - - dprintk(2, "s2255: probe\n"); - + dprintk(2, "%s\n", __func__); /* allocate memory for our device state and initialize it to zero */ dev = kzalloc(sizeof(struct s2255_dev), GFP_KERNEL); if (dev == NULL) { @@ -2643,11 +2578,9 @@ static int s2255_probe(struct usb_interface *interface, } /* set intfdata */ usb_set_intfdata(interface, dev); - dprintk(100, "after intfdata %p\n", dev); init_timer(&dev->timer); dev->timer.function = s2255_timer; dev->timer.data = (unsigned long)dev->fw_data; - init_waitqueue_head(&dev->fw_data->wait_fw); for (i = 0; i < MAX_CHANNELS; i++) { init_waitqueue_head(&dev->wait_setmode[i]); @@ -2696,7 +2629,6 @@ static int s2255_probe(struct usb_interface *interface, retval = s2255_board_init(dev); if (retval) goto errorBOARDINIT; - dprintk(4, "before probe done %p\n", dev); spin_lock_init(&dev->slock); s2255_fwload_start(dev, 0); /* kref for each vdev. Released on video_device_release callback */ @@ -2740,7 +2672,6 @@ static void s2255_disconnect(struct usb_interface *interface) { struct s2255_dev *dev = NULL; int i; - dprintk(1, "s2255: disconnect interface %p\n", interface); dev = usb_get_intfdata(interface); /* unregister each video device. */ for (i = 0; i < MAX_CHANNELS; i++) -- cgit v1.2.3-70-g09d2 From 3a67b5cc6f6ae37500b8f41fd52628395f7276a8 Mon Sep 17 00:00:00 2001 From: Dean Anderson Date: Thu, 8 Apr 2010 23:52:20 -0300 Subject: V4L/DVB: s2255drv: adding v4l2_device structure. video_register_device cleanup adding v4l2_device structure. if one video_register_device call fails, allows use of other devices or channels. Signed-off-by: Dean Anderson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s2255drv.c | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index aba7a72f355..e1de2c4940b 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c @@ -52,6 +52,7 @@ #include #include #include +#include #include #include #include @@ -81,7 +82,6 @@ #define S2255_DEF_BUFS 16 #define S2255_SETMODE_TIMEOUT 500 #define S2255_VIDSTATUS_TIMEOUT 350 -#define MAX_CHANNELS 4 #define S2255_MARKER_FRAME cpu_to_le32(0x2255DA4AL) #define S2255_MARKER_RESPONSE cpu_to_le32(0x2255ACACL) #define S2255_RESPONSE_SETMODE cpu_to_le32(0x01) @@ -229,6 +229,8 @@ struct s2255_fmt; /*forward declaration */ struct s2255_dev { struct video_device vdev[MAX_CHANNELS]; + struct v4l2_device v4l2_dev[MAX_CHANNELS]; + int channels; /* number of channels registered */ int frames; struct mutex lock; struct mutex open_lock; @@ -1710,7 +1712,8 @@ static int s2255_open(struct file *file) int state; dprintk(1, "s2255: open called (dev=%s)\n", video_device_node_name(vdev)); - for (i = 0; i < MAX_CHANNELS; i++) + + for (i = 0; i < dev->channels; i++) if (&dev->vdev[i] == vdev) { cur_channel = i; break; @@ -1944,7 +1947,11 @@ static int s2255_probe_v4l(struct s2255_dev *dev) int ret; int i; int cur_nr = video_nr; - + for (i = 0; i < MAX_CHANNELS; i++) { + ret = v4l2_device_register(&dev->udev->dev, &dev->v4l2_dev[i]); + if (ret) + goto unreg_v4l2; + } /* initialize all video 4 linux */ /* register 4 video devices */ for (i = 0; i < MAX_CHANNELS; i++) { @@ -1963,16 +1970,29 @@ static int s2255_probe_v4l(struct s2255_dev *dev) VFL_TYPE_GRABBER, cur_nr + i); video_set_drvdata(&dev->vdev[i], dev); - - if (ret != 0) { + if (ret) { dev_err(&dev->udev->dev, "failed to register video device!\n"); - return ret; + break; } + dev->channels++; + v4l2_info(&dev->v4l2_dev[i], "V4L2 device registered as %s\n", + video_device_node_name(&dev->vdev[i])); + } + printk(KERN_INFO "Sensoray 2255 V4L driver Revision: %d.%d\n", S2255_MAJOR_VERSION, S2255_MINOR_VERSION); + /* if no channels registered, return error and probe will fail*/ + if (dev->channels == 0) + return ret; + if (dev->channels != MAX_CHANNELS) + printk(KERN_WARNING "s2255: Not all channels available.\n"); + return 0; +unreg_v4l2: + for (i-- ; i > 0; i--) + v4l2_device_unregister(&dev->v4l2_dev[i]); return ret; } @@ -2637,13 +2657,9 @@ static int s2255_probe(struct usb_interface *interface, /* loads v4l specific */ retval = s2255_probe_v4l(dev); if (retval) - goto errorV4L; + goto errorBOARDINIT; dev_info(&interface->dev, "Sensoray 2255 detected\n"); return 0; -errorV4L: - for (i = 0; i < MAX_CHANNELS; i++) - if (video_is_registered(&dev->vdev[i])) - video_unregister_device(&dev->vdev[i]); errorBOARDINIT: s2255_board_shutdown(dev); errorFWMARKER: -- cgit v1.2.3-70-g09d2 From a9fac6b1487aea9f5aaefe93def522fab477f5dc Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sun, 28 Mar 2010 08:29:35 -0300 Subject: V4L/DVB: video/cx231xx: cleanup. remove unneed null checks "dev" is never NULL here so there is no need to check. Signed-off-by: Dan Carpenter Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx231xx/cx231xx-core.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx231xx/cx231xx-core.c b/drivers/media/video/cx231xx/cx231xx-core.c index b24eee115e7..f5e1a2315fc 100644 --- a/drivers/media/video/cx231xx/cx231xx-core.c +++ b/drivers/media/video/cx231xx/cx231xx-core.c @@ -96,10 +96,9 @@ int cx231xx_register_extension(struct cx231xx_ops *ops) mutex_lock(&cx231xx_devlist_mutex); mutex_lock(&cx231xx_extension_devlist_lock); list_add_tail(&ops->next, &cx231xx_extension_devlist); - list_for_each_entry(dev, &cx231xx_devlist, devlist) { - if (dev) - ops->init(dev); - } + list_for_each_entry(dev, &cx231xx_devlist, devlist) + ops->init(dev); + printk(KERN_INFO DRIVER_NAME ": %s initialized\n", ops->name); mutex_unlock(&cx231xx_extension_devlist_lock); mutex_unlock(&cx231xx_devlist_mutex); @@ -112,10 +111,8 @@ void cx231xx_unregister_extension(struct cx231xx_ops *ops) struct cx231xx *dev = NULL; mutex_lock(&cx231xx_devlist_mutex); - list_for_each_entry(dev, &cx231xx_devlist, devlist) { - if (dev) - ops->fini(dev); - } + list_for_each_entry(dev, &cx231xx_devlist, devlist) + ops->fini(dev); mutex_lock(&cx231xx_extension_devlist_lock); printk(KERN_INFO DRIVER_NAME ": %s removed\n", ops->name); -- cgit v1.2.3-70-g09d2 From f24350b48eed2d5518a5f0c2c95d51a655387457 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sun, 28 Mar 2010 08:49:20 -0300 Subject: V4L/DVB: video/zc0301: improve error handling Return an error if the controller is not found. Signed-off-by: Dan Carpenter Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/zc0301/zc0301_core.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/zc0301/zc0301_core.c b/drivers/media/video/zc0301/zc0301_core.c index e44e4b5f3e5..bb51cfb0c64 100644 --- a/drivers/media/video/zc0301/zc0301_core.c +++ b/drivers/media/video/zc0301/zc0301_core.c @@ -1153,7 +1153,7 @@ zc0301_vidioc_s_ctrl(struct zc0301_device* cam, void __user * arg) if (copy_from_user(&ctrl, arg, sizeof(ctrl))) return -EFAULT; - for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) + for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) { if (ctrl.id == s->qctrl[i].id) { if (s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED) return -EINVAL; @@ -1163,7 +1163,9 @@ zc0301_vidioc_s_ctrl(struct zc0301_device* cam, void __user * arg) ctrl.value -= ctrl.value % s->qctrl[i].step; break; } - + } + if (i == ARRAY_SIZE(s->qctrl)) + return -EINVAL; if ((err = s->set_ctrl(cam, &ctrl))) return err; -- cgit v1.2.3-70-g09d2 From 67e13e7709736b3b25dda98f92cc7164b210dda6 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sun, 28 Mar 2010 08:49:45 -0300 Subject: V4L/DVB: video/et61x251: improve error handling The original code doesn't handle the situation where the controller is not found. Signed-off-by: Dan Carpenter Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/et61x251/et61x251_core.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c index e6c23d50986..a5cfc76b40b 100644 --- a/drivers/media/video/et61x251/et61x251_core.c +++ b/drivers/media/video/et61x251/et61x251_core.c @@ -1713,7 +1713,7 @@ et61x251_vidioc_s_ctrl(struct et61x251_device* cam, void __user * arg) if (copy_from_user(&ctrl, arg, sizeof(ctrl))) return -EFAULT; - for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) + for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) { if (ctrl.id == s->qctrl[i].id) { if (s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED) return -EINVAL; @@ -1723,7 +1723,9 @@ et61x251_vidioc_s_ctrl(struct et61x251_device* cam, void __user * arg) ctrl.value -= ctrl.value % s->qctrl[i].step; break; } - + } + if (i == ARRAY_SIZE(s->qctrl)) + return -EINVAL; if ((err = s->set_ctrl(cam, &ctrl))) return err; -- cgit v1.2.3-70-g09d2 From 124371e33ce733a81fde8419946adb0d6c14f4c0 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sun, 28 Mar 2010 08:50:05 -0300 Subject: V4L/DVB: video/sn9c102: improve error handling Return an error if the controller is not found. Signed-off-by: Dan Carpenter Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/sn9c102/sn9c102_core.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c index cbf8087b286..28e19daadec 100644 --- a/drivers/media/video/sn9c102/sn9c102_core.c +++ b/drivers/media/video/sn9c102/sn9c102_core.c @@ -2295,7 +2295,7 @@ sn9c102_vidioc_s_ctrl(struct sn9c102_device* cam, void __user * arg) if (copy_from_user(&ctrl, arg, sizeof(ctrl))) return -EFAULT; - for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) + for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) { if (ctrl.id == s->qctrl[i].id) { if (s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED) return -EINVAL; @@ -2305,7 +2305,9 @@ sn9c102_vidioc_s_ctrl(struct sn9c102_device* cam, void __user * arg) ctrl.value -= ctrl.value % s->qctrl[i].step; break; } - + } + if (i == ARRAY_SIZE(s->qctrl)) + return -EINVAL; if ((err = s->set_ctrl(cam, &ctrl))) return err; -- cgit v1.2.3-70-g09d2 From b400f09246247e2c55b116bd7b71da4fb0cb19dc Mon Sep 17 00:00:00 2001 From: Dmitri Belimov Date: Tue, 30 Mar 2010 03:02:17 -0300 Subject: V4L/DVB: Fix default state Beholder H6 tuner The hybrid tuner FMD1216MEX_MK3 after cold start has disabled IF. This tuner has internal I2C switch. This switch switch I2C bus between DVB-T and IF part. Default state is DVB-T. When module saa7134 is load it can't find IF tda9887 and disable analog TV mode. Sets internal I2C switch of the tuner to IF by send special value to the tuner as for receive analog TV from low band. It can be usefule for other cards. I didn't set configure a tuner by a tuner model because this tuner can have different I2C address. May be we can do it later after discuss for more robust support a tuners. Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-cards.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index b937d4da313..435f821b592 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -7366,6 +7366,23 @@ int saa7134_board_init2(struct saa7134_dev *dev) } break; } + case SAA7134_BOARD_BEHOLD_H6: + { + u8 data[] = { 0x09, 0x9f, 0x86, 0x11}; + struct i2c_msg msg = {.addr = 0x61, .flags = 0, .buf = data, + .len = sizeof(data)}; + + /* The tuner TUNER_PHILIPS_FMD1216MEX_MK3 after hardware */ + /* start has disabled IF and enabled DVB-T. When saa7134 */ + /* scan I2C devices it not detect IF tda9887 and can`t */ + /* watch TV without software reboot. For solve this problem */ + /* switch the tuner to analog TV mode manually. */ + if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1) + printk(KERN_WARNING + "%s: Unable to enable IF of the tuner.\n", + dev->name); + break; + } } /* switch() */ /* initialize tuner */ -- cgit v1.2.3-70-g09d2 From f76280154cdbb0ad02d5402972d1eb85f9e2898a Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 30 Mar 2010 14:32:04 -0300 Subject: V4L/DVB: [-next] gspca: fix build for INPUT=m or INPUT=n Handle case of GSPCA=m, INPUT=m when building gspca core; also handle case of INPUT=n by using stubs. drivers/media/video/gspca/gspca.c:662: error: implicit declaration of function 'gspca_input_destroy_urb' drivers/media/video/gspca/gspca.c:668: error: implicit declaration of function 'gspca_input_create_urb' drivers/media/video/gspca/gspca.c:2284: error: implicit declaration of function 'gspca_input_connect' Signed-off-by: Randy Dunlap Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gspca.c | 23 ++++++++++++++++++----- drivers/media/video/gspca/gspca.h | 6 +++--- 2 files changed, 21 insertions(+), 8 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 1830ea9e73b..972f637c974 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -40,7 +40,7 @@ #include "gspca.h" -#ifdef CONFIG_INPUT +#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) #include #include #endif @@ -115,7 +115,7 @@ static const struct vm_operations_struct gspca_vm_ops = { /* * Input and interrupt endpoint handling functions */ -#ifdef CONFIG_INPUT +#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) static void int_irq(struct urb *urb) { struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context; @@ -279,6 +279,19 @@ static void gspca_input_destroy_urb(struct gspca_dev *gspca_dev) usb_free_urb(urb); } } +#else +static inline void gspca_input_destroy_urb(struct gspca_dev *gspca_dev) +{ +} + +static inline void gspca_input_create_urb(struct gspca_dev *gspca_dev) +{ +} + +static inline int gspca_input_connect(struct gspca_dev *dev) +{ + return 0; +} #endif /* get the current input frame buffer */ @@ -2310,7 +2323,7 @@ int gspca_dev_probe(struct usb_interface *intf, return 0; out: -#ifdef CONFIG_INPUT +#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) if (gspca_dev->input_dev) input_unregister_device(gspca_dev->input_dev); #endif @@ -2329,7 +2342,7 @@ EXPORT_SYMBOL(gspca_dev_probe); void gspca_disconnect(struct usb_interface *intf) { struct gspca_dev *gspca_dev = usb_get_intfdata(intf); -#ifdef CONFIG_INPUT +#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) struct input_dev *input_dev; #endif @@ -2343,7 +2356,7 @@ void gspca_disconnect(struct usb_interface *intf) wake_up_interruptible(&gspca_dev->wq); } -#ifdef CONFIG_INPUT +#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) gspca_input_destroy_urb(gspca_dev); input_dev = gspca_dev->input_dev; if (input_dev) { diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index 8bb242fb79d..8b963dfae86 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h @@ -130,7 +130,7 @@ struct sd_desc { cam_reg_op get_register; #endif cam_ident_op get_chip_ident; -#ifdef CONFIG_INPUT +#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) cam_int_pkt_op int_pkt_scan; /* other_input makes the gspca core create gspca_dev->input even when int_pkt_scan is NULL, for cams with non interrupt driven buttons */ @@ -158,7 +158,7 @@ struct gspca_dev { struct module *module; /* subdriver handling the device */ struct usb_device *dev; struct file *capt_file; /* file doing video capture */ -#ifdef CONFIG_INPUT +#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) struct input_dev *input_dev; char phys[64]; /* physical device path */ #endif @@ -171,7 +171,7 @@ struct gspca_dev { #define USB_BUF_SZ 64 __u8 *usb_buf; /* buffer for USB exchanges */ struct urb *urb[MAX_NURBS]; -#ifdef CONFIG_INPUT +#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) struct urb *int_urb; #endif -- cgit v1.2.3-70-g09d2 From 8e47567f7d24346980f109d7eaed083106ff170d Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 2 Apr 2010 08:30:10 -0300 Subject: V4L/DVB: cx231xx: improve error handling Return -EINVAL if we don't find the control id. Signed-off-by: Dan Carpenter Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx231xx/cx231xx-video.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx231xx/cx231xx-video.c b/drivers/media/video/cx231xx/cx231xx-video.c index 16a73eab672..597c416218c 100644 --- a/drivers/media/video/cx231xx/cx231xx-video.c +++ b/drivers/media/video/cx231xx/cx231xx-video.c @@ -1902,9 +1902,12 @@ static int radio_queryctrl(struct file *file, void *priv, if (c->id < V4L2_CID_BASE || c->id >= V4L2_CID_LASTP1) return -EINVAL; if (c->id == V4L2_CID_AUDIO_MUTE) { - for (i = 0; i < CX231XX_CTLS; i++) + for (i = 0; i < CX231XX_CTLS; i++) { if (cx231xx_ctls[i].v.id == c->id) break; + } + if (i == CX231XX_CTLS) + return -EINVAL; *c = cx231xx_ctls[i].v; } else *c = no_ctl; -- cgit v1.2.3-70-g09d2 From a41b2ea73ad81bb42364841b37d4c3830a53dc0d Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 2 Apr 2010 08:31:50 -0300 Subject: V4L/DVB: cx88: improve error handling Return -EINVAL if we don't find the right query control id. Signed-off-by: Dan Carpenter Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-video.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index f5d1d89bdc2..0fab65c3ab3 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -1538,9 +1538,12 @@ static int radio_queryctrl (struct file *file, void *priv, c->id >= V4L2_CID_LASTP1) return -EINVAL; if (c->id == V4L2_CID_AUDIO_MUTE) { - for (i = 0; i < CX8800_CTLS; i++) + for (i = 0; i < CX8800_CTLS; i++) { if (cx8800_ctls[i].v.id == c->id) break; + } + if (i == CX8800_CTLS) + return -EINVAL; *c = cx8800_ctls[i].v; } else *c = no_ctl; -- cgit v1.2.3-70-g09d2 From 27c6f9e548633f148a45a138f2d6d0e513514172 Mon Sep 17 00:00:00 2001 From: Jean-François Moine Date: Fri, 2 Apr 2010 06:59:13 -0300 Subject: V4L/DVB: gspca: Change some copyrights and module authors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gspca.c | 4 ++-- drivers/media/video/gspca/sonixj.c | 4 ++-- drivers/media/video/gspca/vc032x.c | 10 +++++----- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 972f637c974..68a8431d436 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -1,7 +1,7 @@ /* * Main USB camera driver * - * Copyright (C) 2008-2009 Jean-Francois Moine (http://moinejf.free.fr) + * Copyright (C) 2008-2010 Jean-François Moine * * Camera button input handling by Márton Németh * Copyright (C) 2009-2010 Márton Németh @@ -51,7 +51,7 @@ #error "DEF_NURBS too big" #endif -MODULE_AUTHOR("Jean-Francois Moine "); +MODULE_AUTHOR("Jean-François Moine "); MODULE_DESCRIPTION("GSPCA USB Camera Driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index aaa68ddb1fb..5961d1fab1d 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -1,7 +1,7 @@ /* * Sonix sn9c102p sn9c105 sn9c120 (jpeg) subdriver * - * Copyright (C) 2009 Jean-Francois Moine + * Copyright (C) 2009-2010 Jean-François Moine * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr * * This program is free software; you can redistribute it and/or modify @@ -28,7 +28,7 @@ #define V4L2_CID_INFRARED (V4L2_CID_PRIVATE_BASE + 0) -MODULE_AUTHOR("Michel Xhaard "); +MODULE_AUTHOR("Jean-François Moine "); MODULE_DESCRIPTION("GSPCA/SONIX JPEG USB Camera Driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c index 4989f9afb46..7fde1452e4d 100644 --- a/drivers/media/video/gspca/vc032x.c +++ b/drivers/media/video/gspca/vc032x.c @@ -1,9 +1,9 @@ /* - * Z-star vc0321 library - * Copyright (C) 2006 Koninski Artur takeshi87@o2.pl - * Copyright (C) 2006 Michel Xhaard + * Z-star vc0321 library * - * V4L2 by Jean-Francois Moine + * Copyright (C) 2009-2010 Jean-François Moine + * Copyright (C) 2006 Koninski Artur takeshi87@o2.pl + * Copyright (C) 2006 Michel Xhaard * * 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 @@ -24,7 +24,7 @@ #include "gspca.h" -MODULE_AUTHOR("Michel Xhaard "); +MODULE_AUTHOR("Jean-François Moine "); MODULE_DESCRIPTION("GSPCA/VC032X USB Camera Driver"); MODULE_LICENSE("GPL"); -- cgit v1.2.3-70-g09d2 From 73e4934c80338757dca46ffaa30a3443a31043fb Mon Sep 17 00:00:00 2001 From: Jean-François Moine Date: Fri, 2 Apr 2010 07:05:59 -0300 Subject: V4L/DVB: gspca - sonixj: Let the JPEG header in the device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sonixj.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 5961d1fab1d..0b74ea89ae0 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -84,7 +84,7 @@ enum { } sensors; u8 i2c_addr; - u8 *jpeg_hdr; + u8 jpeg_hdr[JPEG_HDR_SZ]; }; /* V4L2 controls supported by the driver */ @@ -2208,9 +2208,6 @@ static int sd_start(struct gspca_dev *gspca_dev) { 0x14, 0xe7, 0x1e, 0xdd }; /* create the JPEG header */ - sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); - if (!sd->jpeg_hdr) - return -ENOMEM; jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, 0x21); /* JPEG 422 */ jpeg_set_qual(sd->jpeg_hdr, sd->quality); @@ -2507,13 +2504,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev) /* reg_w1(gspca_dev, 0xf1, 0x01); */ } -static void sd_stop0(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - kfree(sd->jpeg_hdr); -} - static void do_autogain(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -2885,7 +2875,6 @@ static const struct sd_desc sd_desc = { .init = sd_init, .start = sd_start, .stopN = sd_stopN, - .stop0 = sd_stop0, .pkt_scan = sd_pkt_scan, .dq_callback = do_autogain, .get_jcomp = sd_get_jcomp, -- cgit v1.2.3-70-g09d2 From c26b12d0646e0f571389a0a990882af3732b26a8 Mon Sep 17 00:00:00 2001 From: Jean-François Moine Date: Fri, 2 Apr 2010 07:08:39 -0300 Subject: V4L/DVB: gspca - sonixj: Add autogain for sensor gc0307 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sonixj.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 0b74ea89ae0..d90c065a98e 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -291,8 +291,7 @@ static const __u32 ctrl_dis[] = { (1 << VFLIP_IDX) | (1 << FREQ_IDX), -[SENSOR_GC0307] = (1 << AUTOGAIN_IDX) | - (1 << INFRARED_IDX) | +[SENSOR_GC0307] = (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX), @@ -642,12 +641,6 @@ static const u8 gc0307_sensor_param1[][8] = { /*param3*/ {0xa0, 0x21, 0x01, 0x6e, 0x00, 0x00, 0x00, 0x10}, {0xa0, 0x21, 0x02, 0x88, 0x00, 0x00, 0x00, 0x10}, - - {0xa0, 0x21, 0x68, 0x22, 0x00, 0x00, 0x00, 0x10}, - {0xdd, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0xa0, 0x21, 0x03, 0x07, 0x00, 0x00, 0x00, 0x10}, - {0xdd, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0xa0, 0x21, 0x04, 0x91, 0x00, 0x00, 0x00, 0x10}, {} }; @@ -1815,6 +1808,18 @@ static u32 setexposure(struct gspca_dev *gspca_dev, struct sd *sd = (struct sd *) gspca_dev; switch (sd->sensor) { + case SENSOR_GC0307: { + int a, b; + + /* expo = 0..255 -> a = 19..43 */ + a = 19 + expo * 25 / 256; + i2c_w1(gspca_dev, 0x68, a); + a -= 12; + b = a * a * 4; /* heuristic */ + i2c_w1(gspca_dev, 0x03, b >> 8); + i2c_w1(gspca_dev, 0x04, b); + break; + } case SENSOR_HV7131R: { u8 Expodoit[] = { 0xc1, 0x11, 0x25, 0x00, 0x00, 0x00, 0x00, 0x16 }; @@ -1925,6 +1930,7 @@ static void setbrightness(struct gspca_dev *gspca_dev) expo = sd->brightness >> 4; sd->exposure = setexposure(gspca_dev, expo); break; + case SENSOR_GC0307: case SENSOR_MT9V111: expo = sd->brightness >> 8; sd->exposure = setexposure(gspca_dev, expo); @@ -2524,6 +2530,14 @@ static void do_autogain(struct gspca_dev *gspca_dev) if (delta < luma_mean - luma_delta || delta > luma_mean + luma_delta) { switch (sd->sensor) { + case SENSOR_GC0307: + expotimes = sd->exposure; + expotimes += (luma_mean - delta) >> 6; + if (expotimes < 0) + expotimes = 0; + sd->exposure = setexposure(gspca_dev, + (unsigned int) expotimes); + break; case SENSOR_HV7131R: expotimes = sd->exposure >> 8; expotimes += (luma_mean - delta) >> 4; -- cgit v1.2.3-70-g09d2 From 5624c64803dd7c6da7add5a1880d66dbf2df8dc5 Mon Sep 17 00:00:00 2001 From: Jean-François Moine Date: Fri, 2 Apr 2010 07:12:42 -0300 Subject: V4L/DVB: gspca - vc032x: Change the ov7670 format to YUYV MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/vc032x.c | 737 ++++++++++++++++++++++++------------- 1 file changed, 482 insertions(+), 255 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c index 7fde1452e4d..732c3dfe46f 100644 --- a/drivers/media/video/gspca/vc032x.c +++ b/drivers/media/video/gspca/vc032x.c @@ -1971,268 +1971,489 @@ static const u8 ov7660_NoFliker[][4] = { {} }; -static const u8 ov7670_initVGA_JPG[][4] = { +static const u8 ov7670_InitVGA[][4] = { {0xb3, 0x01, 0x05, 0xcc}, - {0x00, 0x00, 0x30, 0xdd}, {0xb0, 0x03, 0x19, 0xcc}, + {0x00, 0x00, 0x30, 0xdd}, + {0xb0, 0x03, 0x19, 0xcc}, + {0x00, 0x00, 0x10, 0xdd}, + {0xb0, 0x04, 0x02, 0xcc}, {0x00, 0x00, 0x10, 0xdd}, - {0xb0, 0x04, 0x02, 0xcc}, {0x00, 0x00, 0x10, 0xdd}, - {0xb3, 0x00, 0x66, 0xcc}, {0xb3, 0x00, 0x67, 0xcc}, + {0xb3, 0x00, 0x66, 0xcc}, + {0xb3, 0x00, 0x67, 0xcc}, + {0xb0, 0x16, 0x01, 0xcc}, {0xb3, 0x35, 0xa1, 0xcc}, /* i2c add: 21 */ {0xb3, 0x34, 0x01, 0xcc}, - {0xb3, 0x05, 0x01, 0xcc}, {0xb3, 0x06, 0x01, 0xcc}, - {0xb3, 0x08, 0x01, 0xcc}, {0xb3, 0x09, 0x0c, 0xcc}, - {0xb3, 0x02, 0x02, 0xcc}, {0xb3, 0x03, 0x1f, 0xcc}, - {0xb3, 0x14, 0x00, 0xcc}, {0xb3, 0x15, 0x00, 0xcc}, - {0xb3, 0x16, 0x02, 0xcc}, {0xb3, 0x17, 0x7f, 0xcc}, - {0xb3, 0x04, 0x05, 0xcc}, {0xb3, 0x20, 0x00, 0xcc}, - {0xb3, 0x21, 0x00, 0xcc}, {0xb3, 0x22, 0x01, 0xcc}, - {0xb3, 0x23, 0xe0, 0xcc}, {0xbc, 0x00, 0x41, 0xcc}, - {0xbc, 0x01, 0x01, 0xcc}, {0x00, 0x12, 0x80, 0xaa}, - {0x00, 0x00, 0x20, 0xdd}, {0x00, 0x12, 0x00, 0xaa}, - {0x00, 0x11, 0x40, 0xaa}, {0x00, 0x6b, 0x0a, 0xaa}, - {0x00, 0x3a, 0x04, 0xaa}, {0x00, 0x40, 0xc0, 0xaa}, - {0x00, 0x8c, 0x00, 0xaa}, {0x00, 0x7a, 0x29, 0xaa}, - {0x00, 0x7b, 0x0e, 0xaa}, {0x00, 0x7c, 0x1a, 0xaa}, - {0x00, 0x7d, 0x31, 0xaa}, {0x00, 0x7e, 0x53, 0xaa}, - {0x00, 0x7f, 0x60, 0xaa}, {0x00, 0x80, 0x6b, 0xaa}, - {0x00, 0x81, 0x73, 0xaa}, {0x00, 0x82, 0x7b, 0xaa}, - {0x00, 0x83, 0x82, 0xaa}, {0x00, 0x84, 0x89, 0xaa}, - {0x00, 0x85, 0x96, 0xaa}, {0x00, 0x86, 0xa1, 0xaa}, - {0x00, 0x87, 0xb7, 0xaa}, {0x00, 0x88, 0xcc, 0xaa}, - {0x00, 0x89, 0xe1, 0xaa}, {0x00, 0x13, 0xe0, 0xaa}, - {0x00, 0x00, 0x00, 0xaa}, {0x00, 0x10, 0x00, 0xaa}, - {0x00, 0x0d, 0x40, 0xaa}, {0x00, 0x14, 0x28, 0xaa}, - {0x00, 0xa5, 0x05, 0xaa}, {0x00, 0xab, 0x07, 0xaa}, - {0x00, 0x24, 0x95, 0xaa}, {0x00, 0x25, 0x33, 0xaa}, - {0x00, 0x26, 0xe3, 0xaa}, {0x00, 0x9f, 0x88, 0xaa}, - {0x00, 0xa0, 0x78, 0xaa}, {0x00, 0x55, 0x90, 0xaa}, - {0x00, 0xa1, 0x03, 0xaa}, {0x00, 0xa6, 0xe0, 0xaa}, - {0x00, 0xa7, 0xd8, 0xaa}, {0x00, 0xa8, 0xf0, 0xaa}, - {0x00, 0xa9, 0x90, 0xaa}, {0x00, 0xaa, 0x14, 0xaa}, - {0x00, 0x13, 0xe5, 0xaa}, {0x00, 0x0e, 0x61, 0xaa}, - {0x00, 0x0f, 0x4b, 0xaa}, {0x00, 0x16, 0x02, 0xaa}, + {0xb3, 0x05, 0x01, 0xcc}, + {0xb3, 0x06, 0x01, 0xcc}, + {0xb3, 0x08, 0x01, 0xcc}, + {0xb3, 0x09, 0x0c, 0xcc}, + {0xb3, 0x02, 0x02, 0xcc}, + {0xb3, 0x03, 0x1f, 0xcc}, + {0xb3, 0x14, 0x00, 0xcc}, + {0xb3, 0x15, 0x00, 0xcc}, + {0xb3, 0x16, 0x02, 0xcc}, + {0xb3, 0x17, 0x7f, 0xcc}, + {0xb3, 0x04, 0x05, 0xcc}, + {0xb3, 0x20, 0x00, 0xcc}, + {0xb3, 0x21, 0x00, 0xcc}, + {0xb3, 0x22, 0x01, 0xcc}, + {0xb3, 0x23, 0xe0, 0xcc}, + {0xbc, 0x00, 0x41, 0xcc}, + {0xbc, 0x01, 0x01, 0xcc}, + {0x00, 0x12, 0x80, 0xaa}, + {0x00, 0x00, 0x20, 0xdd}, + {0x00, 0x12, 0x00, 0xaa}, + {0x00, 0x11, 0x40, 0xaa}, + {0x00, 0x6b, 0x0a, 0xaa}, + {0x00, 0x3a, 0x04, 0xaa}, + {0x00, 0x40, 0xc0, 0xaa}, + {0x00, 0x8c, 0x00, 0xaa}, + {0x00, 0x7a, 0x29, 0xaa}, + {0x00, 0x7b, 0x0e, 0xaa}, + {0x00, 0x7c, 0x1a, 0xaa}, + {0x00, 0x7d, 0x31, 0xaa}, + {0x00, 0x7e, 0x53, 0xaa}, + {0x00, 0x7f, 0x60, 0xaa}, + {0x00, 0x80, 0x6b, 0xaa}, + {0x00, 0x81, 0x73, 0xaa}, + {0x00, 0x82, 0x7b, 0xaa}, + {0x00, 0x83, 0x82, 0xaa}, + {0x00, 0x84, 0x89, 0xaa}, + {0x00, 0x85, 0x96, 0xaa}, + {0x00, 0x86, 0xa1, 0xaa}, + {0x00, 0x87, 0xb7, 0xaa}, + {0x00, 0x88, 0xcc, 0xaa}, + {0x00, 0x89, 0xe1, 0xaa}, + {0x00, 0x13, 0xe0, 0xaa}, + {0x00, 0x00, 0x00, 0xaa}, + {0x00, 0x10, 0x00, 0xaa}, + {0x00, 0x0d, 0x40, 0xaa}, + {0x00, 0x14, 0x28, 0xaa}, + {0x00, 0xa5, 0x05, 0xaa}, + {0x00, 0xab, 0x07, 0xaa}, + {0x00, 0x24, 0x95, 0xaa}, + {0x00, 0x25, 0x33, 0xaa}, + {0x00, 0x26, 0xe3, 0xaa}, + {0x00, 0x9f, 0x88, 0xaa}, + {0x00, 0xa0, 0x78, 0xaa}, + {0x00, 0x55, 0x90, 0xaa}, + {0x00, 0xa1, 0x03, 0xaa}, + {0x00, 0xa6, 0xe0, 0xaa}, + {0x00, 0xa7, 0xd8, 0xaa}, + {0x00, 0xa8, 0xf0, 0xaa}, + {0x00, 0xa9, 0x90, 0xaa}, + {0x00, 0xaa, 0x14, 0xaa}, + {0x00, 0x13, 0xe5, 0xaa}, + {0x00, 0x0e, 0x61, 0xaa}, + {0x00, 0x0f, 0x4b, 0xaa}, + {0x00, 0x16, 0x02, 0xaa}, {0x00, 0x1e, 0x07, 0xaa}, /* MVFP */ {0x00, 0x21, 0x02, 0xaa}, - {0x00, 0x22, 0x91, 0xaa}, {0x00, 0x29, 0x07, 0xaa}, - {0x00, 0x33, 0x0b, 0xaa}, {0x00, 0x35, 0x0b, 0xaa}, - {0x00, 0x37, 0x1d, 0xaa}, {0x00, 0x38, 0x71, 0xaa}, - {0x00, 0x39, 0x2a, 0xaa}, {0x00, 0x3c, 0x78, 0xaa}, - {0x00, 0x4d, 0x40, 0xaa}, {0x00, 0x4e, 0x20, 0xaa}, - {0x00, 0x74, 0x19, 0xaa}, {0x00, 0x8d, 0x4f, 0xaa}, - {0x00, 0x8e, 0x00, 0xaa}, {0x00, 0x8f, 0x00, 0xaa}, - {0x00, 0x90, 0x00, 0xaa}, {0x00, 0x91, 0x00, 0xaa}, - {0x00, 0x96, 0x00, 0xaa}, {0x00, 0x9a, 0x80, 0xaa}, - {0x00, 0xb0, 0x84, 0xaa}, {0x00, 0xb1, 0x0c, 0xaa}, - {0x00, 0xb2, 0x0e, 0xaa}, {0x00, 0xb3, 0x82, 0xaa}, - {0x00, 0xb8, 0x0a, 0xaa}, {0x00, 0x43, 0x14, 0xaa}, - {0x00, 0x44, 0xf0, 0xaa}, {0x00, 0x45, 0x45, 0xaa}, - {0x00, 0x46, 0x63, 0xaa}, {0x00, 0x47, 0x2d, 0xaa}, - {0x00, 0x48, 0x46, 0xaa}, {0x00, 0x59, 0x88, 0xaa}, - {0x00, 0x5a, 0xa0, 0xaa}, {0x00, 0x5b, 0xc6, 0xaa}, - {0x00, 0x5c, 0x7d, 0xaa}, {0x00, 0x5d, 0x5f, 0xaa}, - {0x00, 0x5e, 0x19, 0xaa}, {0x00, 0x6c, 0x0a, 0xaa}, - {0x00, 0x6d, 0x55, 0xaa}, {0x00, 0x6e, 0x11, 0xaa}, - {0x00, 0x6f, 0x9e, 0xaa}, {0x00, 0x69, 0x00, 0xaa}, - {0x00, 0x6a, 0x40, 0xaa}, {0x00, 0x01, 0x40, 0xaa}, - {0x00, 0x02, 0x40, 0xaa}, {0x00, 0x13, 0xe7, 0xaa}, - {0x00, 0x5f, 0xf0, 0xaa}, {0x00, 0x60, 0xf0, 0xaa}, - {0x00, 0x61, 0xf0, 0xaa}, {0x00, 0x27, 0xa0, 0xaa}, - {0x00, 0x28, 0x80, 0xaa}, {0x00, 0x2c, 0x90, 0xaa}, - {0x00, 0x4f, 0x66, 0xaa}, {0x00, 0x50, 0x66, 0xaa}, - {0x00, 0x51, 0x00, 0xaa}, {0x00, 0x52, 0x22, 0xaa}, - {0x00, 0x53, 0x5e, 0xaa}, {0x00, 0x54, 0x80, 0xaa}, - {0x00, 0x58, 0x9e, 0xaa}, {0x00, 0x41, 0x08, 0xaa}, - {0x00, 0x3f, 0x00, 0xaa}, {0x00, 0x75, 0x85, 0xaa}, - {0x00, 0x76, 0xe1, 0xaa}, {0x00, 0x4c, 0x00, 0xaa}, - {0x00, 0x77, 0x0a, 0xaa}, {0x00, 0x3d, 0x88, 0xaa}, - {0x00, 0x4b, 0x09, 0xaa}, {0x00, 0xc9, 0x60, 0xaa}, - {0x00, 0x41, 0x38, 0xaa}, {0x00, 0x62, 0x30, 0xaa}, - {0x00, 0x63, 0x30, 0xaa}, {0x00, 0x64, 0x08, 0xaa}, - {0x00, 0x94, 0x07, 0xaa}, {0x00, 0x95, 0x0b, 0xaa}, - {0x00, 0x65, 0x00, 0xaa}, {0x00, 0x66, 0x05, 0xaa}, - {0x00, 0x56, 0x50, 0xaa}, {0x00, 0x34, 0x11, 0xaa}, - {0x00, 0xa4, 0x88, 0xaa}, {0x00, 0x96, 0x00, 0xaa}, - {0x00, 0x97, 0x30, 0xaa}, {0x00, 0x98, 0x20, 0xaa}, - {0x00, 0x99, 0x30, 0xaa}, {0x00, 0x9a, 0x84, 0xaa}, - {0x00, 0x9b, 0x29, 0xaa}, {0x00, 0x9c, 0x03, 0xaa}, - {0x00, 0x78, 0x04, 0xaa}, {0x00, 0x79, 0x01, 0xaa}, - {0x00, 0xc8, 0xf0, 0xaa}, {0x00, 0x79, 0x0f, 0xaa}, - {0x00, 0xc8, 0x00, 0xaa}, {0x00, 0x79, 0x10, 0xaa}, - {0x00, 0xc8, 0x7e, 0xaa}, {0x00, 0x79, 0x0a, 0xaa}, - {0x00, 0xc8, 0x80, 0xaa}, {0x00, 0x79, 0x0b, 0xaa}, - {0x00, 0xc8, 0x01, 0xaa}, {0x00, 0x79, 0x0c, 0xaa}, - {0x00, 0xc8, 0x0f, 0xaa}, {0x00, 0x79, 0x0d, 0xaa}, - {0x00, 0xc8, 0x20, 0xaa}, {0x00, 0x79, 0x09, 0xaa}, - {0x00, 0xc8, 0x80, 0xaa}, {0x00, 0x79, 0x02, 0xaa}, - {0x00, 0xc8, 0xc0, 0xaa}, {0x00, 0x79, 0x03, 0xaa}, - {0x00, 0xc8, 0x40, 0xaa}, {0x00, 0x79, 0x05, 0xaa}, - {0x00, 0xc8, 0x30, 0xaa}, {0x00, 0x79, 0x26, 0xaa}, - {0x00, 0x11, 0x40, 0xaa}, {0x00, 0x3a, 0x04, 0xaa}, - {0x00, 0x12, 0x00, 0xaa}, {0x00, 0x40, 0xc0, 0xaa}, - {0x00, 0x8c, 0x00, 0xaa}, {0x00, 0x17, 0x14, 0xaa}, - {0x00, 0x18, 0x02, 0xaa}, {0x00, 0x32, 0x92, 0xaa}, - {0x00, 0x19, 0x02, 0xaa}, {0x00, 0x1a, 0x7a, 0xaa}, - {0x00, 0x03, 0x0a, 0xaa}, {0x00, 0x0c, 0x00, 0xaa}, - {0x00, 0x3e, 0x00, 0xaa}, {0x00, 0x70, 0x3a, 0xaa}, - {0x00, 0x71, 0x35, 0xaa}, {0x00, 0x72, 0x11, 0xaa}, - {0x00, 0x73, 0xf0, 0xaa}, {0x00, 0xa2, 0x02, 0xaa}, - {0x00, 0xb1, 0x00, 0xaa}, {0x00, 0xb1, 0x0c, 0xaa}, + {0x00, 0x22, 0x91, 0xaa}, + {0x00, 0x29, 0x07, 0xaa}, + {0x00, 0x33, 0x0b, 0xaa}, + {0x00, 0x35, 0x0b, 0xaa}, + {0x00, 0x37, 0x1d, 0xaa}, + {0x00, 0x38, 0x71, 0xaa}, + {0x00, 0x39, 0x2a, 0xaa}, + {0x00, 0x3c, 0x78, 0xaa}, + {0x00, 0x4d, 0x40, 0xaa}, + {0x00, 0x4e, 0x20, 0xaa}, + {0x00, 0x74, 0x19, 0xaa}, + {0x00, 0x8d, 0x4f, 0xaa}, + {0x00, 0x8e, 0x00, 0xaa}, + {0x00, 0x8f, 0x00, 0xaa}, + {0x00, 0x90, 0x00, 0xaa}, + {0x00, 0x91, 0x00, 0xaa}, + {0x00, 0x96, 0x00, 0xaa}, + {0x00, 0x9a, 0x80, 0xaa}, + {0x00, 0xb0, 0x84, 0xaa}, + {0x00, 0xb1, 0x0c, 0xaa}, + {0x00, 0xb2, 0x0e, 0xaa}, + {0x00, 0xb3, 0x82, 0xaa}, + {0x00, 0xb8, 0x0a, 0xaa}, + {0x00, 0x43, 0x14, 0xaa}, + {0x00, 0x44, 0xf0, 0xaa}, + {0x00, 0x45, 0x45, 0xaa}, + {0x00, 0x46, 0x63, 0xaa}, + {0x00, 0x47, 0x2d, 0xaa}, + {0x00, 0x48, 0x46, 0xaa}, + {0x00, 0x59, 0x88, 0xaa}, + {0x00, 0x5a, 0xa0, 0xaa}, + {0x00, 0x5b, 0xc6, 0xaa}, + {0x00, 0x5c, 0x7d, 0xaa}, + {0x00, 0x5d, 0x5f, 0xaa}, + {0x00, 0x5e, 0x19, 0xaa}, + {0x00, 0x6c, 0x0a, 0xaa}, + {0x00, 0x6d, 0x55, 0xaa}, + {0x00, 0x6e, 0x11, 0xaa}, + {0x00, 0x6f, 0x9e, 0xaa}, + {0x00, 0x69, 0x00, 0xaa}, + {0x00, 0x6a, 0x40, 0xaa}, + {0x00, 0x01, 0x40, 0xaa}, + {0x00, 0x02, 0x40, 0xaa}, + {0x00, 0x13, 0xe7, 0xaa}, + {0x00, 0x5f, 0xf0, 0xaa}, + {0x00, 0x60, 0xf0, 0xaa}, + {0x00, 0x61, 0xf0, 0xaa}, + {0x00, 0x27, 0xa0, 0xaa}, + {0x00, 0x28, 0x80, 0xaa}, + {0x00, 0x2c, 0x90, 0xaa}, + {0x00, 0x4f, 0x66, 0xaa}, + {0x00, 0x50, 0x66, 0xaa}, + {0x00, 0x51, 0x00, 0xaa}, + {0x00, 0x52, 0x22, 0xaa}, + {0x00, 0x53, 0x5e, 0xaa}, + {0x00, 0x54, 0x80, 0xaa}, + {0x00, 0x58, 0x9e, 0xaa}, + {0x00, 0x41, 0x08, 0xaa}, + {0x00, 0x3f, 0x00, 0xaa}, + {0x00, 0x75, 0x85, 0xaa}, + {0x00, 0x76, 0xe1, 0xaa}, + {0x00, 0x4c, 0x00, 0xaa}, + {0x00, 0x77, 0x0a, 0xaa}, + {0x00, 0x3d, 0x88, 0xaa}, + {0x00, 0x4b, 0x09, 0xaa}, + {0x00, 0xc9, 0x60, 0xaa}, + {0x00, 0x41, 0x38, 0xaa}, + {0x00, 0x62, 0x30, 0xaa}, + {0x00, 0x63, 0x30, 0xaa}, + {0x00, 0x64, 0x08, 0xaa}, + {0x00, 0x94, 0x07, 0xaa}, + {0x00, 0x95, 0x0b, 0xaa}, + {0x00, 0x65, 0x00, 0xaa}, + {0x00, 0x66, 0x05, 0xaa}, + {0x00, 0x56, 0x50, 0xaa}, + {0x00, 0x34, 0x11, 0xaa}, + {0x00, 0xa4, 0x88, 0xaa}, + {0x00, 0x96, 0x00, 0xaa}, + {0x00, 0x97, 0x30, 0xaa}, + {0x00, 0x98, 0x20, 0xaa}, + {0x00, 0x99, 0x30, 0xaa}, + {0x00, 0x9a, 0x84, 0xaa}, + {0x00, 0x9b, 0x29, 0xaa}, + {0x00, 0x9c, 0x03, 0xaa}, + {0x00, 0x78, 0x04, 0xaa}, + {0x00, 0x79, 0x01, 0xaa}, + {0x00, 0xc8, 0xf0, 0xaa}, + {0x00, 0x79, 0x0f, 0xaa}, + {0x00, 0xc8, 0x00, 0xaa}, + {0x00, 0x79, 0x10, 0xaa}, + {0x00, 0xc8, 0x7e, 0xaa}, + {0x00, 0x79, 0x0a, 0xaa}, + {0x00, 0xc8, 0x80, 0xaa}, + {0x00, 0x79, 0x0b, 0xaa}, + {0x00, 0xc8, 0x01, 0xaa}, + {0x00, 0x79, 0x0c, 0xaa}, + {0x00, 0xc8, 0x0f, 0xaa}, + {0x00, 0x79, 0x0d, 0xaa}, + {0x00, 0xc8, 0x20, 0xaa}, + {0x00, 0x79, 0x09, 0xaa}, + {0x00, 0xc8, 0x80, 0xaa}, + {0x00, 0x79, 0x02, 0xaa}, + {0x00, 0xc8, 0xc0, 0xaa}, + {0x00, 0x79, 0x03, 0xaa}, + {0x00, 0xc8, 0x40, 0xaa}, + {0x00, 0x79, 0x05, 0xaa}, + {0x00, 0xc8, 0x30, 0xaa}, + {0x00, 0x79, 0x26, 0xaa}, + {0x00, 0x11, 0x40, 0xaa}, + {0x00, 0x3a, 0x04, 0xaa}, + {0x00, 0x12, 0x00, 0xaa}, + {0x00, 0x40, 0xc0, 0xaa}, + {0x00, 0x8c, 0x00, 0xaa}, + {0x00, 0x17, 0x14, 0xaa}, + {0x00, 0x18, 0x02, 0xaa}, + {0x00, 0x32, 0x92, 0xaa}, + {0x00, 0x19, 0x02, 0xaa}, + {0x00, 0x1a, 0x7a, 0xaa}, + {0x00, 0x03, 0x0a, 0xaa}, + {0x00, 0x0c, 0x00, 0xaa}, + {0x00, 0x3e, 0x00, 0xaa}, + {0x00, 0x70, 0x3a, 0xaa}, + {0x00, 0x71, 0x35, 0xaa}, + {0x00, 0x72, 0x11, 0xaa}, + {0x00, 0x73, 0xf0, 0xaa}, + {0x00, 0xa2, 0x02, 0xaa}, + {0x00, 0xb1, 0x00, 0xaa}, + {0x00, 0xb1, 0x0c, 0xaa}, {0x00, 0x1e, 0x37, 0xaa}, /* MVFP */ {0x00, 0xaa, 0x14, 0xaa}, - {0x00, 0x24, 0x80, 0xaa}, {0x00, 0x25, 0x74, 0xaa}, - {0x00, 0x26, 0xd3, 0xaa}, {0x00, 0x0d, 0x00, 0xaa}, - {0x00, 0x14, 0x18, 0xaa}, {0x00, 0x9d, 0x99, 0xaa}, - {0x00, 0x9e, 0x7f, 0xaa}, {0x00, 0x64, 0x08, 0xaa}, - {0x00, 0x94, 0x07, 0xaa}, {0x00, 0x95, 0x06, 0xaa}, - {0x00, 0x66, 0x05, 0xaa}, {0x00, 0x41, 0x08, 0xaa}, - {0x00, 0x3f, 0x00, 0xaa}, {0x00, 0x75, 0x07, 0xaa}, - {0x00, 0x76, 0xe1, 0xaa}, {0x00, 0x4c, 0x00, 0xaa}, - {0x00, 0x77, 0x00, 0xaa}, {0x00, 0x3d, 0xc2, 0xaa}, - {0x00, 0x4b, 0x09, 0xaa}, {0x00, 0xc9, 0x60, 0xaa}, - {0x00, 0x41, 0x38, 0xaa}, {0xb6, 0x00, 0x00, 0xcc}, - {0xb6, 0x03, 0x02, 0xcc}, {0xb6, 0x02, 0x80, 0xcc}, - {0xb6, 0x05, 0x01, 0xcc}, {0xb6, 0x04, 0xe0, 0xcc}, - {0xb6, 0x12, 0xf8, 0xcc}, {0xb6, 0x13, 0x13, 0xcc}, - {0xb6, 0x18, 0x02, 0xcc}, {0xb6, 0x17, 0x58, 0xcc}, - {0xb6, 0x16, 0x00, 0xcc}, {0xb6, 0x22, 0x12, 0xcc}, - {0xb6, 0x23, 0x0b, 0xcc}, {0xbf, 0xc0, 0x39, 0xcc}, - {0xbf, 0xc1, 0x04, 0xcc}, {0xbf, 0xcc, 0x00, 0xcc}, - {0xb3, 0x5c, 0x01, 0xcc}, {0xb3, 0x01, 0x45, 0xcc}, + {0x00, 0x24, 0x80, 0xaa}, + {0x00, 0x25, 0x74, 0xaa}, + {0x00, 0x26, 0xd3, 0xaa}, + {0x00, 0x0d, 0x00, 0xaa}, + {0x00, 0x14, 0x18, 0xaa}, + {0x00, 0x9d, 0x99, 0xaa}, + {0x00, 0x9e, 0x7f, 0xaa}, + {0x00, 0x64, 0x08, 0xaa}, + {0x00, 0x94, 0x07, 0xaa}, + {0x00, 0x95, 0x06, 0xaa}, + {0x00, 0x66, 0x05, 0xaa}, + {0x00, 0x41, 0x08, 0xaa}, + {0x00, 0x3f, 0x00, 0xaa}, + {0x00, 0x75, 0x07, 0xaa}, + {0x00, 0x76, 0xe1, 0xaa}, + {0x00, 0x4c, 0x00, 0xaa}, + {0x00, 0x77, 0x00, 0xaa}, + {0x00, 0x3d, 0xc2, 0xaa}, + {0x00, 0x4b, 0x09, 0xaa}, + {0x00, 0xc9, 0x60, 0xaa}, + {0x00, 0x41, 0x38, 0xaa}, + {0xbf, 0xc0, 0x26, 0xcc}, + {0xbf, 0xc1, 0x02, 0xcc}, + {0xbf, 0xcc, 0x04, 0xcc}, + {0xb3, 0x5c, 0x01, 0xcc}, + {0xb3, 0x01, 0x45, 0xcc}, {0x00, 0x77, 0x05, 0xaa}, {}, }; -static const u8 ov7670_initQVGA_JPG[][4] = { - {0xb3, 0x01, 0x05, 0xcc}, {0x00, 0x00, 0x30, 0xdd}, - {0xb0, 0x03, 0x19, 0xcc}, {0x00, 0x00, 0x10, 0xdd}, - {0xb0, 0x04, 0x02, 0xcc}, {0x00, 0x00, 0x10, 0xdd}, - {0xb3, 0x00, 0x66, 0xcc}, {0xb3, 0x00, 0x67, 0xcc}, - {0xb3, 0x35, 0xa1, 0xcc}, {0xb3, 0x34, 0x01, 0xcc}, - {0xb3, 0x05, 0x01, 0xcc}, {0xb3, 0x06, 0x01, 0xcc}, - {0xb3, 0x08, 0x01, 0xcc}, {0xb3, 0x09, 0x0c, 0xcc}, - {0xb3, 0x02, 0x02, 0xcc}, {0xb3, 0x03, 0x1f, 0xcc}, - {0xb3, 0x14, 0x00, 0xcc}, {0xb3, 0x15, 0x00, 0xcc}, - {0xb3, 0x16, 0x02, 0xcc}, {0xb3, 0x17, 0x7f, 0xcc}, - {0xb3, 0x04, 0x05, 0xcc}, {0xb3, 0x20, 0x00, 0xcc}, - {0xb3, 0x21, 0x00, 0xcc}, {0xb3, 0x22, 0x01, 0xcc}, - {0xb3, 0x23, 0xe0, 0xcc}, {0xbc, 0x00, 0xd1, 0xcc}, - {0xbc, 0x01, 0x01, 0xcc}, {0x00, 0x12, 0x80, 0xaa}, - {0x00, 0x00, 0x20, 0xdd}, {0x00, 0x12, 0x00, 0xaa}, - {0x00, 0x11, 0x40, 0xaa}, {0x00, 0x6b, 0x0a, 0xaa}, - {0x00, 0x3a, 0x04, 0xaa}, {0x00, 0x40, 0xc0, 0xaa}, - {0x00, 0x8c, 0x00, 0xaa}, {0x00, 0x7a, 0x29, 0xaa}, - {0x00, 0x7b, 0x0e, 0xaa}, {0x00, 0x7c, 0x1a, 0xaa}, - {0x00, 0x7d, 0x31, 0xaa}, {0x00, 0x7e, 0x53, 0xaa}, - {0x00, 0x7f, 0x60, 0xaa}, {0x00, 0x80, 0x6b, 0xaa}, - {0x00, 0x81, 0x73, 0xaa}, {0x00, 0x82, 0x7b, 0xaa}, - {0x00, 0x83, 0x82, 0xaa}, {0x00, 0x84, 0x89, 0xaa}, - {0x00, 0x85, 0x96, 0xaa}, {0x00, 0x86, 0xa1, 0xaa}, - {0x00, 0x87, 0xb7, 0xaa}, {0x00, 0x88, 0xcc, 0xaa}, - {0x00, 0x89, 0xe1, 0xaa}, {0x00, 0x13, 0xe0, 0xaa}, - {0x00, 0x00, 0x00, 0xaa}, {0x00, 0x10, 0x00, 0xaa}, - {0x00, 0x0d, 0x40, 0xaa}, {0x00, 0x14, 0x28, 0xaa}, - {0x00, 0xa5, 0x05, 0xaa}, {0x00, 0xab, 0x07, 0xaa}, - {0x00, 0x24, 0x95, 0xaa}, {0x00, 0x25, 0x33, 0xaa}, - {0x00, 0x26, 0xe3, 0xaa}, {0x00, 0x9f, 0x88, 0xaa}, - {0x00, 0xa0, 0x78, 0xaa}, {0x00, 0x55, 0x90, 0xaa}, - {0x00, 0xa1, 0x03, 0xaa}, {0x00, 0xa6, 0xe0, 0xaa}, - {0x00, 0xa7, 0xd8, 0xaa}, {0x00, 0xa8, 0xf0, 0xaa}, - {0x00, 0xa9, 0x90, 0xaa}, {0x00, 0xaa, 0x14, 0xaa}, - {0x00, 0x13, 0xe5, 0xaa}, {0x00, 0x0e, 0x61, 0xaa}, - {0x00, 0x0f, 0x4b, 0xaa}, {0x00, 0x16, 0x02, 0xaa}, +static const u8 ov7670_InitQVGA[][4] = { + {0xb3, 0x01, 0x05, 0xcc}, + {0x00, 0x00, 0x30, 0xdd}, + {0xb0, 0x03, 0x19, 0xcc}, + {0x00, 0x00, 0x10, 0xdd}, + {0xb0, 0x04, 0x02, 0xcc}, + {0x00, 0x00, 0x10, 0xdd}, + {0xb3, 0x00, 0x66, 0xcc}, + {0xb3, 0x00, 0x67, 0xcc}, + {0xb0, 0x16, 0x01, 0xcc}, + {0xb3, 0x35, 0xa1, 0xcc}, /* i2c add: 21 */ + {0xb3, 0x34, 0x01, 0xcc}, + {0xb3, 0x05, 0x01, 0xcc}, + {0xb3, 0x06, 0x01, 0xcc}, + {0xb3, 0x08, 0x01, 0xcc}, + {0xb3, 0x09, 0x0c, 0xcc}, + {0xb3, 0x02, 0x02, 0xcc}, + {0xb3, 0x03, 0x1f, 0xcc}, + {0xb3, 0x14, 0x00, 0xcc}, + {0xb3, 0x15, 0x00, 0xcc}, + {0xb3, 0x16, 0x02, 0xcc}, + {0xb3, 0x17, 0x7f, 0xcc}, + {0xb3, 0x04, 0x05, 0xcc}, + {0xb3, 0x20, 0x00, 0xcc}, + {0xb3, 0x21, 0x00, 0xcc}, + {0xb3, 0x22, 0x01, 0xcc}, + {0xb3, 0x23, 0xe0, 0xcc}, + {0xbc, 0x00, 0xd1, 0xcc}, + {0xbc, 0x01, 0x01, 0xcc}, + {0x00, 0x12, 0x80, 0xaa}, + {0x00, 0x00, 0x20, 0xdd}, + {0x00, 0x12, 0x00, 0xaa}, + {0x00, 0x11, 0x40, 0xaa}, + {0x00, 0x6b, 0x0a, 0xaa}, + {0x00, 0x3a, 0x04, 0xaa}, + {0x00, 0x40, 0xc0, 0xaa}, + {0x00, 0x8c, 0x00, 0xaa}, + {0x00, 0x7a, 0x29, 0xaa}, + {0x00, 0x7b, 0x0e, 0xaa}, + {0x00, 0x7c, 0x1a, 0xaa}, + {0x00, 0x7d, 0x31, 0xaa}, + {0x00, 0x7e, 0x53, 0xaa}, + {0x00, 0x7f, 0x60, 0xaa}, + {0x00, 0x80, 0x6b, 0xaa}, + {0x00, 0x81, 0x73, 0xaa}, + {0x00, 0x82, 0x7b, 0xaa}, + {0x00, 0x83, 0x82, 0xaa}, + {0x00, 0x84, 0x89, 0xaa}, + {0x00, 0x85, 0x96, 0xaa}, + {0x00, 0x86, 0xa1, 0xaa}, + {0x00, 0x87, 0xb7, 0xaa}, + {0x00, 0x88, 0xcc, 0xaa}, + {0x00, 0x89, 0xe1, 0xaa}, + {0x00, 0x13, 0xe0, 0xaa}, + {0x00, 0x00, 0x00, 0xaa}, + {0x00, 0x10, 0x00, 0xaa}, + {0x00, 0x0d, 0x40, 0xaa}, + {0x00, 0x14, 0x28, 0xaa}, + {0x00, 0xa5, 0x05, 0xaa}, + {0x00, 0xab, 0x07, 0xaa}, + {0x00, 0x24, 0x95, 0xaa}, + {0x00, 0x25, 0x33, 0xaa}, + {0x00, 0x26, 0xe3, 0xaa}, + {0x00, 0x9f, 0x88, 0xaa}, + {0x00, 0xa0, 0x78, 0xaa}, + {0x00, 0x55, 0x90, 0xaa}, + {0x00, 0xa1, 0x03, 0xaa}, + {0x00, 0xa6, 0xe0, 0xaa}, + {0x00, 0xa7, 0xd8, 0xaa}, + {0x00, 0xa8, 0xf0, 0xaa}, + {0x00, 0xa9, 0x90, 0xaa}, + {0x00, 0xaa, 0x14, 0xaa}, + {0x00, 0x13, 0xe5, 0xaa}, + {0x00, 0x0e, 0x61, 0xaa}, + {0x00, 0x0f, 0x4b, 0xaa}, + {0x00, 0x16, 0x02, 0xaa}, {0x00, 0x1e, 0x07, 0xaa}, /* MVFP */ {0x00, 0x21, 0x02, 0xaa}, - {0x00, 0x22, 0x91, 0xaa}, {0x00, 0x29, 0x07, 0xaa}, - {0x00, 0x33, 0x0b, 0xaa}, {0x00, 0x35, 0x0b, 0xaa}, - {0x00, 0x37, 0x1d, 0xaa}, {0x00, 0x38, 0x71, 0xaa}, - {0x00, 0x39, 0x2a, 0xaa}, {0x00, 0x3c, 0x78, 0xaa}, - {0x00, 0x4d, 0x40, 0xaa}, {0x00, 0x4e, 0x20, 0xaa}, - {0x00, 0x74, 0x19, 0xaa}, {0x00, 0x8d, 0x4f, 0xaa}, - {0x00, 0x8e, 0x00, 0xaa}, {0x00, 0x8f, 0x00, 0xaa}, - {0x00, 0x90, 0x00, 0xaa}, {0x00, 0x91, 0x00, 0xaa}, - {0x00, 0x96, 0x00, 0xaa}, {0x00, 0x9a, 0x80, 0xaa}, - {0x00, 0xb0, 0x84, 0xaa}, {0x00, 0xb1, 0x0c, 0xaa}, - {0x00, 0xb2, 0x0e, 0xaa}, {0x00, 0xb3, 0x82, 0xaa}, - {0x00, 0xb8, 0x0a, 0xaa}, {0x00, 0x43, 0x14, 0xaa}, - {0x00, 0x44, 0xf0, 0xaa}, {0x00, 0x45, 0x45, 0xaa}, - {0x00, 0x46, 0x63, 0xaa}, {0x00, 0x47, 0x2d, 0xaa}, - {0x00, 0x48, 0x46, 0xaa}, {0x00, 0x59, 0x88, 0xaa}, - {0x00, 0x5a, 0xa0, 0xaa}, {0x00, 0x5b, 0xc6, 0xaa}, - {0x00, 0x5c, 0x7d, 0xaa}, {0x00, 0x5d, 0x5f, 0xaa}, - {0x00, 0x5e, 0x19, 0xaa}, {0x00, 0x6c, 0x0a, 0xaa}, - {0x00, 0x6d, 0x55, 0xaa}, {0x00, 0x6e, 0x11, 0xaa}, - {0x00, 0x6f, 0x9e, 0xaa}, {0x00, 0x69, 0x00, 0xaa}, - {0x00, 0x6a, 0x40, 0xaa}, {0x00, 0x01, 0x40, 0xaa}, - {0x00, 0x02, 0x40, 0xaa}, {0x00, 0x13, 0xe7, 0xaa}, - {0x00, 0x5f, 0xf0, 0xaa}, {0x00, 0x60, 0xf0, 0xaa}, - {0x00, 0x61, 0xf0, 0xaa}, {0x00, 0x27, 0xa0, 0xaa}, - {0x00, 0x28, 0x80, 0xaa}, {0x00, 0x2c, 0x90, 0xaa}, - {0x00, 0x4f, 0x66, 0xaa}, {0x00, 0x50, 0x66, 0xaa}, - {0x00, 0x51, 0x00, 0xaa}, {0x00, 0x52, 0x22, 0xaa}, - {0x00, 0x53, 0x5e, 0xaa}, {0x00, 0x54, 0x80, 0xaa}, - {0x00, 0x58, 0x9e, 0xaa}, {0x00, 0x41, 0x08, 0xaa}, - {0x00, 0x3f, 0x00, 0xaa}, {0x00, 0x75, 0x85, 0xaa}, - {0x00, 0x76, 0xe1, 0xaa}, {0x00, 0x4c, 0x00, 0xaa}, - {0x00, 0x77, 0x0a, 0xaa}, {0x00, 0x3d, 0x88, 0xaa}, - {0x00, 0x4b, 0x09, 0xaa}, {0x00, 0xc9, 0x60, 0xaa}, - {0x00, 0x41, 0x38, 0xaa}, {0x00, 0x62, 0x30, 0xaa}, - {0x00, 0x63, 0x30, 0xaa}, {0x00, 0x64, 0x08, 0xaa}, - {0x00, 0x94, 0x07, 0xaa}, {0x00, 0x95, 0x0b, 0xaa}, - {0x00, 0x65, 0x00, 0xaa}, {0x00, 0x66, 0x05, 0xaa}, - {0x00, 0x56, 0x50, 0xaa}, {0x00, 0x34, 0x11, 0xaa}, - {0x00, 0xa4, 0x88, 0xaa}, {0x00, 0x96, 0x00, 0xaa}, - {0x00, 0x97, 0x30, 0xaa}, {0x00, 0x98, 0x20, 0xaa}, - {0x00, 0x99, 0x30, 0xaa}, {0x00, 0x9a, 0x84, 0xaa}, - {0x00, 0x9b, 0x29, 0xaa}, {0x00, 0x9c, 0x03, 0xaa}, - {0x00, 0x78, 0x04, 0xaa}, {0x00, 0x79, 0x01, 0xaa}, - {0x00, 0xc8, 0xf0, 0xaa}, {0x00, 0x79, 0x0f, 0xaa}, - {0x00, 0xc8, 0x00, 0xaa}, {0x00, 0x79, 0x10, 0xaa}, - {0x00, 0xc8, 0x7e, 0xaa}, {0x00, 0x79, 0x0a, 0xaa}, - {0x00, 0xc8, 0x80, 0xaa}, {0x00, 0x79, 0x0b, 0xaa}, - {0x00, 0xc8, 0x01, 0xaa}, {0x00, 0x79, 0x0c, 0xaa}, - {0x00, 0xc8, 0x0f, 0xaa}, {0x00, 0x79, 0x0d, 0xaa}, - {0x00, 0xc8, 0x20, 0xaa}, {0x00, 0x79, 0x09, 0xaa}, - {0x00, 0xc8, 0x80, 0xaa}, {0x00, 0x79, 0x02, 0xaa}, - {0x00, 0xc8, 0xc0, 0xaa}, {0x00, 0x79, 0x03, 0xaa}, - {0x00, 0xc8, 0x40, 0xaa}, {0x00, 0x79, 0x05, 0xaa}, - {0x00, 0xc8, 0x30, 0xaa}, {0x00, 0x79, 0x26, 0xaa}, - {0x00, 0x11, 0x40, 0xaa}, {0x00, 0x3a, 0x04, 0xaa}, - {0x00, 0x12, 0x00, 0xaa}, {0x00, 0x40, 0xc0, 0xaa}, - {0x00, 0x8c, 0x00, 0xaa}, {0x00, 0x17, 0x14, 0xaa}, - {0x00, 0x18, 0x02, 0xaa}, {0x00, 0x32, 0x92, 0xaa}, - {0x00, 0x19, 0x02, 0xaa}, {0x00, 0x1a, 0x7a, 0xaa}, - {0x00, 0x03, 0x0a, 0xaa}, {0x00, 0x0c, 0x00, 0xaa}, - {0x00, 0x3e, 0x00, 0xaa}, {0x00, 0x70, 0x3a, 0xaa}, - {0x00, 0x71, 0x35, 0xaa}, {0x00, 0x72, 0x11, 0xaa}, - {0x00, 0x73, 0xf0, 0xaa}, {0x00, 0xa2, 0x02, 0xaa}, - {0x00, 0xb1, 0x00, 0xaa}, {0x00, 0xb1, 0x0c, 0xaa}, + {0x00, 0x22, 0x91, 0xaa}, + {0x00, 0x29, 0x07, 0xaa}, + {0x00, 0x33, 0x0b, 0xaa}, + {0x00, 0x35, 0x0b, 0xaa}, + {0x00, 0x37, 0x1d, 0xaa}, + {0x00, 0x38, 0x71, 0xaa}, + {0x00, 0x39, 0x2a, 0xaa}, + {0x00, 0x3c, 0x78, 0xaa}, + {0x00, 0x4d, 0x40, 0xaa}, + {0x00, 0x4e, 0x20, 0xaa}, + {0x00, 0x74, 0x19, 0xaa}, + {0x00, 0x8d, 0x4f, 0xaa}, + {0x00, 0x8e, 0x00, 0xaa}, + {0x00, 0x8f, 0x00, 0xaa}, + {0x00, 0x90, 0x00, 0xaa}, + {0x00, 0x91, 0x00, 0xaa}, + {0x00, 0x96, 0x00, 0xaa}, + {0x00, 0x9a, 0x80, 0xaa}, + {0x00, 0xb0, 0x84, 0xaa}, + {0x00, 0xb1, 0x0c, 0xaa}, + {0x00, 0xb2, 0x0e, 0xaa}, + {0x00, 0xb3, 0x82, 0xaa}, + {0x00, 0xb8, 0x0a, 0xaa}, + {0x00, 0x43, 0x14, 0xaa}, + {0x00, 0x44, 0xf0, 0xaa}, + {0x00, 0x45, 0x45, 0xaa}, + {0x00, 0x46, 0x63, 0xaa}, + {0x00, 0x47, 0x2d, 0xaa}, + {0x00, 0x48, 0x46, 0xaa}, + {0x00, 0x59, 0x88, 0xaa}, + {0x00, 0x5a, 0xa0, 0xaa}, + {0x00, 0x5b, 0xc6, 0xaa}, + {0x00, 0x5c, 0x7d, 0xaa}, + {0x00, 0x5d, 0x5f, 0xaa}, + {0x00, 0x5e, 0x19, 0xaa}, + {0x00, 0x6c, 0x0a, 0xaa}, + {0x00, 0x6d, 0x55, 0xaa}, + {0x00, 0x6e, 0x11, 0xaa}, + {0x00, 0x6f, 0x9e, 0xaa}, + {0x00, 0x69, 0x00, 0xaa}, + {0x00, 0x6a, 0x40, 0xaa}, + {0x00, 0x01, 0x40, 0xaa}, + {0x00, 0x02, 0x40, 0xaa}, + {0x00, 0x13, 0xe7, 0xaa}, + {0x00, 0x5f, 0xf0, 0xaa}, + {0x00, 0x60, 0xf0, 0xaa}, + {0x00, 0x61, 0xf0, 0xaa}, + {0x00, 0x27, 0xa0, 0xaa}, + {0x00, 0x28, 0x80, 0xaa}, + {0x00, 0x2c, 0x90, 0xaa}, + {0x00, 0x4f, 0x66, 0xaa}, + {0x00, 0x50, 0x66, 0xaa}, + {0x00, 0x51, 0x00, 0xaa}, + {0x00, 0x52, 0x22, 0xaa}, + {0x00, 0x53, 0x5e, 0xaa}, + {0x00, 0x54, 0x80, 0xaa}, + {0x00, 0x58, 0x9e, 0xaa}, + {0x00, 0x41, 0x08, 0xaa}, + {0x00, 0x3f, 0x00, 0xaa}, + {0x00, 0x75, 0x85, 0xaa}, + {0x00, 0x76, 0xe1, 0xaa}, + {0x00, 0x4c, 0x00, 0xaa}, + {0x00, 0x77, 0x0a, 0xaa}, + {0x00, 0x3d, 0x88, 0xaa}, + {0x00, 0x4b, 0x09, 0xaa}, + {0x00, 0xc9, 0x60, 0xaa}, + {0x00, 0x41, 0x38, 0xaa}, + {0x00, 0x62, 0x30, 0xaa}, + {0x00, 0x63, 0x30, 0xaa}, + {0x00, 0x64, 0x08, 0xaa}, + {0x00, 0x94, 0x07, 0xaa}, + {0x00, 0x95, 0x0b, 0xaa}, + {0x00, 0x65, 0x00, 0xaa}, + {0x00, 0x66, 0x05, 0xaa}, + {0x00, 0x56, 0x50, 0xaa}, + {0x00, 0x34, 0x11, 0xaa}, + {0x00, 0xa4, 0x88, 0xaa}, + {0x00, 0x96, 0x00, 0xaa}, + {0x00, 0x97, 0x30, 0xaa}, + {0x00, 0x98, 0x20, 0xaa}, + {0x00, 0x99, 0x30, 0xaa}, + {0x00, 0x9a, 0x84, 0xaa}, + {0x00, 0x9b, 0x29, 0xaa}, + {0x00, 0x9c, 0x03, 0xaa}, + {0x00, 0x78, 0x04, 0xaa}, + {0x00, 0x79, 0x01, 0xaa}, + {0x00, 0xc8, 0xf0, 0xaa}, + {0x00, 0x79, 0x0f, 0xaa}, + {0x00, 0xc8, 0x00, 0xaa}, + {0x00, 0x79, 0x10, 0xaa}, + {0x00, 0xc8, 0x7e, 0xaa}, + {0x00, 0x79, 0x0a, 0xaa}, + {0x00, 0xc8, 0x80, 0xaa}, + {0x00, 0x79, 0x0b, 0xaa}, + {0x00, 0xc8, 0x01, 0xaa}, + {0x00, 0x79, 0x0c, 0xaa}, + {0x00, 0xc8, 0x0f, 0xaa}, + {0x00, 0x79, 0x0d, 0xaa}, + {0x00, 0xc8, 0x20, 0xaa}, + {0x00, 0x79, 0x09, 0xaa}, + {0x00, 0xc8, 0x80, 0xaa}, + {0x00, 0x79, 0x02, 0xaa}, + {0x00, 0xc8, 0xc0, 0xaa}, + {0x00, 0x79, 0x03, 0xaa}, + {0x00, 0xc8, 0x40, 0xaa}, + {0x00, 0x79, 0x05, 0xaa}, + {0x00, 0xc8, 0x30, 0xaa}, + {0x00, 0x79, 0x26, 0xaa}, + {0x00, 0x11, 0x40, 0xaa}, + {0x00, 0x3a, 0x04, 0xaa}, + {0x00, 0x12, 0x00, 0xaa}, + {0x00, 0x40, 0xc0, 0xaa}, + {0x00, 0x8c, 0x00, 0xaa}, + {0x00, 0x17, 0x14, 0xaa}, + {0x00, 0x18, 0x02, 0xaa}, + {0x00, 0x32, 0x92, 0xaa}, + {0x00, 0x19, 0x02, 0xaa}, + {0x00, 0x1a, 0x7a, 0xaa}, + {0x00, 0x03, 0x0a, 0xaa}, + {0x00, 0x0c, 0x00, 0xaa}, + {0x00, 0x3e, 0x00, 0xaa}, + {0x00, 0x70, 0x3a, 0xaa}, + {0x00, 0x71, 0x35, 0xaa}, + {0x00, 0x72, 0x11, 0xaa}, + {0x00, 0x73, 0xf0, 0xaa}, + {0x00, 0xa2, 0x02, 0xaa}, + {0x00, 0xb1, 0x00, 0xaa}, + {0x00, 0xb1, 0x0c, 0xaa}, {0x00, 0x1e, 0x37, 0xaa}, /* MVFP */ {0x00, 0xaa, 0x14, 0xaa}, - {0x00, 0x24, 0x80, 0xaa}, {0x00, 0x25, 0x74, 0xaa}, - {0x00, 0x26, 0xd3, 0xaa}, {0x00, 0x0d, 0x00, 0xaa}, - {0x00, 0x14, 0x18, 0xaa}, {0x00, 0x9d, 0x99, 0xaa}, - {0x00, 0x9e, 0x7f, 0xaa}, {0x00, 0x64, 0x08, 0xaa}, - {0x00, 0x94, 0x07, 0xaa}, {0x00, 0x95, 0x06, 0xaa}, - {0x00, 0x66, 0x05, 0xaa}, {0x00, 0x41, 0x08, 0xaa}, - {0x00, 0x3f, 0x00, 0xaa}, {0x00, 0x75, 0x07, 0xaa}, - {0x00, 0x76, 0xe1, 0xaa}, {0x00, 0x4c, 0x00, 0xaa}, - {0x00, 0x77, 0x00, 0xaa}, {0x00, 0x3d, 0xc2, 0xaa}, - {0x00, 0x4b, 0x09, 0xaa}, {0x00, 0xc9, 0x60, 0xaa}, - {0x00, 0x41, 0x38, 0xaa}, {0xb6, 0x00, 0x00, 0xcc}, - {0xb6, 0x03, 0x01, 0xcc}, {0xb6, 0x02, 0x40, 0xcc}, - {0xb6, 0x05, 0x00, 0xcc}, {0xb6, 0x04, 0xf0, 0xcc}, - {0xb6, 0x12, 0xf8, 0xcc}, {0xb6, 0x13, 0x21, 0xcc}, - {0xb6, 0x18, 0x00, 0xcc}, {0xb6, 0x17, 0x96, 0xcc}, - {0xb6, 0x16, 0x00, 0xcc}, {0xb6, 0x22, 0x12, 0xcc}, - {0xb6, 0x23, 0x0b, 0xcc}, {0xbf, 0xc0, 0x39, 0xcc}, - {0xbf, 0xc1, 0x04, 0xcc}, {0xbf, 0xcc, 0x00, 0xcc}, - {0xbc, 0x02, 0x18, 0xcc}, {0xbc, 0x03, 0x50, 0xcc}, - {0xbc, 0x04, 0x18, 0xcc}, {0xbc, 0x05, 0x00, 0xcc}, - {0xbc, 0x06, 0x00, 0xcc}, {0xbc, 0x08, 0x30, 0xcc}, - {0xbc, 0x09, 0x40, 0xcc}, {0xbc, 0x0a, 0x10, 0xcc}, - {0xbc, 0x0b, 0x00, 0xcc}, {0xbc, 0x0c, 0x00, 0xcc}, - {0xb3, 0x5c, 0x01, 0xcc}, {0xb3, 0x01, 0x45, 0xcc}, - {0x00, 0x77, 0x05, 0xaa }, + {0x00, 0x24, 0x80, 0xaa}, + {0x00, 0x25, 0x74, 0xaa}, + {0x00, 0x26, 0xd3, 0xaa}, + {0x00, 0x0d, 0x00, 0xaa}, + {0x00, 0x14, 0x18, 0xaa}, + {0x00, 0x9d, 0x99, 0xaa}, + {0x00, 0x9e, 0x7f, 0xaa}, + {0x00, 0x64, 0x08, 0xaa}, + {0x00, 0x94, 0x07, 0xaa}, + {0x00, 0x95, 0x06, 0xaa}, + {0x00, 0x66, 0x05, 0xaa}, + {0x00, 0x41, 0x08, 0xaa}, + {0x00, 0x3f, 0x00, 0xaa}, + {0x00, 0x75, 0x07, 0xaa}, + {0x00, 0x76, 0xe1, 0xaa}, + {0x00, 0x4c, 0x00, 0xaa}, + {0x00, 0x77, 0x00, 0xaa}, + {0x00, 0x3d, 0xc2, 0xaa}, + {0x00, 0x4b, 0x09, 0xaa}, + {0x00, 0xc9, 0x60, 0xaa}, + {0x00, 0x41, 0x38, 0xaa}, + {0xbc, 0x02, 0x18, 0xcc}, + {0xbc, 0x03, 0x50, 0xcc}, + {0xbc, 0x04, 0x18, 0xcc}, + {0xbc, 0x05, 0x00, 0xcc}, + {0xbc, 0x06, 0x00, 0xcc}, + {0xbc, 0x08, 0x30, 0xcc}, + {0xbc, 0x09, 0x40, 0xcc}, + {0xbc, 0x0a, 0x10, 0xcc}, + {0xbc, 0x0b, 0x00, 0xcc}, + {0xbc, 0x0c, 0x00, 0xcc}, + {0xbf, 0xc0, 0x26, 0xcc}, + {0xbf, 0xc1, 0x02, 0xcc}, + {0xbf, 0xcc, 0x04, 0xcc}, + {0xb3, 0x5c, 0x01, 0xcc}, + {0xb3, 0x01, 0x45, 0xcc}, + {0x00, 0x77, 0x05, 0xaa}, {}, }; @@ -3117,6 +3338,10 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->cam_mode = bi_mode; cam->nmodes = ARRAY_SIZE(bi_mode); break; + case SENSOR_OV7670: + cam->cam_mode = bi_mode; + cam->nmodes = ARRAY_SIZE(bi_mode) - 1; + break; default: cam->cam_mode = vc0323_mode; cam->nmodes = ARRAY_SIZE(vc0323_mode) - 1; @@ -3329,14 +3554,6 @@ static int sd_start(struct gspca_dev *gspca_dev) else init = ov7660_initVGA_data; /* 640x480 */ break; - case SENSOR_OV7670: - /*GammaT = ov7660_gamma; */ - /*MatrixT = ov7660_matrix; */ - if (mode) - init = ov7670_initQVGA_JPG; /* 320x240 */ - else - init = ov7670_initVGA_JPG; /* 640x480 */ - break; case SENSOR_MI0360: GammaT = mi1320_gamma; MatrixT = mi0360_matrix; @@ -3373,6 +3590,9 @@ static int sd_start(struct gspca_dev *gspca_dev) MatrixT = mi1320_matrix; init = mi1320_soc_init[mode]; break; + case SENSOR_OV7670: + init = mode == 1 ? ov7670_InitVGA : ov7670_InitQVGA; + break; case SENSOR_PO3130NC: GammaT = po3130_gamma; MatrixT = po3130_matrix; @@ -3426,7 +3646,13 @@ static int sd_start(struct gspca_dev *gspca_dev) sethvflip(gspca_dev); setlightfreq(gspca_dev); } - if (sd->sensor == SENSOR_POxxxx) { + switch (sd->sensor) { + case SENSOR_OV7670: + reg_w(gspca_dev->dev, 0x87, 0xffff, 0xffff); + reg_w(gspca_dev->dev, 0x88, 0xff00, 0xf0f1); + reg_w(gspca_dev->dev, 0xa0, 0x0000, 0xbfff); + break; + case SENSOR_POxxxx: setcolors(gspca_dev); setbrightness(gspca_dev); setcontrast(gspca_dev); @@ -3435,6 +3661,7 @@ static int sd_start(struct gspca_dev *gspca_dev) msleep(80); reg_w(gspca_dev->dev, 0x89, 0xffff, 0xfdff); usb_exchange(gspca_dev, poxxxx_init_end_2); + break; } return 0; } -- cgit v1.2.3-70-g09d2 From 108bdd7ad778ac4616857820cbbc17924073a7d5 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 5 Apr 2010 16:05:39 -0300 Subject: V4L/DVB: pvrusb2-v4l2: Rename dev_info to pdi There is a macro called dev_info that prints struct device specific information. Having variables with the same name can be confusing and prevents conversion of the macro to a function. Rename the existing dev_info variables to something else in preparation to converting the dev_info macro to a function. Signed-off-by: Joe Perches Acked-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-v4l2.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index bf1e0fe9f4d..fe4159d478b 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c @@ -49,7 +49,7 @@ struct pvr2_v4l2_dev { struct pvr2_v4l2_fh { struct pvr2_channel channel; - struct pvr2_v4l2_dev *dev_info; + struct pvr2_v4l2_dev *pdi; enum v4l2_priority prio; struct pvr2_ioread *rhp; struct file *file; @@ -162,7 +162,7 @@ static long pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct pvr2_v4l2_fh *fh = file->private_data; struct pvr2_v4l2 *vp = fh->vhead; - struct pvr2_v4l2_dev *dev_info = fh->dev_info; + struct pvr2_v4l2_dev *pdi = fh->pdi; struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; long ret = -EINVAL; @@ -564,14 +564,14 @@ static long pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) case VIDIOC_STREAMON: { - if (!fh->dev_info->stream) { + if (!fh->pdi->stream) { /* No stream defined for this node. This means that we're not currently allowed to stream from this node. */ ret = -EPERM; break; } - ret = pvr2_hdw_set_stream_type(hdw,dev_info->config); + ret = pvr2_hdw_set_stream_type(hdw,pdi->config); if (ret < 0) return ret; ret = pvr2_hdw_set_streaming(hdw,!0); break; @@ -579,7 +579,7 @@ static long pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) case VIDIOC_STREAMOFF: { - if (!fh->dev_info->stream) { + if (!fh->pdi->stream) { /* No stream defined for this node. This means that we're not currently allowed to stream from this node. */ @@ -1032,7 +1032,7 @@ static int pvr2_v4l2_open(struct file *file) } init_waitqueue_head(&fhp->wait_data); - fhp->dev_info = dip; + fhp->pdi = dip; pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp); pvr2_channel_init(&fhp->channel,vp->channel.mc_head); @@ -1113,7 +1113,7 @@ static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh) struct pvr2_hdw *hdw; if (fh->rhp) return 0; - if (!fh->dev_info->stream) { + if (!fh->pdi->stream) { /* No stream defined for this node. This means that we're not currently allowed to stream from this node. */ return -EPERM; @@ -1122,21 +1122,21 @@ static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh) /* First read() attempt. Try to claim the stream and start it... */ if ((ret = pvr2_channel_claim_stream(&fh->channel, - fh->dev_info->stream)) != 0) { + fh->pdi->stream)) != 0) { /* Someone else must already have it */ return ret; } - fh->rhp = pvr2_channel_create_mpeg_stream(fh->dev_info->stream); + fh->rhp = pvr2_channel_create_mpeg_stream(fh->pdi->stream); if (!fh->rhp) { pvr2_channel_claim_stream(&fh->channel,NULL); return -ENOMEM; } hdw = fh->channel.mc_head->hdw; - sp = fh->dev_info->stream->stream; + sp = fh->pdi->stream->stream; pvr2_stream_set_callback(sp,(pvr2_stream_callback)pvr2_v4l2_notify,fh); - pvr2_hdw_set_stream_type(hdw,fh->dev_info->config); + pvr2_hdw_set_stream_type(hdw,fh->pdi->config); if ((ret = pvr2_hdw_set_streaming(hdw,!0)) < 0) return ret; return pvr2_ioread_set_enabled(fh->rhp,!0); } -- cgit v1.2.3-70-g09d2 From 65c6edb300ee5c2aaac6d20c5fc8d11c3827593e Mon Sep 17 00:00:00 2001 From: Dean Anderson Date: Tue, 20 Apr 2010 17:21:32 -0300 Subject: V4L/DVB: s2255drv: fix: v4l2_dev should be registered once only. usb_set_intfdata should not be used when using v4l2_device_register and a non-NULL argument for the device. Signed-off-by: Dean Anderson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s2255drv.c | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index e1de2c4940b..e6dc7fac5b0 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c @@ -229,7 +229,7 @@ struct s2255_fmt; /*forward declaration */ struct s2255_dev { struct video_device vdev[MAX_CHANNELS]; - struct v4l2_device v4l2_dev[MAX_CHANNELS]; + struct v4l2_device v4l2_dev; int channels; /* number of channels registered */ int frames; struct mutex lock; @@ -278,7 +278,14 @@ struct s2255_dev { u16 pid; /* product id */ struct kref kref; }; -#define to_s2255_dev(d) container_of(d, struct s2255_dev, kref) + +/* kref will be removed soon */ +#define to_s2255_dev_from_kref(d) container_of(d, struct s2255_dev, kref) + +static inline struct s2255_dev *to_s2255_dev(struct v4l2_device *v4l2_dev) +{ + return container_of(v4l2_dev, struct s2255_dev, v4l2_dev); +} struct s2255_fmt { char *name; @@ -1829,7 +1836,7 @@ static unsigned int s2255_poll(struct file *file, static void s2255_destroy(struct kref *kref) { - struct s2255_dev *dev = to_s2255_dev(kref); + struct s2255_dev *dev = to_s2255_dev_from_kref(kref); /* board shutdown stops the read pipe if it is running */ s2255_board_shutdown(dev); /* make sure firmware still not trying to load */ @@ -1947,11 +1954,9 @@ static int s2255_probe_v4l(struct s2255_dev *dev) int ret; int i; int cur_nr = video_nr; - for (i = 0; i < MAX_CHANNELS; i++) { - ret = v4l2_device_register(&dev->udev->dev, &dev->v4l2_dev[i]); - if (ret) - goto unreg_v4l2; - } + ret = v4l2_device_register(&dev->interface->dev, &dev->v4l2_dev); + if (ret) + return ret; /* initialize all video 4 linux */ /* register 4 video devices */ for (i = 0; i < MAX_CHANNELS; i++) { @@ -1976,7 +1981,7 @@ static int s2255_probe_v4l(struct s2255_dev *dev) break; } dev->channels++; - v4l2_info(&dev->v4l2_dev[i], "V4L2 device registered as %s\n", + v4l2_info(&dev->v4l2_dev, "V4L2 device registered as %s\n", video_device_node_name(&dev->vdev[i])); } @@ -1985,15 +1990,13 @@ static int s2255_probe_v4l(struct s2255_dev *dev) S2255_MAJOR_VERSION, S2255_MINOR_VERSION); /* if no channels registered, return error and probe will fail*/ - if (dev->channels == 0) + if (dev->channels == 0) { + v4l2_device_unregister(&dev->v4l2_dev); return ret; + } if (dev->channels != MAX_CHANNELS) printk(KERN_WARNING "s2255: Not all channels available.\n"); return 0; -unreg_v4l2: - for (i-- ; i > 0; i--) - v4l2_device_unregister(&dev->v4l2_dev[i]); - return ret; } /* this function moves the usb stream read pipe data @@ -2596,8 +2599,6 @@ static int s2255_probe(struct usb_interface *interface, dev_err(&interface->dev, "Could not find bulk-in endpoint\n"); goto errorEP; } - /* set intfdata */ - usb_set_intfdata(interface, dev); init_timer(&dev->timer); dev->timer.function = s2255_timer; dev->timer.data = (unsigned long)dev->fw_data; @@ -2682,13 +2683,12 @@ errorFWDATA1: return retval; } - /* disconnect routine. when board is removed physically or with rmmod */ static void s2255_disconnect(struct usb_interface *interface) { - struct s2255_dev *dev = NULL; + struct s2255_dev *dev = to_s2255_dev(usb_get_intfdata(interface)); int i; - dev = usb_get_intfdata(interface); + v4l2_device_unregister(&dev->v4l2_dev); /* unregister each video device. */ for (i = 0; i < MAX_CHANNELS; i++) if (video_is_registered(&dev->vdev[i])) @@ -2702,7 +2702,6 @@ static void s2255_disconnect(struct usb_interface *interface) dev->vidstatus_ready[i] = 1; wake_up(&dev->wait_vidstatus[i]); } - usb_set_intfdata(interface, NULL); kref_put(&dev->kref, s2255_destroy); dev_info(&interface->dev, "%s\n", __func__); } -- cgit v1.2.3-70-g09d2 From d62e85a0949d2b899405a1ffbae06615227d4c97 Mon Sep 17 00:00:00 2001 From: Dean Anderson Date: Fri, 9 Apr 2010 19:54:26 -0300 Subject: V4L/DVB: s2255drv: removes kref tracking and videodev parent kref replaced as suggested in code review uses atomic variable to track when it is ok to delete device removes setting of video device parent, which is now handled in v4l2_device.c Signed-off-by: Dean Anderson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s2255drv.c | 43 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 22 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index e6dc7fac5b0..4dc001b0519 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c @@ -230,7 +230,7 @@ struct s2255_fmt; /*forward declaration */ struct s2255_dev { struct video_device vdev[MAX_CHANNELS]; struct v4l2_device v4l2_dev; - int channels; /* number of channels registered */ + atomic_t channels; /* number of channels registered */ int frames; struct mutex lock; struct mutex open_lock; @@ -276,12 +276,8 @@ struct s2255_dev { /* dsp firmware version (f2255usb.bin) */ int dsp_fw_ver; u16 pid; /* product id */ - struct kref kref; }; -/* kref will be removed soon */ -#define to_s2255_dev_from_kref(d) container_of(d, struct s2255_dev, kref) - static inline struct s2255_dev *to_s2255_dev(struct v4l2_device *v4l2_dev) { return container_of(v4l2_dev, struct s2255_dev, v4l2_dev); @@ -372,7 +368,7 @@ static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn, struct s2255_mode *mode); static int s2255_board_shutdown(struct s2255_dev *dev); static void s2255_fwload_start(struct s2255_dev *dev, int reset); -static void s2255_destroy(struct kref *kref); +static void s2255_destroy(struct s2255_dev *dev); static long s2255_vendor_req(struct s2255_dev *dev, unsigned char req, u16 index, u16 value, void *buf, s32 buf_len, int bOut); @@ -1720,7 +1716,7 @@ static int s2255_open(struct file *file) dprintk(1, "s2255: open called (dev=%s)\n", video_device_node_name(vdev)); - for (i = 0; i < dev->channels; i++) + for (i = 0; i < MAX_CHANNELS; i++) if (&dev->vdev[i] == vdev) { cur_channel = i; break; @@ -1834,9 +1830,8 @@ static unsigned int s2255_poll(struct file *file, return rc; } -static void s2255_destroy(struct kref *kref) +static void s2255_destroy(struct s2255_dev *dev) { - struct s2255_dev *dev = to_s2255_dev_from_kref(kref); /* board shutdown stops the read pipe if it is running */ s2255_board_shutdown(dev); /* make sure firmware still not trying to load */ @@ -1936,7 +1931,9 @@ static const struct v4l2_ioctl_ops s2255_ioctl_ops = { static void s2255_video_device_release(struct video_device *vdev) { struct s2255_dev *dev = video_get_drvdata(vdev); - kref_put(&dev->kref, s2255_destroy); + dprintk(4, "%s, chnls: %d \n", __func__, atomic_read(&dev->channels)); + if (atomic_dec_and_test(&dev->channels)) + s2255_destroy(dev); return; } @@ -1965,7 +1962,8 @@ static int s2255_probe_v4l(struct s2255_dev *dev) dev->vidq[i].channel = i; /* register 4 video devices */ memcpy(&dev->vdev[i], &template, sizeof(struct video_device)); - dev->vdev[i].parent = &dev->interface->dev; + dev->vdev[i].v4l2_dev = &dev->v4l2_dev; + video_set_drvdata(&dev->vdev[i], dev); if (video_nr == -1) ret = video_register_device(&dev->vdev[i], VFL_TYPE_GRABBER, @@ -1974,13 +1972,12 @@ static int s2255_probe_v4l(struct s2255_dev *dev) ret = video_register_device(&dev->vdev[i], VFL_TYPE_GRABBER, cur_nr + i); - video_set_drvdata(&dev->vdev[i], dev); if (ret) { dev_err(&dev->udev->dev, "failed to register video device!\n"); break; } - dev->channels++; + atomic_inc(&dev->channels); v4l2_info(&dev->v4l2_dev, "V4L2 device registered as %s\n", video_device_node_name(&dev->vdev[i])); @@ -1990,11 +1987,11 @@ static int s2255_probe_v4l(struct s2255_dev *dev) S2255_MAJOR_VERSION, S2255_MINOR_VERSION); /* if no channels registered, return error and probe will fail*/ - if (dev->channels == 0) { + if (atomic_read(&dev->channels) == 0) { v4l2_device_unregister(&dev->v4l2_dev); return ret; } - if (dev->channels != MAX_CHANNELS) + if (atomic_read(&dev->channels) != MAX_CHANNELS) printk(KERN_WARNING "s2255: Not all channels available.\n"); return 0; } @@ -2567,7 +2564,7 @@ static int s2255_probe(struct usb_interface *interface, s2255_dev_err(&interface->dev, "out of memory\n"); return -ENOMEM; } - kref_init(&dev->kref); + atomic_set(&dev->channels, 0); dev->pid = id->idProduct; dev->fw_data = kzalloc(sizeof(struct s2255_fw), GFP_KERNEL); if (!dev->fw_data) @@ -2581,7 +2578,7 @@ static int s2255_probe(struct usb_interface *interface, retval = -ENODEV; goto errorUDEV; } - dprintk(1, "dev: %p, kref: %p udev %p interface %p\n", dev, &dev->kref, + dprintk(1, "dev: %p, udev %p interface %p\n", dev, dev->udev, interface); dev->interface = interface; /* set up the endpoint information */ @@ -2652,9 +2649,6 @@ static int s2255_probe(struct usb_interface *interface, goto errorBOARDINIT; spin_lock_init(&dev->slock); s2255_fwload_start(dev, 0); - /* kref for each vdev. Released on video_device_release callback */ - for (i = 0; i < MAX_CHANNELS; i++) - kref_get(&dev->kref); /* loads v4l specific */ retval = s2255_probe_v4l(dev); if (retval) @@ -2688,11 +2682,15 @@ static void s2255_disconnect(struct usb_interface *interface) { struct s2255_dev *dev = to_s2255_dev(usb_get_intfdata(interface)); int i; + int channels = atomic_read(&dev->channels); v4l2_device_unregister(&dev->v4l2_dev); + /*see comments in the uvc_driver.c usb disconnect function */ + atomic_inc(&dev->channels); /* unregister each video device. */ - for (i = 0; i < MAX_CHANNELS; i++) + for (i = 0; i < channels; i++) { if (video_is_registered(&dev->vdev[i])) video_unregister_device(&dev->vdev[i]); + } /* wake up any of our timers */ atomic_set(&dev->fw_data->fw_state, S2255_FW_DISCONNECTING); wake_up(&dev->fw_data->wait_fw); @@ -2702,7 +2700,8 @@ static void s2255_disconnect(struct usb_interface *interface) dev->vidstatus_ready[i] = 1; wake_up(&dev->wait_vidstatus[i]); } - kref_put(&dev->kref, s2255_destroy); + if (atomic_dec_and_test(&dev->channels)) + s2255_destroy(dev); dev_info(&interface->dev, "%s\n", __func__); } -- cgit v1.2.3-70-g09d2 From eb78deecb496a8b0888d24f1cfa73f6e907b82e2 Mon Sep 17 00:00:00 2001 From: Dean Anderson Date: Mon, 12 Apr 2010 15:05:37 -0300 Subject: V4L/DVB: s2255drv: firmware reload on timeout Signed-off-by: Dean Anderson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s2255drv.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index 4dc001b0519..ac9c40cf583 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c @@ -58,7 +58,7 @@ #include #define S2255_MAJOR_VERSION 1 -#define S2255_MINOR_VERSION 19 +#define S2255_MINOR_VERSION 20 #define S2255_RELEASE 0 #define S2255_VERSION KERNEL_VERSION(S2255_MAJOR_VERSION, \ S2255_MINOR_VERSION, \ @@ -1755,7 +1755,7 @@ static int s2255_open(struct file *file) == S2255_FW_SUCCESS) || (atomic_read(&dev->fw_data->fw_state) == S2255_FW_DISCONNECTING)), - msecs_to_jiffies(S2255_LOAD_TIMEOUT)); + msecs_to_jiffies(S2255_LOAD_TIMEOUT)); /* state may have changed, re-read */ state = atomic_read(&dev->fw_data->fw_state); break; @@ -1763,27 +1763,38 @@ static int s2255_open(struct file *file) default: break; } - mutex_unlock(&dev->open_lock); /* state may have changed in above switch statement */ switch (state) { case S2255_FW_SUCCESS: break; case S2255_FW_FAILED: printk(KERN_INFO "2255 firmware load failed.\n"); + mutex_unlock(&dev->open_lock); return -ENODEV; case S2255_FW_DISCONNECTING: printk(KERN_INFO "%s: disconnecting\n", __func__); + mutex_unlock(&dev->open_lock); return -ENODEV; case S2255_FW_LOADED_DSPWAIT: case S2255_FW_NOTLOADED: printk(KERN_INFO "%s: firmware not loaded yet" "please try again later\n", __func__); + /* + * Timeout on firmware load means device unusable. + * Set firmware failure state. + * On next s2255_open the firmware will be reloaded. + */ + atomic_set(&dev->fw_data->fw_state, + S2255_FW_FAILED); + mutex_unlock(&dev->open_lock); return -EAGAIN; default: printk(KERN_INFO "%s: unknown state\n", __func__); + mutex_unlock(&dev->open_lock); return -EFAULT; } + mutex_unlock(&dev->open_lock); /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); if (NULL == fh) @@ -2074,7 +2085,6 @@ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info) dprintk(5, "setmode ready %d\n", cc); break; case S2255_RESPONSE_FW: - dev->chn_ready |= (1 << cc); if ((dev->chn_ready & 0x0f) != 0x0f) break; -- cgit v1.2.3-70-g09d2 From 53aaf07637baae8f53c33b803bbc96047d8da1c4 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 28 Mar 2010 07:54:29 -0300 Subject: V4L/DVB: v4l videobuf: remove mmap_free callback Remove the mmap_free callback from struct videobuf_qtype_ops. All implementations of this callback do the same trivial check: return -EBUSY if any buffer is mmapped. That can also be tested in the videobuf core. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-core.c | 10 ++++------ drivers/media/video/videobuf-dma-contig.c | 14 -------------- drivers/media/video/videobuf-dma-sg.c | 15 --------------- drivers/media/video/videobuf-vmalloc.c | 16 ---------------- include/media/videobuf-core.h | 1 - 5 files changed, 4 insertions(+), 52 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c index 63d7043502d..52bb74b18a6 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/video/videobuf-core.c @@ -311,20 +311,18 @@ static void videobuf_status(struct videobuf_queue *q, struct v4l2_buffer *b, static int __videobuf_mmap_free(struct videobuf_queue *q) { int i; - int rc; if (!q) return 0; MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); - rc = CALL(q, mmap_free, q); + for (i = 0; i < VIDEO_MAX_FRAME; i++) + if (q->bufs[i] && q->bufs[i]->map) + return -EBUSY; q->is_mmapped = 0; - if (rc < 0) - return rc; - for (i = 0; i < VIDEO_MAX_FRAME; i++) { if (NULL == q->bufs[i]) continue; @@ -333,7 +331,7 @@ static int __videobuf_mmap_free(struct videobuf_queue *q) q->bufs[i] = NULL; } - return rc; + return 0; } int videobuf_mmap_free(struct videobuf_queue *q) diff --git a/drivers/media/video/videobuf-dma-contig.c b/drivers/media/video/videobuf-dma-contig.c index dce4f3aa4af..0a32cf810c8 100644 --- a/drivers/media/video/videobuf-dma-contig.c +++ b/drivers/media/video/videobuf-dma-contig.c @@ -263,19 +263,6 @@ static int __videobuf_iolock(struct videobuf_queue *q, return 0; } -static int __videobuf_mmap_free(struct videobuf_queue *q) -{ - unsigned int i; - - dev_dbg(q->dev, "%s\n", __func__); - for (i = 0; i < VIDEO_MAX_FRAME; i++) { - if (q->bufs[i] && q->bufs[i]->map) - return -EBUSY; - } - - return 0; -} - static int __videobuf_mmap_mapper(struct videobuf_queue *q, struct vm_area_struct *vma) { @@ -424,7 +411,6 @@ static struct videobuf_qtype_ops qops = { .alloc = __videobuf_alloc, .iolock = __videobuf_iolock, - .mmap_free = __videobuf_mmap_free, .mmap_mapper = __videobuf_mmap_mapper, .video_copy_to_user = __videobuf_copy_to_user, .copy_stream = __videobuf_copy_stream, diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c index c9d946a388e..7ff275e3009 100644 --- a/drivers/media/video/videobuf-dma-sg.c +++ b/drivers/media/video/videobuf-dma-sg.c @@ -548,20 +548,6 @@ static int __videobuf_sync(struct videobuf_queue *q, return videobuf_dma_sync(q, &mem->dma); } -static int __videobuf_mmap_free(struct videobuf_queue *q) -{ - int i; - - for (i = 0; i < VIDEO_MAX_FRAME; i++) { - if (q->bufs[i]) { - if (q->bufs[i]->map) - return -EBUSY; - } - } - - return 0; -} - static int __videobuf_mmap_mapper(struct videobuf_queue *q, struct vm_area_struct *vma) { @@ -711,7 +697,6 @@ static struct videobuf_qtype_ops sg_ops = { .alloc = __videobuf_alloc, .iolock = __videobuf_iolock, .sync = __videobuf_sync, - .mmap_free = __videobuf_mmap_free, .mmap_mapper = __videobuf_mmap_mapper, .video_copy_to_user = __videobuf_copy_to_user, .copy_stream = __videobuf_copy_stream, diff --git a/drivers/media/video/videobuf-vmalloc.c b/drivers/media/video/videobuf-vmalloc.c index d6a8a38dc9c..43c92882e4c 100644 --- a/drivers/media/video/videobuf-vmalloc.c +++ b/drivers/media/video/videobuf-vmalloc.c @@ -235,21 +235,6 @@ static int __videobuf_sync(struct videobuf_queue *q, return 0; } -static int __videobuf_mmap_free(struct videobuf_queue *q) -{ - unsigned int i; - - dprintk(1, "%s\n", __func__); - for (i = 0; i < VIDEO_MAX_FRAME; i++) { - if (q->bufs[i]) { - if (q->bufs[i]->map) - return -EBUSY; - } - } - - return 0; -} - static int __videobuf_mmap_mapper(struct videobuf_queue *q, struct vm_area_struct *vma) { @@ -385,7 +370,6 @@ static struct videobuf_qtype_ops qops = { .alloc = __videobuf_alloc, .iolock = __videobuf_iolock, .sync = __videobuf_sync, - .mmap_free = __videobuf_mmap_free, .mmap_mapper = __videobuf_mmap_mapper, .video_copy_to_user = __videobuf_copy_to_user, .copy_stream = __videobuf_copy_stream, diff --git a/include/media/videobuf-core.h b/include/media/videobuf-core.h index 3896e29a652..345ec5a45c5 100644 --- a/include/media/videobuf-core.h +++ b/include/media/videobuf-core.h @@ -144,7 +144,6 @@ struct videobuf_qtype_ops { size_t pos, int vbihack, int nonblocking); - int (*mmap_free) (struct videobuf_queue *q); int (*mmap_mapper) (struct videobuf_queue *q, struct vm_area_struct *vma); }; -- cgit v1.2.3-70-g09d2 From 63e424856b4ab0652c58f75a2d2ecb9c1f95db27 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 28 Mar 2010 07:59:11 -0300 Subject: V4L/DVB: v4l videobuf: remove unused is_mmapped field Thanks to Pawel Osciak for noticing this. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-core.c | 3 --- include/media/videobuf-core.h | 1 - 2 files changed, 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c index 52bb74b18a6..d76a7d50002 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/video/videobuf-core.c @@ -321,8 +321,6 @@ static int __videobuf_mmap_free(struct videobuf_queue *q) if (q->bufs[i] && q->bufs[i]->map) return -EBUSY; - q->is_mmapped = 0; - for (i = 0; i < VIDEO_MAX_FRAME; i++) { if (NULL == q->bufs[i]) continue; @@ -1089,7 +1087,6 @@ int videobuf_mmap_mapper(struct videobuf_queue *q, struct vm_area_struct *vma) mutex_lock(&q->vb_lock); retval = CALL(q, mmap_mapper, q, vma); - q->is_mmapped = 1; mutex_unlock(&q->vb_lock); return retval; diff --git a/include/media/videobuf-core.h b/include/media/videobuf-core.h index 345ec5a45c5..22d5a02884a 100644 --- a/include/media/videobuf-core.h +++ b/include/media/videobuf-core.h @@ -166,7 +166,6 @@ struct videobuf_queue { unsigned int streaming:1; unsigned int reading:1; - unsigned int is_mmapped:1; /* capture via mmap() + ioctl(QBUF/DQBUF) */ struct list_head stream; -- cgit v1.2.3-70-g09d2 From a4cf4cac2979a828e7cd0a3cd02d7a5308a44a7f Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 28 Mar 2010 08:09:44 -0300 Subject: V4L/DVB: v4l videobuf: use struct videobuf_buffer * instead of void * for videobuf_alloc videobuf_alloc() returned a void *. Change to struct videobuf_buffer * to get better type checking. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-core.c | 2 +- drivers/media/video/videobuf-dma-contig.c | 2 +- drivers/media/video/videobuf-dma-sg.c | 2 +- drivers/media/video/videobuf-vmalloc.c | 2 +- include/media/videobuf-core.h | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c index d76a7d50002..7b69f6b00a3 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/video/videobuf-core.c @@ -52,7 +52,7 @@ MODULE_LICENSE("GPL"); #define CALL(q, f, arg...) \ ((q->int_ops->f) ? q->int_ops->f(arg) : 0) -void *videobuf_alloc(struct videobuf_queue *q) +struct videobuf_buffer *videobuf_alloc(struct videobuf_queue *q) { struct videobuf_buffer *vb; diff --git a/drivers/media/video/videobuf-dma-contig.c b/drivers/media/video/videobuf-dma-contig.c index 0a32cf810c8..76e158feca6 100644 --- a/drivers/media/video/videobuf-dma-contig.c +++ b/drivers/media/video/videobuf-dma-contig.c @@ -190,7 +190,7 @@ static int videobuf_dma_contig_user_get(struct videobuf_dma_contig_memory *mem, return ret; } -static void *__videobuf_alloc(size_t size) +static struct videobuf_buffer *__videobuf_alloc(size_t size) { struct videobuf_dma_contig_memory *mem; struct videobuf_buffer *vb; diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c index 7ff275e3009..014eb63c096 100644 --- a/drivers/media/video/videobuf-dma-sg.c +++ b/drivers/media/video/videobuf-dma-sg.c @@ -439,7 +439,7 @@ static const struct vm_operations_struct videobuf_vm_ops = { struct videobuf_dma_sg_memory */ -static void *__videobuf_alloc(size_t size) +static struct videobuf_buffer *__videobuf_alloc(size_t size) { struct videobuf_dma_sg_memory *mem; struct videobuf_buffer *vb; diff --git a/drivers/media/video/videobuf-vmalloc.c b/drivers/media/video/videobuf-vmalloc.c index 43c92882e4c..000a60fc456 100644 --- a/drivers/media/video/videobuf-vmalloc.c +++ b/drivers/media/video/videobuf-vmalloc.c @@ -135,7 +135,7 @@ static const struct vm_operations_struct videobuf_vm_ops = { struct videobuf_dma_sg_memory */ -static void *__videobuf_alloc(size_t size) +static struct videobuf_buffer *__videobuf_alloc(size_t size) { struct videobuf_vmalloc_memory *mem; struct videobuf_buffer *vb; diff --git a/include/media/videobuf-core.h b/include/media/videobuf-core.h index 22d5a02884a..4497e23c9d2 100644 --- a/include/media/videobuf-core.h +++ b/include/media/videobuf-core.h @@ -127,7 +127,7 @@ struct videobuf_queue_ops { struct videobuf_qtype_ops { u32 magic; - void *(*alloc) (size_t size); + struct videobuf_buffer *(*alloc)(size_t size); void *(*vmalloc) (struct videobuf_buffer *buf); int (*iolock) (struct videobuf_queue *q, struct videobuf_buffer *vb, @@ -182,7 +182,7 @@ int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr); int videobuf_iolock(struct videobuf_queue *q, struct videobuf_buffer *vb, struct v4l2_framebuffer *fbuf); -void *videobuf_alloc(struct videobuf_queue* q); +struct videobuf_buffer *videobuf_alloc(struct videobuf_queue *q); /* Used on videobuf-dvb */ void *videobuf_queue_to_vmalloc(struct videobuf_queue *q, -- cgit v1.2.3-70-g09d2 From 037c75eb14cd6adb837f81f0c2b2a52c31c91e69 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 28 Mar 2010 08:18:37 -0300 Subject: V4L/DVB: v4l videobuf: rename .vmalloc to .vaddr Rename the .vmalloc op in struct videobuf_qtype_ops to .vaddr. This op returns the virtual kernel address of a buffer. vaddr is a lot less confusing than vmalloc since this callback does do any allocations. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-core.c | 4 ++-- drivers/media/video/videobuf-dma-contig.c | 4 ++-- drivers/media/video/videobuf-dma-sg.c | 4 ++-- drivers/media/video/videobuf-vmalloc.c | 2 +- include/media/videobuf-core.h | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c index 7b69f6b00a3..26241a83389 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/video/videobuf-core.c @@ -108,8 +108,8 @@ EXPORT_SYMBOL_GPL(videobuf_iolock); void *videobuf_queue_to_vmalloc(struct videobuf_queue *q, struct videobuf_buffer *buf) { - if (q->int_ops->vmalloc) - return q->int_ops->vmalloc(buf); + if (q->int_ops->vaddr) + return q->int_ops->vaddr(buf); else return NULL; } diff --git a/drivers/media/video/videobuf-dma-contig.c b/drivers/media/video/videobuf-dma-contig.c index 76e158feca6..7226ca47cbf 100644 --- a/drivers/media/video/videobuf-dma-contig.c +++ b/drivers/media/video/videobuf-dma-contig.c @@ -204,7 +204,7 @@ static struct videobuf_buffer *__videobuf_alloc(size_t size) return vb; } -static void *__videobuf_to_vmalloc(struct videobuf_buffer *buf) +static void *__videobuf_to_vaddr(struct videobuf_buffer *buf) { struct videobuf_dma_contig_memory *mem = buf->priv; @@ -414,7 +414,7 @@ static struct videobuf_qtype_ops qops = { .mmap_mapper = __videobuf_mmap_mapper, .video_copy_to_user = __videobuf_copy_to_user, .copy_stream = __videobuf_copy_stream, - .vmalloc = __videobuf_to_vmalloc, + .vaddr = __videobuf_to_vaddr, }; void videobuf_queue_dma_contig_init(struct videobuf_queue *q, diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c index 014eb63c096..43e78ee24a1 100644 --- a/drivers/media/video/videobuf-dma-sg.c +++ b/drivers/media/video/videobuf-dma-sg.c @@ -460,7 +460,7 @@ static struct videobuf_buffer *__videobuf_alloc(size_t size) return vb; } -static void *__videobuf_to_vmalloc(struct videobuf_buffer *buf) +static void *__videobuf_to_vaddr(struct videobuf_buffer *buf) { struct videobuf_dma_sg_memory *mem = buf->priv; BUG_ON(!mem); @@ -700,7 +700,7 @@ static struct videobuf_qtype_ops sg_ops = { .mmap_mapper = __videobuf_mmap_mapper, .video_copy_to_user = __videobuf_copy_to_user, .copy_stream = __videobuf_copy_stream, - .vmalloc = __videobuf_to_vmalloc, + .vaddr = __videobuf_to_vaddr, }; void *videobuf_sg_alloc(size_t size) diff --git a/drivers/media/video/videobuf-vmalloc.c b/drivers/media/video/videobuf-vmalloc.c index 000a60fc456..6db412abeac 100644 --- a/drivers/media/video/videobuf-vmalloc.c +++ b/drivers/media/video/videobuf-vmalloc.c @@ -373,7 +373,7 @@ static struct videobuf_qtype_ops qops = { .mmap_mapper = __videobuf_mmap_mapper, .video_copy_to_user = __videobuf_copy_to_user, .copy_stream = __videobuf_copy_stream, - .vmalloc = videobuf_to_vmalloc, + .vaddr = videobuf_to_vmalloc, }; void videobuf_queue_vmalloc_init(struct videobuf_queue *q, diff --git a/include/media/videobuf-core.h b/include/media/videobuf-core.h index 4497e23c9d2..8fe3254ed95 100644 --- a/include/media/videobuf-core.h +++ b/include/media/videobuf-core.h @@ -128,7 +128,7 @@ struct videobuf_qtype_ops { u32 magic; struct videobuf_buffer *(*alloc)(size_t size); - void *(*vmalloc) (struct videobuf_buffer *buf); + void *(*vaddr) (struct videobuf_buffer *buf); int (*iolock) (struct videobuf_queue *q, struct videobuf_buffer *vb, struct v4l2_framebuffer *fbuf); -- cgit v1.2.3-70-g09d2 From f4fce60e8b1559306fa1112287bc8765f6977de3 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 28 Mar 2010 08:33:23 -0300 Subject: V4L/DVB: v4l videobuf: rename videobuf_queue_to_vmalloc to videobuf_queue_to_vaddr Ths function returns the virtual kernel address of the buffer and has nothing to do with allocation. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-core.c | 9 ++++----- drivers/media/video/videobuf-dvb.c | 2 +- include/media/videobuf-core.h | 4 ++-- 3 files changed, 7 insertions(+), 8 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c index 26241a83389..fabe45c4163 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/video/videobuf-core.c @@ -105,15 +105,14 @@ int videobuf_iolock(struct videobuf_queue *q, struct videobuf_buffer *vb, } EXPORT_SYMBOL_GPL(videobuf_iolock); -void *videobuf_queue_to_vmalloc(struct videobuf_queue *q, - struct videobuf_buffer *buf) +void *videobuf_queue_to_vaddr(struct videobuf_queue *q, + struct videobuf_buffer *buf) { if (q->int_ops->vaddr) return q->int_ops->vaddr(buf); - else - return NULL; + return NULL; } -EXPORT_SYMBOL_GPL(videobuf_queue_to_vmalloc); +EXPORT_SYMBOL_GPL(videobuf_queue_to_vaddr); /* --------------------------------------------------------------------- */ diff --git a/drivers/media/video/videobuf-dvb.c b/drivers/media/video/videobuf-dvb.c index 0afb62e63d9..3f76398968b 100644 --- a/drivers/media/video/videobuf-dvb.c +++ b/drivers/media/video/videobuf-dvb.c @@ -67,7 +67,7 @@ static int videobuf_dvb_thread(void *data) try_to_freeze(); /* feed buffer data to demux */ - outp = videobuf_queue_to_vmalloc (&dvb->dvbq, buf); + outp = videobuf_queue_to_vaddr(&dvb->dvbq, buf); if (buf->state == VIDEOBUF_DONE) dvb_dmx_swfilter(&dvb->demux, outp, diff --git a/include/media/videobuf-core.h b/include/media/videobuf-core.h index 8fe3254ed95..f73e297e373 100644 --- a/include/media/videobuf-core.h +++ b/include/media/videobuf-core.h @@ -185,8 +185,8 @@ int videobuf_iolock(struct videobuf_queue *q, struct videobuf_buffer *vb, struct videobuf_buffer *videobuf_alloc(struct videobuf_queue *q); /* Used on videobuf-dvb */ -void *videobuf_queue_to_vmalloc(struct videobuf_queue *q, - struct videobuf_buffer *buf); +void *videobuf_queue_to_vaddr(struct videobuf_queue *q, + struct videobuf_buffer *buf); void videobuf_queue_core_init(struct videobuf_queue *q, const struct videobuf_queue_ops *ops, -- cgit v1.2.3-70-g09d2 From 37111039c9521c751ce0597c129fe6d45ba72818 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 28 Mar 2010 09:22:53 -0300 Subject: V4L/DVB: v4l videobuf: move video_copy_to_user and copy_stream to core The video_copy_to_user and copy_stream ops are almost identical for all videobuf memtype variants. All that is needed is to use the new vaddr op and these functions can be moved into the core, ensuring we have just one single implementation instead of three. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-core.c | 47 ++++++++++++++++++++++++-- drivers/media/video/videobuf-dma-contig.c | 55 ------------------------------- drivers/media/video/videobuf-dma-sg.c | 49 --------------------------- drivers/media/video/videobuf-vmalloc.c | 51 ---------------------------- include/media/videobuf-core.h | 10 ------ 5 files changed, 45 insertions(+), 167 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c index fabe45c4163..f1dfcff44e1 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/video/videobuf-core.c @@ -793,6 +793,49 @@ done: return retval; } +static int __videobuf_copy_to_user(struct videobuf_queue *q, + struct videobuf_buffer *buf, + char __user *data, size_t count, + int nonblocking) +{ + void *vaddr = CALL(q, vaddr, buf); + + /* copy to userspace */ + if (count > buf->size - q->read_off) + count = buf->size - q->read_off; + + if (copy_to_user(data, vaddr + q->read_off, count)) + return -EFAULT; + + return count; +} + +static int __videobuf_copy_stream(struct videobuf_queue *q, + struct videobuf_buffer *buf, + char __user *data, size_t count, size_t pos, + int vbihack, int nonblocking) +{ + unsigned int *fc = CALL(q, vaddr, buf); + + if (vbihack) { + /* dirty, undocumented hack -- pass the frame counter + * within the last four bytes of each vbi data block. + * We need that one to maintain backward compatibility + * to all vbi decoding software out there ... */ + fc += (buf->size >> 2) - 1; + *fc = buf->field_count >> 1; + dprintk(1, "vbihack: %d\n", *fc); + } + + /* copy stuff using the common method */ + count = __videobuf_copy_to_user(q, buf, data, count, nonblocking); + + if ((count == -EFAULT) && (pos == 0)) + return -EFAULT; + + return count; +} + ssize_t videobuf_read_one(struct videobuf_queue *q, char __user *data, size_t count, loff_t *ppos, int nonblocking) @@ -861,7 +904,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, } /* Copy to userspace */ - retval = CALL(q, video_copy_to_user, q, data, count, nonblocking); + retval = __videobuf_copy_to_user(q, q->read_buf, data, count, nonblocking); if (retval < 0) goto done; @@ -1003,7 +1046,7 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q, } if (q->read_buf->state == VIDEOBUF_DONE) { - rc = CALL(q, copy_stream, q, data + retval, count, + rc = __videobuf_copy_stream(q, q->read_buf, data + retval, count, retval, vbihack, nonblocking); if (rc < 0) { retval = rc; diff --git a/drivers/media/video/videobuf-dma-contig.c b/drivers/media/video/videobuf-dma-contig.c index 7226ca47cbf..0a0ff85140b 100644 --- a/drivers/media/video/videobuf-dma-contig.c +++ b/drivers/media/video/videobuf-dma-contig.c @@ -353,67 +353,12 @@ error: return -ENOMEM; } -static int __videobuf_copy_to_user(struct videobuf_queue *q, - char __user *data, size_t count, - int nonblocking) -{ - struct videobuf_dma_contig_memory *mem = q->read_buf->priv; - void *vaddr; - - BUG_ON(!mem); - MAGIC_CHECK(mem->magic, MAGIC_DC_MEM); - BUG_ON(!mem->vaddr); - - /* copy to userspace */ - if (count > q->read_buf->size - q->read_off) - count = q->read_buf->size - q->read_off; - - vaddr = mem->vaddr; - - if (copy_to_user(data, vaddr + q->read_off, count)) - return -EFAULT; - - return count; -} - -static int __videobuf_copy_stream(struct videobuf_queue *q, - char __user *data, size_t count, size_t pos, - int vbihack, int nonblocking) -{ - unsigned int *fc; - struct videobuf_dma_contig_memory *mem = q->read_buf->priv; - - BUG_ON(!mem); - MAGIC_CHECK(mem->magic, MAGIC_DC_MEM); - - if (vbihack) { - /* dirty, undocumented hack -- pass the frame counter - * within the last four bytes of each vbi data block. - * We need that one to maintain backward compatibility - * to all vbi decoding software out there ... */ - fc = (unsigned int *)mem->vaddr; - fc += (q->read_buf->size >> 2) - 1; - *fc = q->read_buf->field_count >> 1; - dev_dbg(q->dev, "vbihack: %d\n", *fc); - } - - /* copy stuff using the common method */ - count = __videobuf_copy_to_user(q, data, count, nonblocking); - - if ((count == -EFAULT) && (pos == 0)) - return -EFAULT; - - return count; -} - static struct videobuf_qtype_ops qops = { .magic = MAGIC_QTYPE_OPS, .alloc = __videobuf_alloc, .iolock = __videobuf_iolock, .mmap_mapper = __videobuf_mmap_mapper, - .video_copy_to_user = __videobuf_copy_to_user, - .copy_stream = __videobuf_copy_stream, .vaddr = __videobuf_to_vaddr, }; diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c index 43e78ee24a1..5c55bd392ea 100644 --- a/drivers/media/video/videobuf-dma-sg.c +++ b/drivers/media/video/videobuf-dma-sg.c @@ -644,53 +644,6 @@ done: return retval; } -static int __videobuf_copy_to_user(struct videobuf_queue *q, - char __user *data, size_t count, - int nonblocking) -{ - struct videobuf_dma_sg_memory *mem = q->read_buf->priv; - BUG_ON(!mem); - MAGIC_CHECK(mem->magic, MAGIC_SG_MEM); - - /* copy to userspace */ - if (count > q->read_buf->size - q->read_off) - count = q->read_buf->size - q->read_off; - - if (copy_to_user(data, mem->dma.vmalloc+q->read_off, count)) - return -EFAULT; - - return count; -} - -static int __videobuf_copy_stream(struct videobuf_queue *q, - char __user *data, size_t count, size_t pos, - int vbihack, int nonblocking) -{ - unsigned int *fc; - struct videobuf_dma_sg_memory *mem = q->read_buf->priv; - BUG_ON(!mem); - MAGIC_CHECK(mem->magic, MAGIC_SG_MEM); - - if (vbihack) { - /* dirty, undocumented hack -- pass the frame counter - * within the last four bytes of each vbi data block. - * We need that one to maintain backward compatibility - * to all vbi decoding software out there ... */ - fc = (unsigned int *)mem->dma.vmalloc; - fc += (q->read_buf->size >> 2) - 1; - *fc = q->read_buf->field_count >> 1; - dprintk(1, "vbihack: %d\n", *fc); - } - - /* copy stuff using the common method */ - count = __videobuf_copy_to_user(q, data, count, nonblocking); - - if ((count == -EFAULT) && (0 == pos)) - return -EFAULT; - - return count; -} - static struct videobuf_qtype_ops sg_ops = { .magic = MAGIC_QTYPE_OPS, @@ -698,8 +651,6 @@ static struct videobuf_qtype_ops sg_ops = { .iolock = __videobuf_iolock, .sync = __videobuf_sync, .mmap_mapper = __videobuf_mmap_mapper, - .video_copy_to_user = __videobuf_copy_to_user, - .copy_stream = __videobuf_copy_stream, .vaddr = __videobuf_to_vaddr, }; diff --git a/drivers/media/video/videobuf-vmalloc.c b/drivers/media/video/videobuf-vmalloc.c index 6db412abeac..ad655839827 100644 --- a/drivers/media/video/videobuf-vmalloc.c +++ b/drivers/media/video/videobuf-vmalloc.c @@ -315,55 +315,6 @@ error: return -ENOMEM; } -static int __videobuf_copy_to_user(struct videobuf_queue *q, - char __user *data, size_t count, - int nonblocking) -{ - struct videobuf_vmalloc_memory *mem = q->read_buf->priv; - BUG_ON(!mem); - MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM); - - BUG_ON(!mem->vmalloc); - - /* copy to userspace */ - if (count > q->read_buf->size - q->read_off) - count = q->read_buf->size - q->read_off; - - if (copy_to_user(data, mem->vmalloc+q->read_off, count)) - return -EFAULT; - - return count; -} - -static int __videobuf_copy_stream(struct videobuf_queue *q, - char __user *data, size_t count, size_t pos, - int vbihack, int nonblocking) -{ - unsigned int *fc; - struct videobuf_vmalloc_memory *mem = q->read_buf->priv; - BUG_ON(!mem); - MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM); - - if (vbihack) { - /* dirty, undocumented hack -- pass the frame counter - * within the last four bytes of each vbi data block. - * We need that one to maintain backward compatibility - * to all vbi decoding software out there ... */ - fc = (unsigned int *)mem->vmalloc; - fc += (q->read_buf->size >> 2) - 1; - *fc = q->read_buf->field_count >> 1; - dprintk(1, "vbihack: %d\n", *fc); - } - - /* copy stuff using the common method */ - count = __videobuf_copy_to_user(q, data, count, nonblocking); - - if ((count == -EFAULT) && (0 == pos)) - return -EFAULT; - - return count; -} - static struct videobuf_qtype_ops qops = { .magic = MAGIC_QTYPE_OPS, @@ -371,8 +322,6 @@ static struct videobuf_qtype_ops qops = { .iolock = __videobuf_iolock, .sync = __videobuf_sync, .mmap_mapper = __videobuf_mmap_mapper, - .video_copy_to_user = __videobuf_copy_to_user, - .copy_stream = __videobuf_copy_stream, .vaddr = videobuf_to_vmalloc, }; diff --git a/include/media/videobuf-core.h b/include/media/videobuf-core.h index f73e297e373..821a530f495 100644 --- a/include/media/videobuf-core.h +++ b/include/media/videobuf-core.h @@ -134,16 +134,6 @@ struct videobuf_qtype_ops { struct v4l2_framebuffer *fbuf); int (*sync) (struct videobuf_queue *q, struct videobuf_buffer *buf); - int (*video_copy_to_user)(struct videobuf_queue *q, - char __user *data, - size_t count, - int nonblocking); - int (*copy_stream) (struct videobuf_queue *q, - char __user *data, - size_t count, - size_t pos, - int vbihack, - int nonblocking); int (*mmap_mapper) (struct videobuf_queue *q, struct vm_area_struct *vma); }; -- cgit v1.2.3-70-g09d2 From 0b62b73778554cd47480ea465f0b255cc63b4336 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 28 Mar 2010 09:09:05 -0300 Subject: V4L/DVB: v4l videobuf: add videobuf_buffer *buf as argument to mmap_mapper mmap_mapper should operate on a buffer, not on a complete queue. So let the videobuf-core find the correct buffer instead of duplicating that code in each mmap_mapper implementation. The dma-sg implementation has backwards compatibility code for handling the V4L1_COMPAT layer. This code is now under the v4L1_COMPAT config option. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-core.c | 20 +++++++-- drivers/media/video/videobuf-dma-contig.c | 34 ++++----------- drivers/media/video/videobuf-dma-sg.c | 69 +++++++++++++++---------------- drivers/media/video/videobuf-vmalloc.c | 33 ++++----------- include/media/videobuf-core.h | 3 +- 5 files changed, 67 insertions(+), 92 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c index f1dfcff44e1..dc2f6a8c022 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/video/videobuf-core.c @@ -1123,15 +1123,29 @@ EXPORT_SYMBOL_GPL(videobuf_poll_stream); int videobuf_mmap_mapper(struct videobuf_queue *q, struct vm_area_struct *vma) { - int retval; + int rc = -EINVAL; + int i; MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); + if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED)) { + dprintk(1, "mmap appl bug: PROT_WRITE and MAP_SHARED are required\n"); + return -EINVAL; + } + mutex_lock(&q->vb_lock); - retval = CALL(q, mmap_mapper, q, vma); + for (i = 0; i < VIDEO_MAX_FRAME; i++) { + struct videobuf_buffer *buf = q->bufs[i]; + + if (buf && buf->memory == V4L2_MEMORY_MMAP && + buf->boff == (vma->vm_pgoff << PAGE_SHIFT)) { + rc = CALL(q, mmap_mapper, q, buf, vma); + break; + } + } mutex_unlock(&q->vb_lock); - return retval; + return rc; } EXPORT_SYMBOL_GPL(videobuf_mmap_mapper); diff --git a/drivers/media/video/videobuf-dma-contig.c b/drivers/media/video/videobuf-dma-contig.c index 0a0ff85140b..055ce8439ce 100644 --- a/drivers/media/video/videobuf-dma-contig.c +++ b/drivers/media/video/videobuf-dma-contig.c @@ -264,51 +264,33 @@ static int __videobuf_iolock(struct videobuf_queue *q, } static int __videobuf_mmap_mapper(struct videobuf_queue *q, + struct videobuf_buffer *buf, struct vm_area_struct *vma) { struct videobuf_dma_contig_memory *mem; struct videobuf_mapping *map; - unsigned int first; int retval; - unsigned long size, offset = vma->vm_pgoff << PAGE_SHIFT; + unsigned long size; dev_dbg(q->dev, "%s\n", __func__); - if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED)) - return -EINVAL; - - /* look for first buffer to map */ - for (first = 0; first < VIDEO_MAX_FRAME; first++) { - if (!q->bufs[first]) - continue; - - if (V4L2_MEMORY_MMAP != q->bufs[first]->memory) - continue; - if (q->bufs[first]->boff == offset) - break; - } - if (VIDEO_MAX_FRAME == first) { - dev_dbg(q->dev, "invalid user space offset [offset=0x%lx]\n", - offset); - return -EINVAL; - } /* create mapping + update buffer list */ map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL); if (!map) return -ENOMEM; - q->bufs[first]->map = map; + buf->map = map; map->start = vma->vm_start; map->end = vma->vm_end; map->q = q; - q->bufs[first]->baddr = vma->vm_start; + buf->baddr = vma->vm_start; - mem = q->bufs[first]->priv; + mem = buf->priv; BUG_ON(!mem); MAGIC_CHECK(mem->magic, MAGIC_DC_MEM); - mem->size = PAGE_ALIGN(q->bufs[first]->bsize); + mem->size = PAGE_ALIGN(buf->bsize); mem->vaddr = dma_alloc_coherent(q->dev, mem->size, &mem->dma_handle, GFP_KERNEL); if (!mem->vaddr) { @@ -341,8 +323,8 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, dev_dbg(q->dev, "mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n", map, q, vma->vm_start, vma->vm_end, - (long int) q->bufs[first]->bsize, - vma->vm_pgoff, first); + (long int)buf->bsize, + vma->vm_pgoff, buf->i); videobuf_vm_open(vma); diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c index 5c55bd392ea..1a7f3d3d2f9 100644 --- a/drivers/media/video/videobuf-dma-sg.c +++ b/drivers/media/video/videobuf-dma-sg.c @@ -549,22 +549,15 @@ static int __videobuf_sync(struct videobuf_queue *q, } static int __videobuf_mmap_mapper(struct videobuf_queue *q, - struct vm_area_struct *vma) + struct videobuf_buffer *buf, + struct vm_area_struct *vma) { - struct videobuf_dma_sg_memory *mem; + struct videobuf_dma_sg_memory *mem = buf->priv; struct videobuf_mapping *map; unsigned int first, last, size, i; int retval; retval = -EINVAL; - if (!(vma->vm_flags & VM_WRITE)) { - dprintk(1, "mmap app bug: PROT_WRITE please\n"); - goto done; - } - if (!(vma->vm_flags & VM_SHARED)) { - dprintk(1, "mmap app bug: MAP_SHARED please\n"); - goto done; - } /* This function maintains backwards compatibility with V4L1 and will * map more than one buffer if the vma length is equal to the combined @@ -574,44 +567,48 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, * TODO: Allow drivers to specify if they support this mode */ + BUG_ON(!mem); + MAGIC_CHECK(mem->magic, MAGIC_SG_MEM); + /* look for first buffer to map */ for (first = 0; first < VIDEO_MAX_FRAME; first++) { - if (NULL == q->bufs[first]) - continue; - mem = q->bufs[first]->priv; - BUG_ON(!mem); - MAGIC_CHECK(mem->magic, MAGIC_SG_MEM); - - if (V4L2_MEMORY_MMAP != q->bufs[first]->memory) - continue; - if (q->bufs[first]->boff == (vma->vm_pgoff << PAGE_SHIFT)) + if (buf == q->bufs[first]) { + size = PAGE_ALIGN(q->bufs[first]->bsize); break; + } } + + /* paranoia, should never happen since buf is always valid. */ if (VIDEO_MAX_FRAME == first) { dprintk(1, "mmap app bug: offset invalid [offset=0x%lx]\n", - (vma->vm_pgoff << PAGE_SHIFT)); + (vma->vm_pgoff << PAGE_SHIFT)); goto done; } - /* look for last buffer to map */ - for (size = 0, last = first; last < VIDEO_MAX_FRAME; last++) { - if (NULL == q->bufs[last]) - continue; - if (V4L2_MEMORY_MMAP != q->bufs[last]->memory) - continue; - if (q->bufs[last]->map) { - retval = -EBUSY; + last = first; +#ifdef CONFIG_VIDEO_V4L1_COMPAT + if (size != (vma->vm_end - vma->vm_start)) { + /* look for last buffer to map */ + for (last = first + 1; last < VIDEO_MAX_FRAME; last++) { + if (NULL == q->bufs[last]) + continue; + if (V4L2_MEMORY_MMAP != q->bufs[last]->memory) + continue; + if (q->bufs[last]->map) { + retval = -EBUSY; + goto done; + } + size += PAGE_ALIGN(q->bufs[last]->bsize); + if (size == (vma->vm_end - vma->vm_start)) + break; + } + if (VIDEO_MAX_FRAME == last) { + dprintk(1, "mmap app bug: size invalid [size=0x%lx]\n", + (vma->vm_end - vma->vm_start)); goto done; } - size += PAGE_ALIGN(q->bufs[last]->bsize); - if (size == (vma->vm_end - vma->vm_start)) - break; - } - if (VIDEO_MAX_FRAME == last) { - dprintk(1, "mmap app bug: size invalid [size=0x%lx]\n", - (vma->vm_end - vma->vm_start)); - goto done; } +#endif /* create mapping + update buffer list */ retval = -ENOMEM; diff --git a/drivers/media/video/videobuf-vmalloc.c b/drivers/media/video/videobuf-vmalloc.c index ad655839827..f8b5b563511 100644 --- a/drivers/media/video/videobuf-vmalloc.c +++ b/drivers/media/video/videobuf-vmalloc.c @@ -236,47 +236,28 @@ static int __videobuf_sync(struct videobuf_queue *q, } static int __videobuf_mmap_mapper(struct videobuf_queue *q, - struct vm_area_struct *vma) + struct videobuf_buffer *buf, + struct vm_area_struct *vma) { struct videobuf_vmalloc_memory *mem; struct videobuf_mapping *map; - unsigned int first; int retval, pages; - unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; dprintk(1, "%s\n", __func__); - if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED)) - return -EINVAL; - - /* look for first buffer to map */ - for (first = 0; first < VIDEO_MAX_FRAME; first++) { - if (NULL == q->bufs[first]) - continue; - - if (V4L2_MEMORY_MMAP != q->bufs[first]->memory) - continue; - if (q->bufs[first]->boff == offset) - break; - } - if (VIDEO_MAX_FRAME == first) { - dprintk(1, "mmap app bug: offset invalid [offset=0x%lx]\n", - (vma->vm_pgoff << PAGE_SHIFT)); - return -EINVAL; - } /* create mapping + update buffer list */ map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL); if (NULL == map) return -ENOMEM; - q->bufs[first]->map = map; + buf->map = map; map->start = vma->vm_start; map->end = vma->vm_end; map->q = q; - q->bufs[first]->baddr = vma->vm_start; + buf->baddr = vma->vm_start; - mem = q->bufs[first]->priv; + mem = buf->priv; BUG_ON(!mem); MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM); @@ -302,8 +283,8 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, dprintk(1, "mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n", map, q, vma->vm_start, vma->vm_end, - (long int) q->bufs[first]->bsize, - vma->vm_pgoff, first); + (long int)buf->bsize, + vma->vm_pgoff, buf->i); videobuf_vm_open(vma); diff --git a/include/media/videobuf-core.h b/include/media/videobuf-core.h index 821a530f495..f91a736c133 100644 --- a/include/media/videobuf-core.h +++ b/include/media/videobuf-core.h @@ -135,7 +135,8 @@ struct videobuf_qtype_ops { int (*sync) (struct videobuf_queue *q, struct videobuf_buffer *buf); int (*mmap_mapper) (struct videobuf_queue *q, - struct vm_area_struct *vma); + struct videobuf_buffer *buf, + struct vm_area_struct *vma); }; struct videobuf_queue { -- cgit v1.2.3-70-g09d2 From 18bf99aa0cb80b4fa3974a511fd033c2967b04c8 Mon Sep 17 00:00:00 2001 From: Jean-François Moine Date: Fri, 9 Apr 2010 06:06:11 -0300 Subject: V4L/DVB: gspca - main: Check the file doing stream on/off MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gspca.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 68a8431d436..4fb031cfb64 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -1590,6 +1590,12 @@ static int vidioc_streamon(struct file *file, void *priv, if (mutex_lock_interruptible(&gspca_dev->queue_lock)) return -ERESTARTSYS; + /* check the capture file */ + if (gspca_dev->capt_file != file) { + ret = -EBUSY; + goto out; + } + if (gspca_dev->nframes == 0 || !(gspca_dev->frame[0].v4l2_buf.flags & V4L2_BUF_FLAG_QUEUED)) { ret = -EINVAL; @@ -1627,6 +1633,12 @@ static int vidioc_streamoff(struct file *file, void *priv, if (mutex_lock_interruptible(&gspca_dev->queue_lock)) return -ERESTARTSYS; + /* check the capture file */ + if (gspca_dev->capt_file != file) { + ret = -EBUSY; + goto out; + } + /* stop streaming */ if (mutex_lock_interruptible(&gspca_dev->usb_lock)) { ret = -ERESTARTSYS; -- cgit v1.2.3-70-g09d2 From 832d0a9130c18b9ee4b671c46763b972eb2a2568 Mon Sep 17 00:00:00 2001 From: Jean-François Moine Date: Fri, 9 Apr 2010 06:07:58 -0300 Subject: V4L/DVB: gspca - main: Restart streaming after reqbuf MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gspca.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 4fb031cfb64..9c9d7ea7e62 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -1503,7 +1503,7 @@ static int vidioc_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *rb) { struct gspca_dev *gspca_dev = priv; - int i, ret = 0; + int i, ret = 0, streaming; switch (rb->memory) { case GSPCA_MEMORY_READ: /* (internal call) */ @@ -1538,7 +1538,8 @@ static int vidioc_reqbufs(struct file *file, void *priv, } /* stop streaming */ - if (gspca_dev->streaming) { + streaming = gspca_dev->streaming; + if (streaming) { mutex_lock(&gspca_dev->usb_lock); gspca_dev->usb_err = 0; gspca_stream_off(gspca_dev); @@ -1557,6 +1558,8 @@ static int vidioc_reqbufs(struct file *file, void *priv, if (ret == 0) { rb->count = gspca_dev->nframes; gspca_dev->capt_file = file; + if (streaming) + ret = gspca_init_transfer(gspca_dev); } out: mutex_unlock(&gspca_dev->queue_lock); -- cgit v1.2.3-70-g09d2 From e4dac289f01da80d7966a123bc1ea97be199ba4f Mon Sep 17 00:00:00 2001 From: Jean-François Moine Date: Fri, 9 Apr 2010 06:11:36 -0300 Subject: V4L/DVB: gspca - main: Stop the webcam when bandwidth too small MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gspca.c | 65 +++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 33 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 9c9d7ea7e62..e8d08f88795 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -613,6 +613,37 @@ static void destroy_urbs(struct gspca_dev *gspca_dev) } } +static int gspca_set_alt0(struct gspca_dev *gspca_dev) +{ + int ret; + + if (gspca_dev->alt == 0) + return 0; + ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0); + if (ret < 0) + PDEBUG(D_ERR|D_STREAM, "set alt 0 err %d", ret); + return ret; +} + +/* Note: both the queue and the usb locks should be held when calling this */ +static void gspca_stream_off(struct gspca_dev *gspca_dev) +{ + gspca_dev->streaming = 0; + if (gspca_dev->present) { + if (gspca_dev->sd_desc->stopN) + gspca_dev->sd_desc->stopN(gspca_dev); + destroy_urbs(gspca_dev); + gspca_input_destroy_urb(gspca_dev); + gspca_set_alt0(gspca_dev); + gspca_input_create_urb(gspca_dev); + } + + /* always call stop0 to free the subdriver's resources */ + if (gspca_dev->sd_desc->stop0) + gspca_dev->sd_desc->stop0(gspca_dev); + PDEBUG(D_STREAM, "stream off OK"); +} + /* * look for an input transfer endpoint in an alternate setting */ @@ -838,8 +869,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) } if (ret >= 0) break; - gspca_dev->streaming = 0; - destroy_urbs(gspca_dev); + gspca_stream_off(gspca_dev); if (ret != -ENOSPC) { PDEBUG(D_ERR|D_STREAM, "usb_submit_urb alt %d err %d", @@ -869,37 +899,6 @@ out: return ret; } -static int gspca_set_alt0(struct gspca_dev *gspca_dev) -{ - int ret; - - if (gspca_dev->alt == 0) - return 0; - ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0); - if (ret < 0) - PDEBUG(D_ERR|D_STREAM, "set alt 0 err %d", ret); - return ret; -} - -/* Note: both the queue and the usb locks should be held when calling this */ -static void gspca_stream_off(struct gspca_dev *gspca_dev) -{ - gspca_dev->streaming = 0; - if (gspca_dev->present) { - if (gspca_dev->sd_desc->stopN) - gspca_dev->sd_desc->stopN(gspca_dev); - destroy_urbs(gspca_dev); - gspca_input_destroy_urb(gspca_dev); - gspca_set_alt0(gspca_dev); - gspca_input_create_urb(gspca_dev); - } - - /* always call stop0 to free the subdriver's resources */ - if (gspca_dev->sd_desc->stop0) - gspca_dev->sd_desc->stop0(gspca_dev); - PDEBUG(D_STREAM, "stream off OK"); -} - static void gspca_set_default_mode(struct gspca_dev *gspca_dev) { int i; -- cgit v1.2.3-70-g09d2 From 474675ad8006834be996c046b47436d8ca7a5105 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 25 Apr 2010 11:23:52 -0300 Subject: V4L/DVB: videobuf-dma-sg: Avoid using a wrong size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/media/video/videobuf-dma-sg.c: In function ‘__videobuf_mmap_mapper’: drivers/media/video/videobuf-dma-sg.c:557: warning: ‘size’ may be used uninitialized in this function The condition where size is floating should never happen, due to the paranoia check, but a future change at the logic might break it. So, let's just set size to zero and use it for the paranoia check. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-dma-sg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c index 1a7f3d3d2f9..f733833a021 100644 --- a/drivers/media/video/videobuf-dma-sg.c +++ b/drivers/media/video/videobuf-dma-sg.c @@ -554,7 +554,7 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, { struct videobuf_dma_sg_memory *mem = buf->priv; struct videobuf_mapping *map; - unsigned int first, last, size, i; + unsigned int first, last, size = 0, i; int retval; retval = -EINVAL; @@ -579,7 +579,7 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, } /* paranoia, should never happen since buf is always valid. */ - if (VIDEO_MAX_FRAME == first) { + if (!size) { dprintk(1, "mmap app bug: offset invalid [offset=0x%lx]\n", (vma->vm_pgoff << PAGE_SHIFT)); goto done; -- cgit v1.2.3-70-g09d2 From 730947bc141b7e8feb091dcf3ee8e6a7b9379512 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 10 Apr 2010 04:13:53 -0300 Subject: V4L/DVB: vivi: clean up and a major overhaul - Clean up the code - Use the kernel's built-in vga8x16 font instead of our own. - Drop exclusive open: now multiple users can open the device as per the V4L2 spec. - Move the format description to the vivi device instead of keeping it in the file handle. Again as per the spec. - Streamline and simplify the drawing code. It is now easy to add text on top of the colorbar pattern. - Upgrade the max resolution to 1920x1200. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 1 + drivers/media/video/font.h | 407 ---------------------- drivers/media/video/vivi.c | 809 ++++++++++++++++++-------------------------- 3 files changed, 325 insertions(+), 892 deletions(-) delete mode 100644 drivers/media/video/font.h (limited to 'drivers/media/video') diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 67d31f6cc60..784743187a6 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -543,6 +543,7 @@ config VIDEO_DAVINCI_VPIF config VIDEO_VIVI tristate "Virtual Video Driver" depends on VIDEO_DEV && VIDEO_V4L2 && !SPARC32 && !SPARC64 + select FONT_8x16 select VIDEOBUF_VMALLOC default n ---help--- diff --git a/drivers/media/video/font.h b/drivers/media/video/font.h deleted file mode 100644 index 8b1fecc3759..00000000000 --- a/drivers/media/video/font.h +++ /dev/null @@ -1,407 +0,0 @@ -static unsigned char rom8x16_bits[] = { -/* Character 0 (0x30): - ht=16, width=8 - +--------+ - | | - | | - | ***** | - |** ** | - |** ** | - |** *** | - |** **** | - |**** ** | - |*** ** | - |** ** | - |** ** | - | ***** | - | | - | | - | | - | | - +--------+ */ -0x00, -0x00, -0x7c, -0xc6, -0xc6, -0xce, -0xde, -0xf6, -0xe6, -0xc6, -0xc6, -0x7c, -0x00, -0x00, -0x00, -0x00, - -/* Character 1 (0x31): - ht=16, width=8 - +--------+ - | | - | | - | ** | - | **** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ****** | - | | - | | - | | - | | - +--------+ */ -0x00, -0x00, -0x18, -0x78, -0x18, -0x18, -0x18, -0x18, -0x18, -0x18, -0x18, -0x7e, -0x00, -0x00, -0x00, -0x00, - -/* Character 2 (0x32): - ht=16, width=8 - +--------+ - | | - | | - | ***** | - |** ** | - |** ** | - | ** | - | ** | - | ** | - | ** | - | ** | - |** ** | - |******* | - | | - | | - | | - | | - +--------+ */ -0x00, -0x00, -0x7c, -0xc6, -0xc6, -0x06, -0x0c, -0x18, -0x30, -0x60, -0xc6, -0xfe, -0x00, -0x00, -0x00, -0x00, - -/* Character 3 (0x33): - ht=16, width=8 - +--------+ - | | - | | - | ***** | - |** ** | - | ** | - | ** | - | **** | - | ** | - | ** | - | ** | - |** ** | - | ***** | - | | - | | - | | - | | - +--------+ */ -0x00, -0x00, -0x7c, -0xc6, -0x06, -0x06, -0x3c, -0x06, -0x06, -0x06, -0xc6, -0x7c, -0x00, -0x00, -0x00, -0x00, - -/* Character 4 (0x34): - ht=16, width=8 - +--------+ - | | - | | - | ** | - | *** | - | **** | - | ** ** | - |** ** | - |** ** | - |******* | - | ** | - | ** | - | **** | - | | - | | - | | - | | - +--------+ */ -0x00, -0x00, -0x0c, -0x1c, -0x3c, -0x6c, -0xcc, -0xcc, -0xfe, -0x0c, -0x0c, -0x1e, -0x00, -0x00, -0x00, -0x00, - -/* Character 5 (0x35): - ht=16, width=8 - +--------+ - | | - | | - |******* | - |** | - |** | - |** | - |****** | - | ** | - | ** | - | ** | - |** ** | - | ***** | - | | - | | - | | - | | - +--------+ */ -0x00, -0x00, -0xfe, -0xc0, -0xc0, -0xc0, -0xfc, -0x06, -0x06, -0x06, -0xc6, -0x7c, -0x00, -0x00, -0x00, -0x00, - -/* Character 6 (0x36): - ht=16, width=8 - +--------+ - | | - | | - | ***** | - |** ** | - |** | - |** | - |****** | - |** ** | - |** ** | - |** ** | - |** ** | - | ***** | - | | - | | - | | - | | - +--------+ */ -0x00, -0x00, -0x7c, -0xc6, -0xc0, -0xc0, -0xfc, -0xc6, -0xc6, -0xc6, -0xc6, -0x7c, -0x00, -0x00, -0x00, -0x00, - -/* Character 7 (0x37): - ht=16, width=8 - +--------+ - | | - | | - |******* | - |** ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | | - | | - | | - | | - +--------+ */ -0x00, -0x00, -0xfe, -0xc6, -0x06, -0x0c, -0x18, -0x30, -0x30, -0x30, -0x30, -0x30, -0x00, -0x00, -0x00, -0x00, - -/* Character 8 (0x38): - ht=16, width=8 - +--------+ - | | - | | - | ***** | - |** ** | - |** ** | - |** ** | - | ***** | - |** ** | - |** ** | - |** ** | - |** ** | - | ***** | - | | - | | - | | - | | - +--------+ */ -0x00, -0x00, -0x7c, -0xc6, -0xc6, -0xc6, -0x7c, -0xc6, -0xc6, -0xc6, -0xc6, -0x7c, -0x00, -0x00, -0x00, -0x00, - -/* Character 9 (0x39): - ht=16, width=8 - +--------+ - | | - | | - | ***** | - |** ** | - |** ** | - |** ** | - |** ** | - | ****** | - | ** | - | ** | - |** ** | - | ***** | - | | - | | - | | - | | - +--------+ */ -0x00, -0x00, -0x7c, -0xc6, -0xc6, -0xc6, -0xc6, -0x7e, -0x06, -0x06, -0xc6, -0x7c, -0x00, -0x00, -0x00, -0x00, -/* Character : (0x3a): - ht=16, width=8 - +--------+ - | | - | | - | | - | | - | | - | ** | - | ** | - | | - | | - | ** | - | ** | - | | - | | - | | - | | - | | - +--------+ */ -0x00, -0x00, -0x00, -0x00, -0x00, -0x0c, -0x0c, -0x00, -0x00, -0x0c, -0x0c, -0x00, -0x00, -0x00, -0x00, -0x00, -}; diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 5a736b8a5a3..d5e30b85c55 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -13,29 +13,22 @@ * License, or (at your option) any later version */ #include -#include #include -#include #include -#include -#include -#include #include #include -#include -#include +#include #include #include #include -#include -#include #include -#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) #include +#endif #include #include #include -#include "font.h" +#include #define VIVI_MODULE_NAME "vivi" @@ -44,8 +37,11 @@ #define WAKE_DENOMINATOR 1001 #define BUFFER_TIMEOUT msecs_to_jiffies(500) /* 0.5 seconds */ +#define MAX_WIDTH 1920 +#define MAX_HEIGHT 1200 + #define VIVI_MAJOR_VERSION 0 -#define VIVI_MINOR_VERSION 6 +#define VIVI_MINOR_VERSION 7 #define VIVI_RELEASE 0 #define VIVI_VERSION \ KERNEL_VERSION(VIVI_MAJOR_VERSION, VIVI_MINOR_VERSION, VIVI_RELEASE) @@ -70,56 +66,8 @@ static unsigned int vid_limit = 16; module_param(vid_limit, uint, 0644); MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes"); - -/* supported controls */ -static struct v4l2_queryctrl vivi_qctrl[] = { - { - .id = V4L2_CID_AUDIO_VOLUME, - .name = "Volume", - .minimum = 0, - .maximum = 65535, - .step = 65535/100, - .default_value = 65535, - .flags = V4L2_CTRL_FLAG_SLIDER, - .type = V4L2_CTRL_TYPE_INTEGER, - }, { - .id = V4L2_CID_BRIGHTNESS, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Brightness", - .minimum = 0, - .maximum = 255, - .step = 1, - .default_value = 127, - .flags = V4L2_CTRL_FLAG_SLIDER, - }, { - .id = V4L2_CID_CONTRAST, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Contrast", - .minimum = 0, - .maximum = 255, - .step = 0x1, - .default_value = 0x10, - .flags = V4L2_CTRL_FLAG_SLIDER, - }, { - .id = V4L2_CID_SATURATION, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Saturation", - .minimum = 0, - .maximum = 255, - .step = 0x1, - .default_value = 127, - .flags = V4L2_CTRL_FLAG_SLIDER, - }, { - .id = V4L2_CID_HUE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Hue", - .minimum = -128, - .maximum = 127, - .step = 0x1, - .default_value = 0, - .flags = V4L2_CTRL_FLAG_SLIDER, - } -}; +/* Global font descriptor */ +static const u8 *font8x16; #define dprintk(dev, level, fmt, arg...) \ v4l2_dbg(level, debug, &dev->v4l2_dev, fmt, ## arg) @@ -214,41 +162,38 @@ struct vivi_dev { struct list_head vivi_devlist; struct v4l2_device v4l2_dev; + /* controls */ + int brightness; + int contrast; + int saturation; + int hue; + int volume; + spinlock_t slock; struct mutex mutex; - int users; - /* various device info */ struct video_device *vfd; struct vivi_dmaqueue vidq; /* Several counters */ - int h, m, s, ms; + unsigned ms; unsigned long jiffies; - char timestr[13]; int mv_count; /* Controls bars movement */ /* Input Number */ int input; - /* Control 'registers' */ - int qctl_regs[ARRAY_SIZE(vivi_qctrl)]; -}; - -struct vivi_fh { - struct vivi_dev *dev; - /* video capture */ struct vivi_fmt *fmt; unsigned int width, height; struct videobuf_queue vb_vidq; - enum v4l2_buf_type type; - unsigned char bars[8][3]; - int input; /* Input Number on bars */ + unsigned long generating; + u8 bars[9][3]; + u8 line[MAX_WIDTH * 4]; }; /* ------------------------------------------------------------------ @@ -259,19 +204,20 @@ struct vivi_fh { enum colors { WHITE, - AMBAR, + AMBER, CYAN, GREEN, MAGENTA, RED, BLUE, BLACK, + TEXT_BLACK, }; - /* R G B */ +/* R G B */ #define COLOR_WHITE {204, 204, 204} -#define COLOR_AMBAR {208, 208, 0} -#define COLOR_CIAN { 0, 206, 206} +#define COLOR_AMBER {208, 208, 0} +#define COLOR_CYAN { 0, 206, 206} #define COLOR_GREEN { 0, 239, 0} #define COLOR_MAGENTA {239, 0, 239} #define COLOR_RED {205, 0, 0} @@ -279,56 +225,24 @@ enum colors { #define COLOR_BLACK { 0, 0, 0} struct bar_std { - u8 bar[8][3]; + u8 bar[9][3]; }; /* Maximum number of bars are 10 - otherwise, the input print code should be modified */ static struct bar_std bars[] = { { /* Standard ITU-R color bar sequence */ - { - COLOR_WHITE, - COLOR_AMBAR, - COLOR_CIAN, - COLOR_GREEN, - COLOR_MAGENTA, - COLOR_RED, - COLOR_BLUE, - COLOR_BLACK, - } + { COLOR_WHITE, COLOR_AMBER, COLOR_CYAN, COLOR_GREEN, + COLOR_MAGENTA, COLOR_RED, COLOR_BLUE, COLOR_BLACK, COLOR_BLACK } }, { - { - COLOR_WHITE, - COLOR_AMBAR, - COLOR_BLACK, - COLOR_WHITE, - COLOR_AMBAR, - COLOR_BLACK, - COLOR_WHITE, - COLOR_AMBAR, - } + { COLOR_WHITE, COLOR_AMBER, COLOR_BLACK, COLOR_WHITE, + COLOR_AMBER, COLOR_BLACK, COLOR_WHITE, COLOR_AMBER, COLOR_BLACK } }, { - { - COLOR_WHITE, - COLOR_CIAN, - COLOR_BLACK, - COLOR_WHITE, - COLOR_CIAN, - COLOR_BLACK, - COLOR_WHITE, - COLOR_CIAN, - } + { COLOR_WHITE, COLOR_CYAN, COLOR_BLACK, COLOR_WHITE, + COLOR_CYAN, COLOR_BLACK, COLOR_WHITE, COLOR_CYAN, COLOR_BLACK } }, { - { - COLOR_WHITE, - COLOR_GREEN, - COLOR_BLACK, - COLOR_WHITE, - COLOR_GREEN, - COLOR_BLACK, - COLOR_WHITE, - COLOR_GREEN, - } + { COLOR_WHITE, COLOR_GREEN, COLOR_BLACK, COLOR_WHITE, + COLOR_GREEN, COLOR_BLACK, COLOR_WHITE, COLOR_GREEN, COLOR_BLACK } }, }; @@ -344,21 +258,18 @@ static struct bar_std bars[] = { (((-9714 * r - 19070 * g + 28784 * b + 32768) >> 16) + 128) /* precalculate color bar values to speed up rendering */ -static void precalculate_bars(struct vivi_fh *fh) +static void precalculate_bars(struct vivi_dev *dev) { - struct vivi_dev *dev = fh->dev; - unsigned char r, g, b; + u8 r, g, b; int k, is_yuv; - fh->input = dev->input; - - for (k = 0; k < 8; k++) { - r = bars[fh->input].bar[k][0]; - g = bars[fh->input].bar[k][1]; - b = bars[fh->input].bar[k][2]; + for (k = 0; k < 9; k++) { + r = bars[dev->input].bar[k][0]; + g = bars[dev->input].bar[k][1]; + b = bars[dev->input].bar[k][2]; is_yuv = 0; - switch (fh->fmt->fourcc) { + switch (dev->fmt->fourcc) { case V4L2_PIX_FMT_YUYV: case V4L2_PIX_FMT_UYVY: is_yuv = 1; @@ -378,16 +289,15 @@ static void precalculate_bars(struct vivi_fh *fh) } if (is_yuv) { - fh->bars[k][0] = TO_Y(r, g, b); /* Luma */ - fh->bars[k][1] = TO_U(r, g, b); /* Cb */ - fh->bars[k][2] = TO_V(r, g, b); /* Cr */ + dev->bars[k][0] = TO_Y(r, g, b); /* Luma */ + dev->bars[k][1] = TO_U(r, g, b); /* Cb */ + dev->bars[k][2] = TO_V(r, g, b); /* Cr */ } else { - fh->bars[k][0] = r; - fh->bars[k][1] = g; - fh->bars[k][2] = b; + dev->bars[k][0] = r; + dev->bars[k][1] = g; + dev->bars[k][2] = b; } } - } #define TSTAMP_MIN_Y 24 @@ -395,20 +305,20 @@ static void precalculate_bars(struct vivi_fh *fh) #define TSTAMP_INPUT_X 10 #define TSTAMP_MIN_X (54 + TSTAMP_INPUT_X) -static void gen_twopix(struct vivi_fh *fh, unsigned char *buf, int colorpos) +static void gen_twopix(struct vivi_dev *dev, u8 *buf, int colorpos) { - unsigned char r_y, g_u, b_v; - unsigned char *p; + u8 r_y, g_u, b_v; int color; + u8 *p; - r_y = fh->bars[colorpos][0]; /* R or precalculated Y */ - g_u = fh->bars[colorpos][1]; /* G or precalculated U */ - b_v = fh->bars[colorpos][2]; /* B or precalculated V */ + r_y = dev->bars[colorpos][0]; /* R or precalculated Y */ + g_u = dev->bars[colorpos][1]; /* G or precalculated U */ + b_v = dev->bars[colorpos][2]; /* B or precalculated V */ for (color = 0; color < 4; color++) { p = buf + color; - switch (fh->fmt->fourcc) { + switch (dev->fmt->fourcc) { case V4L2_PIX_FMT_YUYV: switch (color) { case 0: @@ -489,123 +399,88 @@ static void gen_twopix(struct vivi_fh *fh, unsigned char *buf, int colorpos) } } -static void gen_line(struct vivi_fh *fh, char *basep, int inipos, int wmax, - int hmax, int line, int count, char *timestr) +static void precalculate_line(struct vivi_dev *dev) { - int w, i, j; - int pos = inipos; - char *s; - u8 chr; - - /* We will just duplicate the second pixel at the packet */ - wmax /= 2; + int w; - /* Generate a standard color bar pattern */ - for (w = 0; w < wmax; w++) { - int colorpos = ((w + count) * 8/(wmax + 1)) % 8; + for (w = 0; w < dev->width * 2; w += 2) { + int colorpos = (w / (dev->width / 8) % 8); - gen_twopix(fh, basep + pos, colorpos); - pos += 4; /* only 16 bpp supported for now */ + gen_twopix(dev, dev->line + w * 2, colorpos); } +} - /* Prints input entry number */ - - /* Checks if it is possible to input number */ - if (TSTAMP_MAX_Y >= hmax) - goto end; - - if (TSTAMP_INPUT_X + strlen(timestr) >= wmax) - goto end; - - if (line >= TSTAMP_MIN_Y && line <= TSTAMP_MAX_Y) { - chr = rom8x16_bits[fh->input * 16 + line - TSTAMP_MIN_Y]; - pos = TSTAMP_INPUT_X; - for (i = 0; i < 7; i++) { - /* Draw white font on black background */ - if (chr & 1 << (7 - i)) - gen_twopix(fh, basep + pos, WHITE); - else - gen_twopix(fh, basep + pos, BLACK); - pos += 2; - } - } +static void gen_text(struct vivi_dev *dev, char *basep, + int y, int x, char *text) +{ + int line; - /* Checks if it is possible to show timestamp */ - if (TSTAMP_MIN_X + strlen(timestr) >= wmax) - goto end; + /* Checks if it is possible to show string */ + if (y + 16 >= dev->height || x + strlen(text) * 8 >= dev->width) + return; /* Print stream time */ - if (line >= TSTAMP_MIN_Y && line <= TSTAMP_MAX_Y) { - j = TSTAMP_MIN_X; - for (s = timestr; *s; s++) { - chr = rom8x16_bits[(*s-0x30)*16+line-TSTAMP_MIN_Y]; - for (i = 0; i < 7; i++) { - pos = inipos + j * 2; + for (line = y; line < y + 16; line++) { + int j = 0; + char *pos = basep + line * dev->width * 2 + x * 2; + char *s; + + for (s = text; *s; s++) { + u8 chr = font8x16[*s * 16 + line - y]; + int i; + + for (i = 0; i < 7; i++, j++) { /* Draw white font on black background */ - if (chr & 1 << (7 - i)) - gen_twopix(fh, basep + pos, WHITE); + if (chr & (1 << (7 - i))) + gen_twopix(dev, pos + j * 2, WHITE); else - gen_twopix(fh, basep + pos, BLACK); - j++; + gen_twopix(dev, pos + j * 2, TEXT_BLACK); } } } - -end: - return; } -static void vivi_fillbuff(struct vivi_fh *fh, struct vivi_buffer *buf) +static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf) { - struct vivi_dev *dev = fh->dev; - int h , pos = 0; - int hmax = buf->vb.height; - int wmax = buf->vb.width; + int hmax = buf->vb.height; + int wmax = buf->vb.width; struct timeval ts; - char *tmpbuf; void *vbuf = videobuf_to_vmalloc(&buf->vb); + unsigned ms; + char str[100]; + int h, line = 1; if (!vbuf) return; - tmpbuf = kmalloc(wmax * 2, GFP_ATOMIC); - if (!tmpbuf) - return; - - for (h = 0; h < hmax; h++) { - gen_line(fh, tmpbuf, 0, wmax, hmax, h, dev->mv_count, - dev->timestr); - memcpy(vbuf + pos, tmpbuf, wmax * 2); - pos += wmax*2; - } - - dev->mv_count++; - - kfree(tmpbuf); + for (h = 0; h < hmax; h++) + memcpy(vbuf + h * wmax * 2, dev->line + (dev->mv_count % wmax) * 2, wmax * 2); /* Updates stream time */ - dev->ms += jiffies_to_msecs(jiffies-dev->jiffies); + dev->ms += jiffies_to_msecs(jiffies - dev->jiffies); dev->jiffies = jiffies; - if (dev->ms >= 1000) { - dev->ms -= 1000; - dev->s++; - if (dev->s >= 60) { - dev->s -= 60; - dev->m++; - if (dev->m > 60) { - dev->m -= 60; - dev->h++; - if (dev->h > 24) - dev->h -= 24; - } - } - } - sprintf(dev->timestr, "%02d:%02d:%02d:%03d", - dev->h, dev->m, dev->s, dev->ms); - - dprintk(dev, 2, "vivifill at %s: Buffer 0x%08lx size= %d\n", - dev->timestr, (unsigned long)tmpbuf, pos); + ms = dev->ms; + snprintf(str, sizeof(str), " %02d:%02d:%02d:%03d ", + (ms / (60 * 60 * 1000)) % 24, + (ms / (60 * 1000)) % 60, + (ms / 1000) % 60, + ms % 1000); + gen_text(dev, vbuf, line++ * 16, 16, str); + snprintf(str, sizeof(str), " %dx%d, input %d ", + dev->width, dev->height, dev->input); + gen_text(dev, vbuf, line++ * 16, 16, str); + + snprintf(str, sizeof(str), " brightness %3d, contrast %3d, saturation %3d, hue %d ", + dev->brightness, + dev->contrast, + dev->saturation, + dev->hue); + gen_text(dev, vbuf, line++ * 16, 16, str); + snprintf(str, sizeof(str), " volume %3d ", dev->volume); + gen_text(dev, vbuf, line++ * 16, 16, str); + + dev->mv_count += 2; /* Advice that buffer was filled */ buf->vb.field_count++; @@ -614,12 +489,10 @@ static void vivi_fillbuff(struct vivi_fh *fh, struct vivi_buffer *buf) buf->vb.state = VIDEOBUF_DONE; } -static void vivi_thread_tick(struct vivi_fh *fh) +static void vivi_thread_tick(struct vivi_dev *dev) { - struct vivi_buffer *buf; - struct vivi_dev *dev = fh->dev; struct vivi_dmaqueue *dma_q = &dev->vidq; - + struct vivi_buffer *buf; unsigned long flags = 0; dprintk(dev, 1, "Thread tick\n"); @@ -642,22 +515,20 @@ static void vivi_thread_tick(struct vivi_fh *fh) do_gettimeofday(&buf->vb.ts); /* Fill buffer */ - vivi_fillbuff(fh, buf); + vivi_fillbuff(dev, buf); dprintk(dev, 1, "filled buffer %p\n", buf); wake_up(&buf->vb.done); dprintk(dev, 2, "[%p/%d] wakeup\n", buf, buf->vb. i); unlock: spin_unlock_irqrestore(&dev->slock, flags); - return; } #define frames_to_ms(frames) \ ((frames * WAKE_NUMERATOR * 1000) / WAKE_DENOMINATOR) -static void vivi_sleep(struct vivi_fh *fh) +static void vivi_sleep(struct vivi_dev *dev) { - struct vivi_dev *dev = fh->dev; struct vivi_dmaqueue *dma_q = &dev->vidq; int timeout; DECLARE_WAITQUEUE(wait, current); @@ -672,7 +543,7 @@ static void vivi_sleep(struct vivi_fh *fh) /* Calculate time to wake up */ timeout = msecs_to_jiffies(frames_to_ms(1)); - vivi_thread_tick(fh); + vivi_thread_tick(dev); schedule_timeout_interruptible(timeout); @@ -683,15 +554,14 @@ stop_task: static int vivi_thread(void *data) { - struct vivi_fh *fh = data; - struct vivi_dev *dev = fh->dev; + struct vivi_dev *dev = data; dprintk(dev, 1, "thread started\n"); set_freezable(); for (;;) { - vivi_sleep(fh); + vivi_sleep(dev); if (kthread_should_stop()) break; @@ -700,39 +570,61 @@ static int vivi_thread(void *data) return 0; } -static int vivi_start_thread(struct vivi_fh *fh) +static void vivi_start_generating(struct file *file) { - struct vivi_dev *dev = fh->dev; + struct vivi_dev *dev = video_drvdata(file); struct vivi_dmaqueue *dma_q = &dev->vidq; - dma_q->frame = 0; - dma_q->ini_jiffies = jiffies; - dprintk(dev, 1, "%s\n", __func__); - dma_q->kthread = kthread_run(vivi_thread, fh, "vivi"); + if (test_and_set_bit(0, &dev->generating)) + return; + file->private_data = dev; + + /* Resets frame counters */ + dev->ms = 0; + dev->mv_count = 0; + dev->jiffies = jiffies; + + dma_q->frame = 0; + dma_q->ini_jiffies = jiffies; + dma_q->kthread = kthread_run(vivi_thread, dev, dev->v4l2_dev.name); if (IS_ERR(dma_q->kthread)) { v4l2_err(&dev->v4l2_dev, "kernel_thread() failed\n"); - return PTR_ERR(dma_q->kthread); + clear_bit(0, &dev->generating); + return; } /* Wakes thread */ wake_up_interruptible(&dma_q->wq); dprintk(dev, 1, "returning from %s\n", __func__); - return 0; } -static void vivi_stop_thread(struct vivi_dmaqueue *dma_q) +static void vivi_stop_generating(struct file *file) { - struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq); + struct vivi_dev *dev = video_drvdata(file); + struct vivi_dmaqueue *dma_q = &dev->vidq; dprintk(dev, 1, "%s\n", __func__); + + if (!file->private_data) + return; + if (!test_and_clear_bit(0, &dev->generating)) + return; + /* shutdown control thread */ if (dma_q->kthread) { kthread_stop(dma_q->kthread); dma_q->kthread = NULL; } + videobuf_stop(&dev->vb_vidq); + videobuf_mmap_free(&dev->vb_vidq); +} + +static int vivi_is_generating(struct vivi_dev *dev) +{ + return test_bit(0, &dev->generating); } /* ------------------------------------------------------------------ @@ -741,16 +633,15 @@ static void vivi_stop_thread(struct vivi_dmaqueue *dma_q) static int buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) { - struct vivi_fh *fh = vq->priv_data; - struct vivi_dev *dev = fh->dev; + struct vivi_dev *dev = vq->priv_data; - *size = fh->width*fh->height*2; + *size = dev->width * dev->height * 2; if (0 == *count) *count = 32; - if (*size * *count > vid_limit * 1024 * 1024) - *count = (vid_limit * 1024 * 1024) / *size; + while (*size * *count > vid_limit * 1024 * 1024) + (*count)--; dprintk(dev, 1, "%s, count=%d, size=%d\n", __func__, *count, *size); @@ -760,49 +651,43 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) static void free_buffer(struct videobuf_queue *vq, struct vivi_buffer *buf) { - struct vivi_fh *fh = vq->priv_data; - struct vivi_dev *dev = fh->dev; + struct vivi_dev *dev = vq->priv_data; dprintk(dev, 1, "%s, state: %i\n", __func__, buf->vb.state); - if (in_interrupt()) - BUG(); - videobuf_vmalloc_free(&buf->vb); dprintk(dev, 1, "free_buffer: freed\n"); buf->vb.state = VIDEOBUF_NEEDS_INIT; } -#define norm_maxw() 1024 -#define norm_maxh() 768 static int buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, enum v4l2_field field) { - struct vivi_fh *fh = vq->priv_data; - struct vivi_dev *dev = fh->dev; + struct vivi_dev *dev = vq->priv_data; struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb); int rc; dprintk(dev, 1, "%s, field=%d\n", __func__, field); - BUG_ON(NULL == fh->fmt); + BUG_ON(NULL == dev->fmt); - if (fh->width < 48 || fh->width > norm_maxw() || - fh->height < 32 || fh->height > norm_maxh()) + if (dev->width < 48 || dev->width > MAX_WIDTH || + dev->height < 32 || dev->height > MAX_HEIGHT) return -EINVAL; - buf->vb.size = fh->width*fh->height*2; - if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) + buf->vb.size = dev->width * dev->height * 2; + if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) return -EINVAL; /* These properties only change when queue is idle, see s_fmt */ - buf->fmt = fh->fmt; - buf->vb.width = fh->width; - buf->vb.height = fh->height; + buf->fmt = dev->fmt; + buf->vb.width = dev->width; + buf->vb.height = dev->height; buf->vb.field = field; - precalculate_bars(fh); + precalculate_bars(dev); + precalculate_line(dev); if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { rc = videobuf_iolock(vq, &buf->vb, NULL); @@ -811,7 +696,6 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, } buf->vb.state = VIDEOBUF_PREPARED; - return 0; fail: @@ -822,9 +706,8 @@ fail: static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) { - struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb); - struct vivi_fh *fh = vq->priv_data; - struct vivi_dev *dev = fh->dev; + struct vivi_dev *dev = vq->priv_data; + struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb); struct vivi_dmaqueue *vidq = &dev->vidq; dprintk(dev, 1, "%s\n", __func__); @@ -836,9 +719,8 @@ buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) static void buffer_release(struct videobuf_queue *vq, struct videobuf_buffer *vb) { - struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb); - struct vivi_fh *fh = vq->priv_data; - struct vivi_dev *dev = (struct vivi_dev *)fh->dev; + struct vivi_dev *dev = vq->priv_data; + struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb); dprintk(dev, 1, "%s\n", __func__); @@ -858,16 +740,14 @@ static struct videobuf_queue_ops vivi_video_qops = { static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - struct vivi_fh *fh = priv; - struct vivi_dev *dev = fh->dev; + struct vivi_dev *dev = video_drvdata(file); strcpy(cap->driver, "vivi"); strcpy(cap->card, "vivi"); strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info)); cap->version = VIVI_VERSION; - cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_STREAMING | - V4L2_CAP_READWRITE; + cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | \ + V4L2_CAP_READWRITE; return 0; } @@ -889,28 +769,25 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct vivi_fh *fh = priv; + struct vivi_dev *dev = video_drvdata(file); - f->fmt.pix.width = fh->width; - f->fmt.pix.height = fh->height; - f->fmt.pix.field = fh->vb_vidq.field; - f->fmt.pix.pixelformat = fh->fmt->fourcc; + f->fmt.pix.width = dev->width; + f->fmt.pix.height = dev->height; + f->fmt.pix.field = dev->vb_vidq.field; + f->fmt.pix.pixelformat = dev->fmt->fourcc; f->fmt.pix.bytesperline = - (f->fmt.pix.width * fh->fmt->depth) >> 3; + (f->fmt.pix.width * dev->fmt->depth) >> 3; f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; - - return (0); + return 0; } static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct vivi_fh *fh = priv; - struct vivi_dev *dev = fh->dev; + struct vivi_dev *dev = video_drvdata(file); struct vivi_fmt *fmt; enum v4l2_field field; - unsigned int maxw, maxh; fmt = get_format(f); if (!fmt) { @@ -928,113 +805,109 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, return -EINVAL; } - maxw = norm_maxw(); - maxh = norm_maxh(); - f->fmt.pix.field = field; - v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2, - &f->fmt.pix.height, 32, maxh, 0, 0); + v4l_bound_align_image(&f->fmt.pix.width, 48, MAX_WIDTH, 2, + &f->fmt.pix.height, 32, MAX_HEIGHT, 0, 0); f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3; f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; - return 0; } -/*FIXME: This seems to be generic enough to be at videodev2 */ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct vivi_fh *fh = priv; - struct videobuf_queue *q = &fh->vb_vidq; + struct vivi_dev *dev = video_drvdata(file); + struct videobuf_queue *q = &dev->vb_vidq; - int ret = vidioc_try_fmt_vid_cap(file, fh, f); + int ret = vidioc_try_fmt_vid_cap(file, priv, f); if (ret < 0) return ret; mutex_lock(&q->vb_lock); - if (videobuf_queue_is_busy(&fh->vb_vidq)) { - dprintk(fh->dev, 1, "%s queue busy\n", __func__); + if (vivi_is_generating(dev)) { + dprintk(dev, 1, "%s device busy\n", __func__); ret = -EBUSY; goto out; } - fh->fmt = get_format(f); - fh->width = f->fmt.pix.width; - fh->height = f->fmt.pix.height; - fh->vb_vidq.field = f->fmt.pix.field; - fh->type = f->type; - + dev->fmt = get_format(f); + dev->width = f->fmt.pix.width; + dev->height = f->fmt.pix.height; + dev->vb_vidq.field = f->fmt.pix.field; ret = 0; out: mutex_unlock(&q->vb_lock); - return ret; } static int vidioc_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *p) { - struct vivi_fh *fh = priv; + struct vivi_dev *dev = video_drvdata(file); - return (videobuf_reqbufs(&fh->vb_vidq, p)); + return videobuf_reqbufs(&dev->vb_vidq, p); } static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p) { - struct vivi_fh *fh = priv; + struct vivi_dev *dev = video_drvdata(file); - return (videobuf_querybuf(&fh->vb_vidq, p)); + return videobuf_querybuf(&dev->vb_vidq, p); } static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p) { - struct vivi_fh *fh = priv; + struct vivi_dev *dev = video_drvdata(file); - return (videobuf_qbuf(&fh->vb_vidq, p)); + return videobuf_qbuf(&dev->vb_vidq, p); } static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) { - struct vivi_fh *fh = priv; + struct vivi_dev *dev = video_drvdata(file); - return (videobuf_dqbuf(&fh->vb_vidq, p, - file->f_flags & O_NONBLOCK)); + return videobuf_dqbuf(&dev->vb_vidq, p, + file->f_flags & O_NONBLOCK); } #ifdef CONFIG_VIDEO_V4L1_COMPAT static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) { - struct vivi_fh *fh = priv; + struct vivi_dev *dev = video_drvdata(file); - return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8); + return videobuf_cgmbuf(&dev->vb_vidq, mbuf, 8); } #endif static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) { - struct vivi_fh *fh = priv; + struct vivi_dev *dev = video_drvdata(file); + int ret; - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (i != fh->type) + if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; + ret = videobuf_streamon(&dev->vb_vidq); + if (ret) + return ret; - return videobuf_streamon(&fh->vb_vidq); + vivi_start_generating(file); + return 0; } static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) { - struct vivi_fh *fh = priv; + struct vivi_dev *dev = video_drvdata(file); + int ret; - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (i != fh->type) + if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - - return videobuf_streamoff(&fh->vb_vidq); + ret = videobuf_streamoff(&dev->vb_vidq); + if (!ret) + vivi_stop_generating(file); + return ret; } static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i) @@ -1052,80 +925,104 @@ static int vidioc_enum_input(struct file *file, void *priv, inp->type = V4L2_INPUT_TYPE_CAMERA; inp->std = V4L2_STD_525_60; sprintf(inp->name, "Camera %u", inp->index); - - return (0); + return 0; } static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) { - struct vivi_fh *fh = priv; - struct vivi_dev *dev = fh->dev; + struct vivi_dev *dev = video_drvdata(file); *i = dev->input; - - return (0); + return 0; } + static int vidioc_s_input(struct file *file, void *priv, unsigned int i) { - struct vivi_fh *fh = priv; - struct vivi_dev *dev = fh->dev; + struct vivi_dev *dev = video_drvdata(file); if (i >= NUM_INPUTS) return -EINVAL; dev->input = i; - precalculate_bars(fh); - - return (0); + precalculate_bars(dev); + precalculate_line(dev); + return 0; } - /* --- controls ---------------------------------------------- */ +/* --- controls ---------------------------------------------- */ static int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qc) { - int i; - - for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) - if (qc->id && qc->id == vivi_qctrl[i].id) { - memcpy(qc, &(vivi_qctrl[i]), - sizeof(*qc)); - return (0); - } - + switch (qc->id) { + case V4L2_CID_AUDIO_VOLUME: + return v4l2_ctrl_query_fill(qc, 0, 255, 1, 200); + case V4L2_CID_BRIGHTNESS: + return v4l2_ctrl_query_fill(qc, 0, 255, 1, 127); + case V4L2_CID_CONTRAST: + return v4l2_ctrl_query_fill(qc, 0, 255, 1, 16); + case V4L2_CID_SATURATION: + return v4l2_ctrl_query_fill(qc, 0, 255, 1, 127); + case V4L2_CID_HUE: + return v4l2_ctrl_query_fill(qc, -128, 127, 1, 0); + } return -EINVAL; } static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct vivi_fh *fh = priv; - struct vivi_dev *dev = fh->dev; - int i; - - for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) - if (ctrl->id == vivi_qctrl[i].id) { - ctrl->value = dev->qctl_regs[i]; - return 0; - } + struct vivi_dev *dev = video_drvdata(file); + switch (ctrl->id) { + case V4L2_CID_AUDIO_VOLUME: + ctrl->value = dev->volume; + return 0; + case V4L2_CID_BRIGHTNESS: + ctrl->value = dev->brightness; + return 0; + case V4L2_CID_CONTRAST: + ctrl->value = dev->contrast; + return 0; + case V4L2_CID_SATURATION: + ctrl->value = dev->saturation; + return 0; + case V4L2_CID_HUE: + ctrl->value = dev->hue; + return 0; + } return -EINVAL; } + static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct vivi_fh *fh = priv; - struct vivi_dev *dev = fh->dev; - int i; - - for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) - if (ctrl->id == vivi_qctrl[i].id) { - if (ctrl->value < vivi_qctrl[i].minimum || - ctrl->value > vivi_qctrl[i].maximum) { - return -ERANGE; - } - dev->qctl_regs[i] = ctrl->value; - return 0; - } + struct vivi_dev *dev = video_drvdata(file); + struct v4l2_queryctrl qc; + int err; + + qc.id = ctrl->id; + err = vidioc_queryctrl(file, priv, &qc); + if (err < 0) + return err; + if (ctrl->value < qc.minimum || ctrl->value > qc.maximum) + return -ERANGE; + switch (ctrl->id) { + case V4L2_CID_AUDIO_VOLUME: + dev->volume = ctrl->value; + return 0; + case V4L2_CID_BRIGHTNESS: + dev->brightness = ctrl->value; + return 0; + case V4L2_CID_CONTRAST: + dev->contrast = ctrl->value; + return 0; + case V4L2_CID_SATURATION: + dev->saturation = ctrl->value; + return 0; + case V4L2_CID_HUE: + dev->hue = ctrl->value; + return 0; + } return -EINVAL; } @@ -1133,134 +1030,58 @@ static int vidioc_s_ctrl(struct file *file, void *priv, File operations for the device ------------------------------------------------------------------*/ -static int vivi_open(struct file *file) -{ - struct vivi_dev *dev = video_drvdata(file); - struct vivi_fh *fh = NULL; - int retval = 0; - - mutex_lock(&dev->mutex); - dev->users++; - - if (dev->users > 1) { - dev->users--; - mutex_unlock(&dev->mutex); - return -EBUSY; - } - - dprintk(dev, 1, "open %s type=%s users=%d\n", - video_device_node_name(dev->vfd), - v4l2_type_names[V4L2_BUF_TYPE_VIDEO_CAPTURE], dev->users); - - /* allocate + initialize per filehandle data */ - fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) { - dev->users--; - retval = -ENOMEM; - } - mutex_unlock(&dev->mutex); - - if (retval) - return retval; - - file->private_data = fh; - fh->dev = dev; - - fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - fh->fmt = &formats[0]; - fh->width = 640; - fh->height = 480; - - /* Resets frame counters */ - dev->h = 0; - dev->m = 0; - dev->s = 0; - dev->ms = 0; - dev->mv_count = 0; - dev->jiffies = jiffies; - sprintf(dev->timestr, "%02d:%02d:%02d:%03d", - dev->h, dev->m, dev->s, dev->ms); - - videobuf_queue_vmalloc_init(&fh->vb_vidq, &vivi_video_qops, - NULL, &dev->slock, fh->type, V4L2_FIELD_INTERLACED, - sizeof(struct vivi_buffer), fh); - - vivi_start_thread(fh); - - return 0; -} - static ssize_t vivi_read(struct file *file, char __user *data, size_t count, loff_t *ppos) { - struct vivi_fh *fh = file->private_data; + struct vivi_dev *dev = video_drvdata(file); - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - return videobuf_read_stream(&fh->vb_vidq, data, count, ppos, 0, + vivi_start_generating(file); + return videobuf_read_stream(&dev->vb_vidq, data, count, ppos, 0, file->f_flags & O_NONBLOCK); - } - return 0; } static unsigned int vivi_poll(struct file *file, struct poll_table_struct *wait) { - struct vivi_fh *fh = file->private_data; - struct vivi_dev *dev = fh->dev; - struct videobuf_queue *q = &fh->vb_vidq; + struct vivi_dev *dev = video_drvdata(file); + struct videobuf_queue *q = &dev->vb_vidq; dprintk(dev, 1, "%s\n", __func__); - if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type) - return POLLERR; - + vivi_start_generating(file); return videobuf_poll_stream(file, q, wait); } static int vivi_close(struct file *file) { - struct vivi_fh *fh = file->private_data; - struct vivi_dev *dev = fh->dev; - struct vivi_dmaqueue *vidq = &dev->vidq; struct video_device *vdev = video_devdata(file); + struct vivi_dev *dev = video_drvdata(file); - vivi_stop_thread(vidq); - videobuf_stop(&fh->vb_vidq); - videobuf_mmap_free(&fh->vb_vidq); - - kfree(fh); - - mutex_lock(&dev->mutex); - dev->users--; - mutex_unlock(&dev->mutex); - - dprintk(dev, 1, "close called (dev=%s, users=%d)\n", - video_device_node_name(vdev), dev->users); + vivi_stop_generating(file); + dprintk(dev, 1, "close called (dev=%s)\n", + video_device_node_name(vdev)); return 0; } static int vivi_mmap(struct file *file, struct vm_area_struct *vma) { - struct vivi_fh *fh = file->private_data; - struct vivi_dev *dev = fh->dev; + struct vivi_dev *dev = video_drvdata(file); int ret; dprintk(dev, 1, "mmap called, vma=0x%08lx\n", (unsigned long)vma); - ret = videobuf_mmap_mapper(&fh->vb_vidq, vma); + ret = videobuf_mmap_mapper(&dev->vb_vidq, vma); dprintk(dev, 1, "vma start=0x%08lx, size=%ld, ret=%d\n", (unsigned long)vma->vm_start, - (unsigned long)vma->vm_end-(unsigned long)vma->vm_start, + (unsigned long)vma->vm_end - (unsigned long)vma->vm_start, ret); - return ret; } static const struct v4l2_file_operations vivi_fops = { .owner = THIS_MODULE, - .open = vivi_open, .release = vivi_close, .read = vivi_read, .poll = vivi_poll, @@ -1282,11 +1103,11 @@ static const struct v4l2_ioctl_ops vivi_ioctl_ops = { .vidioc_enum_input = vidioc_enum_input, .vidioc_g_input = vidioc_g_input, .vidioc_s_input = vidioc_s_input, + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, .vidioc_queryctrl = vidioc_queryctrl, .vidioc_g_ctrl = vidioc_g_ctrl, .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, #ifdef CONFIG_VIDEO_V4L1_COMPAT .vidiocgmbuf = vidiocgmbuf, #endif @@ -1330,7 +1151,7 @@ static int __init vivi_create_instance(int inst) { struct vivi_dev *dev; struct video_device *vfd; - int ret, i; + int ret; dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) @@ -1342,6 +1163,20 @@ static int __init vivi_create_instance(int inst) if (ret) goto free_dev; + dev->fmt = &formats[0]; + dev->width = 640; + dev->height = 480; + dev->volume = 200; + dev->brightness = 127; + dev->contrast = 16; + dev->saturation = 127; + dev->hue = 0; + + videobuf_queue_vmalloc_init(&dev->vb_vidq, &vivi_video_qops, + NULL, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_INTERLACED, + sizeof(struct vivi_buffer), dev); + /* init video dma queues */ INIT_LIST_HEAD(&dev->vidq.active); init_waitqueue_head(&dev->vidq.wq); @@ -1357,6 +1192,7 @@ static int __init vivi_create_instance(int inst) *vfd = vivi_template; vfd->debug = debug; + vfd->v4l2_dev = &dev->v4l2_dev; ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr); if (ret < 0) @@ -1364,10 +1200,6 @@ static int __init vivi_create_instance(int inst) video_set_drvdata(vfd, dev); - /* Set all controls to their default value. */ - for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) - dev->qctl_regs[i] = vivi_qctrl[i].default_value; - /* Now that everything is fine, let's add it to device list */ list_add_tail(&dev->vivi_devlist, &vivi_devlist); @@ -1396,8 +1228,15 @@ free_dev: */ static int __init vivi_init(void) { + const struct font_desc *font = find_font("VGA8x16"); int ret = 0, i; + if (font == NULL) { + printk(KERN_ERR "vivi: could not find font\n"); + return -ENODEV; + } + font8x16 = font->data; + if (n_devs <= 0) n_devs = 1; @@ -1412,7 +1251,7 @@ static int __init vivi_init(void) } if (ret < 0) { - printk(KERN_INFO "Error %d while loading vivi driver\n", ret); + printk(KERN_ERR "vivi: error %d while loading driver\n", ret); return ret; } -- cgit v1.2.3-70-g09d2 From e622681d124688d3caf1bf62cce96465a9078a11 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 23 Mar 2010 11:23:31 -0300 Subject: V4L/DVB: sh_mobile_ceu_camera.c: preserve output window on VIDIOC_S_CROP Current version of sh_mobile_ceu_camera.c interprets the V4L2 API specification of the VIDIOC_S_CROP ioctl as "change input (for capture devices) area, preserve scaling factors, therefore change output window," whereas a more intuitive interpretation of the API is "change input area, preserve output window." Switch sh_mobile_ceu_camera.c to use this interpretation. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/sh_mobile_ceu_camera.c | 601 +++++++++++++++-------------- 1 file changed, 309 insertions(+), 292 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index 9a46f0a0c1b..4ac3b482fbb 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c @@ -115,9 +115,20 @@ struct sh_mobile_ceu_dev { }; struct sh_mobile_ceu_cam { - struct v4l2_rect ceu_rect; - unsigned int cam_width; - unsigned int cam_height; + /* CEU offsets within scaled by the CEU camera output */ + unsigned int ceu_left; + unsigned int ceu_top; + /* Client output, as seen by the CEU */ + unsigned int width; + unsigned int height; + /* + * User window from S_CROP / G_CROP, produced by client cropping and + * scaling, CEU scaling and CEU cropping, mapped back onto the client + * input window + */ + struct v4l2_rect subrect; + /* Camera cropping rectangle */ + struct v4l2_rect rect; const struct soc_mbus_pixelfmt *extra_fmt; enum v4l2_mbus_pixelcode code; }; @@ -565,38 +576,36 @@ static u16 calc_scale(unsigned int src, unsigned int *dst) } /* rect is guaranteed to not exceed the scaled camera rectangle */ -static void sh_mobile_ceu_set_rect(struct soc_camera_device *icd, - unsigned int out_width, - unsigned int out_height) +static void sh_mobile_ceu_set_rect(struct soc_camera_device *icd) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct sh_mobile_ceu_cam *cam = icd->host_priv; - struct v4l2_rect *rect = &cam->ceu_rect; struct sh_mobile_ceu_dev *pcdev = ici->priv; unsigned int height, width, cdwdr_width, in_width, in_height; unsigned int left_offset, top_offset; u32 camor; - dev_dbg(icd->dev.parent, "Crop %ux%u@%u:%u\n", - rect->width, rect->height, rect->left, rect->top); + dev_geo(icd->dev.parent, "Crop %ux%u@%u:%u\n", + icd->user_width, icd->user_height, cam->ceu_left, cam->ceu_top); - left_offset = rect->left; - top_offset = rect->top; + left_offset = cam->ceu_left; + top_offset = cam->ceu_top; + /* CEU cropping (CFSZR) is applied _after_ the scaling filter (CFLCR) */ if (pcdev->image_mode) { - in_width = rect->width; + in_width = cam->width; if (!pcdev->is_16bit) { in_width *= 2; left_offset *= 2; } - width = out_width; - cdwdr_width = out_width; + width = icd->user_width; + cdwdr_width = icd->user_width; } else { - int bytes_per_line = soc_mbus_bytes_per_line(out_width, + int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, icd->current_fmt->host_fmt); unsigned int w_factor; - width = out_width; + width = icd->user_width; switch (icd->current_fmt->host_fmt->packing) { case SOC_MBUS_PACKING_2X8_PADHI: @@ -606,17 +615,17 @@ static void sh_mobile_ceu_set_rect(struct soc_camera_device *icd, w_factor = 1; } - in_width = rect->width * w_factor; + in_width = cam->width * w_factor; left_offset = left_offset * w_factor; if (bytes_per_line < 0) - cdwdr_width = out_width; + cdwdr_width = icd->user_width; else cdwdr_width = bytes_per_line; } - height = out_height; - in_height = rect->height; + height = icd->user_height; + in_height = cam->height; if (V4L2_FIELD_NONE != pcdev->field) { height /= 2; in_height /= 2; @@ -775,9 +784,10 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, } ceu_write(pcdev, CAIFR, value); - sh_mobile_ceu_set_rect(icd, icd->user_width, icd->user_height); + sh_mobile_ceu_set_rect(icd); mdelay(1); + dev_geo(icd->dev.parent, "CFLCR 0x%x\n", pcdev->cflcr); ceu_write(pcdev, CFLCR, pcdev->cflcr); /* @@ -866,6 +876,8 @@ static bool sh_mobile_ceu_packing_supported(const struct soc_mbus_pixelfmt *fmt) fmt->packing == SOC_MBUS_PACKING_EXTEND16); } +static int client_g_rect(struct v4l2_subdev *sd, struct v4l2_rect *rect); + static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx, struct soc_camera_format_xlate *xlate) { @@ -894,10 +906,55 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx, return 0; if (!icd->host_priv) { + struct v4l2_mbus_framefmt mf; + struct v4l2_rect rect; + struct device *dev = icd->dev.parent; + int shift = 0; + + /* FIXME: subwindow is lost between close / open */ + + /* Cache current client geometry */ + ret = client_g_rect(sd, &rect); + if (ret < 0) + return ret; + + /* First time */ + ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf); + if (ret < 0) + return ret; + + while ((mf.width > 2560 || mf.height > 1920) && shift < 4) { + /* Try 2560x1920, 1280x960, 640x480, 320x240 */ + mf.width = 2560 >> shift; + mf.height = 1920 >> shift; + ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf); + if (ret < 0) + return ret; + shift++; + } + + if (shift == 4) { + dev_err(dev, "Failed to configure the client below %ux%x\n", + mf.width, mf.height); + return -EIO; + } + + dev_geo(dev, "camera fmt %ux%u\n", mf.width, mf.height); + cam = kzalloc(sizeof(*cam), GFP_KERNEL); if (!cam) return -ENOMEM; + /* We are called with current camera crop, initialise subrect with it */ + cam->rect = rect; + cam->subrect = rect; + + cam->width = mf.width; + cam->height = mf.height; + + cam->width = mf.width; + cam->height = mf.height; + icd->host_priv = cam; } else { cam = icd->host_priv; @@ -979,16 +1036,12 @@ static unsigned int scale_down(unsigned int size, unsigned int scale) return (size * 4096 + scale / 2) / scale; } -static unsigned int scale_up(unsigned int size, unsigned int scale) -{ - return (size * scale + 2048) / 4096; -} - static unsigned int calc_generic_scale(unsigned int input, unsigned int output) { return (input * 4096 + output / 2) / output; } +/* Get and store current client crop */ static int client_g_rect(struct v4l2_subdev *sd, struct v4l2_rect *rect) { struct v4l2_crop crop; @@ -1007,25 +1060,51 @@ static int client_g_rect(struct v4l2_subdev *sd, struct v4l2_rect *rect) cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ret = v4l2_subdev_call(sd, video, cropcap, &cap); - if (ret < 0) - return ret; - - *rect = cap.defrect; + if (!ret) + *rect = cap.defrect; return ret; } +/* Client crop has changed, update our sub-rectangle to remain within the area */ +static void update_subrect(struct sh_mobile_ceu_cam *cam) +{ + struct v4l2_rect *rect = &cam->rect, *subrect = &cam->subrect; + + if (rect->width < subrect->width) + subrect->width = rect->width; + + if (rect->height < subrect->height) + subrect->height = rect->height; + + if (rect->left > subrect->left) + subrect->left = rect->left; + else if (rect->left + rect->width > + subrect->left + subrect->width) + subrect->left = rect->left + rect->width - + subrect->width; + + if (rect->top > subrect->top) + subrect->top = rect->top; + else if (rect->top + rect->height > + subrect->top + subrect->height) + subrect->top = rect->top + rect->height - + subrect->height; +} + /* * The common for both scaling and cropping iterative approach is: * 1. try if the client can produce exactly what requested by the user * 2. if (1) failed, try to double the client image until we get one big enough * 3. if (2) failed, try to request the maximum image */ -static int client_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *crop, +static int client_s_crop(struct soc_camera_device *icd, struct v4l2_crop *crop, struct v4l2_crop *cam_crop) { + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct v4l2_rect *rect = &crop->c, *cam_rect = &cam_crop->c; struct device *dev = sd->v4l2_dev->dev; + struct sh_mobile_ceu_cam *cam = icd->host_priv; struct v4l2_cropcap cap; int ret; unsigned int width, height; @@ -1043,6 +1122,7 @@ static int client_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *crop, /* Even if camera S_CROP failed, but camera rectangle matches */ dev_dbg(dev, "Camera S_CROP successful for %dx%d@%d:%d\n", rect->width, rect->height, rect->left, rect->top); + cam->rect = *cam_rect; return 0; } @@ -1057,6 +1137,7 @@ static int client_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *crop, if (ret < 0) return ret; + /* Put user requested rectangle within sensor bounds */ soc_camera_limit_side(&rect->left, &rect->width, cap.bounds.left, 2, cap.bounds.width); soc_camera_limit_side(&rect->top, &rect->height, cap.bounds.top, 4, @@ -1069,6 +1150,10 @@ static int client_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *crop, width = max(cam_rect->width, 2); height = max(cam_rect->height, 2); + /* + * Loop as long as sensor is not covering the requested rectangle and + * is still within its bounds + */ while (!ret && (is_smaller(cam_rect, rect) || is_inside(cam_rect, rect)) && (cap.bounds.width > width || cap.bounds.height > height)) { @@ -1086,6 +1171,7 @@ static int client_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *crop, * target left, set it to the middle point between the current * left and minimum left. But that would add too much * complexity: we would have to iterate each border separately. + * Instead we just drop to the left and top bounds. */ if (cam_rect->left > rect->left) cam_rect->left = cap.bounds.left; @@ -1122,77 +1208,19 @@ static int client_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *crop, cam_rect->left, cam_rect->top); } - return ret; -} - -static int get_camera_scales(struct v4l2_subdev *sd, struct v4l2_rect *rect, - unsigned int *scale_h, unsigned int *scale_v) -{ - struct v4l2_mbus_framefmt mf; - int ret; - - ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf); - if (ret < 0) - return ret; - - *scale_h = calc_generic_scale(rect->width, mf.width); - *scale_v = calc_generic_scale(rect->height, mf.height); - - return 0; -} - -static int get_camera_subwin(struct soc_camera_device *icd, - struct v4l2_rect *cam_subrect, - unsigned int cam_hscale, unsigned int cam_vscale) -{ - struct sh_mobile_ceu_cam *cam = icd->host_priv; - struct v4l2_rect *ceu_rect = &cam->ceu_rect; - - if (!ceu_rect->width) { - struct v4l2_subdev *sd = soc_camera_to_subdev(icd); - struct device *dev = icd->dev.parent; - struct v4l2_mbus_framefmt mf; - int ret; - /* First time */ - - ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf); - if (ret < 0) - return ret; - - dev_geo(dev, "camera fmt %ux%u\n", mf.width, mf.height); - - if (mf.width > 2560) { - ceu_rect->width = 2560; - ceu_rect->left = (mf.width - 2560) / 2; - } else { - ceu_rect->width = mf.width; - ceu_rect->left = 0; - } - - if (mf.height > 1920) { - ceu_rect->height = 1920; - ceu_rect->top = (mf.height - 1920) / 2; - } else { - ceu_rect->height = mf.height; - ceu_rect->top = 0; - } - - dev_geo(dev, "initialised CEU rect %ux%u@%u:%u\n", - ceu_rect->width, ceu_rect->height, - ceu_rect->left, ceu_rect->top); + if (!ret) { + cam->rect = *cam_rect; + update_subrect(cam); } - cam_subrect->width = scale_up(ceu_rect->width, cam_hscale); - cam_subrect->left = scale_up(ceu_rect->left, cam_hscale); - cam_subrect->height = scale_up(ceu_rect->height, cam_vscale); - cam_subrect->top = scale_up(ceu_rect->top, cam_vscale); - - return 0; + return ret; } +/* Iterative s_mbus_fmt, also updates cached client crop on success */ static int client_s_fmt(struct soc_camera_device *icd, struct v4l2_mbus_framefmt *mf, bool ceu_can_scale) { + struct sh_mobile_ceu_cam *cam = icd->host_priv; struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct device *dev = icd->dev.parent; unsigned int width = mf->width, height = mf->height, tmp_w, tmp_h; @@ -1200,6 +1228,15 @@ static int client_s_fmt(struct soc_camera_device *icd, struct v4l2_cropcap cap; int ret; + ret = v4l2_subdev_call(sd, video, s_mbus_fmt, mf); + if (ret < 0) + return ret; + + dev_geo(dev, "camera scaled to %ux%u\n", mf->width, mf->height); + + if ((width == mf->width && height == mf->height) || !ceu_can_scale) + goto update_cache; + cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ret = v4l2_subdev_call(sd, video, cropcap, &cap); @@ -1209,15 +1246,6 @@ static int client_s_fmt(struct soc_camera_device *icd, max_width = min(cap.bounds.width, 2560); max_height = min(cap.bounds.height, 1920); - ret = v4l2_subdev_call(sd, video, s_mbus_fmt, mf); - if (ret < 0) - return ret; - - dev_geo(dev, "camera scaled to %ux%u\n", mf->width, mf->height); - - if ((width == mf->width && height == mf->height) || !ceu_can_scale) - return 0; - /* Camera set a format, but geometry is not precise, try to improve */ tmp_w = mf->width; tmp_h = mf->height; @@ -1239,26 +1267,37 @@ static int client_s_fmt(struct soc_camera_device *icd, } } +update_cache: + /* Update cache */ + ret = client_g_rect(sd, &cam->rect); + if (ret < 0) + return ret; + + update_subrect(cam); + return 0; } /** - * @rect - camera cropped rectangle - * @sub_rect - CEU cropped rectangle, mapped back to camera input area - * @ceu_rect - on output calculated CEU crop rectangle + * @width - on output: user width, mapped back to input + * @height - on output: user height, mapped back to input + * @mf - in- / output camera output window */ -static int client_scale(struct soc_camera_device *icd, struct v4l2_rect *rect, - struct v4l2_rect *sub_rect, struct v4l2_rect *ceu_rect, - struct v4l2_mbus_framefmt *mf, bool ceu_can_scale) +static int client_scale(struct soc_camera_device *icd, + struct v4l2_mbus_framefmt *mf, + unsigned int *width, unsigned int *height, + bool ceu_can_scale) { - struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct sh_mobile_ceu_cam *cam = icd->host_priv; struct device *dev = icd->dev.parent; struct v4l2_mbus_framefmt mf_tmp = *mf; unsigned int scale_h, scale_v; int ret; - /* 5. Apply iterative camera S_FMT for camera user window. */ + /* + * 5. Apply iterative camera S_FMT for camera user window (also updates + * client crop cache and the imaginary sub-rectangle). + */ ret = client_s_fmt(icd, &mf_tmp, ceu_can_scale); if (ret < 0) return ret; @@ -1270,60 +1309,22 @@ static int client_scale(struct soc_camera_device *icd, struct v4l2_rect *rect, /* unneeded - it is already in "mf_tmp" */ - /* 7. Calculate new camera scales. */ - ret = get_camera_scales(sd, rect, &scale_h, &scale_v); - if (ret < 0) - return ret; - - dev_geo(dev, "7: camera scales %u:%u\n", scale_h, scale_v); + /* 7. Calculate new client scales. */ + scale_h = calc_generic_scale(cam->rect.width, mf_tmp.width); + scale_v = calc_generic_scale(cam->rect.height, mf_tmp.height); - cam->cam_width = mf_tmp.width; - cam->cam_height = mf_tmp.height; mf->width = mf_tmp.width; mf->height = mf_tmp.height; mf->colorspace = mf_tmp.colorspace; /* * 8. Calculate new CEU crop - apply camera scales to previously - * calculated "effective" crop. + * updated "effective" crop. */ - ceu_rect->left = scale_down(sub_rect->left, scale_h); - ceu_rect->width = scale_down(sub_rect->width, scale_h); - ceu_rect->top = scale_down(sub_rect->top, scale_v); - ceu_rect->height = scale_down(sub_rect->height, scale_v); + *width = scale_down(cam->subrect.width, scale_h); + *height = scale_down(cam->subrect.height, scale_v); - dev_geo(dev, "8: new CEU rect %ux%u@%u:%u\n", - ceu_rect->width, ceu_rect->height, - ceu_rect->left, ceu_rect->top); - - return 0; -} - -/* Get combined scales */ -static int get_scales(struct soc_camera_device *icd, - unsigned int *scale_h, unsigned int *scale_v) -{ - struct sh_mobile_ceu_cam *cam = icd->host_priv; - struct v4l2_subdev *sd = soc_camera_to_subdev(icd); - struct v4l2_crop cam_crop; - unsigned int width_in, height_in; - int ret; - - cam_crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - ret = client_g_rect(sd, &cam_crop.c); - if (ret < 0) - return ret; - - ret = get_camera_scales(sd, &cam_crop.c, scale_h, scale_v); - if (ret < 0) - return ret; - - width_in = scale_up(cam->ceu_rect.width, *scale_h); - height_in = scale_up(cam->ceu_rect.height, *scale_v); - - *scale_h = calc_generic_scale(width_in, icd->user_width); - *scale_v = calc_generic_scale(height_in, icd->user_height); + dev_geo(dev, "8: new client sub-window %ux%u\n", *width, *height); return 0; } @@ -1342,115 +1343,165 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, struct sh_mobile_ceu_dev *pcdev = ici->priv; struct v4l2_crop cam_crop; struct sh_mobile_ceu_cam *cam = icd->host_priv; - struct v4l2_rect *cam_rect = &cam_crop.c, *ceu_rect = &cam->ceu_rect; + struct v4l2_rect *cam_rect = &cam_crop.c; struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct device *dev = icd->dev.parent; struct v4l2_mbus_framefmt mf; - unsigned int scale_comb_h, scale_comb_v, scale_ceu_h, scale_ceu_v, - out_width, out_height; + unsigned int scale_cam_h, scale_cam_v, scale_ceu_h, scale_ceu_v, + out_width, out_height, scale_h, scale_v; + int interm_width, interm_height; u32 capsr, cflcr; int ret; - /* 1. Calculate current combined scales. */ - ret = get_scales(icd, &scale_comb_h, &scale_comb_v); - if (ret < 0) - return ret; + dev_geo(dev, "S_CROP(%ux%u@%u:%u)\n", rect->width, rect->height, + rect->left, rect->top); - dev_geo(dev, "1: combined scales %u:%u\n", scale_comb_h, scale_comb_v); + /* During camera cropping its output window can change too, stop CEU */ + capsr = capture_save_reset(pcdev); + dev_dbg(dev, "CAPSR 0x%x, CFLCR 0x%x\n", capsr, pcdev->cflcr); - /* 2. Apply iterative camera S_CROP for new input window. */ - ret = client_s_crop(sd, a, &cam_crop); + /* 1. - 2. Apply iterative camera S_CROP for new input window. */ + ret = client_s_crop(icd, a, &cam_crop); if (ret < 0) return ret; - dev_geo(dev, "2: camera cropped to %ux%u@%u:%u\n", + dev_geo(dev, "1-2: camera cropped to %ux%u@%u:%u\n", cam_rect->width, cam_rect->height, cam_rect->left, cam_rect->top); /* On success cam_crop contains current camera crop */ - /* - * 3. If old combined scales applied to new crop produce an impossible - * user window, adjust scales to produce nearest possible window. - */ - out_width = scale_down(rect->width, scale_comb_h); - out_height = scale_down(rect->height, scale_comb_v); - - if (out_width > 2560) - out_width = 2560; - else if (out_width < 2) - out_width = 2; - - if (out_height > 1920) - out_height = 1920; - else if (out_height < 4) - out_height = 4; - - dev_geo(dev, "3: Adjusted output %ux%u\n", out_width, out_height); - - /* 4. Use G_CROP to retrieve actual input window: already in cam_crop */ - - /* - * 5. Using actual input window and calculated combined scales calculate - * camera target output window. - */ - mf.width = scale_down(cam_rect->width, scale_comb_h); - mf.height = scale_down(cam_rect->height, scale_comb_v); - - dev_geo(dev, "5: camera target %ux%u\n", mf.width, mf.height); - - /* 6. - 9. */ - mf.code = cam->code; - mf.field = pcdev->field; - - capsr = capture_save_reset(pcdev); - dev_dbg(dev, "CAPSR 0x%x, CFLCR 0x%x\n", capsr, pcdev->cflcr); + /* 3. Retrieve camera output window */ + ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf); + if (ret < 0) + return ret; - /* Make relative to camera rectangle */ - rect->left -= cam_rect->left; - rect->top -= cam_rect->top; + if (mf.width > 2560 || mf.height > 1920) + return -EINVAL; - ret = client_scale(icd, cam_rect, rect, ceu_rect, &mf, - pcdev->image_mode && - V4L2_FIELD_NONE == pcdev->field); + /* Cache camera output window */ + cam->width = mf.width; + cam->height = mf.height; - dev_geo(dev, "6-9: %d\n", ret); + /* 4. Calculate camera scales */ + scale_cam_h = calc_generic_scale(cam_rect->width, mf.width); + scale_cam_v = calc_generic_scale(cam_rect->height, mf.height); - /* 10. Use CEU cropping to crop to the new window. */ - sh_mobile_ceu_set_rect(icd, out_width, out_height); + /* Calculate intermediate window */ + interm_width = scale_down(rect->width, scale_cam_h); + interm_height = scale_down(rect->height, scale_cam_v); - dev_geo(dev, "10: CEU cropped to %ux%u@%u:%u\n", - ceu_rect->width, ceu_rect->height, - ceu_rect->left, ceu_rect->top); + if (pcdev->image_mode) { + out_width = min(interm_width, icd->user_width); + out_height = min(interm_height, icd->user_height); + } else { + out_width = interm_width; + out_height = interm_height; + } /* - * 11. Calculate CEU scales from camera scales from results of (10) and - * user window from (3) + * 5. Calculate CEU scales from camera scales from results of (5) and + * the user window */ - scale_ceu_h = calc_scale(ceu_rect->width, &out_width); - scale_ceu_v = calc_scale(ceu_rect->height, &out_height); + scale_ceu_h = calc_scale(interm_width, &out_width); + scale_ceu_v = calc_scale(interm_height, &out_height); - dev_geo(dev, "11: CEU scales %u:%u\n", scale_ceu_h, scale_ceu_v); + /* Calculate camera scales */ + scale_h = calc_generic_scale(cam_rect->width, out_width); + scale_v = calc_generic_scale(cam_rect->height, out_height); - /* 12. Apply CEU scales. */ + dev_geo(dev, "5: CEU scales %u:%u\n", scale_ceu_h, scale_ceu_v); + + /* Apply CEU scales. */ cflcr = scale_ceu_h | (scale_ceu_v << 16); if (cflcr != pcdev->cflcr) { pcdev->cflcr = cflcr; ceu_write(pcdev, CFLCR, cflcr); } + icd->user_width = out_width; + icd->user_height = out_height; + cam->ceu_left = scale_down(rect->left - cam_rect->left, scale_h) & ~1; + cam->ceu_top = scale_down(rect->top - cam_rect->top, scale_v) & ~1; + + /* 6. Use CEU cropping to crop to the new window. */ + sh_mobile_ceu_set_rect(icd); + + cam->subrect = *rect; + + dev_geo(dev, "6: CEU cropped to %ux%u@%u:%u\n", + icd->user_width, icd->user_height, + cam->ceu_left, cam->ceu_top); + /* Restore capture */ if (pcdev->active) capsr |= 1; capture_restore(pcdev, capsr); - icd->user_width = out_width; - icd->user_height = out_height; - /* Even if only camera cropping succeeded */ return ret; } +static int sh_mobile_ceu_get_crop(struct soc_camera_device *icd, + struct v4l2_crop *a) +{ + struct sh_mobile_ceu_cam *cam = icd->host_priv; + + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + a->c = cam->subrect; + + return 0; +} + +/* + * Calculate real client output window by applying new scales to the current + * client crop. New scales are calculated from the requested output format and + * CEU crop, mapped backed onto the client input (subrect). + */ +static void calculate_client_output(struct soc_camera_device *icd, + struct v4l2_pix_format *pix, struct v4l2_mbus_framefmt *mf) +{ + struct sh_mobile_ceu_cam *cam = icd->host_priv; + struct device *dev = icd->dev.parent; + struct v4l2_rect *cam_subrect = &cam->subrect; + unsigned int scale_v, scale_h; + + if (cam_subrect->width == cam->rect.width && + cam_subrect->height == cam->rect.height) { + /* No sub-cropping */ + mf->width = pix->width; + mf->height = pix->height; + return; + } + + /* 1.-2. Current camera scales and subwin - cached. */ + + dev_geo(dev, "2: subwin %ux%u@%u:%u\n", + cam_subrect->width, cam_subrect->height, + cam_subrect->left, cam_subrect->top); + + /* + * 3. Calculate new combined scales from input sub-window to requested + * user window. + */ + + /* + * TODO: CEU cannot scale images larger than VGA to smaller than SubQCIF + * (128x96) or larger than VGA + */ + scale_h = calc_generic_scale(cam_subrect->width, pix->width); + scale_v = calc_generic_scale(cam_subrect->height, pix->height); + + dev_geo(dev, "3: scales %u:%u\n", scale_h, scale_v); + + /* + * 4. Calculate client output window by applying combined scales to real + * input window. + */ + mf->width = scale_down(cam->rect.width, scale_h); + mf->height = scale_down(cam->rect.height, scale_v); +} + /* Similar to set_crop multistage iterative algorithm */ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, struct v4l2_format *f) @@ -1460,18 +1511,17 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, struct sh_mobile_ceu_cam *cam = icd->host_priv; struct v4l2_pix_format *pix = &f->fmt.pix; struct v4l2_mbus_framefmt mf; - struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct device *dev = icd->dev.parent; __u32 pixfmt = pix->pixelformat; const struct soc_camera_format_xlate *xlate; - struct v4l2_crop cam_crop; - struct v4l2_rect *cam_rect = &cam_crop.c, cam_subrect, ceu_rect; - unsigned int scale_cam_h, scale_cam_v; + unsigned int ceu_sub_width, ceu_sub_height; u16 scale_v, scale_h; int ret; bool image_mode; enum v4l2_field field; + dev_geo(dev, "S_FMT(pix=0x%x, %ux%u)\n", pixfmt, pix->width, pix->height); + switch (pix->field) { default: pix->field = V4L2_FIELD_NONE; @@ -1492,46 +1542,8 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, return -EINVAL; } - /* 1. Calculate current camera scales. */ - cam_crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - ret = client_g_rect(sd, cam_rect); - if (ret < 0) - return ret; - - ret = get_camera_scales(sd, cam_rect, &scale_cam_h, &scale_cam_v); - if (ret < 0) - return ret; - - dev_geo(dev, "1: camera scales %u:%u\n", scale_cam_h, scale_cam_v); - - /* - * 2. Calculate "effective" input crop (sensor subwindow) - CEU crop - * scaled back at current camera scales onto input window. - */ - ret = get_camera_subwin(icd, &cam_subrect, scale_cam_h, scale_cam_v); - if (ret < 0) - return ret; - - dev_geo(dev, "2: subwin %ux%u@%u:%u\n", - cam_subrect.width, cam_subrect.height, - cam_subrect.left, cam_subrect.top); - - /* - * 3. Calculate new combined scales from "effective" input window to - * requested user window. - */ - scale_h = calc_generic_scale(cam_subrect.width, pix->width); - scale_v = calc_generic_scale(cam_subrect.height, pix->height); - - dev_geo(dev, "3: scales %u:%u\n", scale_h, scale_v); - - /* - * 4. Calculate camera output window by applying combined scales to real - * input window. - */ - mf.width = scale_down(cam_rect->width, scale_h); - mf.height = scale_down(cam_rect->height, scale_v); + /* 1.-4. Calculate client output geometry */ + calculate_client_output(icd, &f->fmt.pix, &mf); mf.field = pix->field; mf.colorspace = pix->colorspace; mf.code = xlate->code; @@ -1547,17 +1559,17 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, image_mode = false; } - dev_geo(dev, "4: camera output %ux%u\n", mf.width, mf.height); + dev_geo(dev, "4: request camera output %ux%u\n", mf.width, mf.height); /* 5. - 9. */ - ret = client_scale(icd, cam_rect, &cam_subrect, &ceu_rect, &mf, + ret = client_scale(icd, &mf, &ceu_sub_width, &ceu_sub_height, image_mode && V4L2_FIELD_NONE == field); - dev_geo(dev, "5-9: client scale %d\n", ret); + dev_geo(dev, "5-9: client scale return %d\n", ret); /* Done with the camera. Now see if we can improve the result */ - dev_dbg(dev, "Camera %d fmt %ux%u, requested %ux%u\n", + dev_geo(dev, "Camera %d fmt %ux%u, requested %ux%u\n", ret, mf.width, mf.height, pix->width, pix->height); if (ret < 0) return ret; @@ -1565,40 +1577,44 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, if (mf.code != xlate->code) return -EINVAL; + /* 9. Prepare CEU crop */ + cam->width = mf.width; + cam->height = mf.height; + /* 10. Use CEU scaling to scale to the requested user window. */ /* We cannot scale up */ - if (pix->width > mf.width) - pix->width = mf.width; - if (pix->width > ceu_rect.width) - pix->width = ceu_rect.width; + if (pix->width > ceu_sub_width) + ceu_sub_width = pix->width; - if (pix->height > mf.height) - pix->height = mf.height; - if (pix->height > ceu_rect.height) - pix->height = ceu_rect.height; + if (pix->height > ceu_sub_height) + ceu_sub_height = pix->height; pix->colorspace = mf.colorspace; if (image_mode) { /* Scale pix->{width x height} down to width x height */ - scale_h = calc_scale(ceu_rect.width, &pix->width); - scale_v = calc_scale(ceu_rect.height, &pix->height); - - pcdev->cflcr = scale_h | (scale_v << 16); + scale_h = calc_scale(ceu_sub_width, &pix->width); + scale_v = calc_scale(ceu_sub_height, &pix->height); } else { - pix->width = ceu_rect.width; - pix->height = ceu_rect.height; - scale_h = scale_v = 0; - pcdev->cflcr = 0; + pix->width = ceu_sub_width; + pix->height = ceu_sub_height; + scale_h = 0; + scale_v = 0; } + pcdev->cflcr = scale_h | (scale_v << 16); + + /* + * We have calculated CFLCR, the actual configuration will be performed + * in sh_mobile_ceu_set_bus_param() + */ + dev_geo(dev, "10: W: %u : 0x%x = %u, H: %u : 0x%x = %u\n", - ceu_rect.width, scale_h, pix->width, - ceu_rect.height, scale_v, pix->height); + ceu_sub_width, scale_h, pix->width, + ceu_sub_height, scale_v, pix->height); cam->code = xlate->code; - cam->ceu_rect = ceu_rect; icd->current_fmt = xlate; pcdev->field = field; @@ -1820,6 +1836,7 @@ static struct soc_camera_host_ops sh_mobile_ceu_host_ops = { .remove = sh_mobile_ceu_remove_device, .get_formats = sh_mobile_ceu_get_formats, .put_formats = sh_mobile_ceu_put_formats, + .get_crop = sh_mobile_ceu_get_crop, .set_crop = sh_mobile_ceu_set_crop, .set_fmt = sh_mobile_ceu_set_fmt, .try_fmt = sh_mobile_ceu_try_fmt, -- cgit v1.2.3-70-g09d2 From ab56d5eb58182b0c9e179c33ddd3f3aabb6c798f Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 23 Mar 2010 11:31:46 -0300 Subject: V4L/DVB: soc-camera: update comment soc-camera no longer requires .set_crop() implementations to update their argument. Update the commentary. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/soc_camera.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 0c65031f3d8..db1ca0e90d7 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c @@ -753,8 +753,7 @@ static int soc_camera_g_crop(struct file *file, void *fh, /* * According to the V4L2 API, drivers shall not update the struct v4l2_crop * argument with the actual geometry, instead, the user shall use G_CROP to - * retrieve it. However, we expect camera host and client drivers to update - * the argument, which we then use internally, but do not return to the user. + * retrieve it. */ static int soc_camera_s_crop(struct file *file, void *fh, struct v4l2_crop *a) -- cgit v1.2.3-70-g09d2 From f35f1bb8fc1e56646a3dab0ecd12e23bca6323c4 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 23 Mar 2010 11:52:11 -0300 Subject: V4L/DVB: videobuf-dma-contig.c: simplify pointer dereference Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-dma-contig.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/videobuf-dma-contig.c b/drivers/media/video/videobuf-dma-contig.c index 055ce8439ce..74730c624cf 100644 --- a/drivers/media/video/videobuf-dma-contig.c +++ b/drivers/media/video/videobuf-dma-contig.c @@ -55,14 +55,14 @@ static void videobuf_vm_close(struct vm_area_struct *vma) struct videobuf_queue *q = map->q; int i; - dev_dbg(map->q->dev, "vm_close %p [count=%u,vma=%08lx-%08lx]\n", + dev_dbg(q->dev, "vm_close %p [count=%u,vma=%08lx-%08lx]\n", map, map->count, vma->vm_start, vma->vm_end); map->count--; if (0 == map->count) { struct videobuf_dma_contig_memory *mem; - dev_dbg(map->q->dev, "munmap %p q=%p\n", map, q); + dev_dbg(q->dev, "munmap %p q=%p\n", map, q); mutex_lock(&q->vb_lock); /* We need first to cancel streams, before unmapping */ @@ -89,7 +89,7 @@ static void videobuf_vm_close(struct vm_area_struct *vma) /* vfree is not atomic - can't be called with IRQ's disabled */ - dev_dbg(map->q->dev, "buf[%d] freeing %p\n", + dev_dbg(q->dev, "buf[%d] freeing %p\n", i, mem->vaddr); dma_free_coherent(q->dev, mem->size, -- cgit v1.2.3-70-g09d2 From a81fb9b223508f5773d8d7e226b1574d1b068642 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 17 Mar 2010 11:21:13 -0300 Subject: V4L/DVB: V4L: SuperH Video Output Unit (VOU) driver A number of SuperH Mobile SoCs, including sh7724, include a Video Output Unit. This patch adds a video (V4L2) output driver for it. The driver uses v4l2-subdev and mediabus APIs to interface to TV encoders. Signed-off-by: Guennadi Liakhovetski Acked-by: Paul Mundt Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 7 + drivers/media/video/Makefile | 4 + drivers/media/video/sh_vou.c | 1476 ++++++++++++++++++++++++++++++++++++++++++ include/media/sh_vou.h | 34 + 4 files changed, 1521 insertions(+) create mode 100644 drivers/media/video/sh_vou.c create mode 100644 include/media/sh_vou.h (limited to 'drivers/media/video') diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 784743187a6..e2fad460a75 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -520,6 +520,13 @@ config DISPLAY_DAVINCI_DM646X_EVM To compile this driver as a module, choose M here: the module will be called vpif_display. +config VIDEO_SH_VOU + tristate "SuperH VOU video output driver" + depends on VIDEO_DEV && ARCH_SHMOBILE + select VIDEOBUF_DMA_CONTIG + help + Support for the Video Output Unit (VOU) on SuperH SoCs. + config CAPTURE_DAVINCI_DM646X_EVM tristate "DM646x EVM Video Capture" depends on VIDEO_DEV && MACH_DAVINCI_DM6467_EVM diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index c51c386559f..ed52b6be4ec 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -160,6 +160,10 @@ obj-$(CONFIG_VIDEO_MX3) += mx3_camera.o obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o +obj-$(CONFIG_ARCH_DAVINCI) += davinci/ + +obj-$(CONFIG_VIDEO_SH_VOU) += sh_vou.o + obj-$(CONFIG_VIDEO_AU0828) += au0828/ obj-$(CONFIG_USB_VIDEO_CLASS) += uvc/ diff --git a/drivers/media/video/sh_vou.c b/drivers/media/video/sh_vou.c new file mode 100644 index 00000000000..f5b892a2a8e --- /dev/null +++ b/drivers/media/video/sh_vou.c @@ -0,0 +1,1476 @@ +/* + * SuperH Video Output Unit (VOU) driver + * + * Copyright (C) 2010, Guennadi Liakhovetski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* Mirror addresses are not available for all registers */ +#define VOUER 0 +#define VOUCR 4 +#define VOUSTR 8 +#define VOUVCR 0xc +#define VOUISR 0x10 +#define VOUBCR 0x14 +#define VOUDPR 0x18 +#define VOUDSR 0x1c +#define VOUVPR 0x20 +#define VOUIR 0x24 +#define VOUSRR 0x28 +#define VOUMSR 0x2c +#define VOUHIR 0x30 +#define VOUDFR 0x34 +#define VOUAD1R 0x38 +#define VOUAD2R 0x3c +#define VOUAIR 0x40 +#define VOUSWR 0x44 +#define VOURCR 0x48 +#define VOURPR 0x50 + +enum sh_vou_status { + SH_VOU_IDLE, + SH_VOU_INITIALISING, + SH_VOU_RUNNING, +}; + +#define VOU_MAX_IMAGE_WIDTH 720 +#define VOU_MAX_IMAGE_HEIGHT 480 + +struct sh_vou_device { + struct v4l2_device v4l2_dev; + struct video_device *vdev; + atomic_t use_count; + struct sh_vou_pdata *pdata; + spinlock_t lock; + void __iomem *base; + /* State information */ + struct v4l2_pix_format pix; + struct v4l2_rect rect; + struct list_head queue; + v4l2_std_id std; + int pix_idx; + struct videobuf_buffer *active; + enum sh_vou_status status; +}; + +struct sh_vou_file { + struct videobuf_queue vbq; +}; + +/* Register access routines for sides A, B and mirror addresses */ +static void sh_vou_reg_a_write(struct sh_vou_device *vou_dev, unsigned int reg, + u32 value) +{ + __raw_writel(value, vou_dev->base + reg); +} + +static void sh_vou_reg_ab_write(struct sh_vou_device *vou_dev, unsigned int reg, + u32 value) +{ + __raw_writel(value, vou_dev->base + reg); + __raw_writel(value, vou_dev->base + reg + 0x1000); +} + +static void sh_vou_reg_m_write(struct sh_vou_device *vou_dev, unsigned int reg, + u32 value) +{ + __raw_writel(value, vou_dev->base + reg + 0x2000); +} + +static u32 sh_vou_reg_a_read(struct sh_vou_device *vou_dev, unsigned int reg) +{ + return __raw_readl(vou_dev->base + reg); +} + +static void sh_vou_reg_a_set(struct sh_vou_device *vou_dev, unsigned int reg, + u32 value, u32 mask) +{ + u32 old = __raw_readl(vou_dev->base + reg); + + value = (value & mask) | (old & ~mask); + __raw_writel(value, vou_dev->base + reg); +} + +static void sh_vou_reg_b_set(struct sh_vou_device *vou_dev, unsigned int reg, + u32 value, u32 mask) +{ + sh_vou_reg_a_set(vou_dev, reg + 0x1000, value, mask); +} + +static void sh_vou_reg_ab_set(struct sh_vou_device *vou_dev, unsigned int reg, + u32 value, u32 mask) +{ + sh_vou_reg_a_set(vou_dev, reg, value, mask); + sh_vou_reg_b_set(vou_dev, reg, value, mask); +} + +struct sh_vou_fmt { + u32 pfmt; + char *desc; + unsigned char bpp; + unsigned char rgb; + unsigned char yf; + unsigned char pkf; +}; + +/* Further pixel formats can be added */ +static struct sh_vou_fmt vou_fmt[] = { + { + .pfmt = V4L2_PIX_FMT_NV12, + .bpp = 12, + .desc = "YVU420 planar", + .yf = 0, + .rgb = 0, + }, + { + .pfmt = V4L2_PIX_FMT_NV16, + .bpp = 16, + .desc = "YVYU planar", + .yf = 1, + .rgb = 0, + }, + { + .pfmt = V4L2_PIX_FMT_RGB24, + .bpp = 24, + .desc = "RGB24", + .pkf = 2, + .rgb = 1, + }, + { + .pfmt = V4L2_PIX_FMT_RGB565, + .bpp = 16, + .desc = "RGB565", + .pkf = 3, + .rgb = 1, + }, + { + .pfmt = V4L2_PIX_FMT_RGB565X, + .bpp = 16, + .desc = "RGB565 byteswapped", + .pkf = 3, + .rgb = 1, + }, +}; + +static void sh_vou_schedule_next(struct sh_vou_device *vou_dev, + struct videobuf_buffer *vb) +{ + dma_addr_t addr1, addr2; + + addr1 = videobuf_to_dma_contig(vb); + switch (vou_dev->pix.pixelformat) { + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV16: + addr2 = addr1 + vou_dev->pix.width * vou_dev->pix.height; + break; + default: + addr2 = 0; + } + + sh_vou_reg_m_write(vou_dev, VOUAD1R, addr1); + sh_vou_reg_m_write(vou_dev, VOUAD2R, addr2); +} + +static void sh_vou_stream_start(struct sh_vou_device *vou_dev, + struct videobuf_buffer *vb) +{ + unsigned int row_coeff; +#ifdef __LITTLE_ENDIAN + u32 dataswap = 7; +#else + u32 dataswap = 0; +#endif + + switch (vou_dev->pix.pixelformat) { + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV16: + row_coeff = 1; + break; + case V4L2_PIX_FMT_RGB565: + dataswap ^= 1; + case V4L2_PIX_FMT_RGB565X: + row_coeff = 2; + break; + case V4L2_PIX_FMT_RGB24: + row_coeff = 3; + break; + } + + sh_vou_reg_a_write(vou_dev, VOUSWR, dataswap); + sh_vou_reg_ab_write(vou_dev, VOUAIR, vou_dev->pix.width * row_coeff); + sh_vou_schedule_next(vou_dev, vb); +} + +static void free_buffer(struct videobuf_queue *vq, struct videobuf_buffer *vb) +{ + BUG_ON(in_interrupt()); + + /* Wait until this buffer is no longer in STATE_QUEUED or STATE_ACTIVE */ + videobuf_waiton(vb, 0, 0); + videobuf_dma_contig_free(vq, vb); + vb->state = VIDEOBUF_NEEDS_INIT; +} + +/* Locking: caller holds vq->vb_lock mutex */ +static int sh_vou_buf_setup(struct videobuf_queue *vq, unsigned int *count, + unsigned int *size) +{ + struct video_device *vdev = vq->priv_data; + struct sh_vou_device *vou_dev = video_get_drvdata(vdev); + + *size = vou_fmt[vou_dev->pix_idx].bpp * vou_dev->pix.width * + vou_dev->pix.height / 8; + + if (*count < 2) + *count = 2; + + /* Taking into account maximum frame size, *count will stay >= 2 */ + if (PAGE_ALIGN(*size) * *count > 4 * 1024 * 1024) + *count = 4 * 1024 * 1024 / PAGE_ALIGN(*size); + + dev_dbg(vq->dev, "%s(): count=%d, size=%d\n", __func__, *count, *size); + + return 0; +} + +/* Locking: caller holds vq->vb_lock mutex */ +static int sh_vou_buf_prepare(struct videobuf_queue *vq, + struct videobuf_buffer *vb, + enum v4l2_field field) +{ + struct video_device *vdev = vq->priv_data; + struct sh_vou_device *vou_dev = video_get_drvdata(vdev); + struct v4l2_pix_format *pix = &vou_dev->pix; + int bytes_per_line = vou_fmt[vou_dev->pix_idx].bpp * pix->width / 8; + int ret; + + dev_dbg(vq->dev, "%s()\n", __func__); + + if (vb->width != pix->width || + vb->height != pix->height || + vb->field != pix->field) { + vb->width = pix->width; + vb->height = pix->height; + vb->field = field; + if (vb->state != VIDEOBUF_NEEDS_INIT) + free_buffer(vq, vb); + } + + vb->size = vb->height * bytes_per_line; + if (vb->baddr && vb->bsize < vb->size) { + /* User buffer too small */ + dev_warn(vq->dev, "User buffer too small: [%u] @ %lx\n", + vb->bsize, vb->baddr); + return -EINVAL; + } + + if (vb->state == VIDEOBUF_NEEDS_INIT) { + ret = videobuf_iolock(vq, vb, NULL); + if (ret < 0) { + dev_warn(vq->dev, "IOLOCK buf-type %d: %d\n", + vb->memory, ret); + return ret; + } + vb->state = VIDEOBUF_PREPARED; + } + + dev_dbg(vq->dev, + "%s(): fmt #%d, %u bytes per line, phys 0x%x, type %d, state %d\n", + __func__, vou_dev->pix_idx, bytes_per_line, + videobuf_to_dma_contig(vb), vb->memory, vb->state); + + return 0; +} + +/* Locking: caller holds vq->vb_lock mutex and vq->irqlock spinlock */ +static void sh_vou_buf_queue(struct videobuf_queue *vq, + struct videobuf_buffer *vb) +{ + struct video_device *vdev = vq->priv_data; + struct sh_vou_device *vou_dev = video_get_drvdata(vdev); + + dev_dbg(vq->dev, "%s()\n", __func__); + + vb->state = VIDEOBUF_QUEUED; + list_add_tail(&vb->queue, &vou_dev->queue); + + if (vou_dev->status == SH_VOU_RUNNING) { + return; + } else if (!vou_dev->active) { + vou_dev->active = vb; + /* Start from side A: we use mirror addresses, so, set B */ + sh_vou_reg_a_write(vou_dev, VOURPR, 1); + dev_dbg(vq->dev, "%s: first buffer status 0x%x\n", __func__, + sh_vou_reg_a_read(vou_dev, VOUSTR)); + sh_vou_schedule_next(vou_dev, vb); + /* Only activate VOU after the second buffer */ + } else if (vou_dev->active->queue.next == &vb->queue) { + /* Second buffer - initialise register side B */ + sh_vou_reg_a_write(vou_dev, VOURPR, 0); + sh_vou_stream_start(vou_dev, vb); + + /* Register side switching with frame VSYNC */ + sh_vou_reg_a_write(vou_dev, VOURCR, 5); + dev_dbg(vq->dev, "%s: second buffer status 0x%x\n", __func__, + sh_vou_reg_a_read(vou_dev, VOUSTR)); + + /* Enable End-of-Frame (VSYNC) interrupts */ + sh_vou_reg_a_write(vou_dev, VOUIR, 0x10004); + /* Two buffers on the queue - activate the hardware */ + + vou_dev->status = SH_VOU_RUNNING; + sh_vou_reg_a_write(vou_dev, VOUER, 0x107); + } +} + +static void sh_vou_buf_release(struct videobuf_queue *vq, + struct videobuf_buffer *vb) +{ + struct video_device *vdev = vq->priv_data; + struct sh_vou_device *vou_dev = video_get_drvdata(vdev); + unsigned long flags; + + dev_dbg(vq->dev, "%s()\n", __func__); + + spin_lock_irqsave(&vou_dev->lock, flags); + + if (vou_dev->active == vb) { + /* disable output */ + sh_vou_reg_a_set(vou_dev, VOUER, 0, 1); + /* ...but the current frame will complete */ + sh_vou_reg_a_set(vou_dev, VOUIR, 0, 0x30000); + vou_dev->active = NULL; + } + + if ((vb->state == VIDEOBUF_ACTIVE || vb->state == VIDEOBUF_QUEUED)) { + vb->state = VIDEOBUF_ERROR; + list_del(&vb->queue); + } + + spin_unlock_irqrestore(&vou_dev->lock, flags); + + free_buffer(vq, vb); +} + +static struct videobuf_queue_ops sh_vou_video_qops = { + .buf_setup = sh_vou_buf_setup, + .buf_prepare = sh_vou_buf_prepare, + .buf_queue = sh_vou_buf_queue, + .buf_release = sh_vou_buf_release, +}; + +/* Video IOCTLs */ +static int sh_vou_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + struct sh_vou_file *vou_file = priv; + + dev_dbg(vou_file->vbq.dev, "%s()\n", __func__); + + strlcpy(cap->card, "SuperH VOU", sizeof(cap->card)); + cap->version = KERNEL_VERSION(0, 1, 0); + cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING; + return 0; +} + +/* Enumerate formats, that the device can accept from the user */ +static int sh_vou_enum_fmt_vid_out(struct file *file, void *priv, + struct v4l2_fmtdesc *fmt) +{ + struct sh_vou_file *vou_file = priv; + + if (fmt->index >= ARRAY_SIZE(vou_fmt)) + return -EINVAL; + + dev_dbg(vou_file->vbq.dev, "%s()\n", __func__); + + fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + strlcpy(fmt->description, vou_fmt[fmt->index].desc, + sizeof(fmt->description)); + fmt->pixelformat = vou_fmt[fmt->index].pfmt; + + return 0; +} + +static int sh_vou_g_fmt_vid_out(struct file *file, void *priv, + struct v4l2_format *fmt) +{ + struct video_device *vdev = video_devdata(file); + struct sh_vou_device *vou_dev = video_get_drvdata(vdev); + + dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__); + + fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + fmt->fmt.pix = vou_dev->pix; + + return 0; +} + +static const unsigned char vou_scale_h_num[] = {1, 9, 2, 9, 4}; +static const unsigned char vou_scale_h_den[] = {1, 8, 1, 4, 1}; +static const unsigned char vou_scale_h_fld[] = {0, 2, 1, 3}; +static const unsigned char vou_scale_v_num[] = {1, 2, 4}; +static const unsigned char vou_scale_v_den[] = {1, 1, 1}; +static const unsigned char vou_scale_v_fld[] = {0, 1}; + +static void sh_vou_configure_geometry(struct sh_vou_device *vou_dev, + int pix_idx, int w_idx, int h_idx) +{ + struct sh_vou_fmt *fmt = vou_fmt + pix_idx; + unsigned int black_left, black_top, width_max, height_max, + frame_in_height, frame_out_height, frame_out_top; + struct v4l2_rect *rect = &vou_dev->rect; + struct v4l2_pix_format *pix = &vou_dev->pix; + u32 vouvcr = 0, dsr_h, dsr_v; + + if (vou_dev->std & V4L2_STD_525_60) { + width_max = 858; + height_max = 262; + } else { + width_max = 864; + height_max = 312; + } + + frame_in_height = pix->height / 2; + frame_out_height = rect->height / 2; + frame_out_top = rect->top / 2; + + /* + * Cropping scheme: max useful image is 720x480, and the total video + * area is 858x525 (NTSC) or 864x625 (PAL). AK8813 / 8814 starts + * sampling data beginning with fixed 276th (NTSC) / 288th (PAL) clock, + * of which the first 33 / 25 clocks HSYNC must be held active. This + * has to be configured in CR[HW]. 1 pixel equals 2 clock periods. + * This gives CR[HW] = 16 / 12, VPR[HVP] = 138 / 144, which gives + * exactly 858 - 138 = 864 - 144 = 720! We call the out-of-display area, + * beyond DSR, specified on the left and top by the VPR register "black + * pixels" and out-of-image area (DPR) "background pixels." We fix VPR + * at 138 / 144 : 20, because that's the HSYNC timing, that our first + * client requires, and that's exactly what leaves us 720 pixels for the + * image; we leave VPR[VVP] at default 20 for now, because the client + * doesn't seem to have any special requirements for it. Otherwise we + * could also set it to max - 240 = 22 / 72. Thus VPR depends only on + * the selected standard, and DPR and DSR are selected according to + * cropping. Q: how does the client detect the first valid line? Does + * HSYNC stay inactive during invalid (black) lines? + */ + black_left = width_max - VOU_MAX_IMAGE_WIDTH; + black_top = 20; + + dsr_h = rect->width + rect->left; + dsr_v = frame_out_height + frame_out_top; + + dev_dbg(vou_dev->v4l2_dev.dev, + "image %ux%u, black %u:%u, offset %u:%u, display %ux%u\n", + pix->width, frame_in_height, black_left, black_top, + rect->left, frame_out_top, dsr_h, dsr_v); + + /* VOUISR height - half of a frame height in frame mode */ + sh_vou_reg_ab_write(vou_dev, VOUISR, (pix->width << 16) | frame_in_height); + sh_vou_reg_ab_write(vou_dev, VOUVPR, (black_left << 16) | black_top); + sh_vou_reg_ab_write(vou_dev, VOUDPR, (rect->left << 16) | frame_out_top); + sh_vou_reg_ab_write(vou_dev, VOUDSR, (dsr_h << 16) | dsr_v); + + /* + * if necessary, we could set VOUHIR to + * max(black_left + dsr_h, width_max) here + */ + + if (w_idx) + vouvcr |= (1 << 15) | (vou_scale_h_fld[w_idx - 1] << 4); + if (h_idx) + vouvcr |= (1 << 14) | vou_scale_v_fld[h_idx - 1]; + + dev_dbg(vou_dev->v4l2_dev.dev, "%s: scaling 0x%x\n", fmt->desc, vouvcr); + + /* To produce a colour bar for testing set bit 23 of VOUVCR */ + sh_vou_reg_ab_write(vou_dev, VOUVCR, vouvcr); + sh_vou_reg_ab_write(vou_dev, VOUDFR, + fmt->pkf | (fmt->yf << 8) | (fmt->rgb << 16)); +} + +struct sh_vou_geometry { + struct v4l2_rect output; + unsigned int in_width; + unsigned int in_height; + int scale_idx_h; + int scale_idx_v; +}; + +/* + * Find input geometry, that we can use to produce output, closest to the + * requested rectangle, using VOU scaling + */ +static void vou_adjust_input(struct sh_vou_geometry *geo, v4l2_std_id std) +{ + /* The compiler cannot know, that best and idx will indeed be set */ + unsigned int best_err = UINT_MAX, best = 0, width_max, height_max; + int i, idx = 0; + + if (std & V4L2_STD_525_60) { + width_max = 858; + height_max = 262; + } else { + width_max = 864; + height_max = 312; + } + + /* Image width must be a multiple of 4 */ + v4l_bound_align_image(&geo->in_width, 0, VOU_MAX_IMAGE_WIDTH, 2, + &geo->in_height, 0, VOU_MAX_IMAGE_HEIGHT, 1, 0); + + /* Select scales to come as close as possible to the output image */ + for (i = ARRAY_SIZE(vou_scale_h_num) - 1; i >= 0; i--) { + unsigned int err; + unsigned int found = geo->output.width * vou_scale_h_den[i] / + vou_scale_h_num[i]; + + if (found > VOU_MAX_IMAGE_WIDTH) + /* scales increase */ + break; + + err = abs(found - geo->in_width); + if (err < best_err) { + best_err = err; + idx = i; + best = found; + } + if (!err) + break; + } + + geo->in_width = best; + geo->scale_idx_h = idx; + + best_err = UINT_MAX; + + /* This loop can be replaced with one division */ + for (i = ARRAY_SIZE(vou_scale_v_num) - 1; i >= 0; i--) { + unsigned int err; + unsigned int found = geo->output.height * vou_scale_v_den[i] / + vou_scale_v_num[i]; + + if (found > VOU_MAX_IMAGE_HEIGHT) + /* scales increase */ + break; + + err = abs(found - geo->in_height); + if (err < best_err) { + best_err = err; + idx = i; + best = found; + } + if (!err) + break; + } + + geo->in_height = best; + geo->scale_idx_v = idx; +} + +/* + * Find output geometry, that we can produce, using VOU scaling, closest to + * the requested rectangle + */ +static void vou_adjust_output(struct sh_vou_geometry *geo, v4l2_std_id std) +{ + unsigned int best_err = UINT_MAX, best, width_max, height_max; + int i, idx; + + if (std & V4L2_STD_525_60) { + width_max = 858; + height_max = 262 * 2; + } else { + width_max = 864; + height_max = 312 * 2; + } + + /* Select scales to come as close as possible to the output image */ + for (i = 0; i < ARRAY_SIZE(vou_scale_h_num); i++) { + unsigned int err; + unsigned int found = geo->in_width * vou_scale_h_num[i] / + vou_scale_h_den[i]; + + if (found > VOU_MAX_IMAGE_WIDTH) + /* scales increase */ + break; + + err = abs(found - geo->output.width); + if (err < best_err) { + best_err = err; + idx = i; + best = found; + } + if (!err) + break; + } + + geo->output.width = best; + geo->scale_idx_h = idx; + if (geo->output.left + best > width_max) + geo->output.left = width_max - best; + + pr_debug("%s(): W %u * %u/%u = %u\n", __func__, geo->in_width, + vou_scale_h_num[idx], vou_scale_h_den[idx], best); + + best_err = UINT_MAX; + + /* This loop can be replaced with one division */ + for (i = 0; i < ARRAY_SIZE(vou_scale_v_num); i++) { + unsigned int err; + unsigned int found = geo->in_height * vou_scale_v_num[i] / + vou_scale_v_den[i]; + + if (found > VOU_MAX_IMAGE_HEIGHT) + /* scales increase */ + break; + + err = abs(found - geo->output.height); + if (err < best_err) { + best_err = err; + idx = i; + best = found; + } + if (!err) + break; + } + + geo->output.height = best; + geo->scale_idx_v = idx; + if (geo->output.top + best > height_max) + geo->output.top = height_max - best; + + pr_debug("%s(): H %u * %u/%u = %u\n", __func__, geo->in_height, + vou_scale_v_num[idx], vou_scale_v_den[idx], best); +} + +static int sh_vou_s_fmt_vid_out(struct file *file, void *priv, + struct v4l2_format *fmt) +{ + struct video_device *vdev = video_devdata(file); + struct sh_vou_device *vou_dev = video_get_drvdata(vdev); + struct v4l2_pix_format *pix = &fmt->fmt.pix; + int pix_idx; + struct sh_vou_geometry geo; + struct v4l2_mbus_framefmt mbfmt = { + /* Revisit: is this the correct code? */ + .code = V4L2_MBUS_FMT_YUYV8_2X8_LE, + .field = V4L2_FIELD_INTERLACED, + .colorspace = V4L2_COLORSPACE_SMPTE170M, + }; + int ret; + + dev_dbg(vou_dev->v4l2_dev.dev, "%s(): %ux%u -> %ux%u\n", __func__, + vou_dev->rect.width, vou_dev->rect.height, + pix->width, pix->height); + + if (pix->field == V4L2_FIELD_ANY) + pix->field = V4L2_FIELD_NONE; + + if (fmt->type != V4L2_BUF_TYPE_VIDEO_OUTPUT || + pix->field != V4L2_FIELD_NONE) + return -EINVAL; + + for (pix_idx = 0; pix_idx < ARRAY_SIZE(vou_fmt); pix_idx++) + if (vou_fmt[pix_idx].pfmt == pix->pixelformat) + break; + + if (pix_idx == ARRAY_SIZE(vou_fmt)) + return -EINVAL; + + /* Image width must be a multiple of 4 */ + v4l_bound_align_image(&pix->width, 0, VOU_MAX_IMAGE_WIDTH, 2, + &pix->height, 0, VOU_MAX_IMAGE_HEIGHT, 1, 0); + + geo.in_width = pix->width; + geo.in_height = pix->height; + geo.output = vou_dev->rect; + + vou_adjust_output(&geo, vou_dev->std); + + mbfmt.width = geo.output.width; + mbfmt.height = geo.output.height; + ret = v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, video, + s_mbus_fmt, &mbfmt); + /* Must be implemented, so, don't check for -ENOIOCTLCMD */ + if (ret < 0) + return ret; + + dev_dbg(vou_dev->v4l2_dev.dev, "%s(): %ux%u -> %ux%u\n", __func__, + geo.output.width, geo.output.height, mbfmt.width, mbfmt.height); + + /* Sanity checks */ + if ((unsigned)mbfmt.width > VOU_MAX_IMAGE_WIDTH || + (unsigned)mbfmt.height > VOU_MAX_IMAGE_HEIGHT || + mbfmt.code != V4L2_MBUS_FMT_YUYV8_2X8_LE) + return -EIO; + + if (mbfmt.width != geo.output.width || + mbfmt.height != geo.output.height) { + geo.output.width = mbfmt.width; + geo.output.height = mbfmt.height; + + vou_adjust_input(&geo, vou_dev->std); + } + + /* We tried to preserve output rectangle, but it could have changed */ + vou_dev->rect = geo.output; + pix->width = geo.in_width; + pix->height = geo.in_height; + + dev_dbg(vou_dev->v4l2_dev.dev, "%s(): %ux%u\n", __func__, + pix->width, pix->height); + + vou_dev->pix_idx = pix_idx; + + vou_dev->pix = *pix; + + sh_vou_configure_geometry(vou_dev, pix_idx, + geo.scale_idx_h, geo.scale_idx_v); + + return 0; +} + +static int sh_vou_try_fmt_vid_out(struct file *file, void *priv, + struct v4l2_format *fmt) +{ + struct sh_vou_file *vou_file = priv; + struct v4l2_pix_format *pix = &fmt->fmt.pix; + int i; + + dev_dbg(vou_file->vbq.dev, "%s()\n", __func__); + + fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + pix->field = V4L2_FIELD_NONE; + + v4l_bound_align_image(&pix->width, 0, VOU_MAX_IMAGE_WIDTH, 1, + &pix->height, 0, VOU_MAX_IMAGE_HEIGHT, 1, 0); + + for (i = 0; ARRAY_SIZE(vou_fmt); i++) + if (vou_fmt[i].pfmt == pix->pixelformat) + return 0; + + pix->pixelformat = vou_fmt[0].pfmt; + + return 0; +} + +static int sh_vou_reqbufs(struct file *file, void *priv, + struct v4l2_requestbuffers *req) +{ + struct sh_vou_file *vou_file = priv; + + dev_dbg(vou_file->vbq.dev, "%s()\n", __func__); + + if (req->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) + return -EINVAL; + + return videobuf_reqbufs(&vou_file->vbq, req); +} + +static int sh_vou_querybuf(struct file *file, void *priv, + struct v4l2_buffer *b) +{ + struct sh_vou_file *vou_file = priv; + + dev_dbg(vou_file->vbq.dev, "%s()\n", __func__); + + return videobuf_querybuf(&vou_file->vbq, b); +} + +static int sh_vou_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) +{ + struct sh_vou_file *vou_file = priv; + + dev_dbg(vou_file->vbq.dev, "%s()\n", __func__); + + return videobuf_qbuf(&vou_file->vbq, b); +} + +static int sh_vou_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) +{ + struct sh_vou_file *vou_file = priv; + + dev_dbg(vou_file->vbq.dev, "%s()\n", __func__); + + return videobuf_dqbuf(&vou_file->vbq, b, file->f_flags & O_NONBLOCK); +} + +static int sh_vou_streamon(struct file *file, void *priv, + enum v4l2_buf_type buftype) +{ + struct video_device *vdev = video_devdata(file); + struct sh_vou_device *vou_dev = video_get_drvdata(vdev); + struct sh_vou_file *vou_file = priv; + int ret; + + dev_dbg(vou_file->vbq.dev, "%s()\n", __func__); + + ret = v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, + video, s_stream, 1); + if (ret < 0 && ret != -ENOIOCTLCMD) + return ret; + + /* This calls our .buf_queue() (== sh_vou_buf_queue) */ + return videobuf_streamon(&vou_file->vbq); +} + +static int sh_vou_streamoff(struct file *file, void *priv, + enum v4l2_buf_type buftype) +{ + struct video_device *vdev = video_devdata(file); + struct sh_vou_device *vou_dev = video_get_drvdata(vdev); + struct sh_vou_file *vou_file = priv; + + dev_dbg(vou_file->vbq.dev, "%s()\n", __func__); + + /* + * This calls buf_release from host driver's videobuf_queue_ops for all + * remaining buffers. When the last buffer is freed, stop streaming + */ + videobuf_streamoff(&vou_file->vbq); + v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, video, s_stream, 0); + + return 0; +} + +static u32 sh_vou_ntsc_mode(enum sh_vou_bus_fmt bus_fmt) +{ + switch (bus_fmt) { + default: + pr_warning("%s(): Invalid bus-format code %d, using default 8-bit\n", + __func__, bus_fmt); + case SH_VOU_BUS_8BIT: + return 1; + case SH_VOU_BUS_16BIT: + return 0; + case SH_VOU_BUS_BT656: + return 3; + } +} + +static int sh_vou_s_std(struct file *file, void *priv, v4l2_std_id *std_id) +{ + struct video_device *vdev = video_devdata(file); + struct sh_vou_device *vou_dev = video_get_drvdata(vdev); + int ret; + + dev_dbg(vou_dev->v4l2_dev.dev, "%s(): 0x%llx\n", __func__, *std_id); + + if (*std_id & ~vdev->tvnorms) + return -EINVAL; + + ret = v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, video, + s_std_output, *std_id); + /* Shall we continue, if the subdev doesn't support .s_std_output()? */ + if (ret < 0 && ret != -ENOIOCTLCMD) + return ret; + + if (*std_id & V4L2_STD_525_60) + sh_vou_reg_ab_set(vou_dev, VOUCR, + sh_vou_ntsc_mode(vou_dev->pdata->bus_fmt) << 29, 7 << 29); + else + sh_vou_reg_ab_set(vou_dev, VOUCR, 5 << 29, 7 << 29); + + vou_dev->std = *std_id; + + return 0; +} + +static int sh_vou_g_std(struct file *file, void *priv, v4l2_std_id *std) +{ + struct video_device *vdev = video_devdata(file); + struct sh_vou_device *vou_dev = video_get_drvdata(vdev); + + dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__); + + *std = vou_dev->std; + + return 0; +} + +static int sh_vou_g_crop(struct file *file, void *fh, struct v4l2_crop *a) +{ + struct video_device *vdev = video_devdata(file); + struct sh_vou_device *vou_dev = video_get_drvdata(vdev); + + dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__); + + a->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + a->c = vou_dev->rect; + + return 0; +} + +/* Assume a dull encoder, do all the work ourselves. */ +static int sh_vou_s_crop(struct file *file, void *fh, struct v4l2_crop *a) +{ + struct video_device *vdev = video_devdata(file); + struct sh_vou_device *vou_dev = video_get_drvdata(vdev); + struct v4l2_rect *rect = &a->c; + struct v4l2_crop sd_crop = {.type = V4L2_BUF_TYPE_VIDEO_OUTPUT}; + struct v4l2_pix_format *pix = &vou_dev->pix; + struct sh_vou_geometry geo; + struct v4l2_mbus_framefmt mbfmt = { + /* Revisit: is this the correct code? */ + .code = V4L2_MBUS_FMT_YUYV8_2X8_LE, + .field = V4L2_FIELD_INTERLACED, + .colorspace = V4L2_COLORSPACE_SMPTE170M, + }; + int ret; + + dev_dbg(vou_dev->v4l2_dev.dev, "%s(): %ux%u@%u:%u\n", __func__, + rect->width, rect->height, rect->left, rect->top); + + if (a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) + return -EINVAL; + + v4l_bound_align_image(&rect->width, 0, VOU_MAX_IMAGE_WIDTH, 1, + &rect->height, 0, VOU_MAX_IMAGE_HEIGHT, 1, 0); + + if (rect->width + rect->left > VOU_MAX_IMAGE_WIDTH) + rect->left = VOU_MAX_IMAGE_WIDTH - rect->width; + + if (rect->height + rect->top > VOU_MAX_IMAGE_HEIGHT) + rect->top = VOU_MAX_IMAGE_HEIGHT - rect->height; + + geo.output = *rect; + geo.in_width = pix->width; + geo.in_height = pix->height; + + /* Configure the encoder one-to-one, position at 0, ignore errors */ + sd_crop.c.width = geo.output.width; + sd_crop.c.height = geo.output.height; + /* + * We first issue a S_CROP, so that the subsequent S_FMT delivers the + * final encoder configuration. + */ + v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, video, + s_crop, &sd_crop); + mbfmt.width = geo.output.width; + mbfmt.height = geo.output.height; + ret = v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, video, + s_mbus_fmt, &mbfmt); + /* Must be implemented, so, don't check for -ENOIOCTLCMD */ + if (ret < 0) + return ret; + + /* Sanity checks */ + if ((unsigned)mbfmt.width > VOU_MAX_IMAGE_WIDTH || + (unsigned)mbfmt.height > VOU_MAX_IMAGE_HEIGHT || + mbfmt.code != V4L2_MBUS_FMT_YUYV8_2X8_LE) + return -EIO; + + geo.output.width = mbfmt.width; + geo.output.height = mbfmt.height; + + /* + * No down-scaling. According to the API, current call has precedence: + * http://v4l2spec.bytesex.org/spec/x1904.htm#AEN1954 paragraph two. + */ + vou_adjust_input(&geo, vou_dev->std); + + /* We tried to preserve output rectangle, but it could have changed */ + vou_dev->rect = geo.output; + pix->width = geo.in_width; + pix->height = geo.in_height; + + sh_vou_configure_geometry(vou_dev, vou_dev->pix_idx, + geo.scale_idx_h, geo.scale_idx_v); + + return 0; +} + +/* + * Total field: NTSC 858 x 2 * 262/263, PAL 864 x 2 * 312/313, default rectangle + * is the initial register values, height takes the interlaced format into + * account. The actual image can only go up to 720 x 2 * 240, So, VOUVPR can + * actually only meaningfully contain values <= 720 and <= 240 respectively, and + * not <= 864 and <= 312. + */ +static int sh_vou_cropcap(struct file *file, void *priv, + struct v4l2_cropcap *a) +{ + struct sh_vou_file *vou_file = priv; + + dev_dbg(vou_file->vbq.dev, "%s()\n", __func__); + + a->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + a->bounds.left = 0; + a->bounds.top = 0; + a->bounds.width = VOU_MAX_IMAGE_WIDTH; + a->bounds.height = VOU_MAX_IMAGE_HEIGHT; + /* Default = max, set VOUDPR = 0, which is not hardware default */ + a->defrect.left = 0; + a->defrect.top = 0; + a->defrect.width = VOU_MAX_IMAGE_WIDTH; + a->defrect.height = VOU_MAX_IMAGE_HEIGHT; + a->pixelaspect.numerator = 1; + a->pixelaspect.denominator = 1; + + return 0; +} + +static irqreturn_t sh_vou_isr(int irq, void *dev_id) +{ + struct sh_vou_device *vou_dev = dev_id; + static unsigned long j; + struct videobuf_buffer *vb; + static int cnt; + static int side; + u32 irq_status = sh_vou_reg_a_read(vou_dev, VOUIR), masked; + u32 vou_status = sh_vou_reg_a_read(vou_dev, VOUSTR); + + if (!(irq_status & 0x300)) { + if (printk_timed_ratelimit(&j, 500)) + dev_warn(vou_dev->v4l2_dev.dev, "IRQ status 0x%x!\n", + irq_status); + return IRQ_NONE; + } + + spin_lock(&vou_dev->lock); + if (!vou_dev->active || list_empty(&vou_dev->queue)) { + if (printk_timed_ratelimit(&j, 500)) + dev_warn(vou_dev->v4l2_dev.dev, + "IRQ without active buffer: %x!\n", irq_status); + /* Just ack: buf_release will disable further interrupts */ + sh_vou_reg_a_set(vou_dev, VOUIR, 0, 0x300); + spin_unlock(&vou_dev->lock); + return IRQ_HANDLED; + } + + masked = ~(0x300 & irq_status) & irq_status & 0x30304; + dev_dbg(vou_dev->v4l2_dev.dev, + "IRQ status 0x%x -> 0x%x, VOU status 0x%x, cnt %d\n", + irq_status, masked, vou_status, cnt); + + cnt++; + side = vou_status & 0x10000; + + /* Clear only set interrupts */ + sh_vou_reg_a_write(vou_dev, VOUIR, masked); + + vb = vou_dev->active; + list_del(&vb->queue); + + vb->state = VIDEOBUF_DONE; + do_gettimeofday(&vb->ts); + vb->field_count++; + wake_up(&vb->done); + + if (list_empty(&vou_dev->queue)) { + /* Stop VOU */ + dev_dbg(vou_dev->v4l2_dev.dev, "%s: queue empty after %d\n", + __func__, cnt); + sh_vou_reg_a_set(vou_dev, VOUER, 0, 1); + vou_dev->active = NULL; + vou_dev->status = SH_VOU_INITIALISING; + /* Disable End-of-Frame (VSYNC) interrupts */ + sh_vou_reg_a_set(vou_dev, VOUIR, 0, 0x30000); + spin_unlock(&vou_dev->lock); + return IRQ_HANDLED; + } + + vou_dev->active = list_entry(vou_dev->queue.next, + struct videobuf_buffer, queue); + + if (vou_dev->active->queue.next != &vou_dev->queue) { + struct videobuf_buffer *new = list_entry(vou_dev->active->queue.next, + struct videobuf_buffer, queue); + sh_vou_schedule_next(vou_dev, new); + } + + spin_unlock(&vou_dev->lock); + + return IRQ_HANDLED; +} + +static int sh_vou_hw_init(struct sh_vou_device *vou_dev) +{ + struct sh_vou_pdata *pdata = vou_dev->pdata; + u32 voucr = sh_vou_ntsc_mode(pdata->bus_fmt) << 29; + int i = 100; + + /* Disable all IRQs */ + sh_vou_reg_a_write(vou_dev, VOUIR, 0); + + /* Reset VOU interfaces - registers unaffected */ + sh_vou_reg_a_write(vou_dev, VOUSRR, 0x101); + while (--i && (sh_vou_reg_a_read(vou_dev, VOUSRR) & 0x101)) + udelay(1); + + if (!i) + return -ETIMEDOUT; + + dev_dbg(vou_dev->v4l2_dev.dev, "Reset took %dus\n", 100 - i); + + if (pdata->flags & SH_VOU_PCLK_FALLING) + voucr |= 1 << 28; + if (pdata->flags & SH_VOU_HSYNC_LOW) + voucr |= 1 << 27; + if (pdata->flags & SH_VOU_VSYNC_LOW) + voucr |= 1 << 26; + sh_vou_reg_ab_set(vou_dev, VOUCR, voucr, 0xfc000000); + + /* Manual register side switching at first */ + sh_vou_reg_a_write(vou_dev, VOURCR, 4); + /* Default - fixed HSYNC length, can be made configurable is required */ + sh_vou_reg_ab_write(vou_dev, VOUMSR, 0x800000); + + return 0; +} + +/* File operations */ +static int sh_vou_open(struct file *file) +{ + struct video_device *vdev = video_devdata(file); + struct sh_vou_device *vou_dev = video_get_drvdata(vdev); + struct sh_vou_file *vou_file = kzalloc(sizeof(struct sh_vou_file), + GFP_KERNEL); + + if (!vou_file) + return -ENOMEM; + + dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__); + + file->private_data = vou_file; + + if (atomic_inc_return(&vou_dev->use_count) == 1) { + int ret; + /* First open */ + vou_dev->status = SH_VOU_INITIALISING; + pm_runtime_get_sync(vdev->v4l2_dev->dev); + ret = sh_vou_hw_init(vou_dev); + if (ret < 0) { + atomic_dec(&vou_dev->use_count); + pm_runtime_put(vdev->v4l2_dev->dev); + vou_dev->status = SH_VOU_IDLE; + return ret; + } + } + + videobuf_queue_dma_contig_init(&vou_file->vbq, &sh_vou_video_qops, + vou_dev->v4l2_dev.dev, &vou_dev->lock, + V4L2_BUF_TYPE_VIDEO_OUTPUT, + V4L2_FIELD_NONE, + sizeof(struct videobuf_buffer), vdev); + + return 0; +} + +static int sh_vou_release(struct file *file) +{ + struct video_device *vdev = video_devdata(file); + struct sh_vou_device *vou_dev = video_get_drvdata(vdev); + struct sh_vou_file *vou_file = file->private_data; + + dev_dbg(vou_file->vbq.dev, "%s()\n", __func__); + + if (!atomic_dec_return(&vou_dev->use_count)) { + /* Last close */ + vou_dev->status = SH_VOU_IDLE; + sh_vou_reg_a_set(vou_dev, VOUER, 0, 0x101); + pm_runtime_put(vdev->v4l2_dev->dev); + } + + file->private_data = NULL; + kfree(vou_file); + + return 0; +} + +static int sh_vou_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct sh_vou_file *vou_file = file->private_data; + + dev_dbg(vou_file->vbq.dev, "%s()\n", __func__); + + return videobuf_mmap_mapper(&vou_file->vbq, vma); +} + +static unsigned int sh_vou_poll(struct file *file, poll_table *wait) +{ + struct sh_vou_file *vou_file = file->private_data; + + dev_dbg(vou_file->vbq.dev, "%s()\n", __func__); + + return videobuf_poll_stream(file, &vou_file->vbq, wait); +} + +static int sh_vou_g_chip_ident(struct file *file, void *fh, + struct v4l2_dbg_chip_ident *id) +{ + struct video_device *vdev = video_devdata(file); + struct sh_vou_device *vou_dev = video_get_drvdata(vdev); + + return v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, core, g_chip_ident, id); +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int sh_vou_g_register(struct file *file, void *fh, + struct v4l2_dbg_register *reg) +{ + struct video_device *vdev = video_devdata(file); + struct sh_vou_device *vou_dev = video_get_drvdata(vdev); + + return v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, core, g_register, reg); +} + +static int sh_vou_s_register(struct file *file, void *fh, + struct v4l2_dbg_register *reg) +{ + struct video_device *vdev = video_devdata(file); + struct sh_vou_device *vou_dev = video_get_drvdata(vdev); + + return v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, core, s_register, reg); +} +#endif + +/* sh_vou display ioctl operations */ +static const struct v4l2_ioctl_ops sh_vou_ioctl_ops = { + .vidioc_querycap = sh_vou_querycap, + .vidioc_enum_fmt_vid_out = sh_vou_enum_fmt_vid_out, + .vidioc_g_fmt_vid_out = sh_vou_g_fmt_vid_out, + .vidioc_s_fmt_vid_out = sh_vou_s_fmt_vid_out, + .vidioc_try_fmt_vid_out = sh_vou_try_fmt_vid_out, + .vidioc_reqbufs = sh_vou_reqbufs, + .vidioc_querybuf = sh_vou_querybuf, + .vidioc_qbuf = sh_vou_qbuf, + .vidioc_dqbuf = sh_vou_dqbuf, + .vidioc_streamon = sh_vou_streamon, + .vidioc_streamoff = sh_vou_streamoff, + .vidioc_s_std = sh_vou_s_std, + .vidioc_g_std = sh_vou_g_std, + .vidioc_cropcap = sh_vou_cropcap, + .vidioc_g_crop = sh_vou_g_crop, + .vidioc_s_crop = sh_vou_s_crop, + .vidioc_g_chip_ident = sh_vou_g_chip_ident, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_register = sh_vou_g_register, + .vidioc_s_register = sh_vou_s_register, +#endif +}; + +static const struct v4l2_file_operations sh_vou_fops = { + .owner = THIS_MODULE, + .open = sh_vou_open, + .release = sh_vou_release, + .ioctl = video_ioctl2, + .mmap = sh_vou_mmap, + .poll = sh_vou_poll, +}; + +static const struct video_device sh_vou_video_template = { + .name = "sh_vou", + .fops = &sh_vou_fops, + .ioctl_ops = &sh_vou_ioctl_ops, + .tvnorms = V4L2_STD_525_60, /* PAL only supported in 8-bit non-bt656 mode */ + .current_norm = V4L2_STD_NTSC_M, +}; + +static int __devinit sh_vou_probe(struct platform_device *pdev) +{ + struct sh_vou_pdata *vou_pdata = pdev->dev.platform_data; + struct v4l2_rect *rect; + struct v4l2_pix_format *pix; + struct i2c_adapter *i2c_adap; + struct video_device *vdev; + struct sh_vou_device *vou_dev; + struct resource *reg_res, *region; + struct v4l2_subdev *subdev; + int irq, ret; + + reg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + irq = platform_get_irq(pdev, 0); + + if (!vou_pdata || !reg_res || irq <= 0) { + dev_err(&pdev->dev, "Insufficient VOU platform information.\n"); + return -ENODEV; + } + + vou_dev = kzalloc(sizeof(*vou_dev), GFP_KERNEL); + if (!vou_dev) + return -ENOMEM; + + INIT_LIST_HEAD(&vou_dev->queue); + spin_lock_init(&vou_dev->lock); + atomic_set(&vou_dev->use_count, 0); + vou_dev->pdata = vou_pdata; + vou_dev->status = SH_VOU_IDLE; + + rect = &vou_dev->rect; + pix = &vou_dev->pix; + + /* Fill in defaults */ + vou_dev->std = sh_vou_video_template.current_norm; + rect->left = 0; + rect->top = 0; + rect->width = VOU_MAX_IMAGE_WIDTH; + rect->height = VOU_MAX_IMAGE_HEIGHT; + pix->width = VOU_MAX_IMAGE_WIDTH; + pix->height = VOU_MAX_IMAGE_HEIGHT; + pix->pixelformat = V4L2_PIX_FMT_YVYU; + pix->field = V4L2_FIELD_NONE; + pix->bytesperline = VOU_MAX_IMAGE_WIDTH * 2; + pix->sizeimage = VOU_MAX_IMAGE_WIDTH * 2 * VOU_MAX_IMAGE_HEIGHT; + pix->colorspace = V4L2_COLORSPACE_SMPTE170M; + + region = request_mem_region(reg_res->start, resource_size(reg_res), + pdev->name); + if (!region) { + dev_err(&pdev->dev, "VOU region already claimed\n"); + ret = -EBUSY; + goto ereqmemreg; + } + + vou_dev->base = ioremap(reg_res->start, resource_size(reg_res)); + if (!vou_dev->base) { + ret = -ENOMEM; + goto emap; + } + + ret = request_irq(irq, sh_vou_isr, 0, "vou", vou_dev); + if (ret < 0) + goto ereqirq; + + ret = v4l2_device_register(&pdev->dev, &vou_dev->v4l2_dev); + if (ret < 0) { + dev_err(&pdev->dev, "Error registering v4l2 device\n"); + goto ev4l2devreg; + } + + /* Allocate memory for video device */ + vdev = video_device_alloc(); + if (vdev == NULL) { + ret = -ENOMEM; + goto evdevalloc; + } + + *vdev = sh_vou_video_template; + if (vou_pdata->bus_fmt == SH_VOU_BUS_8BIT) + vdev->tvnorms |= V4L2_STD_PAL; + vdev->v4l2_dev = &vou_dev->v4l2_dev; + vdev->release = video_device_release; + + vou_dev->vdev = vdev; + video_set_drvdata(vdev, vou_dev); + + pm_runtime_enable(&pdev->dev); + pm_runtime_resume(&pdev->dev); + + i2c_adap = i2c_get_adapter(vou_pdata->i2c_adap); + if (!i2c_adap) { + ret = -ENODEV; + goto ei2cgadap; + } + + ret = sh_vou_hw_init(vou_dev); + if (ret < 0) + goto ereset; + + subdev = v4l2_i2c_new_subdev_board(&vou_dev->v4l2_dev, i2c_adap, + vou_pdata->module_name, vou_pdata->board_info, NULL); + if (!subdev) { + ret = -ENOMEM; + goto ei2cnd; + } + + ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1); + if (ret < 0) + goto evregdev; + + return 0; + +evregdev: +ei2cnd: +ereset: + i2c_put_adapter(i2c_adap); +ei2cgadap: + video_device_release(vdev); + pm_runtime_disable(&pdev->dev); +evdevalloc: + v4l2_device_unregister(&vou_dev->v4l2_dev); +ev4l2devreg: + free_irq(irq, vou_dev); +ereqirq: + iounmap(vou_dev->base); +emap: + release_mem_region(reg_res->start, resource_size(reg_res)); +ereqmemreg: + kfree(vou_dev); + return ret; +} + +static int __devexit sh_vou_remove(struct platform_device *pdev) +{ + int irq = platform_get_irq(pdev, 0); + struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev); + struct sh_vou_device *vou_dev = container_of(v4l2_dev, + struct sh_vou_device, v4l2_dev); + struct v4l2_subdev *sd = list_entry(v4l2_dev->subdevs.next, + struct v4l2_subdev, list); + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct resource *reg_res; + + if (irq > 0) + free_irq(irq, vou_dev); + pm_runtime_disable(&pdev->dev); + video_unregister_device(vou_dev->vdev); + i2c_put_adapter(client->adapter); + v4l2_device_unregister(&vou_dev->v4l2_dev); + iounmap(vou_dev->base); + reg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (reg_res) + release_mem_region(reg_res->start, resource_size(reg_res)); + kfree(vou_dev); + return 0; +} + +static struct platform_driver __refdata sh_vou = { + .remove = __devexit_p(sh_vou_remove), + .driver = { + .name = "sh-vou", + .owner = THIS_MODULE, + }, +}; + +static int __init sh_vou_init(void) +{ + return platform_driver_probe(&sh_vou, sh_vou_probe); +} + +static void __exit sh_vou_exit(void) +{ + platform_driver_unregister(&sh_vou); +} + +module_init(sh_vou_init); +module_exit(sh_vou_exit); + +MODULE_DESCRIPTION("SuperH VOU driver"); +MODULE_AUTHOR("Guennadi Liakhovetski "); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:sh-vou"); diff --git a/include/media/sh_vou.h b/include/media/sh_vou.h new file mode 100644 index 00000000000..a3ef30242b0 --- /dev/null +++ b/include/media/sh_vou.h @@ -0,0 +1,34 @@ +/* + * SuperH Video Output Unit (VOU) driver header + * + * Copyright (C) 2010, Guennadi Liakhovetski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef SH_VOU_H +#define SH_VOU_H + +#include + +/* Bus flags */ +#define SH_VOU_PCLK_FALLING (1 << 0) +#define SH_VOU_HSYNC_LOW (1 << 1) +#define SH_VOU_VSYNC_LOW (1 << 2) + +enum sh_vou_bus_fmt { + SH_VOU_BUS_8BIT, + SH_VOU_BUS_16BIT, + SH_VOU_BUS_BT656, +}; + +struct sh_vou_pdata { + enum sh_vou_bus_fmt bus_fmt; + int i2c_adap; + struct i2c_board_info *board_info; + unsigned long flags; + char *module_name; +}; + +#endif -- cgit v1.2.3-70-g09d2 From aec11e5d495a6c9b10ded81dde5b0e42b0875541 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 29 Mar 2010 04:45:22 -0300 Subject: V4L/DVB: V4L: v4l2-subdev driver for AK8813 and AK8814 TV-encoders from AKM AK8814 only differs from AK8813 by included Macrovision Copy Protection function. This patch adds a driver for AK8813 and AK8814 I2C PAL/NTSC TV encoders. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 6 + drivers/media/video/Makefile | 2 + drivers/media/video/ak881x.c | 368 ++++++++++++++++++++++++++++++++++++++++ include/media/ak881x.h | 25 +++ include/media/v4l2-chip-ident.h | 4 + 5 files changed, 405 insertions(+) create mode 100644 drivers/media/video/ak881x.c create mode 100644 include/media/ak881x.h (limited to 'drivers/media/video') diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index e2fad460a75..747f106e7b5 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -480,6 +480,12 @@ config VIDEO_ADV7343 To compile this driver as a module, choose M here: the module will be called adv7343. +config VIDEO_AK881X + tristate "AK8813/AK8814 video encoders" + depends on I2C + help + Video output driver for AKM AK8813 and AK8814 TV encoders + comment "Video improvement chips" config VIDEO_UPD64031A diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index ed52b6be4ec..4555f5f31ff 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -151,6 +151,8 @@ obj-$(CONFIG_VIDEO_CX18) += cx18/ obj-$(CONFIG_VIDEO_VIVI) += vivi.o obj-$(CONFIG_VIDEO_CX23885) += cx23885/ +obj-$(CONFIG_VIDEO_AK881X) += ak881x.o + obj-$(CONFIG_VIDEO_OMAP2) += omap2cam.o obj-$(CONFIG_SOC_CAMERA) += soc_camera.o soc_mediabus.o obj-$(CONFIG_SOC_CAMERA_PLATFORM) += soc_camera_platform.o diff --git a/drivers/media/video/ak881x.c b/drivers/media/video/ak881x.c new file mode 100644 index 00000000000..35390d4717b --- /dev/null +++ b/drivers/media/video/ak881x.c @@ -0,0 +1,368 @@ +/* + * Driver for AK8813 / AK8814 TV-ecoders from Asahi Kasei Microsystems Co., Ltd. (AKM) + * + * Copyright (C) 2010, Guennadi Liakhovetski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#define AK881X_INTERFACE_MODE 0 +#define AK881X_VIDEO_PROCESS1 1 +#define AK881X_VIDEO_PROCESS2 2 +#define AK881X_VIDEO_PROCESS3 3 +#define AK881X_DAC_MODE 5 +#define AK881X_STATUS 0x24 +#define AK881X_DEVICE_ID 0x25 +#define AK881X_DEVICE_REVISION 0x26 + +struct ak881x { + struct v4l2_subdev subdev; + struct ak881x_pdata *pdata; + unsigned int lines; + int id; /* DEVICE_ID code V4L2_IDENT_AK881X code from v4l2-chip-ident.h */ + char revision; /* DEVICE_REVISION content */ +}; + +static int reg_read(struct i2c_client *client, const u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int reg_write(struct i2c_client *client, const u8 reg, + const u8 data) +{ + return i2c_smbus_write_byte_data(client, reg, data); +} + +static int reg_set(struct i2c_client *client, const u8 reg, + const u8 data, u8 mask) +{ + int ret = reg_read(client, reg); + if (ret < 0) + return ret; + return reg_write(client, reg, (ret & ~mask) | (data & mask)); +} + +static struct ak881x *to_ak881x(const struct i2c_client *client) +{ + return container_of(i2c_get_clientdata(client), struct ak881x, subdev); +} + +static int ak881x_g_chip_ident(struct v4l2_subdev *sd, + struct v4l2_dbg_chip_ident *id) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct ak881x *ak881x = to_ak881x(client); + + if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) + return -EINVAL; + + if (id->match.addr != client->addr) + return -ENODEV; + + id->ident = ak881x->id; + id->revision = ak881x->revision; + + return 0; +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int ak881x_g_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x26) + return -EINVAL; + + if (reg->match.addr != client->addr) + return -ENODEV; + + reg->val = reg_read(client, reg->reg); + + if (reg->val > 0xffff) + return -EIO; + + return 0; +} + +static int ak881x_s_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x26) + return -EINVAL; + + if (reg->match.addr != client->addr) + return -ENODEV; + + if (reg_write(client, reg->reg, reg->val) < 0) + return -EIO; + + return 0; +} +#endif + +static int ak881x_try_g_mbus_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *mf) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct ak881x *ak881x = to_ak881x(client); + + v4l_bound_align_image(&mf->width, 0, 720, 2, + &mf->height, 0, ak881x->lines, 1, 0); + mf->field = V4L2_FIELD_INTERLACED; + mf->code = V4L2_MBUS_FMT_YUYV8_2X8_LE; + mf->colorspace = V4L2_COLORSPACE_SMPTE170M; + + return 0; +} + +static int ak881x_s_mbus_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *mf) +{ + if (mf->field != V4L2_FIELD_INTERLACED || + mf->code != V4L2_MBUS_FMT_YUYV8_2X8_LE) + return -EINVAL; + + return ak881x_try_g_mbus_fmt(sd, mf); +} + +static int ak881x_enum_mbus_fmt(struct v4l2_subdev *sd, int index, + enum v4l2_mbus_pixelcode *code) +{ + if (index) + return -EINVAL; + + *code = V4L2_MBUS_FMT_YUYV8_2X8_LE; + return 0; +} + +static int ak881x_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct ak881x *ak881x = to_ak881x(client); + + a->bounds.left = 0; + a->bounds.top = 0; + a->bounds.width = 720; + a->bounds.height = ak881x->lines; + a->defrect = a->bounds; + a->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + a->pixelaspect.numerator = 1; + a->pixelaspect.denominator = 1; + + return 0; +} + +static int ak881x_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct ak881x *ak881x = to_ak881x(client); + u8 vp1; + + if (std == V4L2_STD_NTSC_443) { + vp1 = 3; + ak881x->lines = 480; + } else if (std == V4L2_STD_PAL_M) { + vp1 = 5; + ak881x->lines = 480; + } else if (std == V4L2_STD_PAL_60) { + vp1 = 7; + ak881x->lines = 480; + } else if (std && !(std & ~V4L2_STD_PAL)) { + vp1 = 0xf; + ak881x->lines = 576; + } else if (std && !(std & ~V4L2_STD_NTSC)) { + vp1 = 0; + ak881x->lines = 480; + } else { + /* No SECAM or PAL_N/Nc supported */ + return -EINVAL; + } + + reg_set(client, AK881X_VIDEO_PROCESS1, vp1, 0xf); + + return 0; +} + +static int ak881x_s_stream(struct v4l2_subdev *sd, int enable) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct ak881x *ak881x = to_ak881x(client); + + if (enable) { + u8 dac; + /* For colour-bar testing set bit 6 of AK881X_VIDEO_PROCESS1 */ + /* Default: composite output */ + if (ak881x->pdata->flags & AK881X_COMPONENT) + dac = 3; + else + dac = 4; + /* Turn on the DAC(s) */ + reg_write(client, AK881X_DAC_MODE, dac); + dev_dbg(&client->dev, "chip status 0x%x\n", + reg_read(client, AK881X_STATUS)); + } else { + /* ...and clear bit 6 of AK881X_VIDEO_PROCESS1 here */ + reg_write(client, AK881X_DAC_MODE, 0); + dev_dbg(&client->dev, "chip status 0x%x\n", + reg_read(client, AK881X_STATUS)); + } + + return 0; +} + +static struct v4l2_subdev_core_ops ak881x_subdev_core_ops = { + .g_chip_ident = ak881x_g_chip_ident, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = ak881x_g_register, + .s_register = ak881x_s_register, +#endif +}; + +static struct v4l2_subdev_video_ops ak881x_subdev_video_ops = { + .s_mbus_fmt = ak881x_s_mbus_fmt, + .g_mbus_fmt = ak881x_try_g_mbus_fmt, + .try_mbus_fmt = ak881x_try_g_mbus_fmt, + .cropcap = ak881x_cropcap, + .enum_mbus_fmt = ak881x_enum_mbus_fmt, + .s_std_output = ak881x_s_std_output, + .s_stream = ak881x_s_stream, +}; + +static struct v4l2_subdev_ops ak881x_subdev_ops = { + .core = &ak881x_subdev_core_ops, + .video = &ak881x_subdev_video_ops, +}; + +static int ak881x_probe(struct i2c_client *client, + const struct i2c_device_id *did) +{ + struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); + struct ak881x *ak881x; + u8 ifmode, data; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_warn(&adapter->dev, + "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n"); + return -EIO; + } + + ak881x = kzalloc(sizeof(struct ak881x), GFP_KERNEL); + if (!ak881x) + return -ENOMEM; + + v4l2_i2c_subdev_init(&ak881x->subdev, client, &ak881x_subdev_ops); + + data = reg_read(client, AK881X_DEVICE_ID); + + switch (data) { + case 0x13: + ak881x->id = V4L2_IDENT_AK8813; + break; + case 0x14: + ak881x->id = V4L2_IDENT_AK8814; + break; + default: + dev_err(&client->dev, + "No ak881x chip detected, register read %x\n", data); + kfree(ak881x); + return -ENODEV; + } + + ak881x->revision = reg_read(client, AK881X_DEVICE_REVISION); + ak881x->pdata = client->dev.platform_data; + + if (ak881x->pdata) { + if (ak881x->pdata->flags & AK881X_FIELD) + ifmode = 4; + else + ifmode = 0; + + switch (ak881x->pdata->flags & AK881X_IF_MODE_MASK) { + case AK881X_IF_MODE_BT656: + ifmode |= 1; + break; + case AK881X_IF_MODE_MASTER: + ifmode |= 2; + break; + case AK881X_IF_MODE_SLAVE: + default: + break; + } + + dev_dbg(&client->dev, "IF mode %x\n", ifmode); + + /* + * "Line Blanking No." seems to be the same as the number of + * "black" lines on, e.g., SuperH VOU, whose default value of 20 + * "incidentally" matches ak881x' default + */ + reg_write(client, AK881X_INTERFACE_MODE, ifmode | (20 << 3)); + } + + /* Hardware default: NTSC-M */ + ak881x->lines = 480; + + dev_info(&client->dev, "Detected an ak881x chip ID %x, revision %x\n", + data, ak881x->revision); + + return 0; +} + +static int ak881x_remove(struct i2c_client *client) +{ + struct ak881x *ak881x = to_ak881x(client); + + v4l2_device_unregister_subdev(&ak881x->subdev); + kfree(ak881x); + + return 0; +} + +static const struct i2c_device_id ak881x_id[] = { + { "ak8813", 0 }, + { "ak8814", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ak881x_id); + +static struct i2c_driver ak881x_i2c_driver = { + .driver = { + .name = "ak881x", + }, + .probe = ak881x_probe, + .remove = ak881x_remove, + .id_table = ak881x_id, +}; + +static int __init ak881x_module_init(void) +{ + return i2c_add_driver(&ak881x_i2c_driver); +} + +static void __exit ak881x_module_exit(void) +{ + i2c_del_driver(&ak881x_i2c_driver); +} + +module_init(ak881x_module_init); +module_exit(ak881x_module_exit); + +MODULE_DESCRIPTION("TV-output driver for ak8813/ak8814"); +MODULE_AUTHOR("Guennadi Liakhovetski "); +MODULE_LICENSE("GPL v2"); diff --git a/include/media/ak881x.h b/include/media/ak881x.h new file mode 100644 index 00000000000..b7f2add5ce7 --- /dev/null +++ b/include/media/ak881x.h @@ -0,0 +1,25 @@ +/* + * Header for AK8813 / AK8814 TV-ecoders from Asahi Kasei Microsystems Co., Ltd. (AKM) + * + * Copyright (C) 2010, Guennadi Liakhovetski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef AK881X_H +#define AK881X_H + +#define AK881X_IF_MODE_MASK (3 << 0) +#define AK881X_IF_MODE_BT656 (0 << 0) +#define AK881X_IF_MODE_MASTER (1 << 0) +#define AK881X_IF_MODE_SLAVE (2 << 0) +#define AK881X_FIELD (1 << 2) +#define AK881X_COMPONENT (1 << 3) + +struct ak881x_pdata { + unsigned long flags; +}; + +#endif diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h index 42759db6794..21b4428c12a 100644 --- a/include/media/v4l2-chip-ident.h +++ b/include/media/v4l2-chip-ident.h @@ -178,6 +178,10 @@ enum { /* module cafe_ccic, just ident 8801 */ V4L2_IDENT_CAFE = 8801, + /* AKM AK8813/AK8814 */ + V4L2_IDENT_AK8813 = 8813, + V4L2_IDENT_AK8814 = 8814, + /* module cx23885 and cx25840 */ V4L2_IDENT_CX23885 = 8850, V4L2_IDENT_CX23885_AV = 8851, /* Integrated A/V decoder */ -- cgit v1.2.3-70-g09d2 From 35e6aa9fc38fb7f47f39711e52cb0f58fbf4441c Mon Sep 17 00:00:00 2001 From: Xiaolin Zhang Date: Sun, 18 Apr 2010 23:06:50 -0300 Subject: V4L/DVB: core: add support for more color effects Add support for more color effects (negative, sketch, emboss, etc) by extending the v4l2_colorfx enum items. Signed-off-by: Xiaolin Zhang Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/v4l/controls.xml | 11 +++++++++-- Documentation/DocBook/v4l/videodev2.h.xml | 7 +++++++ drivers/media/video/v4l2-common.c | 7 +++++++ include/linux/videodev2.h | 7 +++++++ 4 files changed, 30 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/Documentation/DocBook/v4l/controls.xml b/Documentation/DocBook/v4l/controls.xml index 7e0c6874713..8408caaee27 100644 --- a/Documentation/DocBook/v4l/controls.xml +++ b/Documentation/DocBook/v4l/controls.xml @@ -283,8 +283,15 @@ minimum value disables backlight compensation. Selects a color effect. Possible values for enum v4l2_colorfx are: V4L2_COLORFX_NONE (0), -V4L2_COLORFX_BW (1) and -V4L2_COLORFX_SEPIA (2). +V4L2_COLORFX_BW (1), +V4L2_COLORFX_SEPIA (2), +V4L2_COLORFX_NEGATIVE (3), +V4L2_COLORFX_EMBOSS (4), +V4L2_COLORFX_SKETCH (5), +V4L2_COLORFX_SKY_BLUE (6), +V4L2_COLORFX_GRASS_GREEN (7), +V4L2_COLORFX_SKIN_WHITEN (8) and +V4L2_COLORFX_VIVID (9). V4L2_CID_ROTATE diff --git a/Documentation/DocBook/v4l/videodev2.h.xml b/Documentation/DocBook/v4l/videodev2.h.xml index c18dfebedef..865b06d9e67 100644 --- a/Documentation/DocBook/v4l/videodev2.h.xml +++ b/Documentation/DocBook/v4l/videodev2.h.xml @@ -1018,6 +1018,13 @@ enum v4l2_colorfx { V4L2_COLORFX_NONE = 0, V4L2_COLORFX_BW = 1, V4L2_COLORFX_SEPIA = 2, + V4L2_COLORFX_NEGATIVE = 3, + V4L2_COLORFX_EMBOSS = 4, + V4L2_COLORFX_SKETCH = 5, + V4L2_COLORFX_SKY_BLUE = 6, + V4L2_COLORFX_GRASS_GREEN = 7, + V4L2_COLORFX_SKIN_WHITEN = 8, + V4L2_COLORFX_VIVID = 9. }; #define V4L2_CID_AUTOBRIGHTNESS (V4L2_CID_BASE+32) #define V4L2_CID_BAND_STOP_FILTER (V4L2_CID_BASE+33) diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index 67944f53a79..035c414507a 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -343,6 +343,13 @@ const char **v4l2_ctrl_get_menu(u32 id) "None", "Black & White", "Sepia", + "Negative", + "Emboss", + "Sketch", + "Sky blue", + "Grass green", + "Skin whiten", + "Vivid", NULL }; static const char *tune_preemphasis[] = { diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 65d13ec13c1..e878056952c 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -1026,6 +1026,13 @@ enum v4l2_colorfx { V4L2_COLORFX_NONE = 0, V4L2_COLORFX_BW = 1, V4L2_COLORFX_SEPIA = 2, + V4L2_COLORFX_NEGATIVE = 3, + V4L2_COLORFX_EMBOSS = 4, + V4L2_COLORFX_SKETCH = 5, + V4L2_COLORFX_SKY_BLUE = 6, + V4L2_COLORFX_GRASS_GREEN = 7, + V4L2_COLORFX_SKIN_WHITEN = 8, + V4L2_COLORFX_VIVID = 9, }; #define V4L2_CID_AUTOBRIGHTNESS (V4L2_CID_BASE+32) #define V4L2_CID_BAND_STOP_FILTER (V4L2_CID_BASE+33) -- cgit v1.2.3-70-g09d2 From 7f98639def42a676998d734b381af6c0e64d7791 Mon Sep 17 00:00:00 2001 From: Pawel Osciak Date: Fri, 23 Apr 2010 05:38:37 -0300 Subject: V4L/DVB: add memory-to-memory device helper framework for videobuf A mem-to-mem device is a device that uses memory buffers passed by userspace applications for both their source and destination data. This is different from existing drivers, which utilize memory buffers for either input or output, but not both. In terms of V4L2 such a device would be both of OUTPUT and CAPTURE type. Examples of such devices would be: image 'resizers', 'rotators', 'colorspace converters', etc. This patch adds a separate Kconfig sub-menu for mem-to-mem devices as well. Signed-off-by: Pawel Osciak Signed-off-by: Marek Szyprowski Signed-off-by: Kyungmin Park Reviewed-by: Vaibhav Hiremath Tested-by: Vaibhav Hiremath Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 14 + drivers/media/video/Makefile | 2 + drivers/media/video/v4l2-mem2mem.c | 633 +++++++++++++++++++++++++++++++++++++ include/media/v4l2-mem2mem.h | 201 ++++++++++++ 4 files changed, 850 insertions(+) create mode 100644 drivers/media/video/v4l2-mem2mem.c create mode 100644 include/media/v4l2-mem2mem.h (limited to 'drivers/media/video') diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 747f106e7b5..f8cbd4adebf 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -45,6 +45,10 @@ config VIDEO_TUNER tristate depends on MEDIA_TUNER +config V4L2_MEM2MEM_DEV + tristate + depends on VIDEOBUF_GEN + # # Multimedia Video device configuration # @@ -1121,3 +1125,13 @@ config USB_S2255 endif # V4L_USB_DRIVERS endif # VIDEO_CAPTURE_DRIVERS + +menuconfig V4L_MEM2MEM_DRIVERS + bool "Memory-to-memory multimedia devices" + depends on VIDEO_V4L2 + default n + ---help--- + Say Y here to enable selecting drivers for V4L devices that + use system memory for both source and destination buffers, as opposed + to capture and output drivers, which use memory buffers for just + one of those. diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 4555f5f31ff..b57be2f542e 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -117,6 +117,8 @@ obj-$(CONFIG_VIDEOBUF_VMALLOC) += videobuf-vmalloc.o obj-$(CONFIG_VIDEOBUF_DVB) += videobuf-dvb.o obj-$(CONFIG_VIDEO_BTCX) += btcx-risc.o +obj-$(CONFIG_V4L2_MEM2MEM_DEV) += v4l2-mem2mem.o + obj-$(CONFIG_VIDEO_M32R_AR_M64278) += arv.o obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o diff --git a/drivers/media/video/v4l2-mem2mem.c b/drivers/media/video/v4l2-mem2mem.c new file mode 100644 index 00000000000..f45f9405ea3 --- /dev/null +++ b/drivers/media/video/v4l2-mem2mem.c @@ -0,0 +1,633 @@ +/* + * Memory-to-memory device framework for Video for Linux 2 and videobuf. + * + * Helper functions for devices that use videobuf buffers for both their + * source and destination. + * + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. + * Pawel Osciak, + * Marek Szyprowski, + * + * 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 the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include +#include + +#include +#include + +MODULE_DESCRIPTION("Mem to mem device framework for videobuf"); +MODULE_AUTHOR("Pawel Osciak, "); +MODULE_LICENSE("GPL"); + +static bool debug; +module_param(debug, bool, 0644); + +#define dprintk(fmt, arg...) \ + do { \ + if (debug) \ + printk(KERN_DEBUG "%s: " fmt, __func__, ## arg);\ + } while (0) + + +/* Instance is already queued on the job_queue */ +#define TRANS_QUEUED (1 << 0) +/* Instance is currently running in hardware */ +#define TRANS_RUNNING (1 << 1) + + +/* Offset base for buffers on the destination queue - used to distinguish + * between source and destination buffers when mmapping - they receive the same + * offsets but for different queues */ +#define DST_QUEUE_OFF_BASE (1 << 30) + + +/** + * struct v4l2_m2m_dev - per-device context + * @curr_ctx: currently running instance + * @job_queue: instances queued to run + * @job_spinlock: protects job_queue + * @m2m_ops: driver callbacks + */ +struct v4l2_m2m_dev { + struct v4l2_m2m_ctx *curr_ctx; + + struct list_head job_queue; + spinlock_t job_spinlock; + + struct v4l2_m2m_ops *m2m_ops; +}; + +static struct v4l2_m2m_queue_ctx *get_queue_ctx(struct v4l2_m2m_ctx *m2m_ctx, + enum v4l2_buf_type type) +{ + switch (type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + return &m2m_ctx->cap_q_ctx; + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + return &m2m_ctx->out_q_ctx; + default: + printk(KERN_ERR "Invalid buffer type\n"); + return NULL; + } +} + +/** + * v4l2_m2m_get_vq() - return videobuf_queue for the given type + */ +struct videobuf_queue *v4l2_m2m_get_vq(struct v4l2_m2m_ctx *m2m_ctx, + enum v4l2_buf_type type) +{ + struct v4l2_m2m_queue_ctx *q_ctx; + + q_ctx = get_queue_ctx(m2m_ctx, type); + if (!q_ctx) + return NULL; + + return &q_ctx->q; +} +EXPORT_SYMBOL(v4l2_m2m_get_vq); + +/** + * v4l2_m2m_next_buf() - return next buffer from the list of ready buffers + */ +void *v4l2_m2m_next_buf(struct v4l2_m2m_ctx *m2m_ctx, enum v4l2_buf_type type) +{ + struct v4l2_m2m_queue_ctx *q_ctx; + struct videobuf_buffer *vb = NULL; + unsigned long flags; + + q_ctx = get_queue_ctx(m2m_ctx, type); + if (!q_ctx) + return NULL; + + spin_lock_irqsave(q_ctx->q.irqlock, flags); + + if (list_empty(&q_ctx->rdy_queue)) + goto end; + + vb = list_entry(q_ctx->rdy_queue.next, struct videobuf_buffer, queue); + vb->state = VIDEOBUF_ACTIVE; + +end: + spin_unlock_irqrestore(q_ctx->q.irqlock, flags); + return vb; +} +EXPORT_SYMBOL_GPL(v4l2_m2m_next_buf); + +/** + * v4l2_m2m_buf_remove() - take off a buffer from the list of ready buffers and + * return it + */ +void *v4l2_m2m_buf_remove(struct v4l2_m2m_ctx *m2m_ctx, enum v4l2_buf_type type) +{ + struct v4l2_m2m_queue_ctx *q_ctx; + struct videobuf_buffer *vb = NULL; + unsigned long flags; + + q_ctx = get_queue_ctx(m2m_ctx, type); + if (!q_ctx) + return NULL; + + spin_lock_irqsave(q_ctx->q.irqlock, flags); + if (!list_empty(&q_ctx->rdy_queue)) { + vb = list_entry(q_ctx->rdy_queue.next, struct videobuf_buffer, + queue); + list_del(&vb->queue); + q_ctx->num_rdy--; + } + spin_unlock_irqrestore(q_ctx->q.irqlock, flags); + + return vb; +} +EXPORT_SYMBOL_GPL(v4l2_m2m_buf_remove); + +/* + * Scheduling handlers + */ + +/** + * v4l2_m2m_get_curr_priv() - return driver private data for the currently + * running instance or NULL if no instance is running + */ +void *v4l2_m2m_get_curr_priv(struct v4l2_m2m_dev *m2m_dev) +{ + unsigned long flags; + void *ret = NULL; + + spin_lock_irqsave(&m2m_dev->job_spinlock, flags); + if (m2m_dev->curr_ctx) + ret = m2m_dev->curr_ctx->priv; + spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); + + return ret; +} +EXPORT_SYMBOL(v4l2_m2m_get_curr_priv); + +/** + * v4l2_m2m_try_run() - select next job to perform and run it if possible + * + * Get next transaction (if present) from the waiting jobs list and run it. + */ +static void v4l2_m2m_try_run(struct v4l2_m2m_dev *m2m_dev) +{ + unsigned long flags; + + spin_lock_irqsave(&m2m_dev->job_spinlock, flags); + if (NULL != m2m_dev->curr_ctx) { + spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); + dprintk("Another instance is running, won't run now\n"); + return; + } + + if (list_empty(&m2m_dev->job_queue)) { + spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); + dprintk("No job pending\n"); + return; + } + + m2m_dev->curr_ctx = list_entry(m2m_dev->job_queue.next, + struct v4l2_m2m_ctx, queue); + m2m_dev->curr_ctx->job_flags |= TRANS_RUNNING; + spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); + + m2m_dev->m2m_ops->device_run(m2m_dev->curr_ctx->priv); +} + +/** + * v4l2_m2m_try_schedule() - check whether an instance is ready to be added to + * the pending job queue and add it if so. + * @m2m_ctx: m2m context assigned to the instance to be checked + * + * There are three basic requirements an instance has to meet to be able to run: + * 1) at least one source buffer has to be queued, + * 2) at least one destination buffer has to be queued, + * 3) streaming has to be on. + * + * There may also be additional, custom requirements. In such case the driver + * should supply a custom callback (job_ready in v4l2_m2m_ops) that should + * return 1 if the instance is ready. + * An example of the above could be an instance that requires more than one + * src/dst buffer per transaction. + */ +static void v4l2_m2m_try_schedule(struct v4l2_m2m_ctx *m2m_ctx) +{ + struct v4l2_m2m_dev *m2m_dev; + unsigned long flags_job, flags; + + m2m_dev = m2m_ctx->m2m_dev; + dprintk("Trying to schedule a job for m2m_ctx: %p\n", m2m_ctx); + + if (!m2m_ctx->out_q_ctx.q.streaming + || !m2m_ctx->cap_q_ctx.q.streaming) { + dprintk("Streaming needs to be on for both queues\n"); + return; + } + + spin_lock_irqsave(&m2m_dev->job_spinlock, flags_job); + if (m2m_ctx->job_flags & TRANS_QUEUED) { + spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job); + dprintk("On job queue already\n"); + return; + } + + spin_lock_irqsave(m2m_ctx->out_q_ctx.q.irqlock, flags); + if (list_empty(&m2m_ctx->out_q_ctx.rdy_queue)) { + spin_unlock_irqrestore(m2m_ctx->out_q_ctx.q.irqlock, flags); + spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job); + dprintk("No input buffers available\n"); + return; + } + if (list_empty(&m2m_ctx->cap_q_ctx.rdy_queue)) { + spin_unlock_irqrestore(m2m_ctx->out_q_ctx.q.irqlock, flags); + spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job); + dprintk("No output buffers available\n"); + return; + } + spin_unlock_irqrestore(m2m_ctx->out_q_ctx.q.irqlock, flags); + + if (m2m_dev->m2m_ops->job_ready + && (!m2m_dev->m2m_ops->job_ready(m2m_ctx->priv))) { + spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job); + dprintk("Driver not ready\n"); + return; + } + + list_add_tail(&m2m_ctx->queue, &m2m_dev->job_queue); + m2m_ctx->job_flags |= TRANS_QUEUED; + + spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job); + + v4l2_m2m_try_run(m2m_dev); +} + +/** + * v4l2_m2m_job_finish() - inform the framework that a job has been finished + * and have it clean up + * + * Called by a driver to yield back the device after it has finished with it. + * Should be called as soon as possible after reaching a state which allows + * other instances to take control of the device. + * + * This function has to be called only after device_run() callback has been + * called on the driver. To prevent recursion, it should not be called directly + * from the device_run() callback though. + */ +void v4l2_m2m_job_finish(struct v4l2_m2m_dev *m2m_dev, + struct v4l2_m2m_ctx *m2m_ctx) +{ + unsigned long flags; + + spin_lock_irqsave(&m2m_dev->job_spinlock, flags); + if (!m2m_dev->curr_ctx || m2m_dev->curr_ctx != m2m_ctx) { + spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); + dprintk("Called by an instance not currently running\n"); + return; + } + + list_del(&m2m_dev->curr_ctx->queue); + m2m_dev->curr_ctx->job_flags &= ~(TRANS_QUEUED | TRANS_RUNNING); + m2m_dev->curr_ctx = NULL; + + spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); + + /* This instance might have more buffers ready, but since we do not + * allow more than one job on the job_queue per instance, each has + * to be scheduled separately after the previous one finishes. */ + v4l2_m2m_try_schedule(m2m_ctx); + v4l2_m2m_try_run(m2m_dev); +} +EXPORT_SYMBOL(v4l2_m2m_job_finish); + +/** + * v4l2_m2m_reqbufs() - multi-queue-aware REQBUFS multiplexer + */ +int v4l2_m2m_reqbufs(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, + struct v4l2_requestbuffers *reqbufs) +{ + struct videobuf_queue *vq; + + vq = v4l2_m2m_get_vq(m2m_ctx, reqbufs->type); + return videobuf_reqbufs(vq, reqbufs); +} +EXPORT_SYMBOL_GPL(v4l2_m2m_reqbufs); + +/** + * v4l2_m2m_querybuf() - multi-queue-aware QUERYBUF multiplexer + * + * See v4l2_m2m_mmap() documentation for details. + */ +int v4l2_m2m_querybuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, + struct v4l2_buffer *buf) +{ + struct videobuf_queue *vq; + int ret; + + vq = v4l2_m2m_get_vq(m2m_ctx, buf->type); + ret = videobuf_querybuf(vq, buf); + + if (buf->memory == V4L2_MEMORY_MMAP + && vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + buf->m.offset += DST_QUEUE_OFF_BASE; + } + + return ret; +} +EXPORT_SYMBOL_GPL(v4l2_m2m_querybuf); + +/** + * v4l2_m2m_qbuf() - enqueue a source or destination buffer, depending on + * the type + */ +int v4l2_m2m_qbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, + struct v4l2_buffer *buf) +{ + struct videobuf_queue *vq; + int ret; + + vq = v4l2_m2m_get_vq(m2m_ctx, buf->type); + ret = videobuf_qbuf(vq, buf); + if (!ret) + v4l2_m2m_try_schedule(m2m_ctx); + + return ret; +} +EXPORT_SYMBOL_GPL(v4l2_m2m_qbuf); + +/** + * v4l2_m2m_dqbuf() - dequeue a source or destination buffer, depending on + * the type + */ +int v4l2_m2m_dqbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, + struct v4l2_buffer *buf) +{ + struct videobuf_queue *vq; + + vq = v4l2_m2m_get_vq(m2m_ctx, buf->type); + return videobuf_dqbuf(vq, buf, file->f_flags & O_NONBLOCK); +} +EXPORT_SYMBOL_GPL(v4l2_m2m_dqbuf); + +/** + * v4l2_m2m_streamon() - turn on streaming for a video queue + */ +int v4l2_m2m_streamon(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, + enum v4l2_buf_type type) +{ + struct videobuf_queue *vq; + int ret; + + vq = v4l2_m2m_get_vq(m2m_ctx, type); + ret = videobuf_streamon(vq); + if (!ret) + v4l2_m2m_try_schedule(m2m_ctx); + + return ret; +} +EXPORT_SYMBOL_GPL(v4l2_m2m_streamon); + +/** + * v4l2_m2m_streamoff() - turn off streaming for a video queue + */ +int v4l2_m2m_streamoff(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, + enum v4l2_buf_type type) +{ + struct videobuf_queue *vq; + + vq = v4l2_m2m_get_vq(m2m_ctx, type); + return videobuf_streamoff(vq); +} +EXPORT_SYMBOL_GPL(v4l2_m2m_streamoff); + +/** + * v4l2_m2m_poll() - poll replacement, for destination buffers only + * + * Call from the driver's poll() function. Will poll both queues. If a buffer + * is available to dequeue (with dqbuf) from the source queue, this will + * indicate that a non-blocking write can be performed, while read will be + * returned in case of the destination queue. + */ +unsigned int v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, + struct poll_table_struct *wait) +{ + struct videobuf_queue *src_q, *dst_q; + struct videobuf_buffer *src_vb = NULL, *dst_vb = NULL; + unsigned int rc = 0; + + src_q = v4l2_m2m_get_src_vq(m2m_ctx); + dst_q = v4l2_m2m_get_dst_vq(m2m_ctx); + + mutex_lock(&src_q->vb_lock); + mutex_lock(&dst_q->vb_lock); + + if (src_q->streaming && !list_empty(&src_q->stream)) + src_vb = list_first_entry(&src_q->stream, + struct videobuf_buffer, stream); + if (dst_q->streaming && !list_empty(&dst_q->stream)) + dst_vb = list_first_entry(&dst_q->stream, + struct videobuf_buffer, stream); + + if (!src_vb && !dst_vb) { + rc = POLLERR; + goto end; + } + + if (src_vb) { + poll_wait(file, &src_vb->done, wait); + if (src_vb->state == VIDEOBUF_DONE + || src_vb->state == VIDEOBUF_ERROR) + rc |= POLLOUT | POLLWRNORM; + } + if (dst_vb) { + poll_wait(file, &dst_vb->done, wait); + if (dst_vb->state == VIDEOBUF_DONE + || dst_vb->state == VIDEOBUF_ERROR) + rc |= POLLIN | POLLRDNORM; + } + +end: + mutex_unlock(&dst_q->vb_lock); + mutex_unlock(&src_q->vb_lock); + return rc; +} +EXPORT_SYMBOL_GPL(v4l2_m2m_poll); + +/** + * v4l2_m2m_mmap() - source and destination queues-aware mmap multiplexer + * + * Call from driver's mmap() function. Will handle mmap() for both queues + * seamlessly for videobuffer, which will receive normal per-queue offsets and + * proper videobuf queue pointers. The differentiation is made outside videobuf + * by adding a predefined offset to buffers from one of the queues and + * subtracting it before passing it back to videobuf. Only drivers (and + * thus applications) receive modified offsets. + */ +int v4l2_m2m_mmap(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, + struct vm_area_struct *vma) +{ + unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; + struct videobuf_queue *vq; + + if (offset < DST_QUEUE_OFF_BASE) { + vq = v4l2_m2m_get_src_vq(m2m_ctx); + } else { + vq = v4l2_m2m_get_dst_vq(m2m_ctx); + vma->vm_pgoff -= (DST_QUEUE_OFF_BASE >> PAGE_SHIFT); + } + + return videobuf_mmap_mapper(vq, vma); +} +EXPORT_SYMBOL(v4l2_m2m_mmap); + +/** + * v4l2_m2m_init() - initialize per-driver m2m data + * + * Usually called from driver's probe() function. + */ +struct v4l2_m2m_dev *v4l2_m2m_init(struct v4l2_m2m_ops *m2m_ops) +{ + struct v4l2_m2m_dev *m2m_dev; + + if (!m2m_ops) + return ERR_PTR(-EINVAL); + + BUG_ON(!m2m_ops->device_run); + BUG_ON(!m2m_ops->job_abort); + + m2m_dev = kzalloc(sizeof *m2m_dev, GFP_KERNEL); + if (!m2m_dev) + return ERR_PTR(-ENOMEM); + + m2m_dev->curr_ctx = NULL; + m2m_dev->m2m_ops = m2m_ops; + INIT_LIST_HEAD(&m2m_dev->job_queue); + spin_lock_init(&m2m_dev->job_spinlock); + + return m2m_dev; +} +EXPORT_SYMBOL_GPL(v4l2_m2m_init); + +/** + * v4l2_m2m_release() - cleans up and frees a m2m_dev structure + * + * Usually called from driver's remove() function. + */ +void v4l2_m2m_release(struct v4l2_m2m_dev *m2m_dev) +{ + kfree(m2m_dev); +} +EXPORT_SYMBOL_GPL(v4l2_m2m_release); + +/** + * v4l2_m2m_ctx_init() - allocate and initialize a m2m context + * @priv - driver's instance private data + * @m2m_dev - a previously initialized m2m_dev struct + * @vq_init - a callback for queue type-specific initialization function to be + * used for initializing videobuf_queues + * + * Usually called from driver's open() function. + */ +struct v4l2_m2m_ctx *v4l2_m2m_ctx_init(void *priv, struct v4l2_m2m_dev *m2m_dev, + void (*vq_init)(void *priv, struct videobuf_queue *, + enum v4l2_buf_type)) +{ + struct v4l2_m2m_ctx *m2m_ctx; + struct v4l2_m2m_queue_ctx *out_q_ctx, *cap_q_ctx; + + if (!vq_init) + return ERR_PTR(-EINVAL); + + m2m_ctx = kzalloc(sizeof *m2m_ctx, GFP_KERNEL); + if (!m2m_ctx) + return ERR_PTR(-ENOMEM); + + m2m_ctx->priv = priv; + m2m_ctx->m2m_dev = m2m_dev; + + out_q_ctx = get_queue_ctx(m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); + cap_q_ctx = get_queue_ctx(m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); + + INIT_LIST_HEAD(&out_q_ctx->rdy_queue); + INIT_LIST_HEAD(&cap_q_ctx->rdy_queue); + + INIT_LIST_HEAD(&m2m_ctx->queue); + + vq_init(priv, &out_q_ctx->q, V4L2_BUF_TYPE_VIDEO_OUTPUT); + vq_init(priv, &cap_q_ctx->q, V4L2_BUF_TYPE_VIDEO_CAPTURE); + out_q_ctx->q.priv_data = cap_q_ctx->q.priv_data = priv; + + return m2m_ctx; +} +EXPORT_SYMBOL_GPL(v4l2_m2m_ctx_init); + +/** + * v4l2_m2m_ctx_release() - release m2m context + * + * Usually called from driver's release() function. + */ +void v4l2_m2m_ctx_release(struct v4l2_m2m_ctx *m2m_ctx) +{ + struct v4l2_m2m_dev *m2m_dev; + struct videobuf_buffer *vb; + unsigned long flags; + + m2m_dev = m2m_ctx->m2m_dev; + + spin_lock_irqsave(&m2m_dev->job_spinlock, flags); + if (m2m_ctx->job_flags & TRANS_RUNNING) { + spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); + m2m_dev->m2m_ops->job_abort(m2m_ctx->priv); + dprintk("m2m_ctx %p running, will wait to complete", m2m_ctx); + vb = v4l2_m2m_next_dst_buf(m2m_ctx); + BUG_ON(NULL == vb); + wait_event(vb->done, vb->state != VIDEOBUF_ACTIVE + && vb->state != VIDEOBUF_QUEUED); + } else if (m2m_ctx->job_flags & TRANS_QUEUED) { + list_del(&m2m_ctx->queue); + m2m_ctx->job_flags &= ~(TRANS_QUEUED | TRANS_RUNNING); + spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); + dprintk("m2m_ctx: %p had been on queue and was removed\n", + m2m_ctx); + } else { + /* Do nothing, was not on queue/running */ + spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); + } + + videobuf_stop(&m2m_ctx->cap_q_ctx.q); + videobuf_stop(&m2m_ctx->out_q_ctx.q); + + videobuf_mmap_free(&m2m_ctx->cap_q_ctx.q); + videobuf_mmap_free(&m2m_ctx->out_q_ctx.q); + + kfree(m2m_ctx); +} +EXPORT_SYMBOL_GPL(v4l2_m2m_ctx_release); + +/** + * v4l2_m2m_buf_queue() - add a buffer to the proper ready buffers list. + * + * Call from buf_queue(), videobuf_queue_ops callback. + * + * Locking: Caller holds q->irqlock (taken by videobuf before calling buf_queue + * callback in the driver). + */ +void v4l2_m2m_buf_queue(struct v4l2_m2m_ctx *m2m_ctx, struct videobuf_queue *vq, + struct videobuf_buffer *vb) +{ + struct v4l2_m2m_queue_ctx *q_ctx; + + q_ctx = get_queue_ctx(m2m_ctx, vq->type); + if (!q_ctx) + return; + + list_add_tail(&vb->queue, &q_ctx->rdy_queue); + q_ctx->num_rdy++; + + vb->state = VIDEOBUF_QUEUED; +} +EXPORT_SYMBOL_GPL(v4l2_m2m_buf_queue); + diff --git a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h new file mode 100644 index 00000000000..8d149f1c58d --- /dev/null +++ b/include/media/v4l2-mem2mem.h @@ -0,0 +1,201 @@ +/* + * Memory-to-memory device framework for Video for Linux 2. + * + * Helper functions for devices that use memory buffers for both source + * and destination. + * + * Copyright (c) 2009 Samsung Electronics Co., Ltd. + * Pawel Osciak, + * Marek Szyprowski, + * + * 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 the + * Free Software Foundation; either version 2 of the + * License, or (at your option) any later version + */ + +#ifndef _MEDIA_V4L2_MEM2MEM_H +#define _MEDIA_V4L2_MEM2MEM_H + +#include + +/** + * struct v4l2_m2m_ops - mem-to-mem device driver callbacks + * @device_run: required. Begin the actual job (transaction) inside this + * callback. + * The job does NOT have to end before this callback returns + * (and it will be the usual case). When the job finishes, + * v4l2_m2m_job_finish() has to be called. + * @job_ready: optional. Should return 0 if the driver does not have a job + * fully prepared to run yet (i.e. it will not be able to finish a + * transaction without sleeping). If not provided, it will be + * assumed that one source and one destination buffer are all + * that is required for the driver to perform one full transaction. + * This method may not sleep. + * @job_abort: required. Informs the driver that it has to abort the currently + * running transaction as soon as possible (i.e. as soon as it can + * stop the device safely; e.g. in the next interrupt handler), + * even if the transaction would not have been finished by then. + * After the driver performs the necessary steps, it has to call + * v4l2_m2m_job_finish() (as if the transaction ended normally). + * This function does not have to (and will usually not) wait + * until the device enters a state when it can be stopped. + */ +struct v4l2_m2m_ops { + void (*device_run)(void *priv); + int (*job_ready)(void *priv); + void (*job_abort)(void *priv); +}; + +struct v4l2_m2m_dev; + +struct v4l2_m2m_queue_ctx { +/* private: internal use only */ + struct videobuf_queue q; + + /* Queue for buffers ready to be processed as soon as this + * instance receives access to the device */ + struct list_head rdy_queue; + u8 num_rdy; +}; + +struct v4l2_m2m_ctx { +/* private: internal use only */ + struct v4l2_m2m_dev *m2m_dev; + + /* Capture (output to memory) queue context */ + struct v4l2_m2m_queue_ctx cap_q_ctx; + + /* Output (input from memory) queue context */ + struct v4l2_m2m_queue_ctx out_q_ctx; + + /* For device job queue */ + struct list_head queue; + unsigned long job_flags; + + /* Instance private data */ + void *priv; +}; + +void *v4l2_m2m_get_curr_priv(struct v4l2_m2m_dev *m2m_dev); + +struct videobuf_queue *v4l2_m2m_get_vq(struct v4l2_m2m_ctx *m2m_ctx, + enum v4l2_buf_type type); + +void v4l2_m2m_job_finish(struct v4l2_m2m_dev *m2m_dev, + struct v4l2_m2m_ctx *m2m_ctx); + +int v4l2_m2m_reqbufs(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, + struct v4l2_requestbuffers *reqbufs); + +int v4l2_m2m_querybuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, + struct v4l2_buffer *buf); + +int v4l2_m2m_qbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, + struct v4l2_buffer *buf); +int v4l2_m2m_dqbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, + struct v4l2_buffer *buf); + +int v4l2_m2m_streamon(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, + enum v4l2_buf_type type); +int v4l2_m2m_streamoff(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, + enum v4l2_buf_type type); + +unsigned int v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, + struct poll_table_struct *wait); + +int v4l2_m2m_mmap(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, + struct vm_area_struct *vma); + +struct v4l2_m2m_dev *v4l2_m2m_init(struct v4l2_m2m_ops *m2m_ops); +void v4l2_m2m_release(struct v4l2_m2m_dev *m2m_dev); + +struct v4l2_m2m_ctx *v4l2_m2m_ctx_init(void *priv, struct v4l2_m2m_dev *m2m_dev, + void (*vq_init)(void *priv, struct videobuf_queue *, + enum v4l2_buf_type)); +void v4l2_m2m_ctx_release(struct v4l2_m2m_ctx *m2m_ctx); + +void v4l2_m2m_buf_queue(struct v4l2_m2m_ctx *m2m_ctx, struct videobuf_queue *vq, + struct videobuf_buffer *vb); + +/** + * v4l2_m2m_num_src_bufs_ready() - return the number of source buffers ready for + * use + */ +static inline +unsigned int v4l2_m2m_num_src_bufs_ready(struct v4l2_m2m_ctx *m2m_ctx) +{ + return m2m_ctx->cap_q_ctx.num_rdy; +} + +/** + * v4l2_m2m_num_src_bufs_ready() - return the number of destination buffers + * ready for use + */ +static inline +unsigned int v4l2_m2m_num_dst_bufs_ready(struct v4l2_m2m_ctx *m2m_ctx) +{ + return m2m_ctx->out_q_ctx.num_rdy; +} + +void *v4l2_m2m_next_buf(struct v4l2_m2m_ctx *m2m_ctx, enum v4l2_buf_type type); + +/** + * v4l2_m2m_next_src_buf() - return next source buffer from the list of ready + * buffers + */ +static inline void *v4l2_m2m_next_src_buf(struct v4l2_m2m_ctx *m2m_ctx) +{ + return v4l2_m2m_next_buf(m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); +} + +/** + * v4l2_m2m_next_dst_buf() - return next destination buffer from the list of + * ready buffers + */ +static inline void *v4l2_m2m_next_dst_buf(struct v4l2_m2m_ctx *m2m_ctx) +{ + return v4l2_m2m_next_buf(m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); +} + +/** + * v4l2_m2m_get_src_vq() - return videobuf_queue for source buffers + */ +static inline +struct videobuf_queue *v4l2_m2m_get_src_vq(struct v4l2_m2m_ctx *m2m_ctx) +{ + return v4l2_m2m_get_vq(m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); +} + +/** + * v4l2_m2m_get_dst_vq() - return videobuf_queue for destination buffers + */ +static inline +struct videobuf_queue *v4l2_m2m_get_dst_vq(struct v4l2_m2m_ctx *m2m_ctx) +{ + return v4l2_m2m_get_vq(m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); +} + +void *v4l2_m2m_buf_remove(struct v4l2_m2m_ctx *m2m_ctx, + enum v4l2_buf_type type); + +/** + * v4l2_m2m_src_buf_remove() - take off a source buffer from the list of ready + * buffers and return it + */ +static inline void *v4l2_m2m_src_buf_remove(struct v4l2_m2m_ctx *m2m_ctx) +{ + return v4l2_m2m_buf_remove(m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); +} + +/** + * v4l2_m2m_dst_buf_remove() - take off a destination buffer from the list of + * ready buffers and return it + */ +static inline void *v4l2_m2m_dst_buf_remove(struct v4l2_m2m_ctx *m2m_ctx) +{ + return v4l2_m2m_buf_remove(m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); +} + +#endif /* _MEDIA_V4L2_MEM2MEM_H */ + -- cgit v1.2.3-70-g09d2 From 96d8eab5d0a1a9741a4cae1b3c125d75d1aabedf Mon Sep 17 00:00:00 2001 From: Pawel Osciak Date: Fri, 23 Apr 2010 05:38:38 -0300 Subject: V4L/DVB: [v5,2/2] v4l: Add a mem-to-mem videobuf framework test device This is a virtual device driver for testing the memory-to-memory framework. This virtual device uses in-memory buffers for both its source and destination. It is capable of multi-instance, multi-buffer-per-transaction operation (via the mem2mem framework). [mchehab@redhat.com: use videobuf_queue_to_vaddr instead of the removed videobuf_queue_to_vmalloc] Signed-off-by: Pawel Osciak Signed-off-by: Marek Szyprowski Signed-off-by: Kyungmin Park Reviewed-by: Vaibhav Hiremath Tested-by: Vaibhav Hiremath Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 14 + drivers/media/video/Makefile | 1 + drivers/media/video/mem2mem_testdev.c | 1049 +++++++++++++++++++++++++++++++++ 3 files changed, 1064 insertions(+) create mode 100644 drivers/media/video/mem2mem_testdev.c (limited to 'drivers/media/video') diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index f8cbd4adebf..16decdd6e28 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -1135,3 +1135,17 @@ menuconfig V4L_MEM2MEM_DRIVERS use system memory for both source and destination buffers, as opposed to capture and output drivers, which use memory buffers for just one of those. + +if V4L_MEM2MEM_DRIVERS + +config VIDEO_MEM2MEM_TESTDEV + tristate "Virtual test device for mem2mem framework" + depends on VIDEO_DEV && VIDEO_V4L2 + select VIDEOBUF_VMALLOC + select V4L2_MEM2MEM_DEV + default n + ---help--- + This is a virtual test device for the memory-to-memory driver + framework. + +endif # V4L_MEM2MEM_DRIVERS diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index b57be2f542e..a688a0f4387 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -151,6 +151,7 @@ obj-$(CONFIG_VIDEO_IVTV) += ivtv/ obj-$(CONFIG_VIDEO_CX18) += cx18/ obj-$(CONFIG_VIDEO_VIVI) += vivi.o +obj-$(CONFIG_VIDEO_MEM2MEM_TESTDEV) += mem2mem_testdev.o obj-$(CONFIG_VIDEO_CX23885) += cx23885/ obj-$(CONFIG_VIDEO_AK881X) += ak881x.o diff --git a/drivers/media/video/mem2mem_testdev.c b/drivers/media/video/mem2mem_testdev.c new file mode 100644 index 00000000000..baf211b9f6c --- /dev/null +++ b/drivers/media/video/mem2mem_testdev.c @@ -0,0 +1,1049 @@ +/* + * A virtual v4l2-mem2mem example device. + * + * This is a virtual device driver for testing mem-to-mem videobuf framework. + * It simulates a device that uses memory buffers for both source and + * destination, processes the data and issues an "irq" (simulated by a timer). + * The device is capable of multi-instance, multi-buffer-per-transaction + * operation (via the mem2mem framework). + * + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. + * Pawel Osciak, + * Marek Szyprowski, + * + * 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 the + * Free Software Foundation; either version 2 of the + * License, or (at your option) any later version + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define MEM2MEM_TEST_MODULE_NAME "mem2mem-testdev" + +MODULE_DESCRIPTION("Virtual device for mem2mem framework testing"); +MODULE_AUTHOR("Pawel Osciak, "); +MODULE_LICENSE("GPL"); + + +#define MIN_W 32 +#define MIN_H 32 +#define MAX_W 640 +#define MAX_H 480 +#define DIM_ALIGN_MASK 0x08 /* 8-alignment for dimensions */ + +/* Flags that indicate a format can be used for capture/output */ +#define MEM2MEM_CAPTURE (1 << 0) +#define MEM2MEM_OUTPUT (1 << 1) + +#define MEM2MEM_NAME "m2m-testdev" + +/* Per queue */ +#define MEM2MEM_DEF_NUM_BUFS VIDEO_MAX_FRAME +/* In bytes, per queue */ +#define MEM2MEM_VID_MEM_LIMIT (16 * 1024 * 1024) + +/* Default transaction time in msec */ +#define MEM2MEM_DEF_TRANSTIME 1000 +/* Default number of buffers per transaction */ +#define MEM2MEM_DEF_TRANSLEN 1 +#define MEM2MEM_COLOR_STEP (0xff >> 4) +#define MEM2MEM_NUM_TILES 8 + +#define dprintk(dev, fmt, arg...) \ + v4l2_dbg(1, 1, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg) + + +void m2mtest_dev_release(struct device *dev) +{} + +static struct platform_device m2mtest_pdev = { + .name = MEM2MEM_NAME, + .dev.release = m2mtest_dev_release, +}; + +struct m2mtest_fmt { + char *name; + u32 fourcc; + int depth; + /* Types the format can be used for */ + u32 types; +}; + +static struct m2mtest_fmt formats[] = { + { + .name = "RGB565 (BE)", + .fourcc = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */ + .depth = 16, + /* Both capture and output format */ + .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, + }, + { + .name = "4:2:2, packed, YUYV", + .fourcc = V4L2_PIX_FMT_YUYV, + .depth = 16, + /* Output-only format */ + .types = MEM2MEM_OUTPUT, + }, +}; + +/* Per-queue, driver-specific private data */ +struct m2mtest_q_data { + unsigned int width; + unsigned int height; + unsigned int sizeimage; + struct m2mtest_fmt *fmt; +}; + +enum { + V4L2_M2M_SRC = 0, + V4L2_M2M_DST = 1, +}; + +/* Source and destination queue data */ +static struct m2mtest_q_data q_data[2]; + +static struct m2mtest_q_data *get_q_data(enum v4l2_buf_type type) +{ + switch (type) { + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + return &q_data[V4L2_M2M_SRC]; + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + return &q_data[V4L2_M2M_DST]; + default: + BUG(); + } + return NULL; +} + +#define V4L2_CID_TRANS_TIME_MSEC V4L2_CID_PRIVATE_BASE +#define V4L2_CID_TRANS_NUM_BUFS (V4L2_CID_PRIVATE_BASE + 1) + +static struct v4l2_queryctrl m2mtest_ctrls[] = { + { + .id = V4L2_CID_TRANS_TIME_MSEC, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Transaction time (msec)", + .minimum = 1, + .maximum = 10000, + .step = 100, + .default_value = 1000, + .flags = 0, + }, { + .id = V4L2_CID_TRANS_NUM_BUFS, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Buffers per transaction", + .minimum = 1, + .maximum = MEM2MEM_DEF_NUM_BUFS, + .step = 1, + .default_value = 1, + .flags = 0, + }, +}; + +#define NUM_FORMATS ARRAY_SIZE(formats) + +static struct m2mtest_fmt *find_format(struct v4l2_format *f) +{ + struct m2mtest_fmt *fmt; + unsigned int k; + + for (k = 0; k < NUM_FORMATS; k++) { + fmt = &formats[k]; + if (fmt->fourcc == f->fmt.pix.pixelformat) + break; + } + + if (k == NUM_FORMATS) + return NULL; + + return &formats[k]; +} + +struct m2mtest_dev { + struct v4l2_device v4l2_dev; + struct video_device *vfd; + + atomic_t num_inst; + struct mutex dev_mutex; + spinlock_t irqlock; + + struct timer_list timer; + + struct v4l2_m2m_dev *m2m_dev; +}; + +struct m2mtest_ctx { + struct m2mtest_dev *dev; + + /* Processed buffers in this transaction */ + u8 num_processed; + + /* Transaction length (i.e. how many buffers per transaction) */ + u32 translen; + /* Transaction time (i.e. simulated processing time) in milliseconds */ + u32 transtime; + + /* Abort requested by m2m */ + int aborting; + + struct v4l2_m2m_ctx *m2m_ctx; +}; + +struct m2mtest_buffer { + /* vb must be first! */ + struct videobuf_buffer vb; +}; + +static struct v4l2_queryctrl *get_ctrl(int id) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(m2mtest_ctrls); ++i) { + if (id == m2mtest_ctrls[i].id) + return &m2mtest_ctrls[i]; + } + + return NULL; +} + +static int device_process(struct m2mtest_ctx *ctx, + struct m2mtest_buffer *in_buf, + struct m2mtest_buffer *out_buf) +{ + struct m2mtest_dev *dev = ctx->dev; + u8 *p_in, *p_out; + int x, y, t, w; + int tile_w, bytes_left; + struct videobuf_queue *src_q; + struct videobuf_queue *dst_q; + + src_q = v4l2_m2m_get_src_vq(ctx->m2m_ctx); + dst_q = v4l2_m2m_get_dst_vq(ctx->m2m_ctx); + p_in = videobuf_queue_to_vaddr(src_q, &in_buf->vb); + p_out = videobuf_queue_to_vaddr(dst_q, &out_buf->vb); + if (!p_in || !p_out) { + v4l2_err(&dev->v4l2_dev, + "Acquiring kernel pointers to buffers failed\n"); + return -EFAULT; + } + + if (in_buf->vb.size < out_buf->vb.size) { + v4l2_err(&dev->v4l2_dev, "Output buffer is too small\n"); + return -EINVAL; + } + + tile_w = (in_buf->vb.width * (q_data[V4L2_M2M_DST].fmt->depth >> 3)) + / MEM2MEM_NUM_TILES; + bytes_left = in_buf->vb.bytesperline - tile_w * MEM2MEM_NUM_TILES; + w = 0; + + for (y = 0; y < in_buf->vb.height; ++y) { + for (t = 0; t < MEM2MEM_NUM_TILES; ++t) { + if (w & 0x1) { + for (x = 0; x < tile_w; ++x) + *p_out++ = *p_in++ + MEM2MEM_COLOR_STEP; + } else { + for (x = 0; x < tile_w; ++x) + *p_out++ = *p_in++ - MEM2MEM_COLOR_STEP; + } + ++w; + } + p_in += bytes_left; + p_out += bytes_left; + } + + return 0; +} + +static void schedule_irq(struct m2mtest_dev *dev, int msec_timeout) +{ + dprintk(dev, "Scheduling a simulated irq\n"); + mod_timer(&dev->timer, jiffies + msecs_to_jiffies(msec_timeout)); +} + +/* + * mem2mem callbacks + */ + +/** + * job_ready() - check whether an instance is ready to be scheduled to run + */ +static int job_ready(void *priv) +{ + struct m2mtest_ctx *ctx = priv; + + if (v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx) < ctx->translen + || v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) < ctx->translen) { + dprintk(ctx->dev, "Not enough buffers available\n"); + return 0; + } + + return 1; +} + +static void job_abort(void *priv) +{ + struct m2mtest_ctx *ctx = priv; + + /* Will cancel the transaction in the next interrupt handler */ + ctx->aborting = 1; +} + +/* device_run() - prepares and starts the device + * + * This simulates all the immediate preparations required before starting + * a device. This will be called by the framework when it decides to schedule + * a particular instance. + */ +static void device_run(void *priv) +{ + struct m2mtest_ctx *ctx = priv; + struct m2mtest_dev *dev = ctx->dev; + struct m2mtest_buffer *src_buf, *dst_buf; + + src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx); + dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); + + device_process(ctx, src_buf, dst_buf); + + /* Run a timer, which simulates a hardware irq */ + schedule_irq(dev, ctx->transtime); +} + + +static void device_isr(unsigned long priv) +{ + struct m2mtest_dev *m2mtest_dev = (struct m2mtest_dev *)priv; + struct m2mtest_ctx *curr_ctx; + struct m2mtest_buffer *src_buf, *dst_buf; + unsigned long flags; + + curr_ctx = v4l2_m2m_get_curr_priv(m2mtest_dev->m2m_dev); + + if (NULL == curr_ctx) { + printk(KERN_ERR + "Instance released before the end of transaction\n"); + return; + } + + src_buf = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx); + dst_buf = v4l2_m2m_dst_buf_remove(curr_ctx->m2m_ctx); + curr_ctx->num_processed++; + + if (curr_ctx->num_processed == curr_ctx->translen + || curr_ctx->aborting) { + dprintk(curr_ctx->dev, "Finishing transaction\n"); + curr_ctx->num_processed = 0; + spin_lock_irqsave(&m2mtest_dev->irqlock, flags); + src_buf->vb.state = dst_buf->vb.state = VIDEOBUF_DONE; + wake_up(&src_buf->vb.done); + wake_up(&dst_buf->vb.done); + spin_unlock_irqrestore(&m2mtest_dev->irqlock, flags); + v4l2_m2m_job_finish(m2mtest_dev->m2m_dev, curr_ctx->m2m_ctx); + } else { + spin_lock_irqsave(&m2mtest_dev->irqlock, flags); + src_buf->vb.state = dst_buf->vb.state = VIDEOBUF_DONE; + wake_up(&src_buf->vb.done); + wake_up(&dst_buf->vb.done); + spin_unlock_irqrestore(&m2mtest_dev->irqlock, flags); + device_run(curr_ctx); + } +} + + +/* + * video ioctls + */ +static int vidioc_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + strncpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver) - 1); + strncpy(cap->card, MEM2MEM_NAME, sizeof(cap->card) - 1); + cap->bus_info[0] = 0; + cap->version = KERNEL_VERSION(0, 1, 0); + cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT + | V4L2_CAP_STREAMING; + + return 0; +} + +static int enum_fmt(struct v4l2_fmtdesc *f, u32 type) +{ + int i, num; + struct m2mtest_fmt *fmt; + + num = 0; + + for (i = 0; i < NUM_FORMATS; ++i) { + if (formats[i].types & type) { + /* index-th format of type type found ? */ + if (num == f->index) + break; + /* Correct type but haven't reached our index yet, + * just increment per-type index */ + ++num; + } + } + + if (i < NUM_FORMATS) { + /* Format found */ + fmt = &formats[i]; + strncpy(f->description, fmt->name, sizeof(f->description) - 1); + f->pixelformat = fmt->fourcc; + return 0; + } + + /* Format not found */ + return -EINVAL; +} + +static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + return enum_fmt(f, MEM2MEM_CAPTURE); +} + +static int vidioc_enum_fmt_vid_out(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + return enum_fmt(f, MEM2MEM_OUTPUT); +} + +static int vidioc_g_fmt(struct m2mtest_ctx *ctx, struct v4l2_format *f) +{ + struct videobuf_queue *vq; + struct m2mtest_q_data *q_data; + + vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); + if (!vq) + return -EINVAL; + + q_data = get_q_data(f->type); + + f->fmt.pix.width = q_data->width; + f->fmt.pix.height = q_data->height; + f->fmt.pix.field = vq->field; + f->fmt.pix.pixelformat = q_data->fmt->fourcc; + f->fmt.pix.bytesperline = (q_data->width * q_data->fmt->depth) >> 3; + f->fmt.pix.sizeimage = q_data->sizeimage; + + return 0; +} + +static int vidioc_g_fmt_vid_out(struct file *file, void *priv, + struct v4l2_format *f) +{ + return vidioc_g_fmt(priv, f); +} + +static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + return vidioc_g_fmt(priv, f); +} + +static int vidioc_try_fmt(struct v4l2_format *f, struct m2mtest_fmt *fmt) +{ + enum v4l2_field field; + + field = f->fmt.pix.field; + + if (field == V4L2_FIELD_ANY) + field = V4L2_FIELD_NONE; + else if (V4L2_FIELD_NONE != field) + return -EINVAL; + + /* V4L2 specification suggests the driver corrects the format struct + * if any of the dimensions is unsupported */ + f->fmt.pix.field = field; + + if (f->fmt.pix.height < MIN_H) + f->fmt.pix.height = MIN_H; + else if (f->fmt.pix.height > MAX_H) + f->fmt.pix.height = MAX_H; + + if (f->fmt.pix.width < MIN_W) + f->fmt.pix.width = MIN_W; + else if (f->fmt.pix.width > MAX_W) + f->fmt.pix.width = MAX_W; + + f->fmt.pix.width &= ~DIM_ALIGN_MASK; + f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3; + f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; + + return 0; +} + +static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct m2mtest_fmt *fmt; + struct m2mtest_ctx *ctx = priv; + + fmt = find_format(f); + if (!fmt || !(fmt->types & MEM2MEM_CAPTURE)) { + v4l2_err(&ctx->dev->v4l2_dev, + "Fourcc format (0x%08x) invalid.\n", + f->fmt.pix.pixelformat); + return -EINVAL; + } + + return vidioc_try_fmt(f, fmt); +} + +static int vidioc_try_fmt_vid_out(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct m2mtest_fmt *fmt; + struct m2mtest_ctx *ctx = priv; + + fmt = find_format(f); + if (!fmt || !(fmt->types & MEM2MEM_OUTPUT)) { + v4l2_err(&ctx->dev->v4l2_dev, + "Fourcc format (0x%08x) invalid.\n", + f->fmt.pix.pixelformat); + return -EINVAL; + } + + return vidioc_try_fmt(f, fmt); +} + +static int vidioc_s_fmt(struct m2mtest_ctx *ctx, struct v4l2_format *f) +{ + struct m2mtest_q_data *q_data; + struct videobuf_queue *vq; + int ret = 0; + + vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); + if (!vq) + return -EINVAL; + + q_data = get_q_data(f->type); + if (!q_data) + return -EINVAL; + + mutex_lock(&vq->vb_lock); + + if (videobuf_queue_is_busy(vq)) { + v4l2_err(&ctx->dev->v4l2_dev, "%s queue busy\n", __func__); + ret = -EBUSY; + goto out; + } + + q_data->fmt = find_format(f); + q_data->width = f->fmt.pix.width; + q_data->height = f->fmt.pix.height; + q_data->sizeimage = q_data->width * q_data->height + * q_data->fmt->depth >> 3; + vq->field = f->fmt.pix.field; + + dprintk(ctx->dev, + "Setting format for type %d, wxh: %dx%d, fmt: %d\n", + f->type, q_data->width, q_data->height, q_data->fmt->fourcc); + +out: + mutex_unlock(&vq->vb_lock); + return ret; +} + +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + int ret; + + ret = vidioc_try_fmt_vid_cap(file, priv, f); + if (ret) + return ret; + + return vidioc_s_fmt(priv, f); +} + +static int vidioc_s_fmt_vid_out(struct file *file, void *priv, + struct v4l2_format *f) +{ + int ret; + + ret = vidioc_try_fmt_vid_out(file, priv, f); + if (ret) + return ret; + + return vidioc_s_fmt(priv, f); +} + +static int vidioc_reqbufs(struct file *file, void *priv, + struct v4l2_requestbuffers *reqbufs) +{ + struct m2mtest_ctx *ctx = priv; + + return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs); +} + +static int vidioc_querybuf(struct file *file, void *priv, + struct v4l2_buffer *buf) +{ + struct m2mtest_ctx *ctx = priv; + + return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf); +} + +static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) +{ + struct m2mtest_ctx *ctx = priv; + + return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); +} + +static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) +{ + struct m2mtest_ctx *ctx = priv; + + return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); +} + +static int vidioc_streamon(struct file *file, void *priv, + enum v4l2_buf_type type) +{ + struct m2mtest_ctx *ctx = priv; + + return v4l2_m2m_streamon(file, ctx->m2m_ctx, type); +} + +static int vidioc_streamoff(struct file *file, void *priv, + enum v4l2_buf_type type) +{ + struct m2mtest_ctx *ctx = priv; + + return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type); +} + +static int vidioc_queryctrl(struct file *file, void *priv, + struct v4l2_queryctrl *qc) +{ + struct v4l2_queryctrl *c; + + c = get_ctrl(qc->id); + if (!c) + return -EINVAL; + + *qc = *c; + return 0; +} + +static int vidioc_g_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct m2mtest_ctx *ctx = priv; + + switch (ctrl->id) { + case V4L2_CID_TRANS_TIME_MSEC: + ctrl->value = ctx->transtime; + break; + + case V4L2_CID_TRANS_NUM_BUFS: + ctrl->value = ctx->translen; + break; + + default: + v4l2_err(&ctx->dev->v4l2_dev, "Invalid control\n"); + return -EINVAL; + } + + return 0; +} + +static int check_ctrl_val(struct m2mtest_ctx *ctx, struct v4l2_control *ctrl) +{ + struct v4l2_queryctrl *c; + + c = get_ctrl(ctrl->id); + if (!c) + return -EINVAL; + + if (ctrl->value < c->minimum || ctrl->value > c->maximum) { + v4l2_err(&ctx->dev->v4l2_dev, "Value out of range\n"); + return -ERANGE; + } + + return 0; +} + +static int vidioc_s_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct m2mtest_ctx *ctx = priv; + int ret = 0; + + ret = check_ctrl_val(ctx, ctrl); + if (ret != 0) + return ret; + + switch (ctrl->id) { + case V4L2_CID_TRANS_TIME_MSEC: + ctx->transtime = ctrl->value; + break; + + case V4L2_CID_TRANS_NUM_BUFS: + ctx->translen = ctrl->value; + break; + + default: + v4l2_err(&ctx->dev->v4l2_dev, "Invalid control\n"); + return -EINVAL; + } + + return 0; +} + + +static const struct v4l2_ioctl_ops m2mtest_ioctl_ops = { + .vidioc_querycap = vidioc_querycap, + + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, + + .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out, + .vidioc_g_fmt_vid_out = vidioc_g_fmt_vid_out, + .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out, + .vidioc_s_fmt_vid_out = vidioc_s_fmt_vid_out, + + .vidioc_reqbufs = vidioc_reqbufs, + .vidioc_querybuf = vidioc_querybuf, + + .vidioc_qbuf = vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, + + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, + + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, +}; + + +/* + * Queue operations + */ + +static void m2mtest_buf_release(struct videobuf_queue *vq, + struct videobuf_buffer *vb) +{ + struct m2mtest_ctx *ctx = vq->priv_data; + + dprintk(ctx->dev, "type: %d, index: %d, state: %d\n", + vq->type, vb->i, vb->state); + + videobuf_vmalloc_free(vb); + vb->state = VIDEOBUF_NEEDS_INIT; +} + +static int m2mtest_buf_setup(struct videobuf_queue *vq, unsigned int *count, + unsigned int *size) +{ + struct m2mtest_ctx *ctx = vq->priv_data; + struct m2mtest_q_data *q_data; + + q_data = get_q_data(vq->type); + + *size = q_data->width * q_data->height * q_data->fmt->depth >> 3; + dprintk(ctx->dev, "size:%d, w/h %d/%d, depth: %d\n", + *size, q_data->width, q_data->height, q_data->fmt->depth); + + if (0 == *count) + *count = MEM2MEM_DEF_NUM_BUFS; + + while (*size * *count > MEM2MEM_VID_MEM_LIMIT) + (*count)--; + + v4l2_info(&ctx->dev->v4l2_dev, + "%d buffers of size %d set up.\n", *count, *size); + + return 0; +} + +static int m2mtest_buf_prepare(struct videobuf_queue *vq, + struct videobuf_buffer *vb, + enum v4l2_field field) +{ + struct m2mtest_ctx *ctx = vq->priv_data; + struct m2mtest_q_data *q_data; + int ret; + + dprintk(ctx->dev, "type: %d, index: %d, state: %d\n", + vq->type, vb->i, vb->state); + + q_data = get_q_data(vq->type); + + if (vb->baddr) { + /* User-provided buffer */ + if (vb->bsize < q_data->sizeimage) { + /* Buffer too small to fit a frame */ + v4l2_err(&ctx->dev->v4l2_dev, + "User-provided buffer too small\n"); + return -EINVAL; + } + } else if (vb->state != VIDEOBUF_NEEDS_INIT + && vb->bsize < q_data->sizeimage) { + /* We provide the buffer, but it's already been initialized + * and is too small */ + return -EINVAL; + } + + vb->width = q_data->width; + vb->height = q_data->height; + vb->bytesperline = (q_data->width * q_data->fmt->depth) >> 3; + vb->size = q_data->sizeimage; + vb->field = field; + + if (VIDEOBUF_NEEDS_INIT == vb->state) { + ret = videobuf_iolock(vq, vb, NULL); + if (ret) { + v4l2_err(&ctx->dev->v4l2_dev, + "Iolock failed\n"); + goto fail; + } + } + + vb->state = VIDEOBUF_PREPARED; + + return 0; +fail: + m2mtest_buf_release(vq, vb); + return ret; +} + +static void m2mtest_buf_queue(struct videobuf_queue *vq, + struct videobuf_buffer *vb) +{ + struct m2mtest_ctx *ctx = vq->priv_data; + + v4l2_m2m_buf_queue(ctx->m2m_ctx, vq, vb); +} + +static struct videobuf_queue_ops m2mtest_qops = { + .buf_setup = m2mtest_buf_setup, + .buf_prepare = m2mtest_buf_prepare, + .buf_queue = m2mtest_buf_queue, + .buf_release = m2mtest_buf_release, +}; + +static void queue_init(void *priv, struct videobuf_queue *vq, + enum v4l2_buf_type type) +{ + struct m2mtest_ctx *ctx = priv; + + videobuf_queue_vmalloc_init(vq, &m2mtest_qops, ctx->dev->v4l2_dev.dev, + &ctx->dev->irqlock, type, V4L2_FIELD_NONE, + sizeof(struct m2mtest_buffer), priv); +} + + +/* + * File operations + */ +static int m2mtest_open(struct file *file) +{ + struct m2mtest_dev *dev = video_drvdata(file); + struct m2mtest_ctx *ctx = NULL; + + ctx = kzalloc(sizeof *ctx, GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + file->private_data = ctx; + ctx->dev = dev; + ctx->translen = MEM2MEM_DEF_TRANSLEN; + ctx->transtime = MEM2MEM_DEF_TRANSTIME; + ctx->num_processed = 0; + + ctx->m2m_ctx = v4l2_m2m_ctx_init(ctx, dev->m2m_dev, queue_init); + if (IS_ERR(ctx->m2m_ctx)) { + kfree(ctx); + return PTR_ERR(ctx->m2m_ctx); + } + + atomic_inc(&dev->num_inst); + + dprintk(dev, "Created instance %p, m2m_ctx: %p\n", ctx, ctx->m2m_ctx); + + return 0; +} + +static int m2mtest_release(struct file *file) +{ + struct m2mtest_dev *dev = video_drvdata(file); + struct m2mtest_ctx *ctx = file->private_data; + + dprintk(dev, "Releasing instance %p\n", ctx); + + v4l2_m2m_ctx_release(ctx->m2m_ctx); + kfree(ctx); + + atomic_dec(&dev->num_inst); + + return 0; +} + +static unsigned int m2mtest_poll(struct file *file, + struct poll_table_struct *wait) +{ + struct m2mtest_ctx *ctx = (struct m2mtest_ctx *)file->private_data; + + return v4l2_m2m_poll(file, ctx->m2m_ctx, wait); +} + +static int m2mtest_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct m2mtest_ctx *ctx = (struct m2mtest_ctx *)file->private_data; + + return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); +} + +static const struct v4l2_file_operations m2mtest_fops = { + .owner = THIS_MODULE, + .open = m2mtest_open, + .release = m2mtest_release, + .poll = m2mtest_poll, + .ioctl = video_ioctl2, + .mmap = m2mtest_mmap, +}; + +static struct video_device m2mtest_videodev = { + .name = MEM2MEM_NAME, + .fops = &m2mtest_fops, + .ioctl_ops = &m2mtest_ioctl_ops, + .minor = -1, + .release = video_device_release, +}; + +static struct v4l2_m2m_ops m2m_ops = { + .device_run = device_run, + .job_ready = job_ready, + .job_abort = job_abort, +}; + +static int m2mtest_probe(struct platform_device *pdev) +{ + struct m2mtest_dev *dev; + struct video_device *vfd; + int ret; + + dev = kzalloc(sizeof *dev, GFP_KERNEL); + if (!dev) + return -ENOMEM; + + spin_lock_init(&dev->irqlock); + + ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); + if (ret) + goto free_dev; + + atomic_set(&dev->num_inst, 0); + mutex_init(&dev->dev_mutex); + + vfd = video_device_alloc(); + if (!vfd) { + v4l2_err(&dev->v4l2_dev, "Failed to allocate video device\n"); + ret = -ENOMEM; + goto unreg_dev; + } + + *vfd = m2mtest_videodev; + + ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); + if (ret) { + v4l2_err(&dev->v4l2_dev, "Failed to register video device\n"); + goto rel_vdev; + } + + video_set_drvdata(vfd, dev); + snprintf(vfd->name, sizeof(vfd->name), "%s", m2mtest_videodev.name); + dev->vfd = vfd; + v4l2_info(&dev->v4l2_dev, MEM2MEM_TEST_MODULE_NAME + "Device registered as /dev/video%d\n", vfd->num); + + setup_timer(&dev->timer, device_isr, (long)dev); + platform_set_drvdata(pdev, dev); + + dev->m2m_dev = v4l2_m2m_init(&m2m_ops); + if (IS_ERR(dev->m2m_dev)) { + v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem device\n"); + ret = PTR_ERR(dev->m2m_dev); + goto err_m2m; + } + + return 0; + +err_m2m: + video_unregister_device(dev->vfd); +rel_vdev: + video_device_release(vfd); +unreg_dev: + v4l2_device_unregister(&dev->v4l2_dev); +free_dev: + kfree(dev); + + return ret; +} + +static int m2mtest_remove(struct platform_device *pdev) +{ + struct m2mtest_dev *dev = + (struct m2mtest_dev *)platform_get_drvdata(pdev); + + v4l2_info(&dev->v4l2_dev, "Removing " MEM2MEM_TEST_MODULE_NAME); + v4l2_m2m_release(dev->m2m_dev); + del_timer_sync(&dev->timer); + video_unregister_device(dev->vfd); + v4l2_device_unregister(&dev->v4l2_dev); + kfree(dev); + + return 0; +} + +static struct platform_driver m2mtest_pdrv = { + .probe = m2mtest_probe, + .remove = m2mtest_remove, + .driver = { + .name = MEM2MEM_NAME, + .owner = THIS_MODULE, + }, +}; + +static void __exit m2mtest_exit(void) +{ + platform_driver_unregister(&m2mtest_pdrv); + platform_device_unregister(&m2mtest_pdev); +} + +static int __init m2mtest_init(void) +{ + int ret; + + ret = platform_device_register(&m2mtest_pdev); + if (ret) + return ret; + + ret = platform_driver_register(&m2mtest_pdrv); + if (ret) + platform_device_unregister(&m2mtest_pdev); + + return 0; +} + +module_init(m2mtest_init); +module_exit(m2mtest_exit); + -- cgit v1.2.3-70-g09d2 From 1babcb460f2b87c20eb6860b9685a0dab636cc4b Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Tue, 23 Mar 2010 09:25:26 -0300 Subject: V4L/DVB: V4L: File handles This patch adds a list of v4l2_fh structures to every video_device. It allows using file handle related information in V4L2. The event interface is one example of such use. The use of v4l2_fh is not mandatory for drivers. Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Makefile | 2 +- drivers/media/video/v4l2-dev.c | 4 +++ drivers/media/video/v4l2-fh.c | 66 ++++++++++++++++++++++++++++++++++++++++++ include/media/v4l2-dev.h | 5 ++++ include/media/v4l2-fh.h | 63 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 drivers/media/video/v4l2-fh.c create mode 100644 include/media/v4l2-fh.h (limited to 'drivers/media/video') diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index a688a0f4387..c84175c5526 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -10,7 +10,7 @@ stkwebcam-objs := stk-webcam.o stk-sensor.o omap2cam-objs := omap24xxcam.o omap24xxcam-dma.o -videodev-objs := v4l2-dev.o v4l2-ioctl.o v4l2-device.o +videodev-objs := v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-fh.o # V4L2 core modules diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 70906991606..65a7b30524c 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c @@ -421,6 +421,10 @@ static int __video_register_device(struct video_device *vdev, int type, int nr, if (!vdev->release) return -EINVAL; + /* v4l2_fh support */ + spin_lock_init(&vdev->fh_lock); + INIT_LIST_HEAD(&vdev->fh_list); + /* Part 1: check device type */ switch (type) { case VFL_TYPE_GRABBER: diff --git a/drivers/media/video/v4l2-fh.c b/drivers/media/video/v4l2-fh.c new file mode 100644 index 00000000000..93ea0af5fac --- /dev/null +++ b/drivers/media/video/v4l2-fh.c @@ -0,0 +1,66 @@ +/* + * v4l2-fh.c + * + * V4L2 file handles. + * + * Copyright (C) 2009--2010 Nokia Corporation. + * + * Contact: Sakari Ailus + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#include +#include +#include + +int v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev) +{ + fh->vdev = vdev; + INIT_LIST_HEAD(&fh->list); + set_bit(V4L2_FL_USES_V4L2_FH, &fh->vdev->flags); + + return 0; +} +EXPORT_SYMBOL_GPL(v4l2_fh_init); + +void v4l2_fh_add(struct v4l2_fh *fh) +{ + unsigned long flags; + + spin_lock_irqsave(&fh->vdev->fh_lock, flags); + list_add(&fh->list, &fh->vdev->fh_list); + spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); +} +EXPORT_SYMBOL_GPL(v4l2_fh_add); + +void v4l2_fh_del(struct v4l2_fh *fh) +{ + unsigned long flags; + + spin_lock_irqsave(&fh->vdev->fh_lock, flags); + list_del_init(&fh->list); + spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); +} +EXPORT_SYMBOL_GPL(v4l2_fh_del); + +void v4l2_fh_exit(struct v4l2_fh *fh) +{ + if (fh->vdev == NULL) + return; + + fh->vdev = NULL; +} +EXPORT_SYMBOL_GPL(v4l2_fh_exit); diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h index 2dee93892ea..bebe44b03e0 100644 --- a/include/media/v4l2-dev.h +++ b/include/media/v4l2-dev.h @@ -32,6 +32,7 @@ struct v4l2_device; Drivers can clear this flag if they want to block all future device access. It is cleared by video_unregister_device. */ #define V4L2_FL_REGISTERED (0) +#define V4L2_FL_USES_V4L2_FH (1) struct v4l2_file_operations { struct module *owner; @@ -77,6 +78,10 @@ struct video_device /* attribute to differentiate multiple indices on one physical device */ int index; + /* V4L2 file handles */ + spinlock_t fh_lock; /* Lock for all v4l2_fhs */ + struct list_head fh_list; /* List of struct v4l2_fh */ + int debug; /* Activates debug level*/ /* Video standard vars */ diff --git a/include/media/v4l2-fh.h b/include/media/v4l2-fh.h new file mode 100644 index 00000000000..4aaa1508c8b --- /dev/null +++ b/include/media/v4l2-fh.h @@ -0,0 +1,63 @@ +/* + * v4l2-fh.h + * + * V4L2 file handle. Store per file handle data for the V4L2 + * framework. Using file handles is optional for the drivers. + * + * Copyright (C) 2009--2010 Nokia Corporation. + * + * Contact: Sakari Ailus + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#ifndef V4L2_FH_H +#define V4L2_FH_H + +#include + +struct video_device; + +struct v4l2_fh { + struct list_head list; + struct video_device *vdev; +}; + +/* + * Initialise the file handle. Parts of the V4L2 framework using the + * file handles should be initialised in this function. Must be called + * from driver's v4l2_file_operations->open() handler if the driver + * uses v4l2_fh. + */ +int v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev); +/* + * Add the fh to the list of file handles on a video_device. The file + * handle must be initialised first. + */ +void v4l2_fh_add(struct v4l2_fh *fh); +/* + * Remove file handle from the list of file handles. Must be called in + * v4l2_file_operations->release() handler if the driver uses v4l2_fh. + */ +void v4l2_fh_del(struct v4l2_fh *fh); +/* + * Release resources related to a file handle. Parts of the V4L2 + * framework using the v4l2_fh must release their resources here, too. + * Must be called in v4l2_file_operations->release() handler if the + * driver uses v4l2_fh. + */ +void v4l2_fh_exit(struct v4l2_fh *fh); + +#endif /* V4L2_EVENT_H */ -- cgit v1.2.3-70-g09d2 From fda1021477b390506ebed0225eaa6d31a903e2b7 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Wed, 24 Feb 2010 19:19:05 -0300 Subject: V4L/DVB: V4L: Events: Add new ioctls for events This patch adds a set of new ioctls to the V4L2 API. The ioctls conform to V4L2 Events RFC version 2.3: Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-compat-ioctl32.c | 3 +++ drivers/media/video/v4l2-ioctl.c | 3 +++ include/linux/videodev2.h | 26 ++++++++++++++++++++++++++ 3 files changed, 32 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c index f77f84bfe71..9004a5fe764 100644 --- a/drivers/media/video/v4l2-compat-ioctl32.c +++ b/drivers/media/video/v4l2-compat-ioctl32.c @@ -1086,6 +1086,9 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) case VIDIOC_QUERY_DV_PRESET: case VIDIOC_S_DV_TIMINGS: case VIDIOC_G_DV_TIMINGS: + case VIDIOC_DQEVENT: + case VIDIOC_SUBSCRIBE_EVENT: + case VIDIOC_UNSUBSCRIBE_EVENT: ret = do_video_ioctl(file, cmd, arg); break; diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 3da8d8f041d..2ceaa152a45 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -291,6 +291,9 @@ static const char *v4l2_ioctls[] = { [_IOC_NR(VIDIOC_QUERY_DV_PRESET)] = "VIDIOC_QUERY_DV_PRESET", [_IOC_NR(VIDIOC_S_DV_TIMINGS)] = "VIDIOC_S_DV_TIMINGS", [_IOC_NR(VIDIOC_G_DV_TIMINGS)] = "VIDIOC_G_DV_TIMINGS", + [_IOC_NR(VIDIOC_DQEVENT)] = "VIDIOC_DQEVENT", + [_IOC_NR(VIDIOC_SUBSCRIBE_EVENT)] = "VIDIOC_SUBSCRIBE_EVENT", + [_IOC_NR(VIDIOC_UNSUBSCRIBE_EVENT)] = "VIDIOC_UNSUBSCRIBE_EVENT", }; #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index e878056952c..0f627c5b986 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -1636,6 +1636,29 @@ struct v4l2_streamparm { } parm; }; +/* + * E V E N T S + */ + +struct v4l2_event { + __u32 type; + union { + __u8 data[64]; + } u; + __u32 pending; + __u32 sequence; + struct timespec timestamp; + __u32 reserved[9]; +}; + +struct v4l2_event_subscription { + __u32 type; + __u32 reserved[7]; +}; + +#define V4L2_EVENT_ALL 0 +#define V4L2_EVENT_PRIVATE_START 0x08000000 + /* * A D V A N C E D D E B U G G I N G * @@ -1758,6 +1781,9 @@ struct v4l2_dbg_chip_ident { #define VIDIOC_QUERY_DV_PRESET _IOR('V', 86, struct v4l2_dv_preset) #define VIDIOC_S_DV_TIMINGS _IOWR('V', 87, struct v4l2_dv_timings) #define VIDIOC_G_DV_TIMINGS _IOWR('V', 88, struct v4l2_dv_timings) +#define VIDIOC_DQEVENT _IOR('V', 89, struct v4l2_event) +#define VIDIOC_SUBSCRIBE_EVENT _IOW('V', 90, struct v4l2_event_subscription) +#define VIDIOC_UNSUBSCRIBE_EVENT _IOW('V', 91, struct v4l2_event_subscription) /* Reminder: when adding new ioctls please add support for them to drivers/media/video/v4l2-compat-ioctl32.c as well! */ -- cgit v1.2.3-70-g09d2 From c3b5b0241f620a356c97d8f43343e721c718806d Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Mon, 1 Mar 2010 05:14:18 -0300 Subject: V4L/DVB: V4L: Events: Add backend Add event handling backend to V4L2. The backend handles event subscription and delivery to file handles. Event subscriptions are based on file handle. Events may be delivered to all subscribed file handles on a device independent of where they originate from. Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Makefile | 3 +- drivers/media/video/v4l2-event.c | 290 +++++++++++++++++++++++++++++++++++++++ drivers/media/video/v4l2-fh.c | 6 +- include/media/v4l2-event.h | 67 +++++++++ include/media/v4l2-fh.h | 2 + 5 files changed, 366 insertions(+), 2 deletions(-) create mode 100644 drivers/media/video/v4l2-event.c create mode 100644 include/media/v4l2-event.h (limited to 'drivers/media/video') diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index c84175c5526..c96b2b1e2fd 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -10,7 +10,8 @@ stkwebcam-objs := stk-webcam.o stk-sensor.o omap2cam-objs := omap24xxcam.o omap24xxcam-dma.o -videodev-objs := v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-fh.o +videodev-objs := v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-fh.o \ + v4l2-event.o # V4L2 core modules diff --git a/drivers/media/video/v4l2-event.c b/drivers/media/video/v4l2-event.c new file mode 100644 index 00000000000..170e40f56cf --- /dev/null +++ b/drivers/media/video/v4l2-event.c @@ -0,0 +1,290 @@ +/* + * v4l2-event.c + * + * V4L2 events. + * + * Copyright (C) 2009--2010 Nokia Corporation. + * + * Contact: Sakari Ailus + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#include +#include +#include + +#include +#include + +int v4l2_event_init(struct v4l2_fh *fh) +{ + fh->events = kzalloc(sizeof(*fh->events), GFP_KERNEL); + if (fh->events == NULL) + return -ENOMEM; + + init_waitqueue_head(&fh->events->wait); + + INIT_LIST_HEAD(&fh->events->free); + INIT_LIST_HEAD(&fh->events->available); + INIT_LIST_HEAD(&fh->events->subscribed); + + fh->events->sequence = -1; + + return 0; +} + +int v4l2_event_alloc(struct v4l2_fh *fh, unsigned int n) +{ + struct v4l2_events *events = fh->events; + unsigned long flags; + + if (!events) { + WARN_ON(1); + return -ENOMEM; + } + + while (events->nallocated < n) { + struct v4l2_kevent *kev; + + kev = kzalloc(sizeof(*kev), GFP_KERNEL); + if (kev == NULL) + return -ENOMEM; + + spin_lock_irqsave(&fh->vdev->fh_lock, flags); + list_add_tail(&kev->list, &events->free); + events->nallocated++; + spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); + } + + return 0; +} +EXPORT_SYMBOL_GPL(v4l2_event_alloc); + +#define list_kfree(list, type, member) \ + while (!list_empty(list)) { \ + type *hi; \ + hi = list_first_entry(list, type, member); \ + list_del(&hi->member); \ + kfree(hi); \ + } + +void v4l2_event_free(struct v4l2_fh *fh) +{ + struct v4l2_events *events = fh->events; + + if (!events) + return; + + list_kfree(&events->free, struct v4l2_kevent, list); + list_kfree(&events->available, struct v4l2_kevent, list); + list_kfree(&events->subscribed, struct v4l2_subscribed_event, list); + + kfree(events); + fh->events = NULL; +} +EXPORT_SYMBOL_GPL(v4l2_event_free); + +static int __v4l2_event_dequeue(struct v4l2_fh *fh, struct v4l2_event *event) +{ + struct v4l2_events *events = fh->events; + struct v4l2_kevent *kev; + unsigned long flags; + + spin_lock_irqsave(&fh->vdev->fh_lock, flags); + + if (list_empty(&events->available)) { + spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); + return -ENOENT; + } + + WARN_ON(events->navailable == 0); + + kev = list_first_entry(&events->available, struct v4l2_kevent, list); + list_move(&kev->list, &events->free); + events->navailable--; + + kev->event.pending = events->navailable; + *event = kev->event; + + spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); + + return 0; +} + +int v4l2_event_dequeue(struct v4l2_fh *fh, struct v4l2_event *event, + int nonblocking) +{ + struct v4l2_events *events = fh->events; + int ret; + + if (nonblocking) + return __v4l2_event_dequeue(fh, event); + + do { + ret = wait_event_interruptible(events->wait, + events->navailable != 0); + if (ret < 0) + return ret; + + ret = __v4l2_event_dequeue(fh, event); + } while (ret == -ENOENT); + + return ret; +} + +/* Caller must hold fh->event->lock! */ +static struct v4l2_subscribed_event *v4l2_event_subscribed( + struct v4l2_fh *fh, u32 type) +{ + struct v4l2_events *events = fh->events; + struct v4l2_subscribed_event *sev; + + WARN_ON(!spin_is_locked(&fh->vdev->fh_lock)); + + list_for_each_entry(sev, &events->subscribed, list) { + if (sev->type == type) + return sev; + } + + return NULL; +} + +void v4l2_event_queue(struct video_device *vdev, const struct v4l2_event *ev) +{ + struct v4l2_fh *fh; + unsigned long flags; + struct timespec timestamp; + + ktime_get_ts(×tamp); + + spin_lock_irqsave(&vdev->fh_lock, flags); + + list_for_each_entry(fh, &vdev->fh_list, list) { + struct v4l2_events *events = fh->events; + struct v4l2_kevent *kev; + + /* Are we subscribed? */ + if (!v4l2_event_subscribed(fh, ev->type)) + continue; + + /* Increase event sequence number on fh. */ + events->sequence++; + + /* Do we have any free events? */ + if (list_empty(&events->free)) + continue; + + /* Take one and fill it. */ + kev = list_first_entry(&events->free, struct v4l2_kevent, list); + kev->event.type = ev->type; + kev->event.u = ev->u; + kev->event.timestamp = timestamp; + kev->event.sequence = events->sequence; + list_move_tail(&kev->list, &events->available); + + events->navailable++; + + wake_up_all(&events->wait); + } + + spin_unlock_irqrestore(&vdev->fh_lock, flags); +} +EXPORT_SYMBOL_GPL(v4l2_event_queue); + +int v4l2_event_pending(struct v4l2_fh *fh) +{ + return fh->events->navailable; +} +EXPORT_SYMBOL_GPL(v4l2_event_pending); + +int v4l2_event_subscribe(struct v4l2_fh *fh, + struct v4l2_event_subscription *sub) +{ + struct v4l2_events *events = fh->events; + struct v4l2_subscribed_event *sev; + unsigned long flags; + + if (fh->events == NULL) { + WARN_ON(1); + return -ENOMEM; + } + + sev = kmalloc(sizeof(*sev), GFP_KERNEL); + if (!sev) + return -ENOMEM; + + spin_lock_irqsave(&fh->vdev->fh_lock, flags); + + if (v4l2_event_subscribed(fh, sub->type) == NULL) { + INIT_LIST_HEAD(&sev->list); + sev->type = sub->type; + + list_add(&sev->list, &events->subscribed); + sev = NULL; + } + + spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); + + kfree(sev); + + return 0; +} +EXPORT_SYMBOL_GPL(v4l2_event_subscribe); + +static void v4l2_event_unsubscribe_all(struct v4l2_fh *fh) +{ + struct v4l2_events *events = fh->events; + struct v4l2_subscribed_event *sev; + unsigned long flags; + + do { + sev = NULL; + + spin_lock_irqsave(&fh->vdev->fh_lock, flags); + if (!list_empty(&events->subscribed)) { + sev = list_first_entry(&events->subscribed, + struct v4l2_subscribed_event, list); + list_del(&sev->list); + } + spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); + kfree(sev); + } while (sev); +} + +int v4l2_event_unsubscribe(struct v4l2_fh *fh, + struct v4l2_event_subscription *sub) +{ + struct v4l2_subscribed_event *sev; + unsigned long flags; + + if (sub->type == V4L2_EVENT_ALL) { + v4l2_event_unsubscribe_all(fh); + return 0; + } + + spin_lock_irqsave(&fh->vdev->fh_lock, flags); + + sev = v4l2_event_subscribed(fh, sub->type); + if (sev != NULL) + list_del(&sev->list); + + spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); + + kfree(sev); + + return 0; +} +EXPORT_SYMBOL_GPL(v4l2_event_unsubscribe); diff --git a/drivers/media/video/v4l2-fh.c b/drivers/media/video/v4l2-fh.c index 93ea0af5fac..aab2fb639ef 100644 --- a/drivers/media/video/v4l2-fh.c +++ b/drivers/media/video/v4l2-fh.c @@ -25,6 +25,8 @@ #include #include #include +#include +#include int v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev) { @@ -32,7 +34,7 @@ int v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev) INIT_LIST_HEAD(&fh->list); set_bit(V4L2_FL_USES_V4L2_FH, &fh->vdev->flags); - return 0; + return v4l2_event_init(fh); } EXPORT_SYMBOL_GPL(v4l2_fh_init); @@ -62,5 +64,7 @@ void v4l2_fh_exit(struct v4l2_fh *fh) return; fh->vdev = NULL; + + v4l2_event_free(fh); } EXPORT_SYMBOL_GPL(v4l2_fh_exit); diff --git a/include/media/v4l2-event.h b/include/media/v4l2-event.h new file mode 100644 index 00000000000..3b86177c8cd --- /dev/null +++ b/include/media/v4l2-event.h @@ -0,0 +1,67 @@ +/* + * v4l2-event.h + * + * V4L2 events. + * + * Copyright (C) 2009--2010 Nokia Corporation. + * + * Contact: Sakari Ailus + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#ifndef V4L2_EVENT_H +#define V4L2_EVENT_H + +#include +#include +#include + +struct v4l2_fh; +struct video_device; + +struct v4l2_kevent { + struct list_head list; + struct v4l2_event event; +}; + +struct v4l2_subscribed_event { + struct list_head list; + u32 type; +}; + +struct v4l2_events { + wait_queue_head_t wait; + struct list_head subscribed; /* Subscribed events */ + struct list_head free; /* Events ready for use */ + struct list_head available; /* Dequeueable event */ + unsigned int navailable; + unsigned int nallocated; /* Number of allocated events */ + u32 sequence; +}; + +int v4l2_event_init(struct v4l2_fh *fh); +int v4l2_event_alloc(struct v4l2_fh *fh, unsigned int n); +void v4l2_event_free(struct v4l2_fh *fh); +int v4l2_event_dequeue(struct v4l2_fh *fh, struct v4l2_event *event, + int nonblocking); +void v4l2_event_queue(struct video_device *vdev, const struct v4l2_event *ev); +int v4l2_event_pending(struct v4l2_fh *fh); +int v4l2_event_subscribe(struct v4l2_fh *fh, + struct v4l2_event_subscription *sub); +int v4l2_event_unsubscribe(struct v4l2_fh *fh, + struct v4l2_event_subscription *sub); + +#endif /* V4L2_EVENT_H */ diff --git a/include/media/v4l2-fh.h b/include/media/v4l2-fh.h index 4aaa1508c8b..1d72dde320b 100644 --- a/include/media/v4l2-fh.h +++ b/include/media/v4l2-fh.h @@ -29,10 +29,12 @@ #include struct video_device; +struct v4l2_events; struct v4l2_fh { struct list_head list; struct video_device *vdev; + struct v4l2_events *events; /* events, pending and subscribed */ }; /* -- cgit v1.2.3-70-g09d2 From d3d7c963562adad92e968df23c425ae964fe9ce2 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Sat, 27 Mar 2010 11:02:10 -0300 Subject: V4L/DVB: V4L: Events: Support event handling in do_ioctl Add support for event handling to do_ioctl. Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-fh.c | 11 ++++++++- drivers/media/video/v4l2-ioctl.c | 50 ++++++++++++++++++++++++++++++++++++++++ include/media/v4l2-ioctl.h | 7 ++++++ 3 files changed, 67 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/v4l2-fh.c b/drivers/media/video/v4l2-fh.c index aab2fb639ef..d78f184f40c 100644 --- a/drivers/media/video/v4l2-fh.c +++ b/drivers/media/video/v4l2-fh.c @@ -34,7 +34,16 @@ int v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev) INIT_LIST_HEAD(&fh->list); set_bit(V4L2_FL_USES_V4L2_FH, &fh->vdev->flags); - return v4l2_event_init(fh); + /* + * fh->events only needs to be initialized if the driver + * supports the VIDIOC_SUBSCRIBE_EVENT ioctl. + */ + if (vdev->ioctl_ops && vdev->ioctl_ops->vidioc_subscribe_event) + return v4l2_event_init(fh); + + fh->events = NULL; + + return 0; } EXPORT_SYMBOL_GPL(v4l2_fh_init); diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 2ceaa152a45..0eeceae5032 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -26,6 +26,8 @@ #endif #include #include +#include +#include #include #define dbgarg(cmd, fmt, arg...) \ @@ -1951,7 +1953,55 @@ static long __video_do_ioctl(struct file *file, } break; } + case VIDIOC_DQEVENT: + { + struct v4l2_event *ev = arg; + + if (!ops->vidioc_subscribe_event) + break; + + ret = v4l2_event_dequeue(fh, ev, file->f_flags & O_NONBLOCK); + if (ret < 0) { + dbgarg(cmd, "no pending events?"); + break; + } + dbgarg(cmd, + "pending=%d, type=0x%8.8x, sequence=%d, " + "timestamp=%lu.%9.9lu ", + ev->pending, ev->type, ev->sequence, + ev->timestamp.tv_sec, ev->timestamp.tv_nsec); + break; + } + case VIDIOC_SUBSCRIBE_EVENT: + { + struct v4l2_event_subscription *sub = arg; + if (!ops->vidioc_subscribe_event) + break; + + ret = ops->vidioc_subscribe_event(fh, sub); + if (ret < 0) { + dbgarg(cmd, "failed, ret=%ld", ret); + break; + } + dbgarg(cmd, "type=0x%8.8x", sub->type); + break; + } + case VIDIOC_UNSUBSCRIBE_EVENT: + { + struct v4l2_event_subscription *sub = arg; + + if (!ops->vidioc_unsubscribe_event) + break; + + ret = ops->vidioc_unsubscribe_event(fh, sub); + if (ret < 0) { + dbgarg(cmd, "failed, ret=%ld", ret); + break; + } + dbgarg(cmd, "type=0x%8.8x", sub->type); + break; + } default: { if (!ops->vidioc_default) diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h index e8ba0f2efba..06daa6e8e05 100644 --- a/include/media/v4l2-ioctl.h +++ b/include/media/v4l2-ioctl.h @@ -21,6 +21,8 @@ #include #endif +struct v4l2_fh; + struct v4l2_ioctl_ops { /* ioctl callbacks */ @@ -254,6 +256,11 @@ struct v4l2_ioctl_ops { int (*vidioc_g_dv_timings) (struct file *file, void *fh, struct v4l2_dv_timings *timings); + int (*vidioc_subscribe_event) (struct v4l2_fh *fh, + struct v4l2_event_subscription *sub); + int (*vidioc_unsubscribe_event)(struct v4l2_fh *fh, + struct v4l2_event_subscription *sub); + /* For other private ioctls */ long (*vidioc_default) (struct file *file, void *fh, int cmd, void *arg); -- cgit v1.2.3-70-g09d2 From 092501936fc128992456a086193746cf34642815 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 27 Mar 2010 14:10:13 -0300 Subject: V4L/DVB: ivtv: support the new events API Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtv-driver.h | 7 +++++ drivers/media/video/ivtv/ivtv-fileops.c | 53 +++++++++++++++++++++++++-------- drivers/media/video/ivtv/ivtv-ioctl.c | 24 +++++++++++++-- drivers/media/video/ivtv/ivtv-irq.c | 15 ++++++++-- drivers/media/video/ivtv/ivtv-streams.c | 5 ++++ 5 files changed, 87 insertions(+), 17 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h index 851f07de529..5b45fd2b264 100644 --- a/drivers/media/video/ivtv/ivtv-driver.h +++ b/drivers/media/video/ivtv/ivtv-driver.h @@ -63,6 +63,7 @@ #include #include #include +#include #include #include #include @@ -375,6 +376,7 @@ struct ivtv_stream { }; struct ivtv_open_id { + struct v4l2_fh fh; u32 open_id; /* unique ID for this file descriptor */ int type; /* stream type */ int yuv_frames; /* 1: started OUT_UDMA_YUV output mode */ @@ -382,6 +384,11 @@ struct ivtv_open_id { struct ivtv *itv; }; +static inline struct ivtv_open_id *fh2id(struct v4l2_fh *fh) +{ + return container_of(fh, struct ivtv_open_id, fh); +} + struct yuv_frame_info { u32 update; diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c index babcabd73c0..bee9605bd27 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ b/drivers/media/video/ivtv/ivtv-fileops.c @@ -32,6 +32,7 @@ #include "ivtv-yuv.h" #include "ivtv-ioctl.h" #include "ivtv-cards.h" +#include #include /* This function tries to claim the stream for a specific file descriptor. @@ -506,7 +507,7 @@ int ivtv_start_capture(struct ivtv_open_id *id) ssize_t ivtv_v4l2_read(struct file * filp, char __user *buf, size_t count, loff_t * pos) { - struct ivtv_open_id *id = filp->private_data; + struct ivtv_open_id *id = fh2id(filp->private_data); struct ivtv *itv = id->itv; struct ivtv_stream *s = &itv->streams[id->type]; int rc; @@ -541,7 +542,7 @@ int ivtv_start_decoding(struct ivtv_open_id *id, int speed) ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t count, loff_t *pos) { - struct ivtv_open_id *id = filp->private_data; + struct ivtv_open_id *id = fh2id(filp->private_data); struct ivtv *itv = id->itv; struct ivtv_stream *s = &itv->streams[id->type]; struct yuv_playback_info *yi = &itv->yuv_info; @@ -711,19 +712,31 @@ retry: unsigned int ivtv_v4l2_dec_poll(struct file *filp, poll_table *wait) { - struct ivtv_open_id *id = filp->private_data; + struct ivtv_open_id *id = fh2id(filp->private_data); struct ivtv *itv = id->itv; struct ivtv_stream *s = &itv->streams[id->type]; int res = 0; /* add stream's waitq to the poll list */ IVTV_DEBUG_HI_FILE("Decoder poll\n"); - poll_wait(filp, &s->waitq, wait); - set_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags); - if (test_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags) || - test_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags)) - res = POLLPRI; + /* If there are subscribed events, then only use the new event + API instead of the old video.h based API. */ + if (!list_empty(&id->fh.events->subscribed)) { + poll_wait(filp, &id->fh.events->wait, wait); + /* Turn off the old-style vsync events */ + clear_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags); + if (v4l2_event_pending(&id->fh)) + res = POLLPRI; + } else { + /* This is the old-style API which is here only for backwards + compatibility. */ + poll_wait(filp, &s->waitq, wait); + set_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags); + if (test_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags) || + test_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags)) + res = POLLPRI; + } /* Allow write if buffers are available for writing */ if (s->q_free.buffers) @@ -733,7 +746,7 @@ unsigned int ivtv_v4l2_dec_poll(struct file *filp, poll_table *wait) unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait) { - struct ivtv_open_id *id = filp->private_data; + struct ivtv_open_id *id = fh2id(filp->private_data); struct ivtv *itv = id->itv; struct ivtv_stream *s = &itv->streams[id->type]; int eof = test_bit(IVTV_F_S_STREAMOFF, &s->s_flags); @@ -833,13 +846,16 @@ static void ivtv_stop_decoding(struct ivtv_open_id *id, int flags, u64 pts) int ivtv_v4l2_close(struct file *filp) { - struct ivtv_open_id *id = filp->private_data; + struct v4l2_fh *fh = filp->private_data; + struct ivtv_open_id *id = fh2id(fh); struct ivtv *itv = id->itv; struct ivtv_stream *s = &itv->streams[id->type]; IVTV_DEBUG_FILE("close %s\n", s->name); v4l2_prio_close(&itv->prio, &id->prio); + v4l2_fh_del(fh); + v4l2_fh_exit(fh); /* Easy case first: this stream was never claimed by us */ if (s->id != id->open_id) { @@ -895,6 +911,7 @@ static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp) { struct ivtv *itv = s->itv; struct ivtv_open_id *item; + int res = 0; IVTV_DEBUG_FILE("open %s\n", s->name); @@ -915,17 +932,27 @@ static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp) } /* Allocate memory */ - item = kmalloc(sizeof(struct ivtv_open_id), GFP_KERNEL); + item = kzalloc(sizeof(struct ivtv_open_id), GFP_KERNEL); if (NULL == item) { IVTV_DEBUG_WARN("nomem on v4l2 open\n"); return -ENOMEM; } + v4l2_fh_init(&item->fh, s->vdev); + if (s->type == IVTV_DEC_STREAM_TYPE_YUV || + s->type == IVTV_DEC_STREAM_TYPE_MPG) { + res = v4l2_event_alloc(&item->fh, 60); + } + if (res < 0) { + v4l2_fh_exit(&item->fh); + kfree(item); + return res; + } item->itv = itv; item->type = s->type; v4l2_prio_open(&itv->prio, &item->prio); item->open_id = itv->open_id++; - filp->private_data = item; + filp->private_data = &item->fh; if (item->type == IVTV_ENC_STREAM_TYPE_RAD) { /* Try to claim this stream */ @@ -940,6 +967,7 @@ static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp) /* switching to radio while capture is in progress is not polite */ ivtv_release_stream(s); + v4l2_fh_exit(&item->fh); kfree(item); return -EBUSY; } @@ -970,6 +998,7 @@ static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp) 1080 * ((itv->yuv_info.v4l2_src_h + 31) & ~31); itv->yuv_info.stream_size = 0; } + v4l2_fh_add(&item->fh); return 0; } diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index 6422cf8f189..e95ebdeaa72 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -1452,6 +1453,18 @@ static int ivtv_overlay(struct file *file, void *fh, unsigned int on) return 0; } +static int ivtv_subscribe_event(struct v4l2_fh *fh, struct v4l2_event_subscription *sub) +{ + switch (sub->type) { + case V4L2_EVENT_VSYNC: + case V4L2_EVENT_EOS: + break; + default: + return -EINVAL; + } + return v4l2_event_subscribe(fh, sub); +} + static int ivtv_log_status(struct file *file, void *fh) { struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv; @@ -1560,7 +1573,7 @@ static int ivtv_log_status(struct file *file, void *fh) static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg) { - struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data; + struct ivtv_open_id *id = fh2id(filp->private_data); struct ivtv *itv = id->itv; int nonblocking = filp->f_flags & O_NONBLOCK; struct ivtv_stream *s = &itv->streams[id->type]; @@ -1820,7 +1833,7 @@ static long ivtv_serialized_ioctl(struct ivtv *itv, struct file *filp, unsigned int cmd, unsigned long arg) { struct video_device *vfd = video_devdata(filp); - struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data; + struct ivtv_open_id *id = fh2id(filp->private_data); long ret; /* check priority */ @@ -1852,10 +1865,13 @@ static long ivtv_serialized_ioctl(struct ivtv *itv, struct file *filp, long ivtv_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { - struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data; + struct ivtv_open_id *id = fh2id(filp->private_data); struct ivtv *itv = id->itv; long res; + /* DQEVENT can block, so this should not run with the serialize lock */ + if (cmd == VIDIOC_DQEVENT) + return ivtv_serialized_ioctl(itv, filp, cmd, arg); mutex_lock(&itv->serialize_lock); res = ivtv_serialized_ioctl(itv, filp, cmd, arg); mutex_unlock(&itv->serialize_lock); @@ -1926,6 +1942,8 @@ static const struct v4l2_ioctl_ops ivtv_ioctl_ops = { .vidioc_g_ext_ctrls = ivtv_g_ext_ctrls, .vidioc_s_ext_ctrls = ivtv_s_ext_ctrls, .vidioc_try_ext_ctrls = ivtv_try_ext_ctrls, + .vidioc_subscribe_event = ivtv_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, }; void ivtv_set_funcs(struct video_device *vdev) diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c index dbd46c5d697..fea1ec33b0d 100644 --- a/drivers/media/video/ivtv/ivtv-irq.c +++ b/drivers/media/video/ivtv/ivtv-irq.c @@ -25,6 +25,7 @@ #include "ivtv-mailbox.h" #include "ivtv-vbi.h" #include "ivtv-yuv.h" +#include #define DMA_MAGIC_COOKIE 0x000001fe @@ -778,6 +779,14 @@ static void ivtv_irq_vsync(struct ivtv *itv) } } if (frame != (itv->last_vsync_field & 1)) { + static const struct v4l2_event evtop = { + .type = V4L2_EVENT_VSYNC, + .u.vsync.field = V4L2_FIELD_TOP, + }; + static const struct v4l2_event evbottom = { + .type = V4L2_EVENT_VSYNC, + .u.vsync.field = V4L2_FIELD_BOTTOM, + }; struct ivtv_stream *s = ivtv_get_output_stream(itv); itv->last_vsync_field += 1; @@ -791,10 +800,12 @@ static void ivtv_irq_vsync(struct ivtv *itv) if (test_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags)) { set_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags); wake_up(&itv->event_waitq); + if (s) + wake_up(&s->waitq); } + if (s && s->vdev) + v4l2_event_queue(s->vdev, frame ? &evtop : &evbottom); wake_up(&itv->vsync_waitq); - if (s) - wake_up(&s->waitq); /* Send VBI to saa7127 */ if (frame && (itv->output_mode == OUT_PASSTHROUGH || diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c index 6917c497fb7..def507ee106 100644 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ b/drivers/media/video/ivtv/ivtv-streams.c @@ -42,6 +42,7 @@ #include "ivtv-yuv.h" #include "ivtv-cards.h" #include "ivtv-streams.h" +#include static const struct v4l2_file_operations ivtv_v4l2_enc_fops = { .owner = THIS_MODULE, @@ -840,6 +841,9 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end) int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts) { + static const struct v4l2_event ev = { + .type = V4L2_EVENT_EOS, + }; struct ivtv *itv = s->itv; if (s->vdev == NULL) @@ -891,6 +895,7 @@ int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts) set_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags); wake_up(&itv->event_waitq); + v4l2_event_queue(s->vdev, &ev); /* wake up wait queues */ wake_up(&s->waitq); -- cgit v1.2.3-70-g09d2 From 5c7ab6348e7b3fcca2b8ee548306c774472971e2 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Sun, 11 Apr 2010 10:41:49 -0300 Subject: V4L/DVB: V4L2: Add support for OMAP2/3 V4L2 display driver on top of DSS2 Features Supported - 1. Provides V4L2 user interface for the video pipelines of DSS 2. Basic streaming working on LCD, DVI and TV. 3. Works on latest DSS2 library from Tomi 4. Support for various pixel formats like YUV, UYVY, RGB32, RGB24, RGB565 5. Supports Alpha blending. 6. Supports Color keying both source and destination. 7. Supports rotation. 8. Supports cropping. 9. Supports Background color setting. 10. Allocated buffers to only needed size Signed-off-by: Vaibhav Hiremath Reviewed-by: Hans Verkuil Reviewed-by: Muralidharan Karicheri Signed-off-by: Murailidharan Karicheri Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 2 + drivers/media/video/Makefile | 2 + drivers/media/video/omap/Kconfig | 11 + drivers/media/video/omap/Makefile | 7 + drivers/media/video/omap/omap_vout.c | 2644 +++++++++++++++++++++++++++++++ drivers/media/video/omap/omap_voutdef.h | 147 ++ drivers/media/video/omap/omap_voutlib.c | 293 ++++ drivers/media/video/omap/omap_voutlib.h | 34 + 8 files changed, 3140 insertions(+) create mode 100644 drivers/media/video/omap/Kconfig create mode 100644 drivers/media/video/omap/Makefile create mode 100644 drivers/media/video/omap/omap_vout.c create mode 100644 drivers/media/video/omap/omap_voutdef.h create mode 100644 drivers/media/video/omap/omap_voutlib.c create mode 100644 drivers/media/video/omap/omap_voutlib.h (limited to 'drivers/media/video') diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 16decdd6e28..4500cd05434 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -631,6 +631,8 @@ config VIDEO_ISIF To compile this driver as a module, choose M here: the module will be called vpfe. +source "drivers/media/video/omap/Kconfig" + source "drivers/media/video/bt8xx/Kconfig" config VIDEO_PMS diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index c96b2b1e2fd..cc93859d316 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -179,6 +179,8 @@ obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o obj-$(CONFIG_ARCH_DAVINCI) += davinci/ +obj-$(CONFIG_ARCH_OMAP) += omap/ + EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core EXTRA_CFLAGS += -Idrivers/media/dvb/frontends EXTRA_CFLAGS += -Idrivers/media/common/tuners diff --git a/drivers/media/video/omap/Kconfig b/drivers/media/video/omap/Kconfig new file mode 100644 index 00000000000..97c53949ca8 --- /dev/null +++ b/drivers/media/video/omap/Kconfig @@ -0,0 +1,11 @@ +config VIDEO_OMAP2_VOUT + tristate "OMAP2/OMAP3 V4L2-Display driver" + depends on ARCH_OMAP24XX || ARCH_OMAP34XX + select VIDEOBUF_GEN + select VIDEOBUF_DMA_SG + select OMAP2_DSS + select OMAP2_VRAM + select OMAP2_VRFB + default n + ---help--- + V4L2 Display driver support for OMAP2/3 based boards. diff --git a/drivers/media/video/omap/Makefile b/drivers/media/video/omap/Makefile new file mode 100644 index 00000000000..b8bab00ad01 --- /dev/null +++ b/drivers/media/video/omap/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for the omap video device drivers. +# + +# OMAP2/3 Display driver +omap-vout-mod-objs := omap_vout.o omap_voutlib.o +obj-$(CONFIG_VIDEO_OMAP2_VOUT) += omap-vout-mod.o diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c new file mode 100644 index 00000000000..f2100671851 --- /dev/null +++ b/drivers/media/video/omap/omap_vout.c @@ -0,0 +1,2644 @@ +/* + * omap_vout.c + * + * Copyright (C) 2005-2010 Texas Instruments. + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + * + * Leveraged code from the OMAP2 camera driver + * Video-for-Linux (Version 2) camera capture driver for + * the OMAP24xx camera controller. + * + * Author: Andy Lowe (source@mvista.com) + * + * Copyright (C) 2004 MontaVista Software, Inc. + * Copyright (C) 2010 Texas Instruments. + * + * History: + * 20-APR-2006 Khasim Modified VRFB based Rotation, + * The image data is always read from 0 degree + * view and written + * to the virtual space of desired rotation angle + * 4-DEC-2006 Jian Changed to support better memory management + * + * 17-Nov-2008 Hardik Changed driver to use video_ioctl2 + * + * 23-Feb-2010 Vaibhav H Modified to use new DSS2 interface + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include "omap_voutlib.h" +#include "omap_voutdef.h" + +MODULE_AUTHOR("Texas Instruments"); +MODULE_DESCRIPTION("OMAP Video for Linux Video out driver"); +MODULE_LICENSE("GPL"); + + +/* Driver Configuration macros */ +#define VOUT_NAME "omap_vout" + +enum omap_vout_channels { + OMAP_VIDEO1, + OMAP_VIDEO2, +}; + +enum dma_channel_state { + DMA_CHAN_NOT_ALLOTED, + DMA_CHAN_ALLOTED, +}; + +#define QQVGA_WIDTH 160 +#define QQVGA_HEIGHT 120 + +/* Max Resolution supported by the driver */ +#define VID_MAX_WIDTH 1280 /* Largest width */ +#define VID_MAX_HEIGHT 720 /* Largest height */ + +/* Mimimum requirement is 2x2 for DSS */ +#define VID_MIN_WIDTH 2 +#define VID_MIN_HEIGHT 2 + +/* 2048 x 2048 is max res supported by OMAP display controller */ +#define MAX_PIXELS_PER_LINE 2048 + +#define VRFB_TX_TIMEOUT 1000 +#define VRFB_NUM_BUFS 4 + +/* Max buffer size tobe allocated during init */ +#define OMAP_VOUT_MAX_BUF_SIZE (VID_MAX_WIDTH*VID_MAX_HEIGHT*4) + +static struct videobuf_queue_ops video_vbq_ops; +/* Variables configurable through module params*/ +static u32 video1_numbuffers = 3; +static u32 video2_numbuffers = 3; +static u32 video1_bufsize = OMAP_VOUT_MAX_BUF_SIZE; +static u32 video2_bufsize = OMAP_VOUT_MAX_BUF_SIZE; +static u32 vid1_static_vrfb_alloc; +static u32 vid2_static_vrfb_alloc; +static int debug; + +/* Module parameters */ +module_param(video1_numbuffers, uint, S_IRUGO); +MODULE_PARM_DESC(video1_numbuffers, + "Number of buffers to be allocated at init time for Video1 device."); + +module_param(video2_numbuffers, uint, S_IRUGO); +MODULE_PARM_DESC(video2_numbuffers, + "Number of buffers to be allocated at init time for Video2 device."); + +module_param(video1_bufsize, uint, S_IRUGO); +MODULE_PARM_DESC(video1_bufsize, + "Size of the buffer to be allocated for video1 device"); + +module_param(video2_bufsize, uint, S_IRUGO); +MODULE_PARM_DESC(video2_bufsize, + "Size of the buffer to be allocated for video2 device"); + +module_param(vid1_static_vrfb_alloc, bool, S_IRUGO); +MODULE_PARM_DESC(vid1_static_vrfb_alloc, + "Static allocation of the VRFB buffer for video1 device"); + +module_param(vid2_static_vrfb_alloc, bool, S_IRUGO); +MODULE_PARM_DESC(vid2_static_vrfb_alloc, + "Static allocation of the VRFB buffer for video2 device"); + +module_param(debug, bool, S_IRUGO); +MODULE_PARM_DESC(debug, "Debug level (0-1)"); + +/* list of image formats supported by OMAP2 video pipelines */ +const static struct v4l2_fmtdesc omap_formats[] = { + { + /* Note: V4L2 defines RGB565 as: + * + * Byte 0 Byte 1 + * g2 g1 g0 r4 r3 r2 r1 r0 b4 b3 b2 b1 b0 g5 g4 g3 + * + * We interpret RGB565 as: + * + * Byte 0 Byte 1 + * g2 g1 g0 b4 b3 b2 b1 b0 r4 r3 r2 r1 r0 g5 g4 g3 + */ + .description = "RGB565, le", + .pixelformat = V4L2_PIX_FMT_RGB565, + }, + { + /* Note: V4L2 defines RGB32 as: RGB-8-8-8-8 we use + * this for RGB24 unpack mode, the last 8 bits are ignored + * */ + .description = "RGB32, le", + .pixelformat = V4L2_PIX_FMT_RGB32, + }, + { + /* Note: V4L2 defines RGB24 as: RGB-8-8-8 we use + * this for RGB24 packed mode + * + */ + .description = "RGB24, le", + .pixelformat = V4L2_PIX_FMT_RGB24, + }, + { + .description = "YUYV (YUV 4:2:2), packed", + .pixelformat = V4L2_PIX_FMT_YUYV, + }, + { + .description = "UYVY, packed", + .pixelformat = V4L2_PIX_FMT_UYVY, + }, +}; + +#define NUM_OUTPUT_FORMATS (ARRAY_SIZE(omap_formats)) + +/* + * Allocate buffers + */ +static unsigned long omap_vout_alloc_buffer(u32 buf_size, u32 *phys_addr) +{ + u32 order, size; + unsigned long virt_addr, addr; + + size = PAGE_ALIGN(buf_size); + order = get_order(size); + virt_addr = __get_free_pages(GFP_KERNEL | GFP_DMA, order); + addr = virt_addr; + + if (virt_addr) { + while (size > 0) { + SetPageReserved(virt_to_page(addr)); + addr += PAGE_SIZE; + size -= PAGE_SIZE; + } + } + *phys_addr = (u32) virt_to_phys((void *) virt_addr); + return virt_addr; +} + +/* + * Free buffers + */ +static void omap_vout_free_buffer(unsigned long virtaddr, u32 buf_size) +{ + u32 order, size; + unsigned long addr = virtaddr; + + size = PAGE_ALIGN(buf_size); + order = get_order(size); + + while (size > 0) { + ClearPageReserved(virt_to_page(addr)); + addr += PAGE_SIZE; + size -= PAGE_SIZE; + } + free_pages((unsigned long) virtaddr, order); +} + +/* + * Function for allocating video buffers + */ +static int omap_vout_allocate_vrfb_buffers(struct omap_vout_device *vout, + unsigned int *count, int startindex) +{ + int i, j; + + for (i = 0; i < *count; i++) { + if (!vout->smsshado_virt_addr[i]) { + vout->smsshado_virt_addr[i] = + omap_vout_alloc_buffer(vout->smsshado_size, + &vout->smsshado_phy_addr[i]); + } + if (!vout->smsshado_virt_addr[i] && startindex != -1) { + if (V4L2_MEMORY_MMAP == vout->memory && i >= startindex) + break; + } + if (!vout->smsshado_virt_addr[i]) { + for (j = 0; j < i; j++) { + omap_vout_free_buffer( + vout->smsshado_virt_addr[j], + vout->smsshado_size); + vout->smsshado_virt_addr[j] = 0; + vout->smsshado_phy_addr[j] = 0; + } + *count = 0; + return -ENOMEM; + } + memset((void *) vout->smsshado_virt_addr[i], 0, + vout->smsshado_size); + } + return 0; +} + +/* + * Try format + */ +static int omap_vout_try_format(struct v4l2_pix_format *pix) +{ + int ifmt, bpp = 0; + + pix->height = clamp(pix->height, (u32)VID_MIN_HEIGHT, + (u32)VID_MAX_HEIGHT); + pix->width = clamp(pix->width, (u32)VID_MIN_WIDTH, (u32)VID_MAX_WIDTH); + + for (ifmt = 0; ifmt < NUM_OUTPUT_FORMATS; ifmt++) { + if (pix->pixelformat == omap_formats[ifmt].pixelformat) + break; + } + + if (ifmt == NUM_OUTPUT_FORMATS) + ifmt = 0; + + pix->pixelformat = omap_formats[ifmt].pixelformat; + pix->field = V4L2_FIELD_ANY; + pix->priv = 0; + + switch (pix->pixelformat) { + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_UYVY: + default: + pix->colorspace = V4L2_COLORSPACE_JPEG; + bpp = YUYV_BPP; + break; + case V4L2_PIX_FMT_RGB565: + case V4L2_PIX_FMT_RGB565X: + pix->colorspace = V4L2_COLORSPACE_SRGB; + bpp = RGB565_BPP; + break; + case V4L2_PIX_FMT_RGB24: + pix->colorspace = V4L2_COLORSPACE_SRGB; + bpp = RGB24_BPP; + break; + case V4L2_PIX_FMT_RGB32: + case V4L2_PIX_FMT_BGR32: + pix->colorspace = V4L2_COLORSPACE_SRGB; + bpp = RGB32_BPP; + break; + } + pix->bytesperline = pix->width * bpp; + pix->sizeimage = pix->bytesperline * pix->height; + + return bpp; +} + +/* + * omap_vout_uservirt_to_phys: This inline function is used to convert user + * space virtual address to physical address. + */ +static u32 omap_vout_uservirt_to_phys(u32 virtp) +{ + unsigned long physp = 0; + struct vm_area_struct *vma; + struct mm_struct *mm = current->mm; + + vma = find_vma(mm, virtp); + /* For kernel direct-mapped memory, take the easy way */ + if (virtp >= PAGE_OFFSET) { + physp = virt_to_phys((void *) virtp); + } else if (vma && (vma->vm_flags & VM_IO) && vma->vm_pgoff) { + /* this will catch, kernel-allocated, mmaped-to-usermode + addresses */ + physp = (vma->vm_pgoff << PAGE_SHIFT) + (virtp - vma->vm_start); + } else { + /* otherwise, use get_user_pages() for general userland pages */ + int res, nr_pages = 1; + struct page *pages; + down_read(¤t->mm->mmap_sem); + + res = get_user_pages(current, current->mm, virtp, nr_pages, 1, + 0, &pages, NULL); + up_read(¤t->mm->mmap_sem); + + if (res == nr_pages) { + physp = __pa(page_address(&pages[0]) + + (virtp & ~PAGE_MASK)); + } else { + printk(KERN_WARNING VOUT_NAME + "get_user_pages failed\n"); + return 0; + } + } + + return physp; +} + +/* + * Wakes up the application once the DMA transfer to VRFB space is completed. + */ +static void omap_vout_vrfb_dma_tx_callback(int lch, u16 ch_status, void *data) +{ + struct vid_vrfb_dma *t = (struct vid_vrfb_dma *) data; + + t->tx_status = 1; + wake_up_interruptible(&t->wait); +} + +/* + * Release the VRFB context once the module exits + */ +static void omap_vout_release_vrfb(struct omap_vout_device *vout) +{ + int i; + + for (i = 0; i < VRFB_NUM_BUFS; i++) + omap_vrfb_release_ctx(&vout->vrfb_context[i]); + + if (vout->vrfb_dma_tx.req_status == DMA_CHAN_ALLOTED) { + vout->vrfb_dma_tx.req_status = DMA_CHAN_NOT_ALLOTED; + omap_free_dma(vout->vrfb_dma_tx.dma_ch); + } +} + +/* + * Return true if rotation is 90 or 270 + */ +static inline int rotate_90_or_270(const struct omap_vout_device *vout) +{ + return (vout->rotation == dss_rotation_90_degree || + vout->rotation == dss_rotation_270_degree); +} + +/* + * Return true if rotation is enabled + */ +static inline int rotation_enabled(const struct omap_vout_device *vout) +{ + return vout->rotation || vout->mirror; +} + +/* + * Reverse the rotation degree if mirroring is enabled + */ +static inline int calc_rotation(const struct omap_vout_device *vout) +{ + if (!vout->mirror) + return vout->rotation; + + switch (vout->rotation) { + case dss_rotation_90_degree: + return dss_rotation_270_degree; + case dss_rotation_270_degree: + return dss_rotation_90_degree; + case dss_rotation_180_degree: + return dss_rotation_0_degree; + default: + return dss_rotation_180_degree; + } +} + +/* + * Free the V4L2 buffers + */ +static void omap_vout_free_buffers(struct omap_vout_device *vout) +{ + int i, numbuffers; + + /* Allocate memory for the buffers */ + numbuffers = (vout->vid) ? video2_numbuffers : video1_numbuffers; + vout->buffer_size = (vout->vid) ? video2_bufsize : video1_bufsize; + + for (i = 0; i < numbuffers; i++) { + omap_vout_free_buffer(vout->buf_virt_addr[i], + vout->buffer_size); + vout->buf_phy_addr[i] = 0; + vout->buf_virt_addr[i] = 0; + } +} + +/* + * Free VRFB buffers + */ +static void omap_vout_free_vrfb_buffers(struct omap_vout_device *vout) +{ + int j; + + for (j = 0; j < VRFB_NUM_BUFS; j++) { + omap_vout_free_buffer(vout->smsshado_virt_addr[j], + vout->smsshado_size); + vout->smsshado_virt_addr[j] = 0; + vout->smsshado_phy_addr[j] = 0; + } +} + +/* + * Allocate the buffers for the VRFB space. Data is copied from V4L2 + * buffers to the VRFB buffers using the DMA engine. + */ +static int omap_vout_vrfb_buffer_setup(struct omap_vout_device *vout, + unsigned int *count, unsigned int startindex) +{ + int i; + bool yuv_mode; + + /* Allocate the VRFB buffers only if the buffers are not + * allocated during init time. + */ + if ((rotation_enabled(vout)) && !vout->vrfb_static_allocation) + if (omap_vout_allocate_vrfb_buffers(vout, count, startindex)) + return -ENOMEM; + + if (vout->dss_mode == OMAP_DSS_COLOR_YUV2 || + vout->dss_mode == OMAP_DSS_COLOR_UYVY) + yuv_mode = true; + else + yuv_mode = false; + + for (i = 0; i < *count; i++) + omap_vrfb_setup(&vout->vrfb_context[i], + vout->smsshado_phy_addr[i], vout->pix.width, + vout->pix.height, vout->bpp, yuv_mode); + + return 0; +} + +/* + * Convert V4L2 rotation to DSS rotation + * V4L2 understand 0, 90, 180, 270. + * Convert to 0, 1, 2 and 3 repsectively for DSS + */ +static int v4l2_rot_to_dss_rot(int v4l2_rotation, + enum dss_rotation *rotation, bool mirror) +{ + int ret = 0; + + switch (v4l2_rotation) { + case 90: + *rotation = dss_rotation_90_degree; + break; + case 180: + *rotation = dss_rotation_180_degree; + break; + case 270: + *rotation = dss_rotation_270_degree; + break; + case 0: + *rotation = dss_rotation_0_degree; + break; + default: + ret = -EINVAL; + } + return ret; +} + +/* + * Calculate the buffer offsets from which the streaming should + * start. This offset calculation is mainly required because of + * the VRFB 32 pixels alignment with rotation. + */ +static int omap_vout_calculate_offset(struct omap_vout_device *vout) +{ + struct omap_overlay *ovl; + enum dss_rotation rotation; + struct omapvideo_info *ovid; + bool mirroring = vout->mirror; + struct omap_dss_device *cur_display; + struct v4l2_rect *crop = &vout->crop; + struct v4l2_pix_format *pix = &vout->pix; + int *cropped_offset = &vout->cropped_offset; + int vr_ps = 1, ps = 2, temp_ps = 2; + int offset = 0, ctop = 0, cleft = 0, line_length = 0; + + ovid = &vout->vid_info; + ovl = ovid->overlays[0]; + /* get the display device attached to the overlay */ + if (!ovl->manager || !ovl->manager->device) + return -1; + + cur_display = ovl->manager->device; + rotation = calc_rotation(vout); + + if (V4L2_PIX_FMT_YUYV == pix->pixelformat || + V4L2_PIX_FMT_UYVY == pix->pixelformat) { + if (rotation_enabled(vout)) { + /* + * ps - Actual pixel size for YUYV/UYVY for + * VRFB/Mirroring is 4 bytes + * vr_ps - Virtually pixel size for YUYV/UYVY is + * 2 bytes + */ + ps = 4; + vr_ps = 2; + } else { + ps = 2; /* otherwise the pixel size is 2 byte */ + } + } else if (V4L2_PIX_FMT_RGB32 == pix->pixelformat) { + ps = 4; + } else if (V4L2_PIX_FMT_RGB24 == pix->pixelformat) { + ps = 3; + } + vout->ps = ps; + vout->vr_ps = vr_ps; + + if (rotation_enabled(vout)) { + line_length = MAX_PIXELS_PER_LINE; + ctop = (pix->height - crop->height) - crop->top; + cleft = (pix->width - crop->width) - crop->left; + } else { + line_length = pix->width; + } + vout->line_length = line_length; + switch (rotation) { + case dss_rotation_90_degree: + offset = vout->vrfb_context[0].yoffset * + vout->vrfb_context[0].bytespp; + temp_ps = ps / vr_ps; + if (mirroring == 0) { + *cropped_offset = offset + line_length * + temp_ps * cleft + crop->top * temp_ps; + } else { + *cropped_offset = offset + line_length * temp_ps * + cleft + crop->top * temp_ps + (line_length * + ((crop->width / (vr_ps)) - 1) * ps); + } + break; + case dss_rotation_180_degree: + offset = ((MAX_PIXELS_PER_LINE * vout->vrfb_context[0].yoffset * + vout->vrfb_context[0].bytespp) + + (vout->vrfb_context[0].xoffset * + vout->vrfb_context[0].bytespp)); + if (mirroring == 0) { + *cropped_offset = offset + (line_length * ps * ctop) + + (cleft / vr_ps) * ps; + + } else { + *cropped_offset = offset + (line_length * ps * ctop) + + (cleft / vr_ps) * ps + (line_length * + (crop->height - 1) * ps); + } + break; + case dss_rotation_270_degree: + offset = MAX_PIXELS_PER_LINE * vout->vrfb_context[0].xoffset * + vout->vrfb_context[0].bytespp; + temp_ps = ps / vr_ps; + if (mirroring == 0) { + *cropped_offset = offset + line_length * + temp_ps * crop->left + ctop * ps; + } else { + *cropped_offset = offset + line_length * + temp_ps * crop->left + ctop * ps + + (line_length * ((crop->width / vr_ps) - 1) * + ps); + } + break; + case dss_rotation_0_degree: + if (mirroring == 0) { + *cropped_offset = (line_length * ps) * + crop->top + (crop->left / vr_ps) * ps; + } else { + *cropped_offset = (line_length * ps) * + crop->top + (crop->left / vr_ps) * ps + + (line_length * (crop->height - 1) * ps); + } + break; + default: + *cropped_offset = (line_length * ps * crop->top) / + vr_ps + (crop->left * ps) / vr_ps + + ((crop->width / vr_ps) - 1) * ps; + break; + } + v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "%s Offset:%x\n", + __func__, *cropped_offset); + return 0; +} + +/* + * Convert V4L2 pixel format to DSS pixel format + */ +static enum omap_color_mode video_mode_to_dss_mode(struct omap_vout_device + *vout) +{ + struct omap_overlay *ovl; + struct omapvideo_info *ovid; + struct v4l2_pix_format *pix = &vout->pix; + enum omap_color_mode mode; + + ovid = &vout->vid_info; + ovl = ovid->overlays[0]; + + switch (pix->pixelformat) { + case 0: + break; + case V4L2_PIX_FMT_YUYV: + mode = OMAP_DSS_COLOR_YUV2; + break; + case V4L2_PIX_FMT_UYVY: + mode = OMAP_DSS_COLOR_UYVY; + break; + case V4L2_PIX_FMT_RGB565: + mode = OMAP_DSS_COLOR_RGB16; + break; + case V4L2_PIX_FMT_RGB24: + mode = OMAP_DSS_COLOR_RGB24P; + break; + case V4L2_PIX_FMT_RGB32: + mode = (ovl->id == OMAP_DSS_VIDEO1) ? + OMAP_DSS_COLOR_RGB24U : OMAP_DSS_COLOR_ARGB32; + break; + case V4L2_PIX_FMT_BGR32: + mode = OMAP_DSS_COLOR_RGBX32; + break; + default: + mode = -EINVAL; + } + return mode; +} + +/* + * Setup the overlay + */ +int omapvid_setup_overlay(struct omap_vout_device *vout, + struct omap_overlay *ovl, int posx, int posy, int outw, + int outh, u32 addr) +{ + int ret = 0; + struct omap_overlay_info info; + int cropheight, cropwidth, pixheight, pixwidth; + + if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0 && + (outw != vout->pix.width || outh != vout->pix.height)) { + ret = -EINVAL; + goto setup_ovl_err; + } + + vout->dss_mode = video_mode_to_dss_mode(vout); + if (vout->dss_mode == -EINVAL) { + ret = -EINVAL; + goto setup_ovl_err; + } + + /* Setup the input plane parameters according to + * rotation value selected. + */ + if (rotate_90_or_270(vout)) { + cropheight = vout->crop.width; + cropwidth = vout->crop.height; + pixheight = vout->pix.width; + pixwidth = vout->pix.height; + } else { + cropheight = vout->crop.height; + cropwidth = vout->crop.width; + pixheight = vout->pix.height; + pixwidth = vout->pix.width; + } + + ovl->get_overlay_info(ovl, &info); + info.paddr = addr; + info.vaddr = NULL; + info.width = cropwidth; + info.height = cropheight; + info.color_mode = vout->dss_mode; + info.mirror = vout->mirror; + info.pos_x = posx; + info.pos_y = posy; + info.out_width = outw; + info.out_height = outh; + info.global_alpha = vout->win.global_alpha; + if (!rotation_enabled(vout)) { + info.rotation = 0; + info.rotation_type = OMAP_DSS_ROT_DMA; + info.screen_width = pixwidth; + } else { + info.rotation = vout->rotation; + info.rotation_type = OMAP_DSS_ROT_VRFB; + info.screen_width = 2048; + } + + v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, + "%s enable=%d addr=%x width=%d\n height=%d color_mode=%d\n" + "rotation=%d mirror=%d posx=%d posy=%d out_width = %d \n" + "out_height=%d rotation_type=%d screen_width=%d\n", + __func__, info.enabled, info.paddr, info.width, info.height, + info.color_mode, info.rotation, info.mirror, info.pos_x, + info.pos_y, info.out_width, info.out_height, info.rotation_type, + info.screen_width); + + ret = ovl->set_overlay_info(ovl, &info); + if (ret) + goto setup_ovl_err; + + return 0; + +setup_ovl_err: + v4l2_warn(&vout->vid_dev->v4l2_dev, "setup_overlay failed\n"); + return ret; +} + +/* + * Initialize the overlay structure + */ +int omapvid_init(struct omap_vout_device *vout, u32 addr) +{ + int ret = 0, i; + struct v4l2_window *win; + struct omap_overlay *ovl; + int posx, posy, outw, outh, temp; + struct omap_video_timings *timing; + struct omapvideo_info *ovid = &vout->vid_info; + + win = &vout->win; + for (i = 0; i < ovid->num_overlays; i++) { + ovl = ovid->overlays[i]; + if (!ovl->manager || !ovl->manager->device) + return -EINVAL; + + timing = &ovl->manager->device->panel.timings; + + outw = win->w.width; + outh = win->w.height; + switch (vout->rotation) { + case dss_rotation_90_degree: + /* Invert the height and width for 90 + * and 270 degree rotation + */ + temp = outw; + outw = outh; + outh = temp; + posy = (timing->y_res - win->w.width) - win->w.left; + posx = win->w.top; + break; + + case dss_rotation_180_degree: + posx = (timing->x_res - win->w.width) - win->w.left; + posy = (timing->y_res - win->w.height) - win->w.top; + break; + + case dss_rotation_270_degree: + temp = outw; + outw = outh; + outh = temp; + posy = win->w.left; + posx = (timing->x_res - win->w.height) - win->w.top; + break; + + default: + posx = win->w.left; + posy = win->w.top; + break; + } + + ret = omapvid_setup_overlay(vout, ovl, posx, posy, + outw, outh, addr); + if (ret) + goto omapvid_init_err; + } + return 0; + +omapvid_init_err: + v4l2_warn(&vout->vid_dev->v4l2_dev, "apply_changes failed\n"); + return ret; +} + +/* + * Apply the changes set the go bit of DSS + */ +int omapvid_apply_changes(struct omap_vout_device *vout) +{ + int i; + struct omap_overlay *ovl; + struct omapvideo_info *ovid = &vout->vid_info; + + for (i = 0; i < ovid->num_overlays; i++) { + ovl = ovid->overlays[i]; + if (!ovl->manager || !ovl->manager->device) + return -EINVAL; + ovl->manager->apply(ovl->manager); + } + + return 0; +} + +void omap_vout_isr(void *arg, unsigned int irqstatus) +{ + int ret; + u32 addr, fid; + struct omap_overlay *ovl; + struct timeval timevalue; + struct omapvideo_info *ovid; + struct omap_dss_device *cur_display; + struct omap_vout_device *vout = (struct omap_vout_device *)arg; + + if (!vout->streaming) + return; + + ovid = &vout->vid_info; + ovl = ovid->overlays[0]; + /* get the display device attached to the overlay */ + if (!ovl->manager || !ovl->manager->device) + return; + + cur_display = ovl->manager->device; + + spin_lock(&vout->vbq_lock); + do_gettimeofday(&timevalue); + if (cur_display->type == OMAP_DISPLAY_TYPE_DPI) { + if (!(irqstatus & DISPC_IRQ_VSYNC)) + goto vout_isr_err; + + if (!vout->first_int && (vout->cur_frm != vout->next_frm)) { + vout->cur_frm->ts = timevalue; + vout->cur_frm->state = VIDEOBUF_DONE; + wake_up_interruptible(&vout->cur_frm->done); + vout->cur_frm = vout->next_frm; + } + vout->first_int = 0; + if (list_empty(&vout->dma_queue)) + goto vout_isr_err; + + vout->next_frm = list_entry(vout->dma_queue.next, + struct videobuf_buffer, queue); + list_del(&vout->next_frm->queue); + + vout->next_frm->state = VIDEOBUF_ACTIVE; + + addr = (unsigned long) vout->queued_buf_addr[vout->next_frm->i] + + vout->cropped_offset; + + /* First save the configuration in ovelray structure */ + ret = omapvid_init(vout, addr); + if (ret) + printk(KERN_ERR VOUT_NAME + "failed to set overlay info\n"); + /* Enable the pipeline and set the Go bit */ + ret = omapvid_apply_changes(vout); + if (ret) + printk(KERN_ERR VOUT_NAME "failed to change mode\n"); + } else { + + if (vout->first_int) { + vout->first_int = 0; + goto vout_isr_err; + } + if (irqstatus & DISPC_IRQ_EVSYNC_ODD) + fid = 1; + else if (irqstatus & DISPC_IRQ_EVSYNC_EVEN) + fid = 0; + else + goto vout_isr_err; + + vout->field_id ^= 1; + if (fid != vout->field_id) { + if (0 == fid) + vout->field_id = fid; + + goto vout_isr_err; + } + if (0 == fid) { + if (vout->cur_frm == vout->next_frm) + goto vout_isr_err; + + vout->cur_frm->ts = timevalue; + vout->cur_frm->state = VIDEOBUF_DONE; + wake_up_interruptible(&vout->cur_frm->done); + vout->cur_frm = vout->next_frm; + } else if (1 == fid) { + if (list_empty(&vout->dma_queue) || + (vout->cur_frm != vout->next_frm)) + goto vout_isr_err; + + vout->next_frm = list_entry(vout->dma_queue.next, + struct videobuf_buffer, queue); + list_del(&vout->next_frm->queue); + + vout->next_frm->state = VIDEOBUF_ACTIVE; + addr = (unsigned long) + vout->queued_buf_addr[vout->next_frm->i] + + vout->cropped_offset; + /* First save the configuration in ovelray structure */ + ret = omapvid_init(vout, addr); + if (ret) + printk(KERN_ERR VOUT_NAME + "failed to set overlay info\n"); + /* Enable the pipeline and set the Go bit */ + ret = omapvid_apply_changes(vout); + if (ret) + printk(KERN_ERR VOUT_NAME + "failed to change mode\n"); + } + + } + +vout_isr_err: + spin_unlock(&vout->vbq_lock); +} + + +/* Video buffer call backs */ + +/* + * Buffer setup function is called by videobuf layer when REQBUF ioctl is + * called. This is used to setup buffers and return size and count of + * buffers allocated. After the call to this buffer, videobuf layer will + * setup buffer queue depending on the size and count of buffers + */ +static int omap_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count, + unsigned int *size) +{ + int startindex = 0, i, j; + u32 phy_addr = 0, virt_addr = 0; + struct omap_vout_device *vout = q->priv_data; + + if (!vout) + return -EINVAL; + + if (V4L2_BUF_TYPE_VIDEO_OUTPUT != q->type) + return -EINVAL; + + startindex = (vout->vid == OMAP_VIDEO1) ? + video1_numbuffers : video2_numbuffers; + if (V4L2_MEMORY_MMAP == vout->memory && *count < startindex) + *count = startindex; + + if ((rotation_enabled(vout)) && *count > VRFB_NUM_BUFS) + *count = VRFB_NUM_BUFS; + + /* If rotation is enabled, allocate memory for VRFB space also */ + if (rotation_enabled(vout)) + if (omap_vout_vrfb_buffer_setup(vout, count, startindex)) + return -ENOMEM; + + if (V4L2_MEMORY_MMAP != vout->memory) + return 0; + + /* Now allocated the V4L2 buffers */ + *size = PAGE_ALIGN(vout->pix.width * vout->pix.height * vout->bpp); + startindex = (vout->vid == OMAP_VIDEO1) ? + video1_numbuffers : video2_numbuffers; + + for (i = startindex; i < *count; i++) { + vout->buffer_size = *size; + + virt_addr = omap_vout_alloc_buffer(vout->buffer_size, + &phy_addr); + if (!virt_addr) { + if (!rotation_enabled(vout)) + break; + /* Free the VRFB buffers if no space for V4L2 buffers */ + for (j = i; j < *count; j++) { + omap_vout_free_buffer( + vout->smsshado_virt_addr[j], + vout->smsshado_size); + vout->smsshado_virt_addr[j] = 0; + vout->smsshado_phy_addr[j] = 0; + } + } + vout->buf_virt_addr[i] = virt_addr; + vout->buf_phy_addr[i] = phy_addr; + } + *count = vout->buffer_allocated = i; + + return 0; +} + +/* + * Free the V4L2 buffers additionally allocated than default + * number of buffers and free all the VRFB buffers + */ +static void omap_vout_free_allbuffers(struct omap_vout_device *vout) +{ + int num_buffers = 0, i; + + num_buffers = (vout->vid == OMAP_VIDEO1) ? + video1_numbuffers : video2_numbuffers; + + for (i = num_buffers; i < vout->buffer_allocated; i++) { + if (vout->buf_virt_addr[i]) + omap_vout_free_buffer(vout->buf_virt_addr[i], + vout->buffer_size); + + vout->buf_virt_addr[i] = 0; + vout->buf_phy_addr[i] = 0; + } + /* Free the VRFB buffers only if they are allocated + * during reqbufs. Don't free if init time allocated + */ + if (!vout->vrfb_static_allocation) { + for (i = 0; i < VRFB_NUM_BUFS; i++) { + if (vout->smsshado_virt_addr[i]) { + omap_vout_free_buffer( + vout->smsshado_virt_addr[i], + vout->smsshado_size); + vout->smsshado_virt_addr[i] = 0; + vout->smsshado_phy_addr[i] = 0; + } + } + } + vout->buffer_allocated = num_buffers; +} + +/* + * This function will be called when VIDIOC_QBUF ioctl is called. + * It prepare buffers before give out for the display. This function + * converts user space virtual address into physical address if userptr memory + * exchange mechanism is used. If rotation is enabled, it copies entire + * buffer into VRFB memory space before giving it to the DSS. + */ +static int omap_vout_buffer_prepare(struct videobuf_queue *q, + struct videobuf_buffer *vb, + enum v4l2_field field) +{ + struct vid_vrfb_dma *tx; + enum dss_rotation rotation; + struct videobuf_dmabuf *dmabuf = NULL; + struct omap_vout_device *vout = q->priv_data; + u32 dest_frame_index = 0, src_element_index = 0; + u32 dest_element_index = 0, src_frame_index = 0; + u32 elem_count = 0, frame_count = 0, pixsize = 2; + + if (VIDEOBUF_NEEDS_INIT == vb->state) { + vb->width = vout->pix.width; + vb->height = vout->pix.height; + vb->size = vb->width * vb->height * vout->bpp; + vb->field = field; + } + vb->state = VIDEOBUF_PREPARED; + /* if user pointer memory mechanism is used, get the physical + * address of the buffer + */ + if (V4L2_MEMORY_USERPTR == vb->memory) { + if (0 == vb->baddr) + return -EINVAL; + /* Virtual address */ + /* priv points to struct videobuf_pci_sg_memory. But we went + * pointer to videobuf_dmabuf, which is member of + * videobuf_pci_sg_memory */ + dmabuf = videobuf_to_dma(q->bufs[vb->i]); + dmabuf->vmalloc = (void *) vb->baddr; + + /* Physical address */ + dmabuf->bus_addr = + (dma_addr_t) omap_vout_uservirt_to_phys(vb->baddr); + } + + if (!rotation_enabled(vout)) { + dmabuf = videobuf_to_dma(q->bufs[vb->i]); + vout->queued_buf_addr[vb->i] = (u8 *) dmabuf->bus_addr; + return 0; + } + dmabuf = videobuf_to_dma(q->bufs[vb->i]); + /* If rotation is enabled, copy input buffer into VRFB + * memory space using DMA. We are copying input buffer + * into VRFB memory space of desired angle and DSS will + * read image VRFB memory for 0 degree angle + */ + pixsize = vout->bpp * vout->vrfb_bpp; + /* + * DMA transfer in double index mode + */ + + /* Frame index */ + dest_frame_index = ((MAX_PIXELS_PER_LINE * pixsize) - + (vout->pix.width * vout->bpp)) + 1; + + /* Source and destination parameters */ + src_element_index = 0; + src_frame_index = 0; + dest_element_index = 1; + /* Number of elements per frame */ + elem_count = vout->pix.width * vout->bpp; + frame_count = vout->pix.height; + tx = &vout->vrfb_dma_tx; + tx->tx_status = 0; + omap_set_dma_transfer_params(tx->dma_ch, OMAP_DMA_DATA_TYPE_S32, + (elem_count / 4), frame_count, OMAP_DMA_SYNC_ELEMENT, + tx->dev_id, 0x0); + /* src_port required only for OMAP1 */ + omap_set_dma_src_params(tx->dma_ch, 0, OMAP_DMA_AMODE_POST_INC, + dmabuf->bus_addr, src_element_index, src_frame_index); + /*set dma source burst mode for VRFB */ + omap_set_dma_src_burst_mode(tx->dma_ch, OMAP_DMA_DATA_BURST_16); + rotation = calc_rotation(vout); + + /* dest_port required only for OMAP1 */ + omap_set_dma_dest_params(tx->dma_ch, 0, OMAP_DMA_AMODE_DOUBLE_IDX, + vout->vrfb_context[vb->i].paddr[0], dest_element_index, + dest_frame_index); + /*set dma dest burst mode for VRFB */ + omap_set_dma_dest_burst_mode(tx->dma_ch, OMAP_DMA_DATA_BURST_16); + omap_dma_set_global_params(DMA_DEFAULT_ARB_RATE, 0x20, 0); + + omap_start_dma(tx->dma_ch); + interruptible_sleep_on_timeout(&tx->wait, VRFB_TX_TIMEOUT); + + if (tx->tx_status == 0) { + omap_stop_dma(tx->dma_ch); + return -EINVAL; + } + /* Store buffers physical address into an array. Addresses + * from this array will be used to configure DSS */ + vout->queued_buf_addr[vb->i] = (u8 *) + vout->vrfb_context[vb->i].paddr[rotation]; + return 0; +} + +/* + * Buffer queue funtion will be called from the videobuf layer when _QBUF + * ioctl is called. It is used to enqueue buffer, which is ready to be + * displayed. + */ +static void omap_vout_buffer_queue(struct videobuf_queue *q, + struct videobuf_buffer *vb) +{ + struct omap_vout_device *vout = q->priv_data; + + /* Driver is also maintainig a queue. So enqueue buffer in the driver + * queue */ + list_add_tail(&vb->queue, &vout->dma_queue); + + vb->state = VIDEOBUF_QUEUED; +} + +/* + * Buffer release function is called from videobuf layer to release buffer + * which are already allocated + */ +static void omap_vout_buffer_release(struct videobuf_queue *q, + struct videobuf_buffer *vb) +{ + struct omap_vout_device *vout = q->priv_data; + + vb->state = VIDEOBUF_NEEDS_INIT; + + if (V4L2_MEMORY_MMAP != vout->memory) + return; +} + +/* + * File operations + */ +static void omap_vout_vm_open(struct vm_area_struct *vma) +{ + struct omap_vout_device *vout = vma->vm_private_data; + + v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, + "vm_open [vma=%08lx-%08lx]\n", vma->vm_start, vma->vm_end); + vout->mmap_count++; +} + +static void omap_vout_vm_close(struct vm_area_struct *vma) +{ + struct omap_vout_device *vout = vma->vm_private_data; + + v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, + "vm_close [vma=%08lx-%08lx]\n", vma->vm_start, vma->vm_end); + vout->mmap_count--; +} + +static struct vm_operations_struct omap_vout_vm_ops = { + .open = omap_vout_vm_open, + .close = omap_vout_vm_close, +}; + +static int omap_vout_mmap(struct file *file, struct vm_area_struct *vma) +{ + int i; + void *pos; + unsigned long start = vma->vm_start; + unsigned long size = (vma->vm_end - vma->vm_start); + struct videobuf_dmabuf *dmabuf = NULL; + struct omap_vout_device *vout = file->private_data; + struct videobuf_queue *q = &vout->vbq; + + v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, + " %s pgoff=0x%lx, start=0x%lx, end=0x%lx\n", __func__, + vma->vm_pgoff, vma->vm_start, vma->vm_end); + + /* look for the buffer to map */ + for (i = 0; i < VIDEO_MAX_FRAME; i++) { + if (NULL == q->bufs[i]) + continue; + if (V4L2_MEMORY_MMAP != q->bufs[i]->memory) + continue; + if (q->bufs[i]->boff == (vma->vm_pgoff << PAGE_SHIFT)) + break; + } + + if (VIDEO_MAX_FRAME == i) { + v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, + "offset invalid [offset=0x%lx]\n", + (vma->vm_pgoff << PAGE_SHIFT)); + return -EINVAL; + } + q->bufs[i]->baddr = vma->vm_start; + + vma->vm_flags |= VM_RESERVED; + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); + vma->vm_ops = &omap_vout_vm_ops; + vma->vm_private_data = (void *) vout; + dmabuf = videobuf_to_dma(q->bufs[i]); + pos = dmabuf->vmalloc; + vma->vm_pgoff = virt_to_phys((void *)pos) >> PAGE_SHIFT; + while (size > 0) { + unsigned long pfn; + pfn = virt_to_phys((void *) pos) >> PAGE_SHIFT; + if (remap_pfn_range(vma, start, pfn, PAGE_SIZE, PAGE_SHARED)) + return -EAGAIN; + start += PAGE_SIZE; + pos += PAGE_SIZE; + size -= PAGE_SIZE; + } + vout->mmap_count++; + v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "Exiting %s\n", __func__); + + return 0; +} + +static int omap_vout_release(struct file *file) +{ + unsigned int ret, i; + struct videobuf_queue *q; + struct omapvideo_info *ovid; + struct omap_vout_device *vout = file->private_data; + + v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "Entering %s\n", __func__); + ovid = &vout->vid_info; + + if (!vout) + return 0; + + q = &vout->vbq; + /* Disable all the overlay managers connected with this interface */ + for (i = 0; i < ovid->num_overlays; i++) { + struct omap_overlay *ovl = ovid->overlays[i]; + if (ovl->manager && ovl->manager->device) { + struct omap_overlay_info info; + ovl->get_overlay_info(ovl, &info); + info.enabled = 0; + ovl->set_overlay_info(ovl, &info); + } + } + /* Turn off the pipeline */ + ret = omapvid_apply_changes(vout); + if (ret) + v4l2_warn(&vout->vid_dev->v4l2_dev, + "Unable to apply changes\n"); + + /* Free all buffers */ + omap_vout_free_allbuffers(vout); + videobuf_mmap_free(q); + + /* Even if apply changes fails we should continue + freeing allocated memeory */ + if (vout->streaming) { + u32 mask = 0; + + mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN | + DISPC_IRQ_EVSYNC_ODD; + omap_dispc_unregister_isr(omap_vout_isr, vout, mask); + vout->streaming = 0; + + videobuf_streamoff(q); + videobuf_queue_cancel(q); + } + + if (vout->mmap_count != 0) + vout->mmap_count = 0; + + vout->opened -= 1; + file->private_data = NULL; + + if (vout->buffer_allocated) + videobuf_mmap_free(q); + + v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "Exiting %s\n", __func__); + return ret; +} + +static int omap_vout_open(struct file *file) +{ + struct videobuf_queue *q; + struct omap_vout_device *vout = NULL; + + vout = video_drvdata(file); + v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "Entering %s\n", __func__); + + if (vout == NULL) + return -ENODEV; + + /* for now, we only support single open */ + if (vout->opened) + return -EBUSY; + + vout->opened += 1; + + file->private_data = vout; + vout->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + + q = &vout->vbq; + video_vbq_ops.buf_setup = omap_vout_buffer_setup; + video_vbq_ops.buf_prepare = omap_vout_buffer_prepare; + video_vbq_ops.buf_release = omap_vout_buffer_release; + video_vbq_ops.buf_queue = omap_vout_buffer_queue; + spin_lock_init(&vout->vbq_lock); + + videobuf_queue_sg_init(q, &video_vbq_ops, NULL, &vout->vbq_lock, + vout->type, V4L2_FIELD_NONE, + sizeof(struct videobuf_buffer), vout); + + v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "Exiting %s\n", __func__); + return 0; +} + +/* + * V4L2 ioctls + */ +static int vidioc_querycap(struct file *file, void *fh, + struct v4l2_capability *cap) +{ + struct omap_vout_device *vout = fh; + + strlcpy(cap->driver, VOUT_NAME, sizeof(cap->driver)); + strlcpy(cap->card, vout->vfd->name, sizeof(cap->card)); + cap->bus_info[0] = '\0'; + cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT; + + return 0; +} + +static int vidioc_enum_fmt_vid_out(struct file *file, void *fh, + struct v4l2_fmtdesc *fmt) +{ + int index = fmt->index; + enum v4l2_buf_type type = fmt->type; + + fmt->index = index; + fmt->type = type; + if (index >= NUM_OUTPUT_FORMATS) + return -EINVAL; + + fmt->flags = omap_formats[index].flags; + strlcpy(fmt->description, omap_formats[index].description, + sizeof(fmt->description)); + fmt->pixelformat = omap_formats[index].pixelformat; + + return 0; +} + +static int vidioc_g_fmt_vid_out(struct file *file, void *fh, + struct v4l2_format *f) +{ + struct omap_vout_device *vout = fh; + + f->fmt.pix = vout->pix; + return 0; + +} + +static int vidioc_try_fmt_vid_out(struct file *file, void *fh, + struct v4l2_format *f) +{ + struct omap_overlay *ovl; + struct omapvideo_info *ovid; + struct omap_video_timings *timing; + struct omap_vout_device *vout = fh; + + ovid = &vout->vid_info; + ovl = ovid->overlays[0]; + + if (!ovl->manager || !ovl->manager->device) + return -EINVAL; + /* get the display device attached to the overlay */ + timing = &ovl->manager->device->panel.timings; + + vout->fbuf.fmt.height = timing->y_res; + vout->fbuf.fmt.width = timing->x_res; + + omap_vout_try_format(&f->fmt.pix); + return 0; +} + +static int vidioc_s_fmt_vid_out(struct file *file, void *fh, + struct v4l2_format *f) +{ + int ret, bpp; + struct omap_overlay *ovl; + struct omapvideo_info *ovid; + struct omap_video_timings *timing; + struct omap_vout_device *vout = fh; + + if (vout->streaming) + return -EBUSY; + + mutex_lock(&vout->lock); + + ovid = &vout->vid_info; + ovl = ovid->overlays[0]; + + /* get the display device attached to the overlay */ + if (!ovl->manager || !ovl->manager->device) { + ret = -EINVAL; + goto s_fmt_vid_out_exit; + } + timing = &ovl->manager->device->panel.timings; + + /* We dont support RGB24-packed mode if vrfb rotation + * is enabled*/ + if ((rotation_enabled(vout)) && + f->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24) { + ret = -EINVAL; + goto s_fmt_vid_out_exit; + } + + /* get the framebuffer parameters */ + + if (rotate_90_or_270(vout)) { + vout->fbuf.fmt.height = timing->x_res; + vout->fbuf.fmt.width = timing->y_res; + } else { + vout->fbuf.fmt.height = timing->y_res; + vout->fbuf.fmt.width = timing->x_res; + } + + /* change to samller size is OK */ + + bpp = omap_vout_try_format(&f->fmt.pix); + f->fmt.pix.sizeimage = f->fmt.pix.width * f->fmt.pix.height * bpp; + + /* try & set the new output format */ + vout->bpp = bpp; + vout->pix = f->fmt.pix; + vout->vrfb_bpp = 1; + + /* If YUYV then vrfb bpp is 2, for others its 1 */ + if (V4L2_PIX_FMT_YUYV == vout->pix.pixelformat || + V4L2_PIX_FMT_UYVY == vout->pix.pixelformat) + vout->vrfb_bpp = 2; + + /* set default crop and win */ + omap_vout_new_format(&vout->pix, &vout->fbuf, &vout->crop, &vout->win); + + /* Save the changes in the overlay strcuture */ + ret = omapvid_init(vout, 0); + if (ret) { + v4l2_err(&vout->vid_dev->v4l2_dev, "failed to change mode\n"); + goto s_fmt_vid_out_exit; + } + + ret = 0; + +s_fmt_vid_out_exit: + mutex_unlock(&vout->lock); + return ret; +} + +static int vidioc_try_fmt_vid_overlay(struct file *file, void *fh, + struct v4l2_format *f) +{ + int ret = 0; + struct omap_vout_device *vout = fh; + struct v4l2_window *win = &f->fmt.win; + + ret = omap_vout_try_window(&vout->fbuf, win); + + if (!ret) { + if (vout->vid == OMAP_VIDEO1) + win->global_alpha = 255; + else + win->global_alpha = f->fmt.win.global_alpha; + } + + return ret; +} + +static int vidioc_s_fmt_vid_overlay(struct file *file, void *fh, + struct v4l2_format *f) +{ + int ret = 0; + struct omap_overlay *ovl; + struct omapvideo_info *ovid; + struct omap_vout_device *vout = fh; + struct v4l2_window *win = &f->fmt.win; + + mutex_lock(&vout->lock); + ovid = &vout->vid_info; + ovl = ovid->overlays[0]; + + ret = omap_vout_new_window(&vout->crop, &vout->win, &vout->fbuf, win); + if (!ret) { + /* Video1 plane does not support global alpha */ + if (ovl->id == OMAP_DSS_VIDEO1) + vout->win.global_alpha = 255; + else + vout->win.global_alpha = f->fmt.win.global_alpha; + + vout->win.chromakey = f->fmt.win.chromakey; + } + mutex_unlock(&vout->lock); + return ret; +} + +static int vidioc_enum_fmt_vid_overlay(struct file *file, void *fh, + struct v4l2_fmtdesc *fmt) +{ + int index = fmt->index; + enum v4l2_buf_type type = fmt->type; + + fmt->index = index; + fmt->type = type; + if (index >= NUM_OUTPUT_FORMATS) + return -EINVAL; + + fmt->flags = omap_formats[index].flags; + strlcpy(fmt->description, omap_formats[index].description, + sizeof(fmt->description)); + fmt->pixelformat = omap_formats[index].pixelformat; + return 0; +} + +static int vidioc_g_fmt_vid_overlay(struct file *file, void *fh, + struct v4l2_format *f) +{ + u32 key_value = 0; + struct omap_overlay *ovl; + struct omapvideo_info *ovid; + struct omap_vout_device *vout = fh; + struct omap_overlay_manager_info info; + struct v4l2_window *win = &f->fmt.win; + + ovid = &vout->vid_info; + ovl = ovid->overlays[0]; + + win->w = vout->win.w; + win->field = vout->win.field; + win->global_alpha = vout->win.global_alpha; + + if (ovl->manager && ovl->manager->get_manager_info) { + ovl->manager->get_manager_info(ovl->manager, &info); + key_value = info.trans_key; + } + win->chromakey = key_value; + return 0; +} + +static int vidioc_cropcap(struct file *file, void *fh, + struct v4l2_cropcap *cropcap) +{ + struct omap_vout_device *vout = fh; + struct v4l2_pix_format *pix = &vout->pix; + + if (cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) + return -EINVAL; + + /* Width and height are always even */ + cropcap->bounds.width = pix->width & ~1; + cropcap->bounds.height = pix->height & ~1; + + omap_vout_default_crop(&vout->pix, &vout->fbuf, &cropcap->defrect); + cropcap->pixelaspect.numerator = 1; + cropcap->pixelaspect.denominator = 1; + return 0; +} + +static int vidioc_g_crop(struct file *file, void *fh, struct v4l2_crop *crop) +{ + struct omap_vout_device *vout = fh; + + if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) + return -EINVAL; + crop->c = vout->crop; + return 0; +} + +static int vidioc_s_crop(struct file *file, void *fh, struct v4l2_crop *crop) +{ + int ret = -EINVAL; + struct omap_vout_device *vout = fh; + struct omapvideo_info *ovid; + struct omap_overlay *ovl; + struct omap_video_timings *timing; + + if (vout->streaming) + return -EBUSY; + + mutex_lock(&vout->lock); + ovid = &vout->vid_info; + ovl = ovid->overlays[0]; + + if (!ovl->manager || !ovl->manager->device) { + ret = -EINVAL; + goto s_crop_err; + } + /* get the display device attached to the overlay */ + timing = &ovl->manager->device->panel.timings; + + if (rotate_90_or_270(vout)) { + vout->fbuf.fmt.height = timing->x_res; + vout->fbuf.fmt.width = timing->y_res; + } else { + vout->fbuf.fmt.height = timing->y_res; + vout->fbuf.fmt.width = timing->x_res; + } + + if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) + ret = omap_vout_new_crop(&vout->pix, &vout->crop, &vout->win, + &vout->fbuf, &crop->c); + +s_crop_err: + mutex_unlock(&vout->lock); + return ret; +} + +static int vidioc_queryctrl(struct file *file, void *fh, + struct v4l2_queryctrl *ctrl) +{ + int ret = 0; + + switch (ctrl->id) { + case V4L2_CID_ROTATE: + ret = v4l2_ctrl_query_fill(ctrl, 0, 270, 90, 0); + break; + case V4L2_CID_BG_COLOR: + ret = v4l2_ctrl_query_fill(ctrl, 0, 0xFFFFFF, 1, 0); + break; + case V4L2_CID_VFLIP: + ret = v4l2_ctrl_query_fill(ctrl, 0, 1, 1, 0); + break; + default: + ctrl->name[0] = '\0'; + ret = -EINVAL; + } + return ret; +} + +static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *ctrl) +{ + int ret = 0; + struct omap_vout_device *vout = fh; + + switch (ctrl->id) { + case V4L2_CID_ROTATE: + ctrl->value = vout->control[0].value; + break; + case V4L2_CID_BG_COLOR: + { + struct omap_overlay_manager_info info; + struct omap_overlay *ovl; + + ovl = vout->vid_info.overlays[0]; + if (!ovl->manager || !ovl->manager->get_manager_info) { + ret = -EINVAL; + break; + } + + ovl->manager->get_manager_info(ovl->manager, &info); + ctrl->value = info.default_color; + break; + } + case V4L2_CID_VFLIP: + ctrl->value = vout->control[2].value; + break; + default: + ret = -EINVAL; + } + return ret; +} + +static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *a) +{ + int ret = 0; + struct omap_vout_device *vout = fh; + + switch (a->id) { + case V4L2_CID_ROTATE: + { + int rotation = a->value; + + mutex_lock(&vout->lock); + + if (rotation && vout->pix.pixelformat == V4L2_PIX_FMT_RGB24) { + mutex_unlock(&vout->lock); + ret = -EINVAL; + break; + } + + if (v4l2_rot_to_dss_rot(rotation, &vout->rotation, + vout->mirror)) { + mutex_unlock(&vout->lock); + ret = -EINVAL; + break; + } + + vout->control[0].value = rotation; + mutex_unlock(&vout->lock); + break; + } + case V4L2_CID_BG_COLOR: + { + struct omap_overlay *ovl; + unsigned int color = a->value; + struct omap_overlay_manager_info info; + + ovl = vout->vid_info.overlays[0]; + + mutex_lock(&vout->lock); + if (!ovl->manager || !ovl->manager->get_manager_info) { + mutex_unlock(&vout->lock); + ret = -EINVAL; + break; + } + + ovl->manager->get_manager_info(ovl->manager, &info); + info.default_color = color; + if (ovl->manager->set_manager_info(ovl->manager, &info)) { + mutex_unlock(&vout->lock); + ret = -EINVAL; + break; + } + + vout->control[1].value = color; + mutex_unlock(&vout->lock); + break; + } + case V4L2_CID_VFLIP: + { + struct omap_overlay *ovl; + struct omapvideo_info *ovid; + unsigned int mirror = a->value; + + ovid = &vout->vid_info; + ovl = ovid->overlays[0]; + + mutex_lock(&vout->lock); + + if (mirror && vout->pix.pixelformat == V4L2_PIX_FMT_RGB24) { + mutex_unlock(&vout->lock); + ret = -EINVAL; + break; + } + vout->mirror = mirror; + vout->control[2].value = mirror; + mutex_unlock(&vout->lock); + break; + } + default: + ret = -EINVAL; + } + return ret; +} + +static int vidioc_reqbufs(struct file *file, void *fh, + struct v4l2_requestbuffers *req) +{ + int ret = 0; + unsigned int i, num_buffers = 0; + struct omap_vout_device *vout = fh; + struct videobuf_queue *q = &vout->vbq; + struct videobuf_dmabuf *dmabuf = NULL; + + if ((req->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) || (req->count < 0)) + return -EINVAL; + /* if memory is not mmp or userptr + return error */ + if ((V4L2_MEMORY_MMAP != req->memory) && + (V4L2_MEMORY_USERPTR != req->memory)) + return -EINVAL; + + mutex_lock(&vout->lock); + /* Cannot be requested when streaming is on */ + if (vout->streaming) { + ret = -EBUSY; + goto reqbuf_err; + } + + /* If buffers are already allocated free them */ + if (q->bufs[0] && (V4L2_MEMORY_MMAP == q->bufs[0]->memory)) { + if (vout->mmap_count) { + ret = -EBUSY; + goto reqbuf_err; + } + num_buffers = (vout->vid == OMAP_VIDEO1) ? + video1_numbuffers : video2_numbuffers; + for (i = num_buffers; i < vout->buffer_allocated; i++) { + dmabuf = videobuf_to_dma(q->bufs[i]); + omap_vout_free_buffer((u32)dmabuf->vmalloc, + vout->buffer_size); + vout->buf_virt_addr[i] = 0; + vout->buf_phy_addr[i] = 0; + } + vout->buffer_allocated = num_buffers; + videobuf_mmap_free(q); + } else if (q->bufs[0] && (V4L2_MEMORY_USERPTR == q->bufs[0]->memory)) { + if (vout->buffer_allocated) { + videobuf_mmap_free(q); + for (i = 0; i < vout->buffer_allocated; i++) { + kfree(q->bufs[i]); + q->bufs[i] = NULL; + } + vout->buffer_allocated = 0; + } + } + + /*store the memory type in data structure */ + vout->memory = req->memory; + + INIT_LIST_HEAD(&vout->dma_queue); + + /* call videobuf_reqbufs api */ + ret = videobuf_reqbufs(q, req); + if (ret < 0) + goto reqbuf_err; + + vout->buffer_allocated = req->count; + for (i = 0; i < req->count; i++) { + dmabuf = videobuf_to_dma(q->bufs[i]); + dmabuf->vmalloc = (void *) vout->buf_virt_addr[i]; + dmabuf->bus_addr = (dma_addr_t) vout->buf_phy_addr[i]; + dmabuf->sglen = 1; + } +reqbuf_err: + mutex_unlock(&vout->lock); + return ret; +} + +static int vidioc_querybuf(struct file *file, void *fh, + struct v4l2_buffer *b) +{ + struct omap_vout_device *vout = fh; + + return videobuf_querybuf(&vout->vbq, b); +} + +static int vidioc_qbuf(struct file *file, void *fh, + struct v4l2_buffer *buffer) +{ + struct omap_vout_device *vout = fh; + struct videobuf_queue *q = &vout->vbq; + + if ((V4L2_BUF_TYPE_VIDEO_OUTPUT != buffer->type) || + (buffer->index >= vout->buffer_allocated) || + (q->bufs[buffer->index]->memory != buffer->memory)) { + return -EINVAL; + } + if (V4L2_MEMORY_USERPTR == buffer->memory) { + if ((buffer->length < vout->pix.sizeimage) || + (0 == buffer->m.userptr)) { + return -EINVAL; + } + } + + if ((rotation_enabled(vout)) && + vout->vrfb_dma_tx.req_status == DMA_CHAN_NOT_ALLOTED) { + v4l2_warn(&vout->vid_dev->v4l2_dev, + "DMA Channel not allocated for Rotation\n"); + return -EINVAL; + } + + return videobuf_qbuf(q, buffer); +} + +static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b) +{ + struct omap_vout_device *vout = fh; + struct videobuf_queue *q = &vout->vbq; + + if (!vout->streaming) + return -EINVAL; + + if (file->f_flags & O_NONBLOCK) + /* Call videobuf_dqbuf for non blocking mode */ + return videobuf_dqbuf(q, (struct v4l2_buffer *)b, 1); + else + /* Call videobuf_dqbuf for blocking mode */ + return videobuf_dqbuf(q, (struct v4l2_buffer *)b, 0); +} + +static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i) +{ + int ret = 0, j; + u32 addr = 0, mask = 0; + struct omap_vout_device *vout = fh; + struct videobuf_queue *q = &vout->vbq; + struct omapvideo_info *ovid = &vout->vid_info; + + mutex_lock(&vout->lock); + + if (vout->streaming) { + ret = -EBUSY; + goto streamon_err; + } + + ret = videobuf_streamon(q); + if (ret) + goto streamon_err; + + if (list_empty(&vout->dma_queue)) { + ret = -EIO; + goto streamon_err1; + } + + /* Get the next frame from the buffer queue */ + vout->next_frm = vout->cur_frm = list_entry(vout->dma_queue.next, + struct videobuf_buffer, queue); + /* Remove buffer from the buffer queue */ + list_del(&vout->cur_frm->queue); + /* Mark state of the current frame to active */ + vout->cur_frm->state = VIDEOBUF_ACTIVE; + /* Initialize field_id and started member */ + vout->field_id = 0; + + /* set flag here. Next QBUF will start DMA */ + vout->streaming = 1; + + vout->first_int = 1; + + if (omap_vout_calculate_offset(vout)) { + ret = -EINVAL; + goto streamon_err1; + } + addr = (unsigned long) vout->queued_buf_addr[vout->cur_frm->i] + + vout->cropped_offset; + + mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD; + + omap_dispc_register_isr(omap_vout_isr, vout, mask); + + for (j = 0; j < ovid->num_overlays; j++) { + struct omap_overlay *ovl = ovid->overlays[j]; + + if (ovl->manager && ovl->manager->device) { + struct omap_overlay_info info; + ovl->get_overlay_info(ovl, &info); + info.enabled = 1; + info.paddr = addr; + if (ovl->set_overlay_info(ovl, &info)) { + ret = -EINVAL; + goto streamon_err1; + } + } + } + + /* First save the configuration in ovelray structure */ + ret = omapvid_init(vout, addr); + if (ret) + v4l2_err(&vout->vid_dev->v4l2_dev, + "failed to set overlay info\n"); + /* Enable the pipeline and set the Go bit */ + ret = omapvid_apply_changes(vout); + if (ret) + v4l2_err(&vout->vid_dev->v4l2_dev, "failed to change mode\n"); + + ret = 0; + +streamon_err1: + if (ret) + ret = videobuf_streamoff(q); +streamon_err: + mutex_unlock(&vout->lock); + return ret; +} + +static int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i) +{ + u32 mask = 0; + int ret = 0, j; + struct omap_vout_device *vout = fh; + struct omapvideo_info *ovid = &vout->vid_info; + + if (!vout->streaming) + return -EINVAL; + + vout->streaming = 0; + mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD; + + omap_dispc_unregister_isr(omap_vout_isr, vout, mask); + + for (j = 0; j < ovid->num_overlays; j++) { + struct omap_overlay *ovl = ovid->overlays[j]; + + if (ovl->manager && ovl->manager->device) { + struct omap_overlay_info info; + + ovl->get_overlay_info(ovl, &info); + info.enabled = 0; + ret = ovl->set_overlay_info(ovl, &info); + if (ret) + v4l2_err(&vout->vid_dev->v4l2_dev, + "failed to update overlay info in streamoff\n"); + } + } + + /* Turn of the pipeline */ + ret = omapvid_apply_changes(vout); + if (ret) + v4l2_err(&vout->vid_dev->v4l2_dev, "failed to change mode in" + " streamoff\n"); + + INIT_LIST_HEAD(&vout->dma_queue); + ret = videobuf_streamoff(&vout->vbq); + + return ret; +} + +static int vidioc_s_fbuf(struct file *file, void *fh, + struct v4l2_framebuffer *a) +{ + int enable = 0; + struct omap_overlay *ovl; + struct omapvideo_info *ovid; + struct omap_vout_device *vout = fh; + struct omap_overlay_manager_info info; + enum omap_dss_trans_key_type key_type = OMAP_DSS_COLOR_KEY_GFX_DST; + + ovid = &vout->vid_info; + ovl = ovid->overlays[0]; + + /* OMAP DSS doesn't support Source and Destination color + key together */ + if ((a->flags & V4L2_FBUF_FLAG_SRC_CHROMAKEY) && + (a->flags & V4L2_FBUF_FLAG_CHROMAKEY)) + return -EINVAL; + /* OMAP DSS Doesn't support the Destination color key + and alpha blending together */ + if ((a->flags & V4L2_FBUF_FLAG_CHROMAKEY) && + (a->flags & V4L2_FBUF_FLAG_LOCAL_ALPHA)) + return -EINVAL; + + if ((a->flags & V4L2_FBUF_FLAG_SRC_CHROMAKEY)) { + vout->fbuf.flags |= V4L2_FBUF_FLAG_SRC_CHROMAKEY; + key_type = OMAP_DSS_COLOR_KEY_VID_SRC; + } else + vout->fbuf.flags &= ~V4L2_FBUF_FLAG_SRC_CHROMAKEY; + + if ((a->flags & V4L2_FBUF_FLAG_CHROMAKEY)) { + vout->fbuf.flags |= V4L2_FBUF_FLAG_CHROMAKEY; + key_type = OMAP_DSS_COLOR_KEY_GFX_DST; + } else + vout->fbuf.flags &= ~V4L2_FBUF_FLAG_CHROMAKEY; + + if (a->flags & (V4L2_FBUF_FLAG_CHROMAKEY | + V4L2_FBUF_FLAG_SRC_CHROMAKEY)) + enable = 1; + else + enable = 0; + if (ovl->manager && ovl->manager->get_manager_info && + ovl->manager->set_manager_info) { + + ovl->manager->get_manager_info(ovl->manager, &info); + info.trans_enabled = enable; + info.trans_key_type = key_type; + info.trans_key = vout->win.chromakey; + + if (ovl->manager->set_manager_info(ovl->manager, &info)) + return -EINVAL; + } + if (a->flags & V4L2_FBUF_FLAG_LOCAL_ALPHA) { + vout->fbuf.flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA; + enable = 1; + } else { + vout->fbuf.flags &= ~V4L2_FBUF_FLAG_LOCAL_ALPHA; + enable = 0; + } + if (ovl->manager && ovl->manager->get_manager_info && + ovl->manager->set_manager_info) { + ovl->manager->get_manager_info(ovl->manager, &info); + info.alpha_enabled = enable; + if (ovl->manager->set_manager_info(ovl->manager, &info)) + return -EINVAL; + } + + return 0; +} + +static int vidioc_g_fbuf(struct file *file, void *fh, + struct v4l2_framebuffer *a) +{ + struct omap_overlay *ovl; + struct omapvideo_info *ovid; + struct omap_vout_device *vout = fh; + struct omap_overlay_manager_info info; + + ovid = &vout->vid_info; + ovl = ovid->overlays[0]; + + a->flags = 0x0; + a->capability = V4L2_FBUF_CAP_LOCAL_ALPHA | V4L2_FBUF_CAP_CHROMAKEY + | V4L2_FBUF_CAP_SRC_CHROMAKEY; + + if (ovl->manager && ovl->manager->get_manager_info) { + ovl->manager->get_manager_info(ovl->manager, &info); + if (info.trans_key_type == OMAP_DSS_COLOR_KEY_VID_SRC) + a->flags |= V4L2_FBUF_FLAG_SRC_CHROMAKEY; + if (info.trans_key_type == OMAP_DSS_COLOR_KEY_GFX_DST) + a->flags |= V4L2_FBUF_FLAG_CHROMAKEY; + } + if (ovl->manager && ovl->manager->get_manager_info) { + ovl->manager->get_manager_info(ovl->manager, &info); + if (info.alpha_enabled) + a->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA; + } + + return 0; +} + +static const struct v4l2_ioctl_ops vout_ioctl_ops = { + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out, + .vidioc_g_fmt_vid_out = vidioc_g_fmt_vid_out, + .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out, + .vidioc_s_fmt_vid_out = vidioc_s_fmt_vid_out, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_fbuf = vidioc_s_fbuf, + .vidioc_g_fbuf = vidioc_g_fbuf, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_try_fmt_vid_overlay = vidioc_try_fmt_vid_overlay, + .vidioc_s_fmt_vid_overlay = vidioc_s_fmt_vid_overlay, + .vidioc_enum_fmt_vid_overlay = vidioc_enum_fmt_vid_overlay, + .vidioc_g_fmt_vid_overlay = vidioc_g_fmt_vid_overlay, + .vidioc_cropcap = vidioc_cropcap, + .vidioc_g_crop = vidioc_g_crop, + .vidioc_s_crop = vidioc_s_crop, + .vidioc_reqbufs = vidioc_reqbufs, + .vidioc_querybuf = vidioc_querybuf, + .vidioc_qbuf = vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, +}; + +static const struct v4l2_file_operations omap_vout_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = video_ioctl2, + .mmap = omap_vout_mmap, + .open = omap_vout_open, + .release = omap_vout_release, +}; + +/* Init functions used during driver initialization */ +/* Initial setup of video_data */ +static int __init omap_vout_setup_video_data(struct omap_vout_device *vout) +{ + struct video_device *vfd; + struct v4l2_pix_format *pix; + struct v4l2_control *control; + struct omap_dss_device *display = + vout->vid_info.overlays[0]->manager->device; + + /* set the default pix */ + pix = &vout->pix; + + /* Set the default picture of QVGA */ + pix->width = QQVGA_WIDTH; + pix->height = QQVGA_HEIGHT; + + /* Default pixel format is RGB 5-6-5 */ + pix->pixelformat = V4L2_PIX_FMT_RGB565; + pix->field = V4L2_FIELD_ANY; + pix->bytesperline = pix->width * 2; + pix->sizeimage = pix->bytesperline * pix->height; + pix->priv = 0; + pix->colorspace = V4L2_COLORSPACE_JPEG; + + vout->bpp = RGB565_BPP; + vout->fbuf.fmt.width = display->panel.timings.x_res; + vout->fbuf.fmt.height = display->panel.timings.y_res; + + /* Set the data structures for the overlay parameters*/ + vout->win.global_alpha = 255; + vout->fbuf.flags = 0; + vout->fbuf.capability = V4L2_FBUF_CAP_LOCAL_ALPHA | + V4L2_FBUF_CAP_SRC_CHROMAKEY | V4L2_FBUF_CAP_CHROMAKEY; + vout->win.chromakey = 0; + + omap_vout_new_format(pix, &vout->fbuf, &vout->crop, &vout->win); + + /*Initialize the control variables for + rotation, flipping and background color. */ + control = vout->control; + control[0].id = V4L2_CID_ROTATE; + control[0].value = 0; + vout->rotation = 0; + vout->mirror = 0; + vout->control[2].id = V4L2_CID_HFLIP; + vout->control[2].value = 0; + vout->vrfb_bpp = 2; + + control[1].id = V4L2_CID_BG_COLOR; + control[1].value = 0; + + /* initialize the video_device struct */ + vfd = vout->vfd = video_device_alloc(); + + if (!vfd) { + printk(KERN_ERR VOUT_NAME ": could not allocate" + " video device struct\n"); + return -ENOMEM; + } + vfd->release = video_device_release; + vfd->ioctl_ops = &vout_ioctl_ops; + + strlcpy(vfd->name, VOUT_NAME, sizeof(vfd->name)); + + /* need to register for a VID_HARDWARE_* ID in videodev.h */ + vfd->fops = &omap_vout_fops; + vfd->v4l2_dev = &vout->vid_dev->v4l2_dev; + mutex_init(&vout->lock); + + vfd->minor = -1; + return 0; + +} + +/* Setup video buffers */ +static int __init omap_vout_setup_video_bufs(struct platform_device *pdev, + int vid_num) +{ + u32 numbuffers; + int ret = 0, i, j; + int image_width, image_height; + struct video_device *vfd; + struct omap_vout_device *vout; + int static_vrfb_allocation = 0, vrfb_num_bufs = VRFB_NUM_BUFS; + struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev); + struct omap2video_device *vid_dev = + container_of(v4l2_dev, struct omap2video_device, v4l2_dev); + + vout = vid_dev->vouts[vid_num]; + vfd = vout->vfd; + + numbuffers = (vid_num == 0) ? video1_numbuffers : video2_numbuffers; + vout->buffer_size = (vid_num == 0) ? video1_bufsize : video2_bufsize; + dev_info(&pdev->dev, "Buffer Size = %d\n", vout->buffer_size); + + for (i = 0; i < numbuffers; i++) { + vout->buf_virt_addr[i] = + omap_vout_alloc_buffer(vout->buffer_size, + (u32 *) &vout->buf_phy_addr[i]); + if (!vout->buf_virt_addr[i]) { + numbuffers = i; + ret = -ENOMEM; + goto free_buffers; + } + } + + for (i = 0; i < VRFB_NUM_BUFS; i++) { + if (omap_vrfb_request_ctx(&vout->vrfb_context[i])) { + dev_info(&pdev->dev, ": VRFB allocation failed\n"); + for (j = 0; j < i; j++) + omap_vrfb_release_ctx(&vout->vrfb_context[j]); + ret = -ENOMEM; + goto free_buffers; + } + } + vout->cropped_offset = 0; + + /* Calculate VRFB memory size */ + /* allocate for worst case size */ + image_width = VID_MAX_WIDTH / TILE_SIZE; + if (VID_MAX_WIDTH % TILE_SIZE) + image_width++; + + image_width = image_width * TILE_SIZE; + image_height = VID_MAX_HEIGHT / TILE_SIZE; + + if (VID_MAX_HEIGHT % TILE_SIZE) + image_height++; + + image_height = image_height * TILE_SIZE; + vout->smsshado_size = PAGE_ALIGN(image_width * image_height * 2 * 2); + + /* + * Request and Initialize DMA, for DMA based VRFB transfer + */ + vout->vrfb_dma_tx.dev_id = OMAP_DMA_NO_DEVICE; + vout->vrfb_dma_tx.dma_ch = -1; + vout->vrfb_dma_tx.req_status = DMA_CHAN_ALLOTED; + ret = omap_request_dma(vout->vrfb_dma_tx.dev_id, "VRFB DMA TX", + omap_vout_vrfb_dma_tx_callback, + (void *) &vout->vrfb_dma_tx, &vout->vrfb_dma_tx.dma_ch); + if (ret < 0) { + vout->vrfb_dma_tx.req_status = DMA_CHAN_NOT_ALLOTED; + dev_info(&pdev->dev, ": failed to allocate DMA Channel for" + " video%d\n", vfd->minor); + } + init_waitqueue_head(&vout->vrfb_dma_tx.wait); + + /* Allocate VRFB buffers if selected through bootargs */ + static_vrfb_allocation = (vid_num == 0) ? + vid1_static_vrfb_alloc : vid2_static_vrfb_alloc; + + /* statically allocated the VRFB buffer is done through + commands line aruments */ + if (static_vrfb_allocation) { + if (omap_vout_allocate_vrfb_buffers(vout, &vrfb_num_bufs, -1)) { + ret = -ENOMEM; + goto release_vrfb_ctx; + } + vout->vrfb_static_allocation = 1; + } + return 0; + +release_vrfb_ctx: + for (j = 0; j < VRFB_NUM_BUFS; j++) + omap_vrfb_release_ctx(&vout->vrfb_context[j]); + +free_buffers: + for (i = 0; i < numbuffers; i++) { + omap_vout_free_buffer(vout->buf_virt_addr[i], + vout->buffer_size); + vout->buf_virt_addr[i] = 0; + vout->buf_phy_addr[i] = 0; + } + return ret; + +} + +/* Create video out devices */ +static int __init omap_vout_create_video_devices(struct platform_device *pdev) +{ + int ret = 0, k; + struct omap_vout_device *vout; + struct video_device *vfd = NULL; + struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev); + struct omap2video_device *vid_dev = container_of(v4l2_dev, + struct omap2video_device, v4l2_dev); + + for (k = 0; k < pdev->num_resources; k++) { + + vout = kmalloc(sizeof(struct omap_vout_device), GFP_KERNEL); + if (!vout) { + dev_err(&pdev->dev, ": could not allocate memory\n"); + return -ENOMEM; + } + memset(vout, 0, sizeof(struct omap_vout_device)); + + vout->vid = k; + vid_dev->vouts[k] = vout; + vout->vid_dev = vid_dev; + /* Select video2 if only 1 overlay is controlled by V4L2 */ + if (pdev->num_resources == 1) + vout->vid_info.overlays[0] = vid_dev->overlays[k + 2]; + else + /* Else select video1 and video2 one by one. */ + vout->vid_info.overlays[0] = vid_dev->overlays[k + 1]; + vout->vid_info.num_overlays = 1; + vout->vid_info.id = k + 1; + + /* Setup the default configuration for the video devices + */ + if (omap_vout_setup_video_data(vout) != 0) { + ret = -ENOMEM; + goto error; + } + + /* Allocate default number of buffers for the video streaming + * and reserve the VRFB space for rotation + */ + if (omap_vout_setup_video_bufs(pdev, k) != 0) { + ret = -ENOMEM; + goto error1; + } + + /* Register the Video device with V4L2 + */ + vfd = vout->vfd; + if (video_register_device(vfd, VFL_TYPE_GRABBER, k + 1) < 0) { + dev_err(&pdev->dev, ": Could not register " + "Video for Linux device\n"); + vfd->minor = -1; + ret = -ENODEV; + goto error2; + } + video_set_drvdata(vfd, vout); + + /* Configure the overlay structure */ + ret = omapvid_init(vid_dev->vouts[k], 0); + if (!ret) + goto success; + +error2: + omap_vout_release_vrfb(vout); + omap_vout_free_buffers(vout); +error1: + video_device_release(vfd); +error: + kfree(vout); + return ret; + +success: + dev_info(&pdev->dev, ": registered and initialized" + " video device %d\n", vfd->minor); + if (k == (pdev->num_resources - 1)) + return 0; + } + + return -ENODEV; +} +/* Driver functions */ +static void omap_vout_cleanup_device(struct omap_vout_device *vout) +{ + struct video_device *vfd; + + if (!vout) + return; + + vfd = vout->vfd; + if (vfd) { + if (!video_is_registered(vfd)) { + /* + * The device was never registered, so release the + * video_device struct directly. + */ + video_device_release(vfd); + } else { + /* + * The unregister function will release the video_device + * struct as well as unregistering it. + */ + video_unregister_device(vfd); + } + } + + omap_vout_release_vrfb(vout); + omap_vout_free_buffers(vout); + /* Free the VRFB buffer if allocated + * init time + */ + if (vout->vrfb_static_allocation) + omap_vout_free_vrfb_buffers(vout); + + kfree(vout); +} + +static int omap_vout_remove(struct platform_device *pdev) +{ + int k; + struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev); + struct omap2video_device *vid_dev = container_of(v4l2_dev, struct + omap2video_device, v4l2_dev); + + v4l2_device_unregister(v4l2_dev); + for (k = 0; k < pdev->num_resources; k++) + omap_vout_cleanup_device(vid_dev->vouts[k]); + + for (k = 0; k < vid_dev->num_displays; k++) { + if (vid_dev->displays[k]->state != OMAP_DSS_DISPLAY_DISABLED) + vid_dev->displays[k]->disable(vid_dev->displays[k]); + + omap_dss_put_device(vid_dev->displays[k]); + } + kfree(vid_dev); + return 0; +} + +static int __init omap_vout_probe(struct platform_device *pdev) +{ + int ret = 0, i; + struct omap_overlay *ovl; + struct omap_dss_device *dssdev = NULL; + struct omap_dss_device *def_display; + struct omap2video_device *vid_dev = NULL; + + if (pdev->num_resources == 0) { + dev_err(&pdev->dev, "probed for an unknown device\n"); + return -ENODEV; + } + + vid_dev = kzalloc(sizeof(struct omap2video_device), GFP_KERNEL); + if (vid_dev == NULL) + return -ENOMEM; + + vid_dev->num_displays = 0; + for_each_dss_dev(dssdev) { + omap_dss_get_device(dssdev); + vid_dev->displays[vid_dev->num_displays++] = dssdev; + } + + if (vid_dev->num_displays == 0) { + dev_err(&pdev->dev, "no displays\n"); + ret = -EINVAL; + goto probe_err0; + } + + vid_dev->num_overlays = omap_dss_get_num_overlays(); + for (i = 0; i < vid_dev->num_overlays; i++) + vid_dev->overlays[i] = omap_dss_get_overlay(i); + + vid_dev->num_managers = omap_dss_get_num_overlay_managers(); + for (i = 0; i < vid_dev->num_managers; i++) + vid_dev->managers[i] = omap_dss_get_overlay_manager(i); + + /* Get the Video1 overlay and video2 overlay. + * Setup the Display attached to that overlays + */ + for (i = 1; i < vid_dev->num_overlays; i++) { + ovl = omap_dss_get_overlay(i); + if (ovl->manager && ovl->manager->device) { + def_display = ovl->manager->device; + } else { + dev_warn(&pdev->dev, "cannot find display\n"); + def_display = NULL; + } + if (def_display) { + ret = def_display->enable(def_display); + if (ret) { + /* Here we are not considering a error + * as display may be enabled by frame + * buffer driver + */ + dev_warn(&pdev->dev, + "'%s' Display already enabled\n", + def_display->name); + } + /* set the update mode */ + if (def_display->caps & + OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { +#ifdef CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE + if (def_display->enable_te) + def_display->enable_te(def_display, 1); + if (def_display->set_update_mode) + def_display->set_update_mode(def_display, + OMAP_DSS_UPDATE_AUTO); +#else /* MANUAL_UPDATE */ + if (def_display->enable_te) + def_display->enable_te(def_display, 0); + if (def_display->set_update_mode) + def_display->set_update_mode(def_display, + OMAP_DSS_UPDATE_MANUAL); +#endif + } else { + if (def_display->set_update_mode) + def_display->set_update_mode(def_display, + OMAP_DSS_UPDATE_AUTO); + } + } + } + + if (v4l2_device_register(&pdev->dev, &vid_dev->v4l2_dev) < 0) { + dev_err(&pdev->dev, "v4l2_device_register failed\n"); + ret = -ENODEV; + goto probe_err1; + } + + ret = omap_vout_create_video_devices(pdev); + if (ret) + goto probe_err2; + + for (i = 0; i < vid_dev->num_displays; i++) { + struct omap_dss_device *display = vid_dev->displays[i]; + + if (display->update) + display->update(display, 0, 0, + display->panel.timings.x_res, + display->panel.timings.y_res); + } + return 0; + +probe_err2: + v4l2_device_unregister(&vid_dev->v4l2_dev); +probe_err1: + for (i = 1; i < vid_dev->num_overlays; i++) { + def_display = NULL; + ovl = omap_dss_get_overlay(i); + if (ovl->manager && ovl->manager->device) + def_display = ovl->manager->device; + + if (def_display) + def_display->disable(def_display); + } +probe_err0: + kfree(vid_dev); + return ret; +} + +static struct platform_driver omap_vout_driver = { + .driver = { + .name = VOUT_NAME, + }, + .probe = omap_vout_probe, + .remove = omap_vout_remove, +}; + +static int __init omap_vout_init(void) +{ + if (platform_driver_register(&omap_vout_driver) != 0) { + printk(KERN_ERR VOUT_NAME ":Could not register Video driver\n"); + return -EINVAL; + } + return 0; +} + +static void omap_vout_cleanup(void) +{ + platform_driver_unregister(&omap_vout_driver); +} + +late_initcall(omap_vout_init); +module_exit(omap_vout_cleanup); diff --git a/drivers/media/video/omap/omap_voutdef.h b/drivers/media/video/omap/omap_voutdef.h new file mode 100644 index 00000000000..ea3a047f8bc --- /dev/null +++ b/drivers/media/video/omap/omap_voutdef.h @@ -0,0 +1,147 @@ +/* + * omap_voutdef.h + * + * Copyright (C) 2010 Texas Instruments. + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#ifndef OMAP_VOUTDEF_H +#define OMAP_VOUTDEF_H + +#include + +#define YUYV_BPP 2 +#define RGB565_BPP 2 +#define RGB24_BPP 3 +#define RGB32_BPP 4 +#define TILE_SIZE 32 +#define YUYV_VRFB_BPP 2 +#define RGB_VRFB_BPP 1 +#define MAX_CID 3 +#define MAC_VRFB_CTXS 4 +#define MAX_VOUT_DEV 2 +#define MAX_OVLS 3 +#define MAX_DISPLAYS 3 +#define MAX_MANAGERS 3 + +/* Enum for Rotation + * DSS understands rotation in 0, 1, 2, 3 context + * while V4L2 driver understands it as 0, 90, 180, 270 + */ +enum dss_rotation { + dss_rotation_0_degree = 0, + dss_rotation_90_degree = 1, + dss_rotation_180_degree = 2, + dss_rotation_270_degree = 3, +}; +/* + * This structure is used to store the DMA transfer parameters + * for VRFB hidden buffer + */ +struct vid_vrfb_dma { + int dev_id; + int dma_ch; + int req_status; + int tx_status; + wait_queue_head_t wait; +}; + +struct omapvideo_info { + int id; + int num_overlays; + struct omap_overlay *overlays[MAX_OVLS]; +}; + +struct omap2video_device { + struct mutex mtx; + + int state; + + struct v4l2_device v4l2_dev; + struct omap_vout_device *vouts[MAX_VOUT_DEV]; + + int num_displays; + struct omap_dss_device *displays[MAX_DISPLAYS]; + int num_overlays; + struct omap_overlay *overlays[MAX_OVLS]; + int num_managers; + struct omap_overlay_manager *managers[MAX_MANAGERS]; +}; + +/* per-device data structure */ +struct omap_vout_device { + + struct omapvideo_info vid_info; + struct video_device *vfd; + struct omap2video_device *vid_dev; + int vid; + int opened; + + /* we don't allow to change image fmt/size once buffer has + * been allocated + */ + int buffer_allocated; + /* allow to reuse previously allocated buffer which is big enough */ + int buffer_size; + /* keep buffer info across opens */ + unsigned long buf_virt_addr[VIDEO_MAX_FRAME]; + unsigned long buf_phy_addr[VIDEO_MAX_FRAME]; + enum omap_color_mode dss_mode; + + /* we don't allow to request new buffer when old buffers are + * still mmaped + */ + int mmap_count; + + spinlock_t vbq_lock; /* spinlock for videobuf queues */ + unsigned long field_count; /* field counter for videobuf_buffer */ + + /* non-NULL means streaming is in progress. */ + bool streaming; + + struct v4l2_pix_format pix; + struct v4l2_rect crop; + struct v4l2_window win; + struct v4l2_framebuffer fbuf; + + /* Lock to protect the shared data structures in ioctl */ + struct mutex lock; + + /* V4L2 control structure for different control id */ + struct v4l2_control control[MAX_CID]; + enum dss_rotation rotation; + bool mirror; + int flicker_filter; + /* V4L2 control structure for different control id */ + + int bpp; /* bytes per pixel */ + int vrfb_bpp; /* bytes per pixel with respect to VRFB */ + + struct vid_vrfb_dma vrfb_dma_tx; + unsigned int smsshado_phy_addr[MAC_VRFB_CTXS]; + unsigned int smsshado_virt_addr[MAC_VRFB_CTXS]; + struct vrfb vrfb_context[MAC_VRFB_CTXS]; + bool vrfb_static_allocation; + unsigned int smsshado_size; + unsigned char pos; + + int ps, vr_ps, line_length, first_int, field_id; + enum v4l2_memory memory; + struct videobuf_buffer *cur_frm, *next_frm; + struct list_head dma_queue; + u8 *queued_buf_addr[VIDEO_MAX_FRAME]; + u32 cropped_offset; + s32 tv_field1_offset; + void *isr_handle; + + /* Buffer queue variables */ + struct omap_vout_device *vout; + enum v4l2_buf_type type; + struct videobuf_queue vbq; + int io_allowed; + +}; +#endif /* ifndef OMAP_VOUTDEF_H */ diff --git a/drivers/media/video/omap/omap_voutlib.c b/drivers/media/video/omap/omap_voutlib.c new file mode 100644 index 00000000000..b941c761eef --- /dev/null +++ b/drivers/media/video/omap/omap_voutlib.c @@ -0,0 +1,293 @@ +/* + * omap_voutlib.c + * + * Copyright (C) 2005-2010 Texas Instruments. + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + * + * Based on the OMAP2 camera driver + * Video-for-Linux (Version 2) camera capture driver for + * the OMAP24xx camera controller. + * + * Author: Andy Lowe (source@mvista.com) + * + * Copyright (C) 2004 MontaVista Software, Inc. + * Copyright (C) 2010 Texas Instruments. + * + */ + +#include +#include +#include +#include +#include + +#include + +MODULE_AUTHOR("Texas Instruments"); +MODULE_DESCRIPTION("OMAP Video library"); +MODULE_LICENSE("GPL"); + +/* Return the default overlay cropping rectangle in crop given the image + * size in pix and the video display size in fbuf. The default + * cropping rectangle is the largest rectangle no larger than the capture size + * that will fit on the display. The default cropping rectangle is centered in + * the image. All dimensions and offsets are rounded down to even numbers. + */ +void omap_vout_default_crop(struct v4l2_pix_format *pix, + struct v4l2_framebuffer *fbuf, struct v4l2_rect *crop) +{ + crop->width = (pix->width < fbuf->fmt.width) ? + pix->width : fbuf->fmt.width; + crop->height = (pix->height < fbuf->fmt.height) ? + pix->height : fbuf->fmt.height; + crop->width &= ~1; + crop->height &= ~1; + crop->left = ((pix->width - crop->width) >> 1) & ~1; + crop->top = ((pix->height - crop->height) >> 1) & ~1; +} +EXPORT_SYMBOL_GPL(omap_vout_default_crop); + +/* Given a new render window in new_win, adjust the window to the + * nearest supported configuration. The adjusted window parameters are + * returned in new_win. + * Returns zero if succesful, or -EINVAL if the requested window is + * impossible and cannot reasonably be adjusted. + */ +int omap_vout_try_window(struct v4l2_framebuffer *fbuf, + struct v4l2_window *new_win) +{ + struct v4l2_rect try_win; + + /* make a working copy of the new_win rectangle */ + try_win = new_win->w; + + /* adjust the preview window so it fits on the display by clipping any + * offscreen areas + */ + if (try_win.left < 0) { + try_win.width += try_win.left; + try_win.left = 0; + } + if (try_win.top < 0) { + try_win.height += try_win.top; + try_win.top = 0; + } + try_win.width = (try_win.width < fbuf->fmt.width) ? + try_win.width : fbuf->fmt.width; + try_win.height = (try_win.height < fbuf->fmt.height) ? + try_win.height : fbuf->fmt.height; + if (try_win.left + try_win.width > fbuf->fmt.width) + try_win.width = fbuf->fmt.width - try_win.left; + if (try_win.top + try_win.height > fbuf->fmt.height) + try_win.height = fbuf->fmt.height - try_win.top; + try_win.width &= ~1; + try_win.height &= ~1; + + if (try_win.width <= 0 || try_win.height <= 0) + return -EINVAL; + + /* We now have a valid preview window, so go with it */ + new_win->w = try_win; + new_win->field = V4L2_FIELD_ANY; + return 0; +} +EXPORT_SYMBOL_GPL(omap_vout_try_window); + +/* Given a new render window in new_win, adjust the window to the + * nearest supported configuration. The image cropping window in crop + * will also be adjusted if necessary. Preference is given to keeping the + * the window as close to the requested configuration as possible. If + * successful, new_win, vout->win, and crop are updated. + * Returns zero if succesful, or -EINVAL if the requested preview window is + * impossible and cannot reasonably be adjusted. + */ +int omap_vout_new_window(struct v4l2_rect *crop, + struct v4l2_window *win, struct v4l2_framebuffer *fbuf, + struct v4l2_window *new_win) +{ + int err; + + err = omap_vout_try_window(fbuf, new_win); + if (err) + return err; + + /* update our preview window */ + win->w = new_win->w; + win->field = new_win->field; + win->chromakey = new_win->chromakey; + + /* Adjust the cropping window to allow for resizing limitation */ + if (cpu_is_omap24xx()) { + /* For 24xx limit is 8x to 1/2x scaling. */ + if ((crop->height/win->w.height) >= 2) + crop->height = win->w.height * 2; + + if ((crop->width/win->w.width) >= 2) + crop->width = win->w.width * 2; + + if (crop->width > 768) { + /* The OMAP2420 vertical resizing line buffer is 768 + * pixels wide. If the cropped image is wider than + * 768 pixels then it cannot be vertically resized. + */ + if (crop->height != win->w.height) + crop->width = 768; + } + } else if (cpu_is_omap34xx()) { + /* For 34xx limit is 8x to 1/4x scaling. */ + if ((crop->height/win->w.height) >= 4) + crop->height = win->w.height * 4; + + if ((crop->width/win->w.width) >= 4) + crop->width = win->w.width * 4; + } + return 0; +} +EXPORT_SYMBOL_GPL(omap_vout_new_window); + +/* Given a new cropping rectangle in new_crop, adjust the cropping rectangle to + * the nearest supported configuration. The image render window in win will + * also be adjusted if necessary. The preview window is adjusted such that the + * horizontal and vertical rescaling ratios stay constant. If the render + * window would fall outside the display boundaries, the cropping rectangle + * will also be adjusted to maintain the rescaling ratios. If successful, crop + * and win are updated. + * Returns zero if succesful, or -EINVAL if the requested cropping rectangle is + * impossible and cannot reasonably be adjusted. + */ +int omap_vout_new_crop(struct v4l2_pix_format *pix, + struct v4l2_rect *crop, struct v4l2_window *win, + struct v4l2_framebuffer *fbuf, const struct v4l2_rect *new_crop) +{ + struct v4l2_rect try_crop; + unsigned long vresize, hresize; + + /* make a working copy of the new_crop rectangle */ + try_crop = *new_crop; + + /* adjust the cropping rectangle so it fits in the image */ + if (try_crop.left < 0) { + try_crop.width += try_crop.left; + try_crop.left = 0; + } + if (try_crop.top < 0) { + try_crop.height += try_crop.top; + try_crop.top = 0; + } + try_crop.width = (try_crop.width < pix->width) ? + try_crop.width : pix->width; + try_crop.height = (try_crop.height < pix->height) ? + try_crop.height : pix->height; + if (try_crop.left + try_crop.width > pix->width) + try_crop.width = pix->width - try_crop.left; + if (try_crop.top + try_crop.height > pix->height) + try_crop.height = pix->height - try_crop.top; + + try_crop.width &= ~1; + try_crop.height &= ~1; + + if (try_crop.width <= 0 || try_crop.height <= 0) + return -EINVAL; + + if (cpu_is_omap24xx()) { + if (crop->height != win->w.height) { + /* If we're resizing vertically, we can't support a + * crop width wider than 768 pixels. + */ + if (try_crop.width > 768) + try_crop.width = 768; + } + } + /* vertical resizing */ + vresize = (1024 * crop->height) / win->w.height; + if (cpu_is_omap24xx() && (vresize > 2048)) + vresize = 2048; + else if (cpu_is_omap34xx() && (vresize > 4096)) + vresize = 4096; + + win->w.height = ((1024 * try_crop.height) / vresize) & ~1; + if (win->w.height == 0) + win->w.height = 2; + if (win->w.height + win->w.top > fbuf->fmt.height) { + /* We made the preview window extend below the bottom of the + * display, so clip it to the display boundary and resize the + * cropping height to maintain the vertical resizing ratio. + */ + win->w.height = (fbuf->fmt.height - win->w.top) & ~1; + if (try_crop.height == 0) + try_crop.height = 2; + } + /* horizontal resizing */ + hresize = (1024 * crop->width) / win->w.width; + if (cpu_is_omap24xx() && (hresize > 2048)) + hresize = 2048; + else if (cpu_is_omap34xx() && (hresize > 4096)) + hresize = 4096; + + win->w.width = ((1024 * try_crop.width) / hresize) & ~1; + if (win->w.width == 0) + win->w.width = 2; + if (win->w.width + win->w.left > fbuf->fmt.width) { + /* We made the preview window extend past the right side of the + * display, so clip it to the display boundary and resize the + * cropping width to maintain the horizontal resizing ratio. + */ + win->w.width = (fbuf->fmt.width - win->w.left) & ~1; + if (try_crop.width == 0) + try_crop.width = 2; + } + if (cpu_is_omap24xx()) { + if ((try_crop.height/win->w.height) >= 2) + try_crop.height = win->w.height * 2; + + if ((try_crop.width/win->w.width) >= 2) + try_crop.width = win->w.width * 2; + + if (try_crop.width > 768) { + /* The OMAP2420 vertical resizing line buffer is + * 768 pixels wide. If the cropped image is wider + * than 768 pixels then it cannot be vertically resized. + */ + if (try_crop.height != win->w.height) + try_crop.width = 768; + } + } else if (cpu_is_omap34xx()) { + if ((try_crop.height/win->w.height) >= 4) + try_crop.height = win->w.height * 4; + + if ((try_crop.width/win->w.width) >= 4) + try_crop.width = win->w.width * 4; + } + /* update our cropping rectangle and we're done */ + *crop = try_crop; + return 0; +} +EXPORT_SYMBOL_GPL(omap_vout_new_crop); + +/* Given a new format in pix and fbuf, crop and win + * structures are initialized to default values. crop + * is initialized to the largest window size that will fit on the display. The + * crop window is centered in the image. win is initialized to + * the same size as crop and is centered on the display. + * All sizes and offsets are constrained to be even numbers. + */ +void omap_vout_new_format(struct v4l2_pix_format *pix, + struct v4l2_framebuffer *fbuf, struct v4l2_rect *crop, + struct v4l2_window *win) +{ + /* crop defines the preview source window in the image capture + * buffer + */ + omap_vout_default_crop(pix, fbuf, crop); + + /* win defines the preview target window on the display */ + win->w.width = crop->width; + win->w.height = crop->height; + win->w.left = ((fbuf->fmt.width - win->w.width) >> 1) & ~1; + win->w.top = ((fbuf->fmt.height - win->w.height) >> 1) & ~1; +} +EXPORT_SYMBOL_GPL(omap_vout_new_format); + diff --git a/drivers/media/video/omap/omap_voutlib.h b/drivers/media/video/omap/omap_voutlib.h new file mode 100644 index 00000000000..a60b16e8bfc --- /dev/null +++ b/drivers/media/video/omap/omap_voutlib.h @@ -0,0 +1,34 @@ +/* + * omap_voutlib.h + * + * Copyright (C) 2010 Texas Instruments. + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + * + */ + +#ifndef OMAP_VOUTLIB_H +#define OMAP_VOUTLIB_H + +extern void omap_vout_default_crop(struct v4l2_pix_format *pix, + struct v4l2_framebuffer *fbuf, struct v4l2_rect *crop); + +extern int omap_vout_new_crop(struct v4l2_pix_format *pix, + struct v4l2_rect *crop, struct v4l2_window *win, + struct v4l2_framebuffer *fbuf, + const struct v4l2_rect *new_crop); + +extern int omap_vout_try_window(struct v4l2_framebuffer *fbuf, + struct v4l2_window *new_win); + +extern int omap_vout_new_window(struct v4l2_rect *crop, + struct v4l2_window *win, struct v4l2_framebuffer *fbuf, + struct v4l2_window *new_win); + +extern void omap_vout_new_format(struct v4l2_pix_format *pix, + struct v4l2_framebuffer *fbuf, struct v4l2_rect *crop, + struct v4l2_window *win); +#endif /* #ifndef OMAP_VOUTLIB_H */ + -- cgit v1.2.3-70-g09d2 From 72fcf2a8daac43f8e3bce62a1c1124859b323006 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Sun, 11 Apr 2010 10:50:23 -0300 Subject: V4L/DVB: omap_vout:V4L2 Display: Changed enum return type to int Signed-off-by: Vaibhav Hiremath Signed-off-by: Muralidharan Karicheri Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/omap/omap_vout.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c index f2100671851..4c0ab499228 100644 --- a/drivers/media/video/omap/omap_vout.c +++ b/drivers/media/video/omap/omap_vout.c @@ -622,8 +622,7 @@ static int omap_vout_calculate_offset(struct omap_vout_device *vout) /* * Convert V4L2 pixel format to DSS pixel format */ -static enum omap_color_mode video_mode_to_dss_mode(struct omap_vout_device - *vout) +static int video_mode_to_dss_mode(struct omap_vout_device *vout) { struct omap_overlay *ovl; struct omapvideo_info *ovid; -- cgit v1.2.3-70-g09d2 From 96f2ec67b8d4761471409e1df0adfe4da5262f84 Mon Sep 17 00:00:00 2001 From: Pawel Osciak Date: Wed, 21 Apr 2010 06:44:27 -0300 Subject: V4L/DVB: v4l: videobuf: qbuf now uses relevant v4l2_buffer fields for OUTPUT types According to the V4L2 specification, applications set bytesused, field and timestamp fields of struct v4l2_buffer when the buffer is intended for output and memory type is MMAP. This adds proper copying of those values to videobuf_buffer so drivers can use them. Signed-off-by: Pawel Osciak Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-core.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c index dc2f6a8c022..9f99e3bf539 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/video/videobuf-core.c @@ -544,6 +544,13 @@ int videobuf_qbuf(struct videobuf_queue *q, struct v4l2_buffer *b) "but buffer addr is zero!\n"); goto done; } + if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT + || q->type == V4L2_BUF_TYPE_VBI_OUTPUT + || q->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) { + buf->size = b->bytesused; + buf->field = b->field; + buf->ts = b->timestamp; + } break; case V4L2_MEMORY_USERPTR: if (b->length < buf->bsize) { -- cgit v1.2.3-70-g09d2 From bdd2b93c44bf70eac3c5ef7da62355e1e48ee1eb Mon Sep 17 00:00:00 2001 From: Jean-François Moine Date: Sun, 25 Apr 2010 14:23:39 -0300 Subject: V4L/DVB: gspca - sonixj: Split the init sequence of sensor ov7630 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sonixj.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index d90c065a98e..01c4a20b787 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -878,7 +878,9 @@ static const u8 ov7630_sensor_init[][8] = { {0xc1, 0x21, 0x7b, 0x00, 0x4c, 0xf7, 0x00, 0x10}, {0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10}, {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10}, -/* */ + {} +}; +static const u8 ov7630_sensor_param1[][8] = { {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10}, {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10}, /*fixme: + 0x12, 0x04*/ @@ -2369,6 +2371,7 @@ static int sd_start(struct gspca_dev *gspca_dev) reg17 = 0x64; /* 640 MCKSIZE */ break; case SENSOR_OV7630: + init = ov7630_sensor_param1; reg17 = 0xe2; reg1 = 0x44; break; -- cgit v1.2.3-70-g09d2 From cfd23c8eca3587fcb20f308532293e92d1f248a8 Mon Sep 17 00:00:00 2001 From: Jean-François Moine Date: Sun, 25 Apr 2010 14:27:39 -0300 Subject: V4L/DVB: gspca - sonixj: Adjust debug output. - fix bad function name - add debug info for i2c buffer write MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sonixj.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 01c4a20b787..ae826186f35 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -1337,7 +1337,7 @@ static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val) { struct sd *sd = (struct sd *) gspca_dev; - PDEBUG(D_USBO, "i2c_w2 [%02x] = %02x", reg, val); + PDEBUG(D_USBO, "i2c_w1 [%02x] = %02x", reg, val); switch (sd->sensor) { case SENSOR_ADCM1700: case SENSOR_OM6802: @@ -1369,6 +1369,8 @@ static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val) static void i2c_w8(struct gspca_dev *gspca_dev, const u8 *buffer) { + PDEBUG(D_USBO, "i2c_w8 [%02x] = %02x ..", + buffer[2], buffer[3]); memcpy(gspca_dev->usb_buf, buffer, 8); usb_control_msg(gspca_dev->dev, usb_sndctrlpipe(gspca_dev->dev, 0), -- cgit v1.2.3-70-g09d2 From fff2f708f8838c9be0099d32ed1739e9aa42af6f Mon Sep 17 00:00:00 2001 From: Jean-François Moine Date: Sun, 25 Apr 2010 14:31:05 -0300 Subject: V4L/DVB: gspca - sonixj: Set the colors at startup time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sonixj.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index ae826186f35..612c5419c95 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -2467,6 +2467,7 @@ static int sd_start(struct gspca_dev *gspca_dev) setvflip(sd); setbrightness(gspca_dev); setcontrast(gspca_dev); + setcolors(gspca_dev); setautogain(gspca_dev); setfreq(gspca_dev); return 0; -- cgit v1.2.3-70-g09d2 From 0a85c74b5d48f6cb41770ec3951a582738446b33 Mon Sep 17 00:00:00 2001 From: Jean-François Moine Date: Sun, 25 Apr 2010 14:33:31 -0300 Subject: V4L/DVB: gspca - sonixj: Adjust minor values of sensor ov7630. - set the color gains to null at init time - change value of register 0x9a MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sonixj.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 612c5419c95..a4ca3c11c42 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -442,7 +442,7 @@ static const u8 sn_om6802[0x1c] = { static const u8 sn_ov7630[0x1c] = { /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ - 0x00, 0x21, 0x40, 0x00, 0x1a, 0x20, 0x1f, 0x20, + 0x00, 0x21, 0x40, 0x00, 0x1a, 0x00, 0x00, 0x00, /* reg8 reg9 rega regb regc regd rege regf */ 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ @@ -2315,6 +2315,7 @@ static int sd_start(struct gspca_dev *gspca_dev) case SENSOR_MT9V111: reg_w1(gspca_dev, 0x9a, 0x07); break; + case SENSOR_OV7630: case SENSOR_OV7648: reg_w1(gspca_dev, 0x9a, 0x0a); break; -- cgit v1.2.3-70-g09d2 From e3302cad9bc111e158e03eff763dff36bce02fe6 Mon Sep 17 00:00:00 2001 From: Jean-François Moine Date: Sun, 25 Apr 2010 14:41:51 -0300 Subject: V4L/DVB: gspca - sonixj: Reset the bridge after sensor probe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sonixj.c | 41 ++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 22 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index a4ca3c11c42..19ae4f5ca73 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -1498,42 +1498,43 @@ static void mi0360_probe(struct gspca_dev *gspca_dev) static void ov7648_probe(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + u16 val; /* check ov76xx */ reg_w1(gspca_dev, 0x17, 0x62); reg_w1(gspca_dev, 0x01, 0x08); sd->i2c_addr = 0x21; i2c_r(gspca_dev, 0x0a, 2); - if (gspca_dev->usb_buf[3] == 0x76) { /* ov76xx */ - PDEBUG(D_PROBE, "Sensor ov%02x%02x", - gspca_dev->usb_buf[3], gspca_dev->usb_buf[4]); - return; - } - - /* reset */ + val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4]; reg_w1(gspca_dev, 0x01, 0x29); reg_w1(gspca_dev, 0x17, 0x42); + if ((val & 0xff00) == 0x7600) { /* ov76xx */ + PDEBUG(D_PROBE, "Sensor ov%04x", val); + return; + } /* check po1030 */ reg_w1(gspca_dev, 0x17, 0x62); reg_w1(gspca_dev, 0x01, 0x08); sd->i2c_addr = 0x6e; i2c_r(gspca_dev, 0x00, 2); - if (gspca_dev->usb_buf[3] == 0x10 /* po1030 */ - && gspca_dev->usb_buf[4] == 0x30) { + val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4]; + reg_w1(gspca_dev, 0x01, 0x29); + reg_w1(gspca_dev, 0x17, 0x42); + if (val == 0x1030) { /* po1030 */ PDEBUG(D_PROBE, "Sensor po1030"); sd->sensor = SENSOR_PO1030; return; } - PDEBUG(D_PROBE, "Unknown sensor %02x%02x", - gspca_dev->usb_buf[3], gspca_dev->usb_buf[4]); + PDEBUG(D_PROBE, "Unknown sensor %04x", val); } /* 0c45:6142 sensor may be po2030n, gc0305 or gc0307 */ static void po2030n_probe(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + u16 val; /* check gc0307 */ reg_w1(gspca_dev, 0x17, 0x62); @@ -1541,11 +1542,10 @@ static void po2030n_probe(struct gspca_dev *gspca_dev) reg_w1(gspca_dev, 0x02, 0x22); sd->i2c_addr = 0x21; i2c_r(gspca_dev, 0x00, 1); - + val = gspca_dev->usb_buf[4]; reg_w1(gspca_dev, 0x01, 0x29); /* reset */ reg_w1(gspca_dev, 0x17, 0x42); - - if (gspca_dev->usb_buf[4] == 0x99) { /* gc0307 (?) */ + if (val == 0x99) { /* gc0307 (?) */ PDEBUG(D_PROBE, "Sensor gc0307"); sd->sensor = SENSOR_GC0307; return; @@ -1556,18 +1556,15 @@ static void po2030n_probe(struct gspca_dev *gspca_dev) reg_w1(gspca_dev, 0x01, 0x0a); sd->i2c_addr = 0x6e; i2c_r(gspca_dev, 0x00, 2); - + val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4]; reg_w1(gspca_dev, 0x01, 0x29); reg_w1(gspca_dev, 0x17, 0x42); - - if (gspca_dev->usb_buf[3] == 0x20 - && gspca_dev->usb_buf[4] == 0x30) + if (val == 0x2030) { PDEBUG(D_PROBE, "Sensor po2030n"); /* sd->sensor = SENSOR_PO2030N; */ - else - PDEBUG(D_PROBE, "Unknown sensor ID %02x%02x", - gspca_dev->usb_buf[3], - gspca_dev->usb_buf[4]); + } else { + PDEBUG(D_PROBE, "Unknown sensor ID %04x", val); + } } static void bridge_init(struct gspca_dev *gspca_dev, -- cgit v1.2.3-70-g09d2 From 03ed2a11eac62c15be28f58b182003fc56ca4f82 Mon Sep 17 00:00:00 2001 From: Jean-François Moine Date: Sun, 25 Apr 2010 14:45:43 -0300 Subject: V4L/DVB: gspca - sonixj: Add sensor soi768 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The webcams 0c45:613e may contain the sensors ov7630 or soi768. A sensor probe is done at init time when the sensor is declared ov7630. Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sonixj.c | 95 +++++++++++++++++++++++++++++++++++++- 1 file changed, 94 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 19ae4f5ca73..bb923efb75b 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -80,6 +80,7 @@ enum { SENSOR_OV7660, SENSOR_PO1030, SENSOR_PO2030N, + SENSOR_SOI768, SENSOR_SP80708, } sensors; u8 i2c_addr; @@ -330,6 +331,10 @@ static const __u32 ctrl_dis[] = { (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX), +[SENSOR_SOI768] = (1 << AUTOGAIN_IDX) | + (1 << INFRARED_IDX) | + (1 << VFLIP_IDX) | + (1 << FREQ_IDX), [SENSOR_SP80708] = (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | @@ -495,6 +500,17 @@ static const u8 sn_po2030n[0x1c] = { 0x07, 0x00, 0x00, 0x00 }; +static const u8 sn_soi768[0x1c] = { +/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ + 0x00, 0x21, 0x40, 0x00, 0x1a, 0x00, 0x00, 0x00, +/* reg8 reg9 rega regb regc regd rege regf */ + 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ + 0x03, 0x00, 0x00, 0x01, 0x08, 0x28, 0x1e, 0x00, +/* reg18 reg19 reg1a reg1b */ + 0x07, 0x00, 0x00, 0x00 +}; + static const u8 sn_sp80708[0x1c] = { /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ 0x00, 0x63, 0x60, 0x00, 0x1a, 0x20, 0x20, 0x20, @@ -520,7 +536,8 @@ static const u8 *sn_tb[] = { [SENSOR_OV7660] = sn_ov7660, [SENSOR_PO1030] = sn_po1030, [SENSOR_PO2030N] = sn_po2030n, -[SENSOR_SP80708] = sn_sp80708 +[SENSOR_SOI768] = sn_soi768, +[SENSOR_SP80708] = sn_sp80708, }; /* default gamma table */ @@ -1173,6 +1190,37 @@ static const u8 po2030n_sensor_param1[][8] = { {} }; +static const u8 soi768_sensor_init[][8] = { + {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset */ + {0xdd, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 96ms */ + {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x21, 0x13, 0x80, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x21, 0x0f, 0x03, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x21, 0x19, 0x00, 0x00, 0x00, 0x00, 0x10}, + {} +}; +static const u8 soi768_sensor_param1[][8] = { + {0xa1, 0x21, 0x10, 0x10, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xb1, 0x21, 0x01, 0x7f, 0x7f, 0x00, 0x00, 0x10}, +/* */ +/* {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, */ +/* {0xa1, 0x21, 0x2d, 0x25, 0x00, 0x00, 0x00, 0x10}, */ + {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, +/* {0xb1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, */ + {0xa1, 0x21, 0x02, 0x8d, 0x00, 0x00, 0x00, 0x10}, +/* the next sequence should be used for auto gain */ + {0xa1, 0x21, 0x00, 0x07, 0x00, 0x00, 0x00, 0x10}, + /* global gain ? : 07 - change with 0x15 at the end */ + {0xa1, 0x21, 0x10, 0x3f, 0x00, 0x00, 0x00, 0x10}, /* ???? : 063f */ + {0xa1, 0x21, 0x04, 0x06, 0x00, 0x00, 0x00, 0x10}, + {0xb1, 0x21, 0x2d, 0x00, 0x02, 0x00, 0x00, 0x10}, + /* exposure ? : 0200 - change with 0x1e at the end */ + {} +}; + static const u8 sp80708_sensor_init[][8] = { {0xa1, 0x18, 0x06, 0xf9, 0x00, 0x00, 0x00, 0x10}, {0xa1, 0x18, 0x09, 0x1f, 0x00, 0x00, 0x00, 0x10}, @@ -1271,6 +1319,7 @@ static const u8 (*sensor_init[])[8] = { [SENSOR_OV7660] = ov7660_sensor_init, [SENSOR_PO1030] = po1030_sensor_init, [SENSOR_PO2030N] = po2030n_sensor_init, +[SENSOR_SOI768] = soi768_sensor_init, [SENSOR_SP80708] = sp80708_sensor_init, }; @@ -1495,6 +1544,30 @@ static void mi0360_probe(struct gspca_dev *gspca_dev) } } +static void ov7630_probe(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + u16 val; + + /* check ov76xx */ + reg_w1(gspca_dev, 0x17, 0x62); + reg_w1(gspca_dev, 0x01, 0x08); + sd->i2c_addr = 0x21; + i2c_r(gspca_dev, 0x0a, 2); + val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4]; + reg_w1(gspca_dev, 0x01, 0x29); + reg_w1(gspca_dev, 0x17, 0x42); + if (val == 0x7628) { /* soi768 */ + sd->sensor = SENSOR_SOI768; +/*fixme: only valid for 0c45:613e?*/ + gspca_dev->cam.input_flags = + V4L2_IN_ST_VFLIP | V4L2_IN_ST_HFLIP; + PDEBUG(D_PROBE, "Sensor soi768"); + return; + } + PDEBUG(D_PROBE, "Sensor ov%04x", val); +} + static void ov7648_probe(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -1591,6 +1664,7 @@ static void bridge_init(struct gspca_dev *gspca_dev, case SENSOR_OV7660: case SENSOR_PO1030: case SENSOR_PO2030N: + case SENSOR_SOI768: case SENSOR_SP80708: reg9a = reg9a_spec; break; @@ -1656,6 +1730,7 @@ static void bridge_init(struct gspca_dev *gspca_dev, reg_w1(gspca_dev, 0x01, 0x42); break; case SENSOR_PO1030: + case SENSOR_SOI768: reg_w1(gspca_dev, 0x01, 0x61); reg_w1(gspca_dev, 0x17, 0x20); reg_w1(gspca_dev, 0x01, 0x60); @@ -1771,6 +1846,9 @@ static int sd_init(struct gspca_dev *gspca_dev) case SENSOR_MI0360: mi0360_probe(gspca_dev); break; + case SENSOR_OV7630: + ov7630_probe(gspca_dev); + break; case SENSOR_OV7648: ov7648_probe(gspca_dev); break; @@ -2280,6 +2358,7 @@ static int sd_start(struct gspca_dev *gspca_dev) reg17 = 0x20; break; case SENSOR_OV7660: + case SENSOR_SOI768: reg17 = 0xa0; break; case SENSOR_PO1030: @@ -2317,6 +2396,7 @@ static int sd_start(struct gspca_dev *gspca_dev) reg_w1(gspca_dev, 0x9a, 0x0a); break; case SENSOR_PO2030N: + case SENSOR_SOI768: reg_w1(gspca_dev, 0x9a, 0x06); break; default: @@ -2403,6 +2483,11 @@ static int sd_start(struct gspca_dev *gspca_dev) reg1 = 0x46; reg17 = 0xa2; break; + case SENSOR_SOI768: + init = soi768_sensor_param1; + reg1 = 0x44; + reg17 = 0xa2; + break; default: /* case SENSOR_SP80708: */ init = sp80708_sensor_param1; @@ -2425,6 +2510,7 @@ static int sd_start(struct gspca_dev *gspca_dev) switch (sd->sensor) { case SENSOR_ADCM1700: case SENSOR_GC0307: + case SENSOR_SOI768: reg_w(gspca_dev, 0xca, CA_adcm1700, 4); break; case SENSOR_PO2030N: @@ -2439,6 +2525,7 @@ static int sd_start(struct gspca_dev *gspca_dev) case SENSOR_OV7630: case SENSOR_OV7648: case SENSOR_OV7660: + case SENSOR_SOI768: reg_w(gspca_dev, 0xce, CE_ov76xx, 4); break; case SENSOR_GC0307: @@ -2480,6 +2567,8 @@ static void sd_stopN(struct gspca_dev *gspca_dev) { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 }; static const u8 stopov7648[] = { 0xa1, 0x21, 0x76, 0x20, 0x00, 0x00, 0x00, 0x10 }; + static const u8 stopsoi768[] = + { 0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10 }; u8 data; const u8 *sn9c1xx; @@ -2504,6 +2593,10 @@ static void sd_stopN(struct gspca_dev *gspca_dev) case SENSOR_PO1030: data = 0x29; break; + case SENSOR_SOI768: + i2c_w8(gspca_dev, stopsoi768); + data = 0x29; + break; } sn9c1xx = sn_tb[sd->sensor]; reg_w1(gspca_dev, 0x01, sn9c1xx[1]); -- cgit v1.2.3-70-g09d2 From a6a86f0d2cb472450f72774794db4a76a570766d Mon Sep 17 00:00:00 2001 From: Jean-François Moine Date: Sun, 25 Apr 2010 14:57:10 -0300 Subject: V4L/DVB: gspca - zc3xx: Fix the light frequency values for pas202b and pb0330 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The error was introduced by "gspca - zc3xx: Rename the USB sequences." in commit e945e2e44c798f84494260c02478d3c23965bb93. Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/zc3xx.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index 7d7814c43f9..582a30dcb50 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -6203,13 +6203,13 @@ static int setlightfreq(struct gspca_dev *gspca_dev) pas106b_50HZ, pas106b_50HZ, pas106b_60HZ, pas106b_60HZ}, /* SENSOR_PAS202B 13 */ - {pas202b_NoFlikerScale, pas202b_NoFliker, - pas202b_50HZScale, pas202b_50HZ, - pas202b_60HZScale, pas202b_60HZ}, + {pas202b_NoFliker, pas202b_NoFlikerScale, + pas202b_50HZ, pas202b_50HZScale, + pas202b_60HZ, pas202b_60HZScale}, /* SENSOR_PB0330 14 */ - {pb0330_NoFlikerScale, pb0330_NoFliker, - pb0330_50HZScale, pb0330_50HZ, - pb0330_60HZScale, pb0330_60HZ}, + {pb0330_NoFliker, pb0330_NoFlikerScale, + pb0330_50HZ, pb0330_50HZScale, + pb0330_60HZ, pb0330_60HZScale}, /* SENSOR_PO2030 15 */ {po2030_NoFliker, po2030_NoFliker, po2030_50HZ, po2030_50HZ, -- cgit v1.2.3-70-g09d2 From 07ae4918f75f26f4f4200de186a27178c7e58038 Mon Sep 17 00:00:00 2001 From: Jean-François Moine Date: Sun, 25 Apr 2010 15:05:31 -0300 Subject: V4L/DVB: gspca - zc3xx.c: Remove the brightness control MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Brightness is done by the gamma tables and not by single bridge registers. It will be back as soon as an algorithm will be found. This change also fixes the autogain problem found by Jose Alberto Reguero (webcam 046d:08dd). Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/zc3xx.c | 73 +-------------------------------------- 1 file changed, 1 insertion(+), 72 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index 582a30dcb50..1bab5086bad 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -40,7 +40,6 @@ static int force_sensor = -1; struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ - u8 brightness; u8 contrast; u8 gamma; u8 autogain; @@ -80,8 +79,6 @@ struct sd { }; /* V4L2 controls supported by the driver */ -static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); -static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); @@ -94,21 +91,6 @@ static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val); static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); static const struct ctrl sd_ctrls[] = { -#define BRIGHTNESS_IDX 0 - { - { - .id = V4L2_CID_BRIGHTNESS, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Brightness", - .minimum = 0, - .maximum = 255, - .step = 1, -#define BRIGHTNESS_DEF 128 - .default_value = BRIGHTNESS_DEF, - }, - .set = sd_setbrightness, - .get = sd_getbrightness, - }, { { .id = V4L2_CID_CONTRAST, @@ -150,7 +132,7 @@ static const struct ctrl sd_ctrls[] = { .set = sd_setautogain, .get = sd_getautogain, }, -#define LIGHTFREQ_IDX 4 +#define LIGHTFREQ_IDX 3 { { .id = V4L2_CID_POWER_LINE_FREQUENCY, @@ -6004,33 +5986,6 @@ static void setmatrix(struct gspca_dev *gspca_dev) reg_w(gspca_dev->dev, matrix[i], 0x010a + i); } -static void setbrightness(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - u8 brightness; - - switch (sd->sensor) { - case SENSOR_GC0305: - case SENSOR_OV7620: - case SENSOR_PAS202B: - case SENSOR_PO2030: - return; - } -/*fixme: is it really write to 011d and 018d for all other sensors? */ - brightness = sd->brightness; - reg_w(gspca_dev->dev, brightness, 0x011d); - switch (sd->sensor) { - case SENSOR_ADCM2700: - case SENSOR_HV7131B: - return; - } - if (brightness < 0x70) - brightness += 0x10; - else - brightness = 0x80; - reg_w(gspca_dev->dev, brightness, 0x018d); -} - static void setsharpness(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -6789,7 +6744,6 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->nmodes = ARRAY_SIZE(broken_vga_mode); break; } - sd->brightness = BRIGHTNESS_DEF; sd->contrast = CONTRAST_DEF; sd->gamma = gamma[sd->sensor]; sd->autogain = AUTOGAIN_DEF; @@ -6797,12 +6751,6 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->quality = QUALITY_DEF; switch (sd->sensor) { - case SENSOR_GC0305: - case SENSOR_OV7620: - case SENSOR_PAS202B: - case SENSOR_PO2030: - gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX); - break; case SENSOR_HV7131B: case SENSOR_HV7131C: case SENSOR_OV7630C: @@ -6893,7 +6841,6 @@ static int sd_start(struct gspca_dev *gspca_dev) } setmatrix(gspca_dev); - setbrightness(gspca_dev); switch (sd->sensor) { case SENSOR_ADCM2700: case SENSOR_OV7620: @@ -7015,24 +6962,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, gspca_frame_add(gspca_dev, INTER_PACKET, data, len); } -static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->brightness = val; - if (gspca_dev->streaming) - setbrightness(gspca_dev); - return 0; -} - -static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - *val = sd->brightness; - return 0; -} - static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; -- cgit v1.2.3-70-g09d2 From a85675316f24835ce0c3286ee3cb33fa2f24bca7 Mon Sep 17 00:00:00 2001 From: Jean-François Moine Date: Sun, 25 Apr 2010 15:25:42 -0300 Subject: V4L/DVB: gspca - zc3xx: Fix the gamma calculation from the contrast MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/zc3xx.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index 1bab5086bad..d02aa5c8472 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -6014,8 +6014,8 @@ static void setcontrast(struct gspca_dev *gspca_dev) int g, i, k, adj, gp; u8 gr[16]; static const u8 delta_tb[16] = /* delta for contrast */ - {0x15, 0x0d, 0x0a, 0x09, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08}; + {0x2c, 0x1a, 0x12, 0x0c, 0x0a, 0x06, 0x06, 0x06, + 0x04, 0x06, 0x04, 0x04, 0x03, 0x03, 0x02, 0x02}; static const u8 gamma_tb[6][16] = { {0x00, 0x00, 0x03, 0x0d, 0x1b, 0x2e, 0x45, 0x5f, 0x79, 0x93, 0xab, 0xc1, 0xd4, 0xe5, 0xf3, 0xff}, @@ -6037,11 +6037,11 @@ static void setcontrast(struct gspca_dev *gspca_dev) adj = 0; gp = 0; for (i = 0; i < 16; i++) { - g = Tgamma[i] - delta_tb[i] * k / 128 - adj / 2; + g = Tgamma[i] - delta_tb[i] * k / 256 - adj / 2; if (g > 0xff) g = 0xff; - else if (g <= 0) - g = 1; + else if (g < 0) + g = 0; reg_w(dev, g, 0x0120 + i); /* gamma */ if (k > 0) adj--; -- cgit v1.2.3-70-g09d2 From f3cd385a9c95e1ea90e886448ab1e83ee2fc7e51 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Mon, 3 May 2010 12:42:46 -0300 Subject: V4L/DVB: V4L: Events: Replace bad WARN_ON() with assert_spin_locked() spin_is_locked() always returns zero when spinlock debugging is disabled on a single CPU machine. Replace WARN_ON() with assert_spin_locked(). Thanks to Laurent Pinchart for spotting this! Signed-off-by: Sakari Ailus Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-event.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/v4l2-event.c b/drivers/media/video/v4l2-event.c index 170e40f56cf..91bb1c82399 100644 --- a/drivers/media/video/v4l2-event.c +++ b/drivers/media/video/v4l2-event.c @@ -152,7 +152,7 @@ static struct v4l2_subscribed_event *v4l2_event_subscribed( struct v4l2_events *events = fh->events; struct v4l2_subscribed_event *sev; - WARN_ON(!spin_is_locked(&fh->vdev->fh_lock)); + assert_spin_locked(&fh->vdev->fh_lock); list_for_each_entry(sev, &events->subscribed, list) { if (sev->type == type) -- cgit v1.2.3-70-g09d2 From 0a4f8d0798c834472b9d8d50df32b62c733009fd Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 2 May 2010 14:32:43 -0300 Subject: V4L/DVB: event: Export the v4l2_event_init and v4l2_event_dequeue functions Signed-off-by: Laurent Pinchart Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-event.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/v4l2-event.c b/drivers/media/video/v4l2-event.c index 91bb1c82399..de74ce07b5e 100644 --- a/drivers/media/video/v4l2-event.c +++ b/drivers/media/video/v4l2-event.c @@ -45,6 +45,7 @@ int v4l2_event_init(struct v4l2_fh *fh) return 0; } +EXPORT_SYMBOL_GPL(v4l2_event_init); int v4l2_event_alloc(struct v4l2_fh *fh, unsigned int n) { @@ -144,6 +145,7 @@ int v4l2_event_dequeue(struct v4l2_fh *fh, struct v4l2_event *event, return ret; } +EXPORT_SYMBOL_GPL(v4l2_event_dequeue); /* Caller must hold fh->event->lock! */ static struct v4l2_subscribed_event *v4l2_event_subscribed( -- cgit v1.2.3-70-g09d2 From 5a143b12ebbd37154cb06699a757e9c5845c5e19 Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Sat, 24 Apr 2010 18:14:00 -0300 Subject: V4L/DVB: ir-core: remove IR_TYPE_PD MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pulse-distance is not a protocol, it is a line coding (used by some protocols, like NEC). Looking at the uses of IR_TYPE_PD, the real protocol seems to be NEC in all cases (drivers/media/video/cx88/cx88-input.c is the only user). So, remove IR_TYPE_PD while it is still easy to do so. Signed-off-by: David Härdeman Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-sysfs.c | 6 ------ drivers/media/video/cx88/cx88-input.c | 8 ++++---- include/media/ir-kbd-i2c.h | 2 +- include/media/rc-map.h | 9 ++++----- 4 files changed, 9 insertions(+), 16 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c index 002b1412331..d7da63e16c9 100644 --- a/drivers/media/IR/ir-sysfs.c +++ b/drivers/media/IR/ir-sysfs.c @@ -57,8 +57,6 @@ static ssize_t show_protocol(struct device *d, s = "Unknown"; else if (ir_type == IR_TYPE_RC5) s = "rc-5"; - else if (ir_type == IR_TYPE_PD) - s = "pulse-distance"; else if (ir_type == IR_TYPE_NEC) s = "nec"; else if (ir_type == IR_TYPE_RC6) @@ -100,8 +98,6 @@ static ssize_t store_protocol(struct device *d, while ((buf = strsep((char **) &data, " \n")) != NULL) { if (!strcasecmp(buf, "rc-5") || !strcasecmp(buf, "rc5")) ir_type |= IR_TYPE_RC5; - if (!strcasecmp(buf, "pd") || !strcasecmp(buf, "pulse-distance")) - ir_type |= IR_TYPE_PD; if (!strcasecmp(buf, "nec")) ir_type |= IR_TYPE_NEC; if (!strcasecmp(buf, "jvc")) @@ -146,8 +142,6 @@ static ssize_t show_supported_protocols(struct device *d, buf += sprintf(buf, "unknown "); if (ir_dev->props->allowed_protos & IR_TYPE_RC5) buf += sprintf(buf, "rc-5 "); - if (ir_dev->props->allowed_protos & IR_TYPE_PD) - buf += sprintf(buf, "pulse-distance "); if (ir_dev->props->allowed_protos & IR_TYPE_NEC) buf += sprintf(buf, "nec "); if (buf == orgbuf) diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index 76733349c6c..e185289e446 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -272,7 +272,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) break; case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: ir_codes = RC_MAP_CINERGY_1400; - ir_type = IR_TYPE_PD; + ir_type = IR_TYPE_NEC; ir->sampling = 0xeb04; /* address */ break; case CX88_BOARD_HAUPPAUGE: @@ -375,18 +375,18 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) case CX88_BOARD_PROF_7301: case CX88_BOARD_PROF_6200: ir_codes = RC_MAP_TBS_NEC; - ir_type = IR_TYPE_PD; + ir_type = IR_TYPE_NEC; ir->sampling = 0xff00; /* address */ break; case CX88_BOARD_TEVII_S460: case CX88_BOARD_TEVII_S420: ir_codes = RC_MAP_TEVII_NEC; - ir_type = IR_TYPE_PD; + ir_type = IR_TYPE_NEC; ir->sampling = 0xff00; /* address */ break; case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: ir_codes = RC_MAP_DNTV_LIVE_DVBT_PRO; - ir_type = IR_TYPE_PD; + ir_type = IR_TYPE_NEC; ir->sampling = 0xff00; /* address */ break; case CX88_BOARD_NORWOOD_MICRO: diff --git a/include/media/ir-kbd-i2c.h b/include/media/ir-kbd-i2c.h index 057ff64f349..0506e45c9a4 100644 --- a/include/media/ir-kbd-i2c.h +++ b/include/media/ir-kbd-i2c.h @@ -36,7 +36,7 @@ enum ir_kbd_get_key_fn { struct IR_i2c_init_data { char *ir_codes; const char *name; - u64 type; /* IR_TYPE_RC5, IR_TYPE_PD, etc */ + u64 type; /* IR_TYPE_RC5, etc */ /* * Specify either a function pointer or a value indicating one of * ir_kbd_i2c's internal get_key functions diff --git a/include/media/rc-map.h b/include/media/rc-map.h index 280d1ed9a9a..5833966a710 100644 --- a/include/media/rc-map.h +++ b/include/media/rc-map.h @@ -13,11 +13,10 @@ #define IR_TYPE_UNKNOWN 0 #define IR_TYPE_RC5 (1 << 0) /* Philips RC5 protocol */ -#define IR_TYPE_PD (1 << 1) /* Pulse distance encoded IR */ -#define IR_TYPE_NEC (1 << 2) -#define IR_TYPE_RC6 (1 << 3) /* Philips RC6 protocol */ -#define IR_TYPE_JVC (1 << 4) /* JVC protocol */ -#define IR_TYPE_SONY (1 << 5) /* Sony12/15/20 protocol */ +#define IR_TYPE_NEC (1 << 1) +#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_OTHER (1u << 31) struct ir_scancode { -- cgit v1.2.3-70-g09d2 From 96c1f99621a73c58f97d7ca615b2fe936abda555 Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Sat, 24 Apr 2010 18:14:16 -0300 Subject: V4L/DVB: ir-core: remove ir-functions usage from cx231xx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convert drivers/media/video/cx231xx/cx231xx-input.c to not rely on ir-functions.c. (I do not have the hardware so I can only compile test this) Signed-off-by: David Härdeman Cc: Srinivasa Deevi Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx231xx/cx231xx-input.c | 47 ++++++----------------------- drivers/media/video/cx231xx/cx231xx.h | 2 +- 2 files changed, 10 insertions(+), 39 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx231xx/cx231xx-input.c b/drivers/media/video/cx231xx/cx231xx-input.c index 04ae0839dea..fd099153b74 100644 --- a/drivers/media/video/cx231xx/cx231xx-input.c +++ b/drivers/media/video/cx231xx/cx231xx-input.c @@ -61,7 +61,6 @@ struct cx231xx_ir_poll_result { struct cx231xx_IR { struct cx231xx *dev; struct input_dev *input; - struct ir_input_state ir; char name[32]; char phys[32]; @@ -69,9 +68,7 @@ struct cx231xx_IR { int polling; struct work_struct work; struct timer_list timer; - unsigned int last_toggle:1; unsigned int last_readcount; - unsigned int repeat_interval; int (*get_key) (struct cx231xx_IR *, struct cx231xx_ir_poll_result *); }; @@ -83,7 +80,6 @@ struct cx231xx_IR { static void cx231xx_ir_handle_key(struct cx231xx_IR *ir) { int result; - int do_sendkey = 0; struct cx231xx_ir_poll_result poll_result; /* read the registers containing the IR status */ @@ -97,44 +93,23 @@ static void cx231xx_ir_handle_key(struct cx231xx_IR *ir) poll_result.toggle_bit, poll_result.read_count, ir->last_readcount, poll_result.rc_data[0]); - if (ir->dev->chip_id == CHIP_ID_EM2874) { + if (poll_result.read_count > 0 && + poll_result.read_count != ir->last_readcount) + ir_keydown(ir->input, + poll_result.rc_data[0], + poll_result.toggle_bit); + + if (ir->dev->chip_id == CHIP_ID_EM2874) /* The em2874 clears the readcount field every time the register is read. The em2860/2880 datasheet says that it is supposed to clear the readcount, but it doesn't. So with the em2874, we are looking for a non-zero read count as opposed to a readcount that is incrementing */ ir->last_readcount = 0; - } - - if (poll_result.read_count == 0) { - /* The button has not been pressed since the last read */ - } else if (ir->last_toggle != poll_result.toggle_bit) { - /* A button has been pressed */ - dprintk("button has been pressed\n"); - ir->last_toggle = poll_result.toggle_bit; - ir->repeat_interval = 0; - do_sendkey = 1; - } else if (poll_result.toggle_bit == ir->last_toggle && - poll_result.read_count > 0 && - poll_result.read_count != ir->last_readcount) { - /* The button is still being held down */ - dprintk("button being held down\n"); - - /* Debouncer for first keypress */ - if (ir->repeat_interval++ > 9) { - /* Start repeating after 1 second */ - do_sendkey = 1; - } - } + else + ir->last_readcount = poll_result.read_count; - if (do_sendkey) { - dprintk("sending keypress\n"); - ir_input_keydown(ir->input, &ir->ir, poll_result.rc_data[0]); - ir_input_nokey(ir->input, &ir->ir); } - - ir->last_readcount = poll_result.read_count; - return; } static void ir_timer(unsigned long data) @@ -200,10 +175,6 @@ int cx231xx_ir_init(struct cx231xx *dev) usb_make_path(dev->udev, ir->phys, sizeof(ir->phys)); strlcat(ir->phys, "/input0", sizeof(ir->phys)); - err = ir_input_init(input_dev, &ir->ir, IR_TYPE_OTHER); - if (err < 0) - goto err_out_free; - input_dev->name = ir->name; input_dev->phys = ir->phys; input_dev->id.bustype = BUS_USB; diff --git a/drivers/media/video/cx231xx/cx231xx.h b/drivers/media/video/cx231xx/cx231xx.h index 17d4d1a800c..38d417191a6 100644 --- a/drivers/media/video/cx231xx/cx231xx.h +++ b/drivers/media/video/cx231xx/cx231xx.h @@ -32,7 +32,7 @@ #include #include -#include +#include #if defined(CONFIG_VIDEO_CX231XX_DVB) || \ defined(CONFIG_VIDEO_CX231XX_DVB_MODULE) #include -- cgit v1.2.3-70-g09d2 From d922b8ea33afad725920375b2d3bd65218cdb133 Mon Sep 17 00:00:00 2001 From: Istvan Varga Date: Sat, 27 Mar 2010 09:47:45 -0300 Subject: V4L/DVB: cx88: fix setting input when using DVB In cx88-mpeg.c, there is code that sets core->input to CX88_VMUX_DVB. However, this may be incorrect, since core->input is actually an index to core->board.input[], which has not enough elements to be indexed by the value of CX88_VMUX_DVB. So, the modified code searches core->board.input[] for an input with a type of CX88_VMUX_DVB, and if it does not find one, the index is simply set to zero. The change may not have much effect, though, since it appears the only case when core->input is actually used is when the current input is being queried. Signed-off-by: Istvan Varga Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-mpeg.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index 6aba7af9160..499f8d512ad 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/video/cx88/cx88-mpeg.c @@ -599,13 +599,22 @@ struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board static int cx8802_request_acquire(struct cx8802_driver *drv) { struct cx88_core *core = drv->core; + unsigned int i; /* Fail a request for hardware if the device is busy. */ if (core->active_type_id != CX88_BOARD_NONE && core->active_type_id != drv->type_id) return -EBUSY; - core->input = CX88_VMUX_DVB; + core->input = 0; + for (i = 0; + i < (sizeof(core->board.input) / sizeof(struct cx88_input)); + i++) { + if (core->board.input[i].type == CX88_VMUX_DVB) { + core->input = i; + break; + } + } if (drv->advise_acquire) { -- cgit v1.2.3-70-g09d2 From 5013318ca4fd22e30fd891f234b60daa3ca2f62d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 7 Apr 2010 17:07:58 -0300 Subject: V4L/DVB: em28xx: fix locks during dvb init sequence Serialize DVB initialization, to avoid it to happen while analog initialization is still happening. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-core.c | 13 ++++--------- drivers/media/video/em28xx/em28xx-dvb.c | 10 ++++++---- 2 files changed, 10 insertions(+), 13 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 258041d0be9..d3813ed789d 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -1178,21 +1178,18 @@ void em28xx_add_into_devlist(struct em28xx *dev) */ static LIST_HEAD(em28xx_extension_devlist); -static DEFINE_MUTEX(em28xx_extension_devlist_lock); int em28xx_register_extension(struct em28xx_ops *ops) { struct em28xx *dev = NULL; mutex_lock(&em28xx_devlist_mutex); - mutex_lock(&em28xx_extension_devlist_lock); list_add_tail(&ops->next, &em28xx_extension_devlist); list_for_each_entry(dev, &em28xx_devlist, devlist) { if (dev) ops->init(dev); } printk(KERN_INFO "Em28xx: Initialized (%s) extension\n", ops->name); - mutex_unlock(&em28xx_extension_devlist_lock); mutex_unlock(&em28xx_devlist_mutex); return 0; } @@ -1208,10 +1205,8 @@ void em28xx_unregister_extension(struct em28xx_ops *ops) ops->fini(dev); } - mutex_lock(&em28xx_extension_devlist_lock); printk(KERN_INFO "Em28xx: Removed (%s) extension\n", ops->name); list_del(&ops->next); - mutex_unlock(&em28xx_extension_devlist_lock); mutex_unlock(&em28xx_devlist_mutex); } EXPORT_SYMBOL(em28xx_unregister_extension); @@ -1220,26 +1215,26 @@ void em28xx_init_extension(struct em28xx *dev) { struct em28xx_ops *ops = NULL; - mutex_lock(&em28xx_extension_devlist_lock); + mutex_lock(&em28xx_devlist_mutex); if (!list_empty(&em28xx_extension_devlist)) { list_for_each_entry(ops, &em28xx_extension_devlist, next) { if (ops->init) ops->init(dev); } } - mutex_unlock(&em28xx_extension_devlist_lock); + mutex_unlock(&em28xx_devlist_mutex); } void em28xx_close_extension(struct em28xx *dev) { struct em28xx_ops *ops = NULL; - mutex_lock(&em28xx_extension_devlist_lock); + mutex_lock(&em28xx_devlist_mutex); if (!list_empty(&em28xx_extension_devlist)) { list_for_each_entry(ops, &em28xx_extension_devlist, next) { if (ops->fini) ops->fini(dev); } } - mutex_unlock(&em28xx_extension_devlist_lock); + mutex_unlock(&em28xx_devlist_mutex); } diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index e7b3d537155..cf1d8c3655f 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c @@ -467,6 +467,7 @@ static int dvb_init(struct em28xx *dev) } dev->dvb = dvb; + mutex_lock(&dev->lock); em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); /* init frontend */ switch (dev->model) { @@ -590,15 +591,16 @@ static int dvb_init(struct em28xx *dev) if (result < 0) goto out_free; - em28xx_set_mode(dev, EM28XX_SUSPEND); em28xx_info("Successfully loaded em28xx-dvb\n"); - return 0; +ret: + em28xx_set_mode(dev, EM28XX_SUSPEND); + mutex_unlock(&dev->lock); + return result; out_free: - em28xx_set_mode(dev, EM28XX_SUSPEND); kfree(dvb); dev->dvb = NULL; - return result; + goto ret; } static int dvb_fini(struct em28xx *dev) -- cgit v1.2.3-70-g09d2 From 16bfdaa41be85512432212382f2600fcdf7c1c37 Mon Sep 17 00:00:00 2001 From: Pierre Gronlier Date: Mon, 26 Apr 2010 13:26:29 -0300 Subject: V4L/DVB: Read MAC for TeVii S470 PCI-e DVB-S2 card This patch retrieve the correct mac address from the eeprom for TeVii S470 card. Signed-off-by: Pierre Gronlier Cc: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx23885/cx23885-dvb.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 939079d7bbb..9e1460828b2 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -1006,6 +1006,22 @@ static int dvb_register(struct cx23885_tsport *port) netup_ci_init(port); break; } + case CX23885_BOARD_TEVII_S470: { + u8 eeprom[256]; /* 24C02 i2c eeprom */ + + if (port->nr != 1) + break; + + /* Read entire EEPROM */ + dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1; + tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom, sizeof(eeprom)); + printk(KERN_INFO "TeVii S470 MAC= " + "%02X:%02X:%02X:%02X:%02X:%02X\n", + eeprom[0xa0], eeprom[0xa1], eeprom[0xa2], + eeprom[0xa3], eeprom[0xa4], eeprom[0xa5]); + memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xa0, 6); + break; + } } return ret; -- cgit v1.2.3-70-g09d2 From b7589ac4aea794920528c28fe36288908462ddec Mon Sep 17 00:00:00 2001 From: Kirill Smelkov Date: Tue, 27 Apr 2010 13:17:51 -0300 Subject: V4L/DVB: bttv: Add another ids for IVC-200 I have 3 IVC-200 cards (with 4 video channels on each). 2 of the cards identify theirselves as 000[0-3]:a155 (ids already in cardlist) and another one identifies itself as 080[0-3]:a155, which ids were unknown so far. Note - it's IVC-200, not IVC-200G. Signed-off-by: Kirill Smelkov Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.bttv | 2 +- drivers/media/video/bt8xx/bttv-cards.c | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/Documentation/video4linux/CARDLIST.bttv b/Documentation/video4linux/CARDLIST.bttv index f11c583295e..4739d568430 100644 --- a/Documentation/video4linux/CARDLIST.bttv +++ b/Documentation/video4linux/CARDLIST.bttv @@ -100,7 +100,7 @@ 99 -> AD-TVK503 100 -> Hercules Smart TV Stereo 101 -> Pace TV & Radio Card -102 -> IVC-200 [0000:a155,0001:a155,0002:a155,0003:a155,0100:a155,0101:a155,0102:a155,0103:a155] +102 -> IVC-200 [0000:a155,0001:a155,0002:a155,0003:a155,0100:a155,0101:a155,0102:a155,0103:a155,0800:a155,0801:a155,0802:a155,0803:a155] 103 -> Grand X-Guard / Trust 814PCI [0304:0102] 104 -> Nebula Electronics DigiTV [0071:0101] 105 -> ProVideo PV143 [aa00:1430,aa00:1431,aa00:1432,aa00:1433,aa03:1433] diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index 716870ae85d..7af56cde0c7 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -241,6 +241,10 @@ static struct CARD { { 0xa1550101, BTTV_BOARD_IVC200, "IVC-200G" }, { 0xa1550102, BTTV_BOARD_IVC200, "IVC-200G" }, { 0xa1550103, BTTV_BOARD_IVC200, "IVC-200G" }, + { 0xa1550800, BTTV_BOARD_IVC200, "IVC-200" }, + { 0xa1550801, BTTV_BOARD_IVC200, "IVC-200" }, + { 0xa1550802, BTTV_BOARD_IVC200, "IVC-200" }, + { 0xa1550803, BTTV_BOARD_IVC200, "IVC-200" }, { 0xa182ff00, BTTV_BOARD_IVC120, "IVC-120G" }, { 0xa182ff01, BTTV_BOARD_IVC120, "IVC-120G" }, { 0xa182ff02, BTTV_BOARD_IVC120, "IVC-120G" }, -- cgit v1.2.3-70-g09d2 From b2dfd1a45f014e24f0eecc50a7edc954425c348a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 28 Apr 2010 04:05:22 -0300 Subject: V4L/DVB: videobuf: Add support for V4L2_BUF_FLAG_ERROR For recoverable stream errors dqbuf() now returns 0 and the error flag is set instead of returning EIO. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-core.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c index 9f99e3bf539..f47cf1ca123 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/video/videobuf-core.c @@ -285,8 +285,10 @@ static void videobuf_status(struct videobuf_queue *q, struct v4l2_buffer *b, case VIDEOBUF_ACTIVE: b->flags |= V4L2_BUF_FLAG_QUEUED; break; - case VIDEOBUF_DONE: case VIDEOBUF_ERROR: + b->flags |= V4L2_BUF_FLAG_ERROR; + /* fall through */ + case VIDEOBUF_DONE: b->flags |= V4L2_BUF_FLAG_DONE; break; case VIDEOBUF_NEEDS_INIT: @@ -670,6 +672,7 @@ int videobuf_dqbuf(struct videobuf_queue *q, MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); + memset(b, 0, sizeof(*b)); mutex_lock(&q->vb_lock); retval = stream_next_buffer(q, &buf, nonblocking); @@ -681,23 +684,20 @@ int videobuf_dqbuf(struct videobuf_queue *q, switch (buf->state) { case VIDEOBUF_ERROR: dprintk(1, "dqbuf: state is error\n"); - retval = -EIO; - CALL(q, sync, q, buf); - buf->state = VIDEOBUF_IDLE; break; case VIDEOBUF_DONE: dprintk(1, "dqbuf: state is done\n"); - CALL(q, sync, q, buf); - buf->state = VIDEOBUF_IDLE; break; default: dprintk(1, "dqbuf: state invalid\n"); retval = -EINVAL; goto done; } - list_del(&buf->stream); - memset(b, 0, sizeof(*b)); + CALL(q, sync, q, buf); videobuf_status(q, b, buf, q->type); + list_del(&buf->stream); + buf->state = VIDEOBUF_IDLE; + b->flags &= ~V4L2_BUF_FLAG_DONE; done: mutex_unlock(&q->vb_lock); return retval; -- cgit v1.2.3-70-g09d2 From 97f8105dcd62a5c122f31ca5ae53c924c3e7d42b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 5 May 2010 16:23:09 -0300 Subject: V4L/DVB: videobuf-dma-sg: remove external function videobuf_dma_sync() While analyzing one of the videobuf patches, I noticed that videobuf_dma_sync is only used internally inside videobuf-dma-sg. So, let's remove this function, merging the code at __videobuf_dma_sync() Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-dma-sg.c | 20 +++++++------------- include/media/videobuf-dma-sg.h | 1 - 2 files changed, 7 insertions(+), 14 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c index f733833a021..b49f1e23298 100644 --- a/drivers/media/video/videobuf-dma-sg.c +++ b/drivers/media/video/videobuf-dma-sg.c @@ -279,17 +279,6 @@ int videobuf_dma_map(struct videobuf_queue *q, struct videobuf_dmabuf *dma) } EXPORT_SYMBOL_GPL(videobuf_dma_map); -int videobuf_dma_sync(struct videobuf_queue *q, struct videobuf_dmabuf *dma) -{ - MAGIC_CHECK(dma->magic, MAGIC_DMABUF); - BUG_ON(!dma->sglen); - - dma_sync_sg_for_cpu(q->dev, dma->sglist, dma->nr_pages, dma->direction); - - return 0; -} -EXPORT_SYMBOL_GPL(videobuf_dma_sync); - int videobuf_dma_unmap(struct videobuf_queue *q, struct videobuf_dmabuf *dma) { MAGIC_CHECK(dma->magic, MAGIC_DMABUF); @@ -542,10 +531,15 @@ static int __videobuf_sync(struct videobuf_queue *q, struct videobuf_buffer *buf) { struct videobuf_dma_sg_memory *mem = buf->priv; - BUG_ON(!mem); + BUG_ON(!mem || !mem->dma.sglen); + MAGIC_CHECK(mem->magic, MAGIC_SG_MEM); + MAGIC_CHECK(mem->dma.magic, MAGIC_DMABUF); - return videobuf_dma_sync(q, &mem->dma); + dma_sync_sg_for_cpu(q->dev, mem->dma.sglist, + mem->dma.nr_pages, mem->dma.direction); + + return 0; } static int __videobuf_mmap_mapper(struct videobuf_queue *q, diff --git a/include/media/videobuf-dma-sg.h b/include/media/videobuf-dma-sg.h index dbfd8cf7b7c..a195f3b9c00 100644 --- a/include/media/videobuf-dma-sg.h +++ b/include/media/videobuf-dma-sg.h @@ -97,7 +97,6 @@ int videobuf_dma_init_overlay(struct videobuf_dmabuf *dma, int direction, int videobuf_dma_free(struct videobuf_dmabuf *dma); int videobuf_dma_map(struct videobuf_queue *q, struct videobuf_dmabuf *dma); -int videobuf_dma_sync(struct videobuf_queue *q, struct videobuf_dmabuf *dma); int videobuf_dma_unmap(struct videobuf_queue *q, struct videobuf_dmabuf *dma); struct videobuf_dmabuf *videobuf_to_dma(struct videobuf_buffer *buf); -- cgit v1.2.3-70-g09d2 From c06b062bea411f616b0890d502044c7871d5332f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 5 May 2010 17:16:35 -0300 Subject: V4L/DVB: videobuf-vmalloc: remove __videobuf_sync() videobuf-core checks if .sync ops is defined before calling. So, we don't need a do-nothing function. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-vmalloc.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/videobuf-vmalloc.c b/drivers/media/video/videobuf-vmalloc.c index f8b5b563511..583728f4c22 100644 --- a/drivers/media/video/videobuf-vmalloc.c +++ b/drivers/media/video/videobuf-vmalloc.c @@ -229,12 +229,6 @@ static int __videobuf_iolock(struct videobuf_queue *q, return 0; } -static int __videobuf_sync(struct videobuf_queue *q, - struct videobuf_buffer *buf) -{ - return 0; -} - static int __videobuf_mmap_mapper(struct videobuf_queue *q, struct videobuf_buffer *buf, struct vm_area_struct *vma) @@ -301,7 +295,6 @@ static struct videobuf_qtype_ops qops = { .alloc = __videobuf_alloc, .iolock = __videobuf_iolock, - .sync = __videobuf_sync, .mmap_mapper = __videobuf_mmap_mapper, .vaddr = videobuf_to_vmalloc, }; -- cgit v1.2.3-70-g09d2 From fc7f8fd42c2b934ac348995e0c530c917fc277d5 Mon Sep 17 00:00:00 2001 From: Arnout Vandecappelle Date: Wed, 17 Mar 2010 19:53:04 -0300 Subject: V4L/DVB: buf-dma-sg.c: don't assume nr_pages == sglen videobuf_pages_to_sg() and videobuf_vmalloc_to_sg() happen to create a scatterlist element for every page. However, this is not true for bus addresses, so other functions shouldn't rely on the length of the scatter list being equal to nr_pages. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-dma-sg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c index b49f1e23298..8359e6badd3 100644 --- a/drivers/media/video/videobuf-dma-sg.c +++ b/drivers/media/video/videobuf-dma-sg.c @@ -286,7 +286,7 @@ int videobuf_dma_unmap(struct videobuf_queue *q, struct videobuf_dmabuf *dma) if (!dma->sglen) return 0; - dma_unmap_sg(q->dev, dma->sglist, dma->nr_pages, dma->direction); + dma_unmap_sg(q->dev, dma->sglist, dma->sglen, dma->direction); vfree(dma->sglist); dma->sglist = NULL; @@ -537,7 +537,7 @@ static int __videobuf_sync(struct videobuf_queue *q, MAGIC_CHECK(mem->dma.magic, MAGIC_DMABUF); dma_sync_sg_for_cpu(q->dev, mem->dma.sglist, - mem->dma.nr_pages, mem->dma.direction); + mem->dma.sglen, mem->dma.direction); return 0; } -- cgit v1.2.3-70-g09d2 From 9b558434136138edc79710385aaf613cb4b30459 Mon Sep 17 00:00:00 2001 From: Pawel Osciak Date: Mon, 29 Mar 2010 05:16:31 -0300 Subject: V4L/DVB: videobuf: make poll() report proper flags for output video devices According to the V4L2 specification, poll() should set POLLOUT | POLLWRNORM flags for output devices after the frame has been displayed. Signed-off-by: Pawel Osciak Reviewed-by: Kyungmin Park Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-core.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c index f47cf1ca123..7d3378437de 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/video/videobuf-core.c @@ -1120,8 +1120,18 @@ unsigned int videobuf_poll_stream(struct file *file, if (0 == rc) { poll_wait(file, &buf->done, wait); if (buf->state == VIDEOBUF_DONE || - buf->state == VIDEOBUF_ERROR) - rc = POLLIN|POLLRDNORM; + buf->state == VIDEOBUF_ERROR) { + switch (q->type) { + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + case V4L2_BUF_TYPE_VBI_OUTPUT: + case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: + rc = POLLOUT | POLLWRNORM; + break; + default: + rc = POLLIN | POLLRDNORM; + break; + } + } } mutex_unlock(&q->vb_lock); return rc; -- cgit v1.2.3-70-g09d2 From 0faa2ed5bfd08d94a04c8d4b55823676175f451f Mon Sep 17 00:00:00 2001 From: Dmitri Belimov Date: Tue, 6 Apr 2010 01:00:05 -0300 Subject: V4L/DVB: saa7134: Add support new Behold TV cards [dougsland@redhat.com: Fixed cards numbers reject due changes in saa7134.h] Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.saa7134 | 2 + drivers/media/video/saa7134/saa7134-cards.c | 72 +++++++++++++++++++++++++++++ drivers/media/video/saa7134/saa7134-dvb.c | 9 ++++ drivers/media/video/saa7134/saa7134-input.c | 2 + drivers/media/video/saa7134/saa7134.h | 2 + 5 files changed, 87 insertions(+) (limited to 'drivers/media/video') diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index bb3d5faa34e..070f2576707 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -176,3 +176,5 @@ 175 -> Leadtek Winfast DTV1000S [107d:6655] 176 -> Beholder BeholdTV 505 RDS [0000:5051] 177 -> Hawell HW-404M7 +179 -> Beholder BeholdTV H7 [5ace:7190] +180 -> Beholder BeholdTV A7 [5ace:7090] diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 435f821b592..72700d4e394 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -5372,6 +5372,62 @@ struct saa7134_board saa7134_boards[] = { .gpio = 0x01fc00, } }, }, + [SAA7134_BOARD_BEHOLD_H7] = { + /* Beholder Intl. Ltd. Dmitry Belimov */ + .name = "Beholder BeholdTV H7", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_XC5000, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .mpeg = SAA7134_MPEG_DVB, + .ts_type = SAA7134_MPEG_TS_PARALLEL, + .inputs = { { + .name = name_tv, + .vmux = 2, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 0, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 9, + .amux = LINE1, + } }, + .radio = { + .name = name_radio, + .amux = TV, + }, + }, + [SAA7134_BOARD_BEHOLD_A7] = { + /* Beholder Intl. Ltd. Dmitry Belimov */ + .name = "Beholder BeholdTV A7", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_XC5000, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .inputs = { { + .name = name_tv, + .vmux = 2, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 0, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 9, + .amux = LINE1, + } }, + .radio = { + .name = name_radio, + .amux = TV, + }, + }, }; @@ -6566,6 +6622,18 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, .driver_data = SAA7134_BOARD_UNKNOWN, + }, { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x5ace, /* Beholder Intl. Ltd. */ + .subdevice = 0x7190, + .driver_data = SAA7134_BOARD_BEHOLD_H7, + }, { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x5ace, /* Beholder Intl. Ltd. */ + .subdevice = 0x7090, + .driver_data = SAA7134_BOARD_BEHOLD_A7, },{ /* --- end of list --- */ } @@ -6619,6 +6687,8 @@ static int saa7134_xc5000_callback(struct saa7134_dev *dev, { switch (dev->board) { case SAA7134_BOARD_BEHOLD_X7: + case SAA7134_BOARD_BEHOLD_H7: + case SAA7134_BOARD_BEHOLD_A7: if (command == XC5000_TUNER_RESET) { /* Down and UP pheripherial RESET pin for reset all chips */ saa_writeb(SAA7134_SPECIAL_MODE, 0x00); @@ -6990,6 +7060,8 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_BEHOLD_M6_EXTRA: case SAA7134_BOARD_BEHOLD_H6: case SAA7134_BOARD_BEHOLD_X7: + case SAA7134_BOARD_BEHOLD_H7: + case SAA7134_BOARD_BEHOLD_A7: dev->has_remote = SAA7134_REMOTE_I2C; break; case SAA7134_BOARD_AVERMEDIA_A169_B: diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 4ab4a987c9b..31e82be1b7e 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -1532,6 +1532,15 @@ static int dvb_init(struct saa7134_dev *dev) &dev->i2c_adap, &behold_x7_tunerconfig); } break; + case SAA7134_BOARD_BEHOLD_H7: + fe0->dvb.frontend = dvb_attach(zl10353_attach, + &behold_x7_config, + &dev->i2c_adap); + if (fe0->dvb.frontend) { + dvb_attach(xc5000_attach, fe0->dvb.frontend, + &dev->i2c_adap, &behold_x7_tunerconfig); + } + break; case SAA7134_BOARD_AVERMEDIA_A700_PRO: case SAA7134_BOARD_AVERMEDIA_A700_HYBRID: /* Zarlink ZL10313 */ diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index e4681eda01f..e5565e2fd42 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -982,6 +982,8 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) case SAA7134_BOARD_BEHOLD_M6_EXTRA: case SAA7134_BOARD_BEHOLD_H6: case SAA7134_BOARD_BEHOLD_X7: + case SAA7134_BOARD_BEHOLD_H7: + case SAA7134_BOARD_BEHOLD_A7: dev->init_data.name = "BeholdTV"; dev->init_data.get_key = get_key_beholdm6xx; dev->init_data.ir_codes = RC_MAP_BEHOLD; diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index cad8aee98e5..3962534267b 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -301,6 +301,8 @@ struct saa7134_format { #define SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S 175 #define SAA7134_BOARD_BEHOLD_505RDS_MK3 176 #define SAA7134_BOARD_HAWELL_HW_404M7 177 +#define SAA7134_BOARD_BEHOLD_H7 178 +#define SAA7134_BOARD_BEHOLD_A7 179 #define SAA7134_MAXBOARDS 32 #define SAA7134_INPUT_MAX 8 -- cgit v1.2.3-70-g09d2 From acc8cc43865edbd4fe8602531c92fa748ad7778f Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 5 May 2010 19:44:11 -0300 Subject: V4L/DVB: [-next] media: fix vivi build error vivi uses find_font(), which is only available when FONTS is enabled, so make vivi depend on FONTS. ERROR: "find_font" [drivers/media/video/vivi.ko] undefined! Signed-off-by: Randy Dunlap Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 4500cd05434..ad9e6f9c22e 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -559,7 +559,7 @@ config VIDEO_DAVINCI_VPIF config VIDEO_VIVI tristate "Virtual Video Driver" - depends on VIDEO_DEV && VIDEO_V4L2 && !SPARC32 && !SPARC64 + depends on VIDEO_DEV && VIDEO_V4L2 && !SPARC32 && !SPARC64 && FONTS select FONT_8x16 select VIDEOBUF_VMALLOC default n -- cgit v1.2.3-70-g09d2 From 61421206833a4085d9bdf35b2b84cd9a67dfdfac Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 12 Apr 2010 10:41:22 -0300 Subject: V4L/DVB: uvcvideo: Add support for V4L2_PIX_FMT_Y16 The Miricle 307K (17dc:0202) camera reports a 16-bit greyscale format, support it in the driver. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_driver.c | 7 ++++++- drivers/media/video/uvc/uvcvideo.h | 4 +++- 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index 72a705802f1..838b56f097c 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c @@ -91,10 +91,15 @@ static struct uvc_format_desc uvc_fmts[] = { .fcc = V4L2_PIX_FMT_UYVY, }, { - .name = "Greyscale", + .name = "Greyscale (8-bit)", .guid = UVC_GUID_FORMAT_Y800, .fcc = V4L2_PIX_FMT_GREY, }, + { + .name = "Greyscale (16-bit)", + .guid = UVC_GUID_FORMAT_Y16, + .fcc = V4L2_PIX_FMT_Y16, + }, { .name = "RGB Bayer", .guid = UVC_GUID_FORMAT_BY8, diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h index 2bba059259e..d1f88406a5e 100644 --- a/drivers/media/video/uvc/uvcvideo.h +++ b/drivers/media/video/uvc/uvcvideo.h @@ -131,11 +131,13 @@ struct uvc_xu_control { #define UVC_GUID_FORMAT_Y800 \ { 'Y', '8', '0', '0', 0x00, 0x00, 0x10, 0x00, \ 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} +#define UVC_GUID_FORMAT_Y16 \ + { 'Y', '1', '6', ' ', 0x00, 0x00, 0x10, 0x00, \ + 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} #define UVC_GUID_FORMAT_BY8 \ { 'B', 'Y', '8', ' ', 0x00, 0x00, 0x10, 0x00, \ 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} - /* ------------------------------------------------------------------------ * Driver specific constants. */ -- cgit v1.2.3-70-g09d2 From a90ef69c1f67319ddbba0170767c660c7fb5d4c9 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 25 Apr 2010 16:23:24 -0300 Subject: V4L/DVB: uvcvideo: Flag relative controls as write-only The UVC relative controls (exposure time, iris, focus, zoom, pan/tilt) are write-only (despite the UVC specification stating that the GET_CUR request is mandatory). Mark the controls as such, and report the related V4L2 controls V4L2_CTRL_FLAG_WRITE_ONLY. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_ctrl.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c index 5d6d7bda233..2703c952439 100644 --- a/drivers/media/video/uvc/uvc_ctrl.c +++ b/drivers/media/video/uvc/uvc_ctrl.c @@ -217,8 +217,7 @@ static struct uvc_control_info uvc_ctrls[] = { .selector = UVC_CT_EXPOSURE_TIME_RELATIVE_CONTROL, .index = 4, .size = 1, - .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR - | UVC_CONTROL_RESTORE, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_RESTORE, }, { .entity = UVC_GUID_UVC_CAMERA, @@ -233,8 +232,9 @@ static struct uvc_control_info uvc_ctrls[] = { .selector = UVC_CT_FOCUS_RELATIVE_CONTROL, .index = 6, .size = 2, - .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE - | UVC_CONTROL_AUTO_UPDATE, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_MIN + | UVC_CONTROL_GET_MAX | UVC_CONTROL_GET_RES + | UVC_CONTROL_GET_DEF | UVC_CONTROL_AUTO_UPDATE, }, { .entity = UVC_GUID_UVC_CAMERA, @@ -249,8 +249,7 @@ static struct uvc_control_info uvc_ctrls[] = { .selector = UVC_CT_IRIS_RELATIVE_CONTROL, .index = 8, .size = 1, - .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR - | UVC_CONTROL_AUTO_UPDATE, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_AUTO_UPDATE, }, { .entity = UVC_GUID_UVC_CAMERA, @@ -265,8 +264,9 @@ static struct uvc_control_info uvc_ctrls[] = { .selector = UVC_CT_ZOOM_RELATIVE_CONTROL, .index = 10, .size = 3, - .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE - | UVC_CONTROL_AUTO_UPDATE, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_MIN + | UVC_CONTROL_GET_MAX | UVC_CONTROL_GET_RES + | UVC_CONTROL_GET_DEF | UVC_CONTROL_AUTO_UPDATE, }, { .entity = UVC_GUID_UVC_CAMERA, @@ -281,8 +281,9 @@ static struct uvc_control_info uvc_ctrls[] = { .selector = UVC_CT_PANTILT_RELATIVE_CONTROL, .index = 12, .size = 4, - .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE - | UVC_CONTROL_AUTO_UPDATE, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_MIN + | UVC_CONTROL_GET_MAX | UVC_CONTROL_GET_RES + | UVC_CONTROL_GET_DEF | UVC_CONTROL_AUTO_UPDATE, }, { .entity = UVC_GUID_UVC_CAMERA, @@ -297,8 +298,9 @@ static struct uvc_control_info uvc_ctrls[] = { .selector = UVC_CT_ROLL_RELATIVE_CONTROL, .index = 14, .size = 2, - .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE - | UVC_CONTROL_AUTO_UPDATE, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_MIN + | UVC_CONTROL_GET_MAX | UVC_CONTROL_GET_RES + | UVC_CONTROL_GET_DEF | UVC_CONTROL_AUTO_UPDATE, }, { .entity = UVC_GUID_UVC_CAMERA, @@ -842,6 +844,8 @@ int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, strlcpy(v4l2_ctrl->name, mapping->name, sizeof v4l2_ctrl->name); v4l2_ctrl->flags = 0; + if (!(ctrl->info->flags & UVC_CONTROL_GET_CUR)) + v4l2_ctrl->flags |= V4L2_CTRL_FLAG_WRITE_ONLY; if (!(ctrl->info->flags & UVC_CONTROL_SET_CUR)) v4l2_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; -- cgit v1.2.3-70-g09d2 From cf7a50eeb6f462a0b7d1619fcb27a727a2981769 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 25 Apr 2010 16:27:14 -0300 Subject: V4L/DVB: uvcvideo: Prevent division by 0 when control step value is 0 The control step values reported by the device are used as a divisor unchecked, which can result in a division by zero. Check the step value and make it 1 when null. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_ctrl.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c index 2703c952439..aa0720af07a 100644 --- a/drivers/media/video/uvc/uvc_ctrl.c +++ b/drivers/media/video/uvc/uvc_ctrl.c @@ -1071,6 +1071,8 @@ int uvc_ctrl_set(struct uvc_video_chain *chain, uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MAX)); step = mapping->get(mapping, UVC_GET_RES, uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES)); + if (step == 0) + step = 1; xctrl->value = min + (xctrl->value - min + step/2) / step * step; xctrl->value = clamp(xctrl->value, min, max); -- cgit v1.2.3-70-g09d2 From b26d6e21788864039bfb24840a668f2cb0848930 Mon Sep 17 00:00:00 2001 From: Jean-François Moine Date: Thu, 29 Apr 2010 06:01:53 -0300 Subject: V4L/DVB: gspca - main: Convert wMaxPacketSize from little endian 16 to cpu MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gspca.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index e8d08f88795..efe61593878 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -199,7 +199,7 @@ static int alloc_and_submit_int_urb(struct gspca_dev *gspca_dev, void *buffer = NULL; int ret = -EINVAL; - buffer_len = ep->wMaxPacketSize; + buffer_len = le16_to_cpu(ep->wMaxPacketSize); interval = ep->bInterval; PDEBUG(D_PROBE, "found int in endpoint: 0x%x, " "buffer_len=%u, interval=%u", @@ -213,7 +213,7 @@ static int alloc_and_submit_int_urb(struct gspca_dev *gspca_dev, goto error; } - buffer = usb_buffer_alloc(dev, ep->wMaxPacketSize, + buffer = usb_buffer_alloc(dev, buffer_len, GFP_KERNEL, &urb->transfer_dma); if (!buffer) { ret = -ENOMEM; -- cgit v1.2.3-70-g09d2 From 32cd527f59f8aa8549067a2c5f989b736f7da79a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 14 Mar 2010 09:57:30 -0300 Subject: V4L/DVB: v4l: move vbi-specific video ops to a new vbi ops struct Only a relatively small number of video receivers and transmitters actually support VBI. So start moving the vbi specific ops to an ops struct of their own. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-av-core.c | 6 +++- drivers/media/video/cx18/cx18-vbi.c | 2 +- drivers/media/video/cx25840/cx25840-core.c | 6 +++- drivers/media/video/ivtv/ivtv-vbi.c | 16 ++++----- drivers/media/video/saa7115.c | 8 +++-- drivers/media/video/saa7127.c | 6 +++- drivers/media/video/tvp5150.c | 4 +++ include/media/v4l2-subdev.h | 57 ++++++++++++++++-------------- 8 files changed, 65 insertions(+), 40 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c index 3ce45297e56..4454997c1bf 100644 --- a/drivers/media/video/cx18/cx18-av-core.c +++ b/drivers/media/video/cx18/cx18-av-core.c @@ -1403,17 +1403,21 @@ static const struct v4l2_subdev_audio_ops cx18_av_audio_ops = { static const struct v4l2_subdev_video_ops cx18_av_video_ops = { .s_routing = cx18_av_s_video_routing, - .decode_vbi_line = cx18_av_decode_vbi_line, .s_stream = cx18_av_s_stream, .g_fmt = cx18_av_g_fmt, .s_fmt = cx18_av_s_fmt, }; +static const struct v4l2_subdev_vbi_ops cx18_av_vbi_ops = { + .decode_vbi_line = cx18_av_decode_vbi_line, +}; + static const struct v4l2_subdev_ops cx18_av_ops = { .core = &cx18_av_general_ops, .tuner = &cx18_av_tuner_ops, .audio = &cx18_av_audio_ops, .video = &cx18_av_video_ops, + .vbi = &cx18_av_vbi_ops, }; int cx18_av_probe(struct cx18 *cx) diff --git a/drivers/media/video/cx18/cx18-vbi.c b/drivers/media/video/cx18/cx18-vbi.c index 574c1c6974f..582227522cf 100644 --- a/drivers/media/video/cx18/cx18-vbi.c +++ b/drivers/media/video/cx18/cx18-vbi.c @@ -174,7 +174,7 @@ static u32 compress_sliced_buf(struct cx18 *cx, u8 *buf, u32 size, p[3] != sliced_vbi_eav_rp[1])) continue; vbi.p = p + 4; - v4l2_subdev_call(cx->sd_av, video, decode_vbi_line, &vbi); + v4l2_subdev_call(cx->sd_av, vbi, decode_vbi_line, &vbi); if (vbi.type) { cx->vbi.sliced_data[line].id = vbi.type; cx->vbi.sliced_data[line].field = vbi.is_second_field; diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index f2461cd3de5..a0f6f82993b 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -1635,15 +1635,19 @@ static const struct v4l2_subdev_video_ops cx25840_video_ops = { .s_routing = cx25840_s_video_routing, .g_fmt = cx25840_g_fmt, .s_fmt = cx25840_s_fmt, - .decode_vbi_line = cx25840_decode_vbi_line, .s_stream = cx25840_s_stream, }; +static const struct v4l2_subdev_vbi_ops cx25840_vbi_ops = { + .decode_vbi_line = cx25840_decode_vbi_line, +}; + static const struct v4l2_subdev_ops cx25840_ops = { .core = &cx25840_core_ops, .tuner = &cx25840_tuner_ops, .audio = &cx25840_audio_ops, .video = &cx25840_video_ops, + .vbi = &cx25840_vbi_ops, }; /* ----------------------------------------------------------------------- */ diff --git a/drivers/media/video/ivtv/ivtv-vbi.c b/drivers/media/video/ivtv/ivtv-vbi.c index d73af45dede..e1c347e5ebd 100644 --- a/drivers/media/video/ivtv/ivtv-vbi.c +++ b/drivers/media/video/ivtv/ivtv-vbi.c @@ -38,7 +38,7 @@ static void ivtv_set_vps(struct ivtv *itv, int enabled) data.data[9] = itv->vbi.vps_payload.data[2]; data.data[10] = itv->vbi.vps_payload.data[3]; data.data[11] = itv->vbi.vps_payload.data[4]; - ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_vbi_data, &data); + ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data); } static void ivtv_set_cc(struct ivtv *itv, int mode, const struct vbi_cc *cc) @@ -52,12 +52,12 @@ static void ivtv_set_cc(struct ivtv *itv, int mode, const struct vbi_cc *cc) data.line = (mode & 1) ? 21 : 0; data.data[0] = cc->odd[0]; data.data[1] = cc->odd[1]; - ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_vbi_data, &data); + ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data); data.field = 1; data.line = (mode & 2) ? 21 : 0; data.data[0] = cc->even[0]; data.data[1] = cc->even[1]; - ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_vbi_data, &data); + ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data); } static void ivtv_set_wss(struct ivtv *itv, int enabled, int mode) @@ -80,7 +80,7 @@ static void ivtv_set_wss(struct ivtv *itv, int enabled, int mode) data.line = enabled ? 23 : 0; data.data[0] = mode & 0xff; data.data[1] = (mode >> 8) & 0xff; - ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_vbi_data, &data); + ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data); } static int odd_parity(u8 c) @@ -316,7 +316,7 @@ static u32 compress_sliced_buf(struct ivtv *itv, u32 line, u8 *buf, u32 size, u8 continue; } vbi.p = p + 4; - v4l2_subdev_call(itv->sd_video, video, decode_vbi_line, &vbi); + v4l2_subdev_call(itv->sd_video, vbi, decode_vbi_line, &vbi); if (vbi.type && !(lines & (1 << vbi.line))) { lines |= 1 << vbi.line; itv->vbi.sliced_data[line].id = vbi.type; @@ -440,7 +440,7 @@ void ivtv_vbi_work_handler(struct ivtv *itv) data.id = V4L2_SLICED_WSS_625; data.field = 0; - if (v4l2_subdev_call(itv->sd_video, video, g_vbi_data, &data) == 0) { + if (v4l2_subdev_call(itv->sd_video, vbi, g_vbi_data, &data) == 0) { ivtv_set_wss(itv, 1, data.data[0] & 0xf); vi->wss_missing_cnt = 0; } else if (vi->wss_missing_cnt == 4) { @@ -454,13 +454,13 @@ void ivtv_vbi_work_handler(struct ivtv *itv) data.id = V4L2_SLICED_CAPTION_525; data.field = 0; - if (v4l2_subdev_call(itv->sd_video, video, g_vbi_data, &data) == 0) { + if (v4l2_subdev_call(itv->sd_video, vbi, g_vbi_data, &data) == 0) { mode |= 1; cc.odd[0] = data.data[0]; cc.odd[1] = data.data[1]; } data.field = 1; - if (v4l2_subdev_call(itv->sd_video, video, g_vbi_data, &data) == 0) { + if (v4l2_subdev_call(itv->sd_video, vbi, g_vbi_data, &data) == 0) { mode |= 2; cc.even[0] = data.data[0]; cc.even[1] = data.data[1]; diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index 72eaa662b66..cfee323d9c2 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -1550,18 +1550,22 @@ static const struct v4l2_subdev_video_ops saa711x_video_ops = { .s_crystal_freq = saa711x_s_crystal_freq, .g_fmt = saa711x_g_fmt, .s_fmt = saa711x_s_fmt, - .g_vbi_data = saa711x_g_vbi_data, - .decode_vbi_line = saa711x_decode_vbi_line, .s_stream = saa711x_s_stream, .querystd = saa711x_querystd, .g_input_status = saa711x_g_input_status, }; +static const struct v4l2_subdev_vbi_ops saa711x_vbi_ops = { + .g_vbi_data = saa711x_g_vbi_data, + .decode_vbi_line = saa711x_decode_vbi_line, +}; + static const struct v4l2_subdev_ops saa711x_ops = { .core = &saa711x_core_ops, .tuner = &saa711x_tuner_ops, .audio = &saa711x_audio_ops, .video = &saa711x_video_ops, + .vbi = &saa711x_vbi_ops, }; /* ----------------------------------------------------------------------- */ diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c index 250ef84cf5c..32e11fc9c85 100644 --- a/drivers/media/video/saa7127.c +++ b/drivers/media/video/saa7127.c @@ -727,16 +727,20 @@ static const struct v4l2_subdev_core_ops saa7127_core_ops = { }; static const struct v4l2_subdev_video_ops saa7127_video_ops = { - .s_vbi_data = saa7127_s_vbi_data, .g_fmt = saa7127_g_fmt, .s_std_output = saa7127_s_std_output, .s_routing = saa7127_s_routing, .s_stream = saa7127_s_stream, }; +static const struct v4l2_subdev_vbi_ops saa7127_vbi_ops = { + .s_vbi_data = saa7127_s_vbi_data, +}; + static const struct v4l2_subdev_ops saa7127_ops = { .core = &saa7127_core_ops, .video = &saa7127_video_ops, + .vbi = &saa7127_vbi_ops, }; /* ----------------------------------------------------------------------- */ diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index 908ffb68e92..caf0a708542 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c @@ -1046,6 +1046,9 @@ static const struct v4l2_subdev_video_ops tvp5150_video_ops = { .s_routing = tvp5150_s_routing, .g_fmt = tvp5150_g_fmt, .s_fmt = tvp5150_s_fmt, +}; + +static const struct v4l2_subdev_vbi_ops tvp5150_vbi_ops = { .g_sliced_vbi_cap = tvp5150_g_sliced_vbi_cap, }; @@ -1053,6 +1056,7 @@ static const struct v4l2_subdev_ops tvp5150_ops = { .core = &tvp5150_core_ops, .tuner = &tvp5150_tuner_ops, .video = &tvp5150_video_ops, + .vbi = &tvp5150_vbi_ops, }; diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 09758789be0..433cd2b0626 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -184,28 +184,6 @@ struct v4l2_subdev_audio_ops { }; /* - decode_vbi_line: video decoders that support sliced VBI need to implement - this ioctl. Field p of the v4l2_sliced_vbi_line struct is set to the - start of the VBI data that was generated by the decoder. The driver - then parses the sliced VBI data and sets the other fields in the - struct accordingly. The pointer p is updated to point to the start of - the payload which can be copied verbatim into the data field of the - v4l2_sliced_vbi_data struct. If no valid VBI data was found, then the - type field is set to 0 on return. - - s_vbi_data: used to generate VBI signals on a video signal. - v4l2_sliced_vbi_data is filled with the data packets that should be - output. Note that if you set the line field to 0, then that VBI signal - is disabled. If no valid VBI data was found, then the type field is - set to 0 on return. - - g_vbi_data: used to obtain the sliced VBI packet from a readback register. - Not all video decoders support this. If no data is available because - the readback register contains invalid or erroneous data -EIO is - returned. Note that you must fill in the 'id' member and the 'field' - member (to determine whether CC data from the first or second field - should be obtained). - s_std_output: set v4l2_std_id for video OUTPUT devices. This is ignored by video input devices. @@ -243,10 +221,6 @@ struct v4l2_subdev_audio_ops { struct v4l2_subdev_video_ops { int (*s_routing)(struct v4l2_subdev *sd, u32 input, u32 output, u32 config); int (*s_crystal_freq)(struct v4l2_subdev *sd, u32 freq, u32 flags); - int (*decode_vbi_line)(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi_line); - int (*s_vbi_data)(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *vbi_data); - int (*g_vbi_data)(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_data *vbi_data); - int (*g_sliced_vbi_cap)(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_cap *cap); int (*s_std_output)(struct v4l2_subdev *sd, v4l2_std_id std); int (*querystd)(struct v4l2_subdev *sd, v4l2_std_id *std); int (*g_input_status)(struct v4l2_subdev *sd, u32 *status); @@ -280,6 +254,36 @@ struct v4l2_subdev_video_ops { struct v4l2_mbus_framefmt *fmt); }; +/* + decode_vbi_line: video decoders that support sliced VBI need to implement + this ioctl. Field p of the v4l2_sliced_vbi_line struct is set to the + start of the VBI data that was generated by the decoder. The driver + then parses the sliced VBI data and sets the other fields in the + struct accordingly. The pointer p is updated to point to the start of + the payload which can be copied verbatim into the data field of the + v4l2_sliced_vbi_data struct. If no valid VBI data was found, then the + type field is set to 0 on return. + + s_vbi_data: used to generate VBI signals on a video signal. + v4l2_sliced_vbi_data is filled with the data packets that should be + output. Note that if you set the line field to 0, then that VBI signal + is disabled. If no valid VBI data was found, then the type field is + set to 0 on return. + + g_vbi_data: used to obtain the sliced VBI packet from a readback register. + Not all video decoders support this. If no data is available because + the readback register contains invalid or erroneous data -EIO is + returned. Note that you must fill in the 'id' member and the 'field' + member (to determine whether CC data from the first or second field + should be obtained). + */ +struct v4l2_subdev_vbi_ops { + int (*decode_vbi_line)(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi_line); + int (*s_vbi_data)(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *vbi_data); + int (*g_vbi_data)(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_data *vbi_data); + int (*g_sliced_vbi_cap)(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_cap *cap); +}; + /** * struct v4l2_subdev_sensor_ops - v4l2-subdev sensor operations * @g_skip_top_lines: number of lines at the top of the image to be skipped. @@ -379,6 +383,7 @@ struct v4l2_subdev_ops { const struct v4l2_subdev_tuner_ops *tuner; const struct v4l2_subdev_audio_ops *audio; const struct v4l2_subdev_video_ops *video; + const struct v4l2_subdev_vbi_ops *vbi; const struct v4l2_subdev_ir_ops *ir; const struct v4l2_subdev_sensor_ops *sensor; }; -- cgit v1.2.3-70-g09d2 From 63d8adccecd404badcdbbf892765995fd028b3d0 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 14 Mar 2010 10:10:14 -0300 Subject: V4L/DVB: saa7115: support new vbi ops to set/get VBI format Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7115.c | 39 +++++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 12 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index cfee323d9c2..cf77318ede4 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -1091,7 +1091,7 @@ static void saa711x_set_lcr(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_forma saa7115_cfg_vbi_off); } -static int saa711x_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) +static int saa711x_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *sliced) { static u16 lcr2vbi[] = { 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */ @@ -1100,11 +1100,8 @@ static int saa711x_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) V4L2_SLICED_VPS, 0, 0, 0, 0, /* 7 */ 0, 0, 0, 0 }; - struct v4l2_sliced_vbi_format *sliced = &fmt->fmt.sliced; int i; - if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) - return -EINVAL; memset(sliced, 0, sizeof(*sliced)); /* done if using raw VBI */ if (saa711x_read(sd, R_80_GLOBAL_CNTL_1) & 0x10) @@ -1120,16 +1117,31 @@ static int saa711x_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) return 0; } +static int saa711x_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) +{ + if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) + return -EINVAL; + return saa711x_g_sliced_fmt(sd, &fmt->fmt.sliced); +} + +static int saa711x_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt) +{ + saa711x_set_lcr(sd, NULL); + return 0; +} + +static int saa711x_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt) +{ + saa711x_set_lcr(sd, fmt); + return 0; +} + static int saa711x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) { - if (fmt->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) { - saa711x_set_lcr(sd, &fmt->fmt.sliced); - return 0; - } - if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - saa711x_set_lcr(sd, NULL); - return 0; - } + if (fmt->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) + return saa711x_s_sliced_fmt(sd, &fmt->fmt.sliced); + if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) + return saa711x_s_raw_fmt(sd, &fmt->fmt.vbi); if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; @@ -1558,6 +1570,9 @@ static const struct v4l2_subdev_video_ops saa711x_video_ops = { static const struct v4l2_subdev_vbi_ops saa711x_vbi_ops = { .g_vbi_data = saa711x_g_vbi_data, .decode_vbi_line = saa711x_decode_vbi_line, + .g_sliced_fmt = saa711x_g_sliced_fmt, + .s_sliced_fmt = saa711x_s_sliced_fmt, + .s_raw_fmt = saa711x_s_raw_fmt, }; static const struct v4l2_subdev_ops saa711x_ops = { -- cgit v1.2.3-70-g09d2 From 5393db43f46e3228e4f84dd47050aeadaee23c0b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 14 Mar 2010 10:16:46 -0300 Subject: V4L/DVB: cx25840: support new vbi ops to set/get VBI format Also removed the bogus zeroing of fmt.sliced when setting up raw VBI. Switching between raw and sliced VBI changed in 2.6.28 and this memset should have been removed at that time. It was never noticed because the bridge driver will fill in the fmt.vbi values anyway. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx25840/cx25840-core.c | 9 ++++--- drivers/media/video/cx25840/cx25840-core.h | 5 ++-- drivers/media/video/cx25840/cx25840-vbi.c | 40 +++++++++++++----------------- 3 files changed, 26 insertions(+), 28 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index a0f6f82993b..a20df8c184e 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -1018,7 +1018,7 @@ static int cx25840_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) { switch (fmt->type) { case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: - return cx25840_vbi_g_fmt(sd, fmt); + return cx25840_g_sliced_fmt(sd, &fmt->fmt.sliced); default: return -EINVAL; } @@ -1080,10 +1080,10 @@ static int cx25840_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) break; case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: - return cx25840_vbi_s_fmt(sd, fmt); + return cx25840_s_sliced_fmt(sd, &fmt->fmt.sliced); case V4L2_BUF_TYPE_VBI_CAPTURE: - return cx25840_vbi_s_fmt(sd, fmt); + return cx25840_s_raw_fmt(sd, &fmt->fmt.vbi); default: return -EINVAL; @@ -1640,6 +1640,9 @@ static const struct v4l2_subdev_video_ops cx25840_video_ops = { static const struct v4l2_subdev_vbi_ops cx25840_vbi_ops = { .decode_vbi_line = cx25840_decode_vbi_line, + .s_raw_fmt = cx25840_s_raw_fmt, + .s_sliced_fmt = cx25840_s_sliced_fmt, + .g_sliced_fmt = cx25840_g_sliced_fmt, }; static const struct v4l2_subdev_ops cx25840_ops = { diff --git a/drivers/media/video/cx25840/cx25840-core.h b/drivers/media/video/cx25840/cx25840-core.h index 55345444417..04393b97156 100644 --- a/drivers/media/video/cx25840/cx25840-core.h +++ b/drivers/media/video/cx25840/cx25840-core.h @@ -99,8 +99,9 @@ int cx25840_audio_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl); /* ----------------------------------------------------------------------- */ /* cx25850-vbi.c */ -int cx25840_vbi_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt); -int cx25840_vbi_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt); +int cx25840_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt); +int cx25840_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt); +int cx25840_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt); int cx25840_decode_vbi_line(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi); #endif diff --git a/drivers/media/video/cx25840/cx25840-vbi.c b/drivers/media/video/cx25840/cx25840-vbi.c index 35f6592f6c4..64a4004f8a9 100644 --- a/drivers/media/video/cx25840/cx25840-vbi.c +++ b/drivers/media/video/cx25840/cx25840-vbi.c @@ -82,11 +82,10 @@ static int decode_vps(u8 * dst, u8 * p) return err & 0xf0; } -int cx25840_vbi_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) +int cx25840_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *svbi) { struct i2c_client *client = v4l2_get_subdevdata(sd); struct cx25840_state *state = to_state(sd); - struct v4l2_sliced_vbi_format *svbi; static const u16 lcr2vbi[] = { 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */ 0, V4L2_SLICED_WSS_625, 0, /* 4 */ @@ -97,9 +96,6 @@ int cx25840_vbi_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) int is_pal = !(state->std & V4L2_STD_525_60); int i; - if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) - return -EINVAL; - svbi = &fmt->fmt.sliced; memset(svbi, 0, sizeof(*svbi)); /* we're done if raw VBI is active */ if ((cx25840_read(client, 0x404) & 0x10) == 0) @@ -127,32 +123,30 @@ int cx25840_vbi_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) return 0; } -int cx25840_vbi_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) +int cx25840_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt) { struct i2c_client *client = v4l2_get_subdevdata(sd); struct cx25840_state *state = to_state(sd); - struct v4l2_sliced_vbi_format *svbi; int is_pal = !(state->std & V4L2_STD_525_60); int vbi_offset = is_pal ? 1 : 0; - int i, x; - u8 lcr[24]; - if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE && - fmt->type != V4L2_BUF_TYPE_VBI_CAPTURE) - return -EINVAL; - svbi = &fmt->fmt.sliced; - if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - /* raw VBI */ - memset(svbi, 0, sizeof(*svbi)); + /* Setup standard */ + cx25840_std_setup(client); - /* Setup standard */ - cx25840_std_setup(client); + /* VBI Offset */ + cx25840_write(client, 0x47f, vbi_offset); + cx25840_write(client, 0x404, 0x2e); + return 0; +} - /* VBI Offset */ - cx25840_write(client, 0x47f, vbi_offset); - cx25840_write(client, 0x404, 0x2e); - return 0; - } +int cx25840_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *svbi) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct cx25840_state *state = to_state(sd); + int is_pal = !(state->std & V4L2_STD_525_60); + int vbi_offset = is_pal ? 1 : 0; + int i, x; + u8 lcr[24]; for (x = 0; x <= 23; x++) lcr[x] = 0x00; -- cgit v1.2.3-70-g09d2 From 1585927de689a3ca033b98ab5df709e0bf2c3ccc Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 14 Mar 2010 10:49:48 -0300 Subject: V4L/DVB: cx18: support new vbi ops to set/get VBI format Also removed the bogus zeroing of fmt.sliced when setting up raw VBI. This should have been removed in ivtv, but it was just copied-and-pasted into cx18. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-av-core.c | 13 ++++++---- drivers/media/video/cx18/cx18-av-core.h | 5 ++-- drivers/media/video/cx18/cx18-av-vbi.c | 42 ++++++++++++++------------------- 3 files changed, 29 insertions(+), 31 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c index 4454997c1bf..c0289230209 100644 --- a/drivers/media/video/cx18/cx18-av-core.c +++ b/drivers/media/video/cx18/cx18-av-core.c @@ -1023,9 +1023,9 @@ static int cx18_av_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) static int cx18_av_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) { - struct cx18 *cx = v4l2_get_subdevdata(sd); - - return cx18_av_vbi_g_fmt(cx, fmt); + if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) + return -EINVAL; + return cx18_av_g_sliced_fmt(sd, &fmt->fmt.sliced); } static int cx18_av_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) @@ -1099,10 +1099,10 @@ static int cx18_av_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) break; case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: - return cx18_av_vbi_s_fmt(cx, fmt); + return cx18_av_s_sliced_fmt(sd, &fmt->fmt.sliced); case V4L2_BUF_TYPE_VBI_CAPTURE: - return cx18_av_vbi_s_fmt(cx, fmt); + return cx18_av_s_raw_fmt(sd, &fmt->fmt.vbi); default: return -EINVAL; @@ -1410,6 +1410,9 @@ static const struct v4l2_subdev_video_ops cx18_av_video_ops = { static const struct v4l2_subdev_vbi_ops cx18_av_vbi_ops = { .decode_vbi_line = cx18_av_decode_vbi_line, + .g_sliced_fmt = cx18_av_g_sliced_fmt, + .s_sliced_fmt = cx18_av_s_sliced_fmt, + .s_raw_fmt = cx18_av_s_raw_fmt, }; static const struct v4l2_subdev_ops cx18_av_ops = { diff --git a/drivers/media/video/cx18/cx18-av-core.h b/drivers/media/video/cx18/cx18-av-core.h index 74546806b03..c106967bdcc 100644 --- a/drivers/media/video/cx18/cx18-av-core.h +++ b/drivers/media/video/cx18/cx18-av-core.h @@ -378,7 +378,8 @@ void cx18_av_audio_set_path(struct cx18 *cx); /* cx18_av-vbi.c */ int cx18_av_decode_vbi_line(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi); -int cx18_av_vbi_g_fmt(struct cx18 *cx, struct v4l2_format *fmt); -int cx18_av_vbi_s_fmt(struct cx18 *cx, struct v4l2_format *fmt); +int cx18_av_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt); +int cx18_av_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt); +int cx18_av_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt); #endif diff --git a/drivers/media/video/cx18/cx18-av-vbi.c b/drivers/media/video/cx18/cx18-av-vbi.c index a51732bcca4..baa36fbcd4d 100644 --- a/drivers/media/video/cx18/cx18-av-vbi.c +++ b/drivers/media/video/cx18/cx18-av-vbi.c @@ -129,10 +129,10 @@ static int decode_vps(u8 *dst, u8 *p) return err & 0xf0; } -int cx18_av_vbi_g_fmt(struct cx18 *cx, struct v4l2_format *fmt) +int cx18_av_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *svbi) { + struct cx18 *cx = v4l2_get_subdevdata(sd); struct cx18_av_state *state = &cx->av_state; - struct v4l2_sliced_vbi_format *svbi; static const u16 lcr2vbi[] = { 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */ 0, V4L2_SLICED_WSS_625, 0, /* 4 */ @@ -143,9 +143,6 @@ int cx18_av_vbi_g_fmt(struct cx18 *cx, struct v4l2_format *fmt) int is_pal = !(state->std & V4L2_STD_525_60); int i; - if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) - return -EINVAL; - svbi = &fmt->fmt.sliced; memset(svbi, 0, sizeof(*svbi)); /* we're done if raw VBI is active */ if ((cx18_av_read(cx, 0x404) & 0x10) == 0) @@ -173,30 +170,27 @@ int cx18_av_vbi_g_fmt(struct cx18 *cx, struct v4l2_format *fmt) return 0; } -int cx18_av_vbi_s_fmt(struct cx18 *cx, struct v4l2_format *fmt) +int cx18_av_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt) { + struct cx18 *cx = v4l2_get_subdevdata(sd); struct cx18_av_state *state = &cx->av_state; - struct v4l2_sliced_vbi_format *svbi; - int is_pal = !(state->std & V4L2_STD_525_60); - int i, x; - u8 lcr[24]; - if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE && - fmt->type != V4L2_BUF_TYPE_VBI_CAPTURE) - return -EINVAL; - svbi = &fmt->fmt.sliced; - if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - /* raw VBI */ - memset(svbi, 0, sizeof(*svbi)); + /* Setup standard */ + cx18_av_std_setup(cx); - /* Setup standard */ - cx18_av_std_setup(cx); + /* VBI Offset */ + cx18_av_write(cx, 0x47f, state->slicer_line_delay); + cx18_av_write(cx, 0x404, 0x2e); + return 0; +} - /* VBI Offset */ - cx18_av_write(cx, 0x47f, state->slicer_line_delay); - cx18_av_write(cx, 0x404, 0x2e); - return 0; - } +int cx18_av_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *svbi) +{ + struct cx18 *cx = v4l2_get_subdevdata(sd); + struct cx18_av_state *state = &cx->av_state; + int is_pal = !(state->std & V4L2_STD_525_60); + int i, x; + u8 lcr[24]; for (x = 0; x <= 23; x++) lcr[x] = 0x00; -- cgit v1.2.3-70-g09d2 From 1dbf85397a686488b4be412af1cc069ae63a5ecc Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 14 Mar 2010 10:54:47 -0300 Subject: V4L/DVB: saa7127: support new vbi ops to set/get VBI format Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7127.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c index 32e11fc9c85..87986ad62f8 100644 --- a/drivers/media/video/saa7127.c +++ b/drivers/media/video/saa7127.c @@ -625,29 +625,33 @@ static int saa7127_s_stream(struct v4l2_subdev *sd, int enable) return saa7127_set_video_enable(sd, enable); } -static int saa7127_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) +static int saa7127_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt) { struct saa7127_state *state = to_state(sd); - if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) - return -EINVAL; - - memset(&fmt->fmt.sliced, 0, sizeof(fmt->fmt.sliced)); + memset(fmt, 0, sizeof(*fmt)); if (state->vps_enable) - fmt->fmt.sliced.service_lines[0][16] = V4L2_SLICED_VPS; + fmt->service_lines[0][16] = V4L2_SLICED_VPS; if (state->wss_enable) - fmt->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625; + fmt->service_lines[0][23] = V4L2_SLICED_WSS_625; if (state->cc_enable) { - fmt->fmt.sliced.service_lines[0][21] = V4L2_SLICED_CAPTION_525; - fmt->fmt.sliced.service_lines[1][21] = V4L2_SLICED_CAPTION_525; + fmt->service_lines[0][21] = V4L2_SLICED_CAPTION_525; + fmt->service_lines[1][21] = V4L2_SLICED_CAPTION_525; } - fmt->fmt.sliced.service_set = + fmt->service_set = (state->vps_enable ? V4L2_SLICED_VPS : 0) | (state->wss_enable ? V4L2_SLICED_WSS_625 : 0) | (state->cc_enable ? V4L2_SLICED_CAPTION_525 : 0); return 0; } +static int saa7127_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) +{ + if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) + return -EINVAL; + return saa7127_g_sliced_fmt(sd, &fmt->fmt.sliced); +} + static int saa7127_s_vbi_data(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *data) { switch (data->id) { @@ -735,6 +739,7 @@ static const struct v4l2_subdev_video_ops saa7127_video_ops = { static const struct v4l2_subdev_vbi_ops saa7127_vbi_ops = { .s_vbi_data = saa7127_s_vbi_data, + .g_sliced_fmt = saa7127_g_sliced_fmt, }; static const struct v4l2_subdev_ops saa7127_ops = { -- cgit v1.2.3-70-g09d2 From d37dad497c77149e99cb3f4086cfc3b8d8150135 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 14 Mar 2010 10:59:16 -0300 Subject: V4L/DVB: tvp5150: support new vbi ops to set/get VBI format Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvp5150.c | 66 +++++++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 25 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index caf0a708542..853dd6f39b9 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c @@ -891,29 +891,26 @@ static int tvp5150_s_routing(struct v4l2_subdev *sd, return 0; } -static int tvp5150_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) +static int tvp5150_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt) +{ + /* this is for capturing 36 raw vbi lines + if there's a way to cut off the beginning 2 vbi lines + with the tvp5150 then the vbi line count could be lowered + to 17 lines/field again, although I couldn't find a register + which could do that cropping */ + if (fmt->sample_format == V4L2_PIX_FMT_GREY) + tvp5150_write(sd, TVP5150_LUMA_PROC_CTL_1, 0x70); + if (fmt->count[0] == 18 && fmt->count[1] == 18) { + tvp5150_write(sd, TVP5150_VERT_BLANKING_START, 0x00); + tvp5150_write(sd, TVP5150_VERT_BLANKING_STOP, 0x01); + } + return 0; +} + +static int tvp5150_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *svbi) { - struct v4l2_sliced_vbi_format *svbi; int i; - /* raw vbi */ - if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - /* this is for capturing 36 raw vbi lines - if there's a way to cut off the beginning 2 vbi lines - with the tvp5150 then the vbi line count could be lowered - to 17 lines/field again, although I couldn't find a register - which could do that cropping */ - if (fmt->fmt.vbi.sample_format == V4L2_PIX_FMT_GREY) - tvp5150_write(sd, TVP5150_LUMA_PROC_CTL_1, 0x70); - if (fmt->fmt.vbi.count[0] == 18 && fmt->fmt.vbi.count[1] == 18) { - tvp5150_write(sd, TVP5150_VERT_BLANKING_START, 0x00); - tvp5150_write(sd, TVP5150_VERT_BLANKING_STOP, 0x01); - } - return 0; - } - if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) - return -EINVAL; - svbi = &fmt->fmt.sliced; if (svbi->service_set != 0) { for (i = 0; i <= 23; i++) { svbi->service_lines[1][i] = 0; @@ -937,14 +934,24 @@ static int tvp5150_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) return 0; } -static int tvp5150_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) +static int tvp5150_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) { - struct v4l2_sliced_vbi_format *svbi; - int i, mask = 0; + switch (fmt->type) { + case V4L2_BUF_TYPE_VBI_CAPTURE: + return tvp5150_s_raw_fmt(sd, &fmt->fmt.vbi); - if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) + case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: + return tvp5150_s_sliced_fmt(sd, &fmt->fmt.sliced); + + default: return -EINVAL; - svbi = &fmt->fmt.sliced; + } +} + +static int tvp5150_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *svbi) +{ + int i, mask = 0; + memset(svbi, 0, sizeof(*svbi)); for (i = 0; i <= 23; i++) { @@ -956,6 +963,12 @@ static int tvp5150_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) return 0; } +static int tvp5150_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) +{ + if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) + return -EINVAL; + return tvp5150_g_sliced_fmt(sd, &fmt->fmt.sliced); +} static int tvp5150_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) @@ -1050,6 +1063,9 @@ static const struct v4l2_subdev_video_ops tvp5150_video_ops = { static const struct v4l2_subdev_vbi_ops tvp5150_vbi_ops = { .g_sliced_vbi_cap = tvp5150_g_sliced_vbi_cap, + .g_sliced_fmt = tvp5150_g_sliced_fmt, + .s_sliced_fmt = tvp5150_s_sliced_fmt, + .s_raw_fmt = tvp5150_s_raw_fmt, }; static const struct v4l2_subdev_ops tvp5150_ops = { -- cgit v1.2.3-70-g09d2 From 4ff0790b6d8b26a4160e46bbd7bf6f4f48e391f9 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 14 Mar 2010 12:18:18 -0300 Subject: V4L/DVB: ivtv: switch to new vbi subdev ops Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtv-ioctl.c | 6 +++--- drivers/media/video/ivtv/ivtv-streams.c | 5 ++++- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index e95ebdeaa72..a17c659e632 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c @@ -392,7 +392,7 @@ static int ivtv_g_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_fo return 0; } - v4l2_subdev_call(itv->sd_video, video, g_fmt, fmt); + v4l2_subdev_call(itv->sd_video, vbi, g_sliced_fmt, vbifmt); vbifmt->service_set = ivtv_get_service_set(vbifmt); return 0; } @@ -598,7 +598,7 @@ static int ivtv_s_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f return -EBUSY; itv->vbi.sliced_in->service_set = 0; itv->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE; - v4l2_subdev_call(itv->sd_video, video, s_fmt, fmt); + v4l2_subdev_call(itv->sd_video, vbi, s_raw_fmt, &fmt->fmt.vbi); return ivtv_g_fmt_vbi_cap(file, fh, fmt); } @@ -616,7 +616,7 @@ static int ivtv_s_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_fo if (ivtv_raw_vbi(itv) && atomic_read(&itv->capturing) > 0) return -EBUSY; itv->vbi.in.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; - v4l2_subdev_call(itv->sd_video, video, s_fmt, fmt); + v4l2_subdev_call(itv->sd_video, vbi, s_sliced_fmt, vbifmt); memcpy(itv->vbi.sliced_in, vbifmt, sizeof(*itv->vbi.sliced_in)); return 0; } diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c index def507ee106..de4288cc188 100644 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ b/drivers/media/video/ivtv/ivtv-streams.c @@ -344,7 +344,10 @@ static void ivtv_vbi_setup(struct ivtv *itv) ivtv_vapi(itv, CX2341X_ENC_SET_VBI_LINE, 5, 0xffff , 0, 0, 0, 0); /* setup VBI registers */ - v4l2_subdev_call(itv->sd_video, video, s_fmt, &itv->vbi.in); + if (raw) + v4l2_subdev_call(itv->sd_video, vbi, s_raw_fmt, &itv->vbi.in.fmt.vbi); + else + v4l2_subdev_call(itv->sd_video, vbi, s_sliced_fmt, &itv->vbi.in.fmt.sliced); /* determine number of lines and total number of VBI bytes. A raw line takes 1443 bytes: 2 * 720 + 4 byte frame header - 1 -- cgit v1.2.3-70-g09d2 From add632cd2580ceb4de9f71ab58c658e9bdebd7f7 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 14 Mar 2010 12:24:15 -0300 Subject: V4L/DVB: cx18: switch to new vbi subdev ops Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-ioctl.c | 6 +++--- drivers/media/video/cx18/cx18-streams.c | 5 ++++- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c index b81dd0ea8eb..2e6addab3ed 100644 --- a/drivers/media/video/cx18/cx18-ioctl.c +++ b/drivers/media/video/cx18/cx18-ioctl.c @@ -208,7 +208,7 @@ static int cx18_g_fmt_sliced_vbi_cap(struct file *file, void *fh, * digitizer/slicer. Note, cx18_av_vbi() wipes the passed in * fmt->fmt.sliced under valid calling conditions */ - if (v4l2_subdev_call(cx->sd_av, video, g_fmt, fmt)) + if (v4l2_subdev_call(cx->sd_av, vbi, g_sliced_fmt, &fmt->fmt.sliced)) return -EINVAL; /* Ensure V4L2 spec compliant output */ @@ -322,7 +322,7 @@ static int cx18_s_fmt_vbi_cap(struct file *file, void *fh, * Note cx18_av_vbi_wipes out alot of the passed in fmt under valid * calling conditions */ - ret = v4l2_subdev_call(cx->sd_av, video, s_fmt, fmt); + ret = v4l2_subdev_call(cx->sd_av, vbi, s_raw_fmt, &fmt->fmt.vbi); if (ret) return ret; @@ -359,7 +359,7 @@ static int cx18_s_fmt_sliced_vbi_cap(struct file *file, void *fh, * Note, cx18_av_vbi() wipes some "impossible" service lines in the * passed in fmt->fmt.sliced under valid calling conditions */ - ret = v4l2_subdev_call(cx->sd_av, video, s_fmt, fmt); + ret = v4l2_subdev_call(cx->sd_av, vbi, s_sliced_fmt, &fmt->fmt.sliced); if (ret) return ret; /* Store our current v4l2 sliced VBI settings */ diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index 054450f65a6..f5c91261b2d 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c @@ -374,7 +374,10 @@ static void cx18_vbi_setup(struct cx18_stream *s) } /* setup VBI registers */ - v4l2_subdev_call(cx->sd_av, video, s_fmt, &cx->vbi.in); + if (raw) + v4l2_subdev_call(cx->sd_av, vbi, s_raw_fmt, &cx->vbi.in.fmt.vbi); + else + v4l2_subdev_call(cx->sd_av, vbi, s_sliced_fmt, &cx->vbi.in.fmt.sliced); /* * Send the CX18_CPU_SET_RAW_VBI_PARAM API command to setup Encoder Raw -- cgit v1.2.3-70-g09d2 From 09419af39b510851ed14319a93b6d214b80025db Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 14 Mar 2010 12:27:48 -0300 Subject: V4L/DVB: pvrusb2: switch to new vbi subdev ops Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 712b300f723..301ef197d03 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2028,7 +2028,7 @@ static void pvr2_hdw_cx25840_vbi_hack(struct pvr2_hdw *hdw) memset(&fmt, 0, sizeof(fmt)); fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; v4l2_device_call_all(&hdw->v4l2_dev, hdw->decoder_client_id, - video, s_fmt, &fmt); + vbi, s_sliced_fmt, &fmt.fmt.sliced); } -- cgit v1.2.3-70-g09d2 From 7e87ddb101caa747edf388220c758c99553566f5 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 14 Mar 2010 12:31:08 -0300 Subject: V4L/DVB: cx231xx: switch to new vbi subdev ops Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx231xx/cx231xx-video.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx231xx/cx231xx-video.c b/drivers/media/video/cx231xx/cx231xx-video.c index 597c416218c..2782709b263 100644 --- a/drivers/media/video/cx231xx/cx231xx-video.c +++ b/drivers/media/video/cx231xx/cx231xx-video.c @@ -1669,7 +1669,7 @@ static int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *priv, f->fmt.sliced.service_set = 0; - call_all(dev, video, g_fmt, f); + call_all(dev, vbi, g_sliced_fmt, &f->fmt.sliced); if (f->fmt.sliced.service_set == 0) rc = -EINVAL; @@ -1690,7 +1690,7 @@ static int vidioc_try_set_sliced_vbi_cap(struct file *file, void *priv, return rc; mutex_lock(&dev->lock); - call_all(dev, video, g_fmt, f); + call_all(dev, vbi, g_sliced_fmt, &f->fmt.sliced); mutex_unlock(&dev->lock); if (f->fmt.sliced.service_set == 0) -- cgit v1.2.3-70-g09d2 From 4a61ecbd344c2349ec3b7a8db0db128135285dd7 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 14 Mar 2010 12:39:27 -0300 Subject: V4L/DVB: em28xx: switch to new vbi subdev ops Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-video.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index b6ac99de97d..8565fb3ff94 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -1831,7 +1831,7 @@ static int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *priv, mutex_lock(&dev->lock); f->fmt.sliced.service_set = 0; - v4l2_device_call_all(&dev->v4l2_dev, 0, video, g_fmt, f); + v4l2_device_call_all(&dev->v4l2_dev, 0, vbi, g_sliced_fmt, &f->fmt.sliced); if (f->fmt.sliced.service_set == 0) rc = -EINVAL; @@ -1853,7 +1853,7 @@ static int vidioc_try_set_sliced_vbi_cap(struct file *file, void *priv, return rc; mutex_lock(&dev->lock); - v4l2_device_call_all(&dev->v4l2_dev, 0, video, g_fmt, f); + v4l2_device_call_all(&dev->v4l2_dev, 0, vbi, g_sliced_fmt, &f->fmt.sliced); mutex_unlock(&dev->lock); if (f->fmt.sliced.service_set == 0) -- cgit v1.2.3-70-g09d2 From aae6e33f8df8845603880468624ca29edf4bac64 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 1 May 2010 16:07:04 -0300 Subject: V4L/DVB: cx18/cx25840/saa7115/tvp5150: remove vbi support from s_fmt Now that s_fmt is no longer used for VBI format setup in subdevs, remove the VBI support from s_fmt. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-av-core.c | 6 ------ drivers/media/video/cx25840/cx25840-core.c | 6 ------ drivers/media/video/saa7115.c | 4 ---- drivers/media/video/tvp5150.c | 3 --- 4 files changed, 19 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c index c0289230209..0e5006b1427 100644 --- a/drivers/media/video/cx18/cx18-av-core.c +++ b/drivers/media/video/cx18/cx18-av-core.c @@ -1098,12 +1098,6 @@ static int cx18_av_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) cx18_av_write(cx, 0x41e, 0x8 | filter); break; - case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: - return cx18_av_s_sliced_fmt(sd, &fmt->fmt.sliced); - - case V4L2_BUF_TYPE_VBI_CAPTURE: - return cx18_av_s_raw_fmt(sd, &fmt->fmt.vbi); - default: return -EINVAL; } diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index a20df8c184e..8b6fb354437 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -1079,12 +1079,6 @@ static int cx25840_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) cx25840_write(client, 0x41e, 0x8 | filter); break; - case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: - return cx25840_s_sliced_fmt(sd, &fmt->fmt.sliced); - - case V4L2_BUF_TYPE_VBI_CAPTURE: - return cx25840_s_raw_fmt(sd, &fmt->fmt.vbi); - default: return -EINVAL; } diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index cf77318ede4..53b6fcde380 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -1138,10 +1138,6 @@ static int saa711x_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_f static int saa711x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) { - if (fmt->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) - return saa711x_s_sliced_fmt(sd, &fmt->fmt.sliced); - if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) - return saa711x_s_raw_fmt(sd, &fmt->fmt.vbi); if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index 853dd6f39b9..47f0582d50a 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c @@ -937,9 +937,6 @@ static int tvp5150_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_f static int tvp5150_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) { switch (fmt->type) { - case V4L2_BUF_TYPE_VBI_CAPTURE: - return tvp5150_s_raw_fmt(sd, &fmt->fmt.vbi); - case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: return tvp5150_s_sliced_fmt(sd, &fmt->fmt.sliced); -- cgit v1.2.3-70-g09d2 From 530d2d32068eaf3616e0ce9e58a5fde5701c3380 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 1 May 2010 08:00:18 -0300 Subject: V4L/DVB: bttv: remove bogus prio check in g_frequency Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/bttv-driver.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 350e7af7588..fcfc934a366 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -1987,11 +1987,6 @@ static int bttv_g_frequency(struct file *file, void *priv, { struct bttv_fh *fh = priv; struct bttv *btv = fh->btv; - int err; - - err = v4l2_prio_check(&btv->prio, &fh->prio); - if (0 != err) - return err; f->type = btv->radio_user ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; f->frequency = btv->freq; -- cgit v1.2.3-70-g09d2 From ffb4877ba013f94322083f77cbb05b35c2a218aa Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 1 May 2010 08:03:24 -0300 Subject: V4L/DVB: v4l2-common: simplify prio utility functions v4l2_prio_init/open/close returned an int when in fact they would always return 0. Make these void functions. v4l2_prio_close and v4l2_prio_check pass an enum v4l2_priority as a pointer for no good reason. Replace with a normal enum v4l2_priority argument. These changes will simplify the work of moving priority handling into the v4l core. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/bttv-driver.c | 18 +++++++++--------- drivers/media/video/cpia2/cpia2_v4l.c | 4 ++-- drivers/media/video/cx18/cx18-controls.c | 2 +- drivers/media/video/cx18/cx18-fileops.c | 2 +- drivers/media/video/cx18/cx18-ioctl.c | 16 ++++++++-------- drivers/media/video/davinci/vpfe_capture.c | 2 +- drivers/media/video/davinci/vpif_capture.c | 8 ++++---- drivers/media/video/davinci/vpif_display.c | 4 ++-- drivers/media/video/ivtv/ivtv-fileops.c | 2 +- drivers/media/video/ivtv/ivtv-ioctl.c | 2 +- drivers/media/video/pvrusb2/pvrusb2-v4l2.c | 6 +++--- drivers/media/video/saa7134/saa7134-video.c | 14 +++++++------- drivers/media/video/v4l2-common.c | 22 +++++++++------------- drivers/staging/cx25821/cx25821-audups11.c | 6 +++--- drivers/staging/cx25821/cx25821-video.c | 11 +++++------ drivers/staging/cx25821/cx25821-video0.c | 6 +++--- drivers/staging/cx25821/cx25821-video1.c | 6 +++--- drivers/staging/cx25821/cx25821-video2.c | 6 +++--- drivers/staging/cx25821/cx25821-video3.c | 6 +++--- drivers/staging/cx25821/cx25821-video4.c | 6 +++--- drivers/staging/cx25821/cx25821-video5.c | 6 +++--- drivers/staging/cx25821/cx25821-video6.c | 6 +++--- drivers/staging/cx25821/cx25821-video7.c | 6 +++--- drivers/staging/cx25821/cx25821-videoioctl.c | 6 +++--- drivers/staging/cx25821/cx25821-vidups10.c | 6 +++--- drivers/staging/cx25821/cx25821-vidups9.c | 6 +++--- include/media/v4l2-common.h | 8 ++++---- 27 files changed, 94 insertions(+), 99 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index fcfc934a366..38c7f78ad9c 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -1525,7 +1525,7 @@ static int bttv_s_ctrl(struct file *file, void *f, struct bttv_fh *fh = f; struct bttv *btv = fh->btv; - err = v4l2_prio_check(&btv->prio, &fh->prio); + err = v4l2_prio_check(&btv->prio, fh->prio); if (0 != err) return err; @@ -1859,7 +1859,7 @@ static int bttv_s_std(struct file *file, void *priv, v4l2_std_id *id) unsigned int i; int err; - err = v4l2_prio_check(&btv->prio, &fh->prio); + err = v4l2_prio_check(&btv->prio, fh->prio); if (0 != err) return err; @@ -1941,7 +1941,7 @@ static int bttv_s_input(struct file *file, void *priv, unsigned int i) int err; - err = v4l2_prio_check(&btv->prio, &fh->prio); + err = v4l2_prio_check(&btv->prio, fh->prio); if (0 != err) return err; @@ -1961,7 +1961,7 @@ static int bttv_s_tuner(struct file *file, void *priv, struct bttv *btv = fh->btv; int err; - err = v4l2_prio_check(&btv->prio, &fh->prio); + err = v4l2_prio_check(&btv->prio, fh->prio); if (0 != err) return err; @@ -2001,7 +2001,7 @@ static int bttv_s_frequency(struct file *file, void *priv, struct bttv *btv = fh->btv; int err; - err = v4l2_prio_check(&btv->prio, &fh->prio); + err = v4l2_prio_check(&btv->prio, fh->prio); if (0 != err) return err; @@ -3024,7 +3024,7 @@ static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop) crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY) return -EINVAL; - retval = v4l2_prio_check(&btv->prio, &fh->prio); + retval = v4l2_prio_check(&btv->prio, fh->prio); if (0 != retval) return retval; @@ -3236,7 +3236,7 @@ static int bttv_open(struct file *file) *fh = btv->init; fh->type = type; fh->ov.setup_ok = 0; - v4l2_prio_open(&btv->prio,&fh->prio); + v4l2_prio_open(&btv->prio, &fh->prio); videobuf_queue_sg_init(&fh->cap, &bttv_video_qops, &btv->c.pci->dev, &btv->s_lock, @@ -3307,7 +3307,7 @@ static int bttv_release(struct file *file) /* free stuff */ videobuf_mmap_free(&fh->cap); videobuf_mmap_free(&fh->vbi); - v4l2_prio_close(&btv->prio,&fh->prio); + v4l2_prio_close(&btv->prio, fh->prio); file->private_data = NULL; kfree(fh); @@ -3444,7 +3444,7 @@ static int radio_release(struct file *file) struct bttv *btv = fh->btv; struct rds_command cmd; - v4l2_prio_close(&btv->prio,&fh->prio); + v4l2_prio_close(&btv->prio, fh->prio); file->private_data = NULL; kfree(fh); diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c index 6f91415eb7b..5520789854d 100644 --- a/drivers/media/video/cpia2/cpia2_v4l.c +++ b/drivers/media/video/cpia2/cpia2_v4l.c @@ -324,7 +324,7 @@ static int cpia2_close(struct file *file) { if(fh->mmapped) cam->mmapped = 0; - v4l2_prio_close(&cam->prio,&fh->prio); + v4l2_prio_close(&cam->prio, fh->prio); file->private_data = NULL; kfree(fh); } @@ -1592,7 +1592,7 @@ static long cpia2_do_ioctl(struct file *file, unsigned int cmd, void *arg) case VIDIOC_S_FMT: { struct cpia2_fh *fh = file->private_data; - retval = v4l2_prio_check(&cam->prio, &fh->prio); + retval = v4l2_prio_check(&cam->prio, fh->prio); if(retval) { mutex_unlock(&cam->busy_lock); return retval; diff --git a/drivers/media/video/cx18/cx18-controls.c b/drivers/media/video/cx18/cx18-controls.c index 7fa589240ff..4b4b46544d5 100644 --- a/drivers/media/video/cx18/cx18-controls.c +++ b/drivers/media/video/cx18/cx18-controls.c @@ -263,7 +263,7 @@ int cx18_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c) int ret; struct v4l2_control ctrl; - ret = v4l2_prio_check(&cx->prio, &id->prio); + ret = v4l2_prio_check(&cx->prio, id->prio); if (ret) return ret; diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c index 863ce775823..e12a15020cd 100644 --- a/drivers/media/video/cx18/cx18-fileops.c +++ b/drivers/media/video/cx18/cx18-fileops.c @@ -700,7 +700,7 @@ int cx18_v4l2_close(struct file *filp) CX18_DEBUG_IOCTL("close() of %s\n", s->name); - v4l2_prio_close(&cx->prio, &id->prio); + v4l2_prio_close(&cx->prio, id->prio); /* Easy case first: this stream was never claimed by us */ if (s->id != id->open_id) { diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c index 2e6addab3ed..2530fc54daa 100644 --- a/drivers/media/video/cx18/cx18-ioctl.c +++ b/drivers/media/video/cx18/cx18-ioctl.c @@ -277,7 +277,7 @@ static int cx18_s_fmt_vid_cap(struct file *file, void *fh, int ret; int w, h; - ret = v4l2_prio_check(&cx->prio, &id->prio); + ret = v4l2_prio_check(&cx->prio, id->prio); if (ret) return ret; @@ -306,7 +306,7 @@ static int cx18_s_fmt_vbi_cap(struct file *file, void *fh, struct cx18 *cx = id->cx; int ret; - ret = v4l2_prio_check(&cx->prio, &id->prio); + ret = v4l2_prio_check(&cx->prio, id->prio); if (ret) return ret; @@ -341,7 +341,7 @@ static int cx18_s_fmt_sliced_vbi_cap(struct file *file, void *fh, int ret; struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; - ret = v4l2_prio_check(&cx->prio, &id->prio); + ret = v4l2_prio_check(&cx->prio, id->prio); if (ret) return ret; @@ -549,7 +549,7 @@ static int cx18_s_crop(struct file *file, void *fh, struct v4l2_crop *crop) struct cx18 *cx = id->cx; int ret; - ret = v4l2_prio_check(&cx->prio, &id->prio); + ret = v4l2_prio_check(&cx->prio, id->prio); if (ret) return ret; @@ -601,7 +601,7 @@ int cx18_s_input(struct file *file, void *fh, unsigned int inp) struct cx18 *cx = id->cx; int ret; - ret = v4l2_prio_check(&cx->prio, &id->prio); + ret = v4l2_prio_check(&cx->prio, id->prio); if (ret) return ret; @@ -647,7 +647,7 @@ int cx18_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf) struct cx18 *cx = id->cx; int ret; - ret = v4l2_prio_check(&cx->prio, &id->prio); + ret = v4l2_prio_check(&cx->prio, id->prio); if (ret) return ret; @@ -675,7 +675,7 @@ int cx18_s_std(struct file *file, void *fh, v4l2_std_id *std) struct cx18 *cx = id->cx; int ret; - ret = v4l2_prio_check(&cx->prio, &id->prio); + ret = v4l2_prio_check(&cx->prio, id->prio); if (ret) return ret; @@ -715,7 +715,7 @@ static int cx18_s_tuner(struct file *file, void *fh, struct v4l2_tuner *vt) struct cx18 *cx = id->cx; int ret; - ret = v4l2_prio_check(&cx->prio, &id->prio); + ret = v4l2_prio_check(&cx->prio, id->prio); if (ret) return ret; diff --git a/drivers/media/video/davinci/vpfe_capture.c b/drivers/media/video/davinci/vpfe_capture.c index f6648f6ba2f..1c258824728 100644 --- a/drivers/media/video/davinci/vpfe_capture.c +++ b/drivers/media/video/davinci/vpfe_capture.c @@ -736,7 +736,7 @@ static int vpfe_release(struct file *file) /* Decrement device usrs counter */ vpfe_dev->usrs--; /* Close the priority */ - v4l2_prio_close(&vpfe_dev->prio, &fh->prio); + v4l2_prio_close(&vpfe_dev->prio, fh->prio); /* If this is the last file handle */ if (!vpfe_dev->usrs) { vpfe_dev->initialized = 0; diff --git a/drivers/media/video/davinci/vpif_capture.c b/drivers/media/video/davinci/vpif_capture.c index 2e5a7fb2d0c..a7f48b53d3f 100644 --- a/drivers/media/video/davinci/vpif_capture.c +++ b/drivers/media/video/davinci/vpif_capture.c @@ -869,7 +869,7 @@ static int vpif_release(struct file *filep) mutex_unlock(&common->lock); /* Close the priority */ - v4l2_prio_close(&ch->prio, &fh->prio); + v4l2_prio_close(&ch->prio, fh->prio); if (fh->initialized) ch->initialized = 0; @@ -1444,7 +1444,7 @@ static int vpif_s_std(struct file *file, void *priv, v4l2_std_id *std_id) } } - ret = v4l2_prio_check(&ch->prio, &fh->prio); + ret = v4l2_prio_check(&ch->prio, fh->prio); if (0 != ret) return ret; @@ -1554,7 +1554,7 @@ static int vpif_s_input(struct file *file, void *priv, unsigned int index) } } - ret = v4l2_prio_check(&ch->prio, &fh->prio); + ret = v4l2_prio_check(&ch->prio, fh->prio); if (0 != ret) return ret; @@ -1710,7 +1710,7 @@ static int vpif_s_fmt_vid_cap(struct file *file, void *priv, } } - ret = v4l2_prio_check(&ch->prio, &fh->prio); + ret = v4l2_prio_check(&ch->prio, fh->prio); if (0 != ret) return ret; diff --git a/drivers/media/video/davinci/vpif_display.c b/drivers/media/video/davinci/vpif_display.c index e5bab3d0d53..da07607cbc5 100644 --- a/drivers/media/video/davinci/vpif_display.c +++ b/drivers/media/video/davinci/vpif_display.c @@ -671,7 +671,7 @@ static int vpif_release(struct file *filep) ch->initialized = 0; /* Close the priority */ - v4l2_prio_close(&ch->prio, &fh->prio); + v4l2_prio_close(&ch->prio, fh->prio); filep->private_data = NULL; fh->initialized = 0; kfree(fh); @@ -753,7 +753,7 @@ static int vpif_s_fmt_vid_out(struct file *file, void *priv, } /* Check for the priority */ - ret = v4l2_prio_check(&ch->prio, &fh->prio); + ret = v4l2_prio_check(&ch->prio, fh->prio); if (0 != ret) return ret; fh->initialized = 1; diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c index bee9605bd27..abf410943cc 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ b/drivers/media/video/ivtv/ivtv-fileops.c @@ -853,7 +853,7 @@ int ivtv_v4l2_close(struct file *filp) IVTV_DEBUG_FILE("close %s\n", s->name); - v4l2_prio_close(&itv->prio, &id->prio); + v4l2_prio_close(&itv->prio, id->prio); v4l2_fh_del(fh); v4l2_fh_exit(fh); diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index a17c659e632..6573764f506 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c @@ -1851,7 +1851,7 @@ static long ivtv_serialized_ioctl(struct ivtv *itv, struct file *filp, case VIDIOC_S_EXT_CTRLS: case VIDIOC_S_FBUF: case VIDIOC_OVERLAY: - ret = v4l2_prio_check(&itv->prio, &id->prio); + ret = v4l2_prio_check(&itv->prio, id->prio); if (ret) return ret; } diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index fe4159d478b..5ffa0d2b0b0 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c @@ -183,7 +183,7 @@ static long pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) case VIDIOC_S_INPUT: case VIDIOC_S_TUNER: case VIDIOC_S_FREQUENCY: - ret = v4l2_prio_check(&vp->prio, &fh->prio); + ret = v4l2_prio_check(&vp->prio, fh->prio); if (ret) return ret; } @@ -972,7 +972,7 @@ static int pvr2_v4l2_release(struct file *file) fhp->rhp = NULL; } - v4l2_prio_close(&vp->prio, &fhp->prio); + v4l2_prio_close(&vp->prio, fhp->prio); file->private_data = NULL; if (fhp->vnext) { @@ -1093,7 +1093,7 @@ static int pvr2_v4l2_open(struct file *file) fhp->file = file; file->private_data = fhp; - v4l2_prio_open(&vp->prio,&fhp->prio); + v4l2_prio_open(&vp->prio, &fhp->prio); fhp->fw_mode_flag = pvr2_hdw_cpufw_get_enabled(hdw); diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index 7806fb17e74..45f0ac8f3c0 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -1180,7 +1180,7 @@ int saa7134_s_ctrl_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, str That needs to be fixed somehow, but for now this is good enough. */ if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); + err = v4l2_prio_check(&dev->prio, fh->prio); if (0 != err) return err; } @@ -1359,7 +1359,7 @@ static int video_open(struct file *file) fh->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24); fh->width = 720; fh->height = 576; - v4l2_prio_open(&dev->prio,&fh->prio); + v4l2_prio_open(&dev->prio, &fh->prio); videobuf_queue_sg_init(&fh->cap, &video_qops, &dev->pci->dev, &dev->slock, @@ -1502,7 +1502,7 @@ static int video_release(struct file *file) saa7134_pgtable_free(dev->pci,&fh->pt_cap); saa7134_pgtable_free(dev->pci,&fh->pt_vbi); - v4l2_prio_close(&dev->prio,&fh->prio); + v4l2_prio_close(&dev->prio, fh->prio); file->private_data = NULL; kfree(fh); return 0; @@ -1785,7 +1785,7 @@ static int saa7134_s_input(struct file *file, void *priv, unsigned int i) struct saa7134_dev *dev = fh->dev; int err; - err = v4l2_prio_check(&dev->prio, &fh->prio); + err = v4l2_prio_check(&dev->prio, fh->prio); if (0 != err) return err; @@ -1839,7 +1839,7 @@ int saa7134_s_std_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, v4l2_ That needs to be fixed somehow, but for now this is good enough. */ if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); + err = v4l2_prio_check(&dev->prio, fh->prio); if (0 != err) return err; } else if (res_locked(dev, RESOURCE_OVERLAY)) { @@ -2023,7 +2023,7 @@ static int saa7134_s_tuner(struct file *file, void *priv, struct saa7134_dev *dev = fh->dev; int rx, mode, err; - err = v4l2_prio_check(&dev->prio, &fh->prio); + err = v4l2_prio_check(&dev->prio, fh->prio); if (0 != err) return err; @@ -2057,7 +2057,7 @@ static int saa7134_s_frequency(struct file *file, void *priv, struct saa7134_dev *dev = fh->dev; int err; - err = v4l2_prio_check(&dev->prio, &fh->prio); + err = v4l2_prio_check(&dev->prio, fh->prio); if (0 != err) return err; diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index 035c414507a..4e53b0b3339 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -88,10 +88,9 @@ MODULE_LICENSE("GPL"); val == V4L2_PRIORITY_INTERACTIVE || \ val == V4L2_PRIORITY_RECORD) -int v4l2_prio_init(struct v4l2_prio_state *global) +void v4l2_prio_init(struct v4l2_prio_state *global) { - memset(global,0,sizeof(*global)); - return 0; + memset(global, 0, sizeof(*global)); } EXPORT_SYMBOL(v4l2_prio_init); @@ -111,17 +110,16 @@ int v4l2_prio_change(struct v4l2_prio_state *global, enum v4l2_priority *local, } EXPORT_SYMBOL(v4l2_prio_change); -int v4l2_prio_open(struct v4l2_prio_state *global, enum v4l2_priority *local) +void v4l2_prio_open(struct v4l2_prio_state *global, enum v4l2_priority *local) { - return v4l2_prio_change(global,local,V4L2_PRIORITY_DEFAULT); + v4l2_prio_change(global, local, V4L2_PRIORITY_DEFAULT); } EXPORT_SYMBOL(v4l2_prio_open); -int v4l2_prio_close(struct v4l2_prio_state *global, enum v4l2_priority *local) +void v4l2_prio_close(struct v4l2_prio_state *global, enum v4l2_priority local) { - if (V4L2_PRIO_VALID(*local)) - atomic_dec(&global->prios[*local]); - return 0; + if (V4L2_PRIO_VALID(local)) + atomic_dec(&global->prios[local]); } EXPORT_SYMBOL(v4l2_prio_close); @@ -137,11 +135,9 @@ enum v4l2_priority v4l2_prio_max(struct v4l2_prio_state *global) } EXPORT_SYMBOL(v4l2_prio_max); -int v4l2_prio_check(struct v4l2_prio_state *global, enum v4l2_priority *local) +int v4l2_prio_check(struct v4l2_prio_state *global, enum v4l2_priority local) { - if (*local < v4l2_prio_max(global)) - return -EBUSY; - return 0; + return (local < v4l2_prio_max(global)) ? -EBUSY : 0; } EXPORT_SYMBOL(v4l2_prio_check); diff --git a/drivers/staging/cx25821/cx25821-audups11.c b/drivers/staging/cx25821/cx25821-audups11.c index 9193a6eb7cf..e49ead982f3 100644 --- a/drivers/staging/cx25821/cx25821-audups11.c +++ b/drivers/staging/cx25821/cx25821-audups11.c @@ -203,7 +203,7 @@ static int video_release(struct file *file) videobuf_mmap_free(&fh->vidq); - v4l2_prio_close(&dev->prio, &fh->prio); + v4l2_prio_close(&dev->prio, fh->prio); file->private_data = NULL; kfree(fh); @@ -258,7 +258,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, int err; if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); + err = v4l2_prio_check(&dev->prio, fh->prio); if (0 != err) return err; } @@ -350,7 +350,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, if (fh) { dev = fh->dev; - err = v4l2_prio_check(&dev->prio, &fh->prio); + err = v4l2_prio_check(&dev->prio, fh->prio); if (0 != err) return err; } diff --git a/drivers/staging/cx25821/cx25821-video.c b/drivers/staging/cx25821/cx25821-video.c index a3bea2739ce..791212c1a66 100644 --- a/drivers/staging/cx25821/cx25821-video.c +++ b/drivers/staging/cx25821/cx25821-video.c @@ -846,7 +846,7 @@ int cx25821_vidioc_s_std(struct file *file, void *priv, v4l2_std_id * tvnorms) dprintk(1, "%s()\n", __func__); if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); + err = v4l2_prio_check(&dev->prio, fh->prio); if (0 != err) return err; } @@ -916,7 +916,7 @@ int cx25821_vidioc_s_input(struct file *file, void *priv, unsigned int i) dprintk(1, "%s(%d)\n", __func__, i); if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); + err = v4l2_prio_check(&dev->prio, fh->prio); if (0 != err) return err; } @@ -967,8 +967,7 @@ int cx25821_vidioc_s_frequency(struct file *file, void *priv, struct v4l2_freque int err; if (fh) { - dev = fh->dev; - err = v4l2_prio_check(&dev->prio, &fh->prio); + err = v4l2_prio_check(&dev->prio, fh->prio); if (0 != err) return err; } @@ -1032,7 +1031,7 @@ int cx25821_vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t) int err; if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); + err = v4l2_prio_check(&dev->prio, fh->prio); if (0 != err) return err; } @@ -1240,7 +1239,7 @@ int cx25821_vidioc_s_crop(struct file *file, void *priv, struct v4l2_crop *crop) int err; if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); + err = v4l2_prio_check(&dev->prio, fh->prio); if (0 != err) return err; } diff --git a/drivers/staging/cx25821/cx25821-video0.c b/drivers/staging/cx25821/cx25821-video0.c index 1f95ddba849..0be2cc15d85 100644 --- a/drivers/staging/cx25821/cx25821-video0.c +++ b/drivers/staging/cx25821/cx25821-video0.c @@ -219,7 +219,7 @@ static int video_release(struct file *file) videobuf_mmap_free(&fh->vidq); - v4l2_prio_close(&dev->prio, &fh->prio); + v4l2_prio_close(&dev->prio, fh->prio); file->private_data = NULL; kfree(fh); @@ -274,7 +274,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, int pix_format = PIXEL_FRMT_422; if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); + err = v4l2_prio_check(&dev->prio, fh->prio); if (0 != err) return err; } @@ -363,7 +363,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, int err; if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); + err = v4l2_prio_check(&dev->prio, fh->prio); if (0 != err) return err; } diff --git a/drivers/staging/cx25821/cx25821-video1.c b/drivers/staging/cx25821/cx25821-video1.c index 9b94462a62c..b0bae627bfb 100644 --- a/drivers/staging/cx25821/cx25821-video1.c +++ b/drivers/staging/cx25821/cx25821-video1.c @@ -219,7 +219,7 @@ static int video_release(struct file *file) videobuf_mmap_free(&fh->vidq); - v4l2_prio_close(&dev->prio, &fh->prio); + v4l2_prio_close(&dev->prio, fh->prio); file->private_data = NULL; kfree(fh); @@ -274,7 +274,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, int pix_format = 0; if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); + err = v4l2_prio_check(&dev->prio, fh->prio); if (0 != err) return err; } @@ -363,7 +363,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, int err; if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); + err = v4l2_prio_check(&dev->prio, fh->prio); if (0 != err) return err; } diff --git a/drivers/staging/cx25821/cx25821-video2.c b/drivers/staging/cx25821/cx25821-video2.c index 31c46aa2e56..400cdb80674 100644 --- a/drivers/staging/cx25821/cx25821-video2.c +++ b/drivers/staging/cx25821/cx25821-video2.c @@ -219,7 +219,7 @@ static int video_release(struct file *file) videobuf_mmap_free(&fh->vidq); - v4l2_prio_close(&dev->prio, &fh->prio); + v4l2_prio_close(&dev->prio, fh->prio); file->private_data = NULL; kfree(fh); @@ -274,7 +274,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, int pix_format = 0; if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); + err = v4l2_prio_check(&dev->prio, fh->prio); if (0 != err) return err; } @@ -365,7 +365,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, int err; if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); + err = v4l2_prio_check(&dev->prio, fh->prio); if (0 != err) return err; } diff --git a/drivers/staging/cx25821/cx25821-video3.c b/drivers/staging/cx25821/cx25821-video3.c index cbc5cad24a0..3b216ed0906 100644 --- a/drivers/staging/cx25821/cx25821-video3.c +++ b/drivers/staging/cx25821/cx25821-video3.c @@ -219,7 +219,7 @@ static int video_release(struct file *file) videobuf_mmap_free(&fh->vidq); - v4l2_prio_close(&dev->prio, &fh->prio); + v4l2_prio_close(&dev->prio, fh->prio); file->private_data = NULL; kfree(fh); @@ -274,7 +274,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, int pix_format = 0; if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); + err = v4l2_prio_check(&dev->prio, fh->prio); if (0 != err) return err; } @@ -364,7 +364,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, int err; if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); + err = v4l2_prio_check(&dev->prio, fh->prio); if (0 != err) return err; } diff --git a/drivers/staging/cx25821/cx25821-video4.c b/drivers/staging/cx25821/cx25821-video4.c index 101074ad742..f7b08c51868 100644 --- a/drivers/staging/cx25821/cx25821-video4.c +++ b/drivers/staging/cx25821/cx25821-video4.c @@ -218,7 +218,7 @@ static int video_release(struct file *file) videobuf_mmap_free(&fh->vidq); - v4l2_prio_close(&dev->prio, &fh->prio); + v4l2_prio_close(&dev->prio, fh->prio); file->private_data = NULL; kfree(fh); @@ -274,7 +274,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, // check priority if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); + err = v4l2_prio_check(&dev->prio, fh->prio); if (0 != err) return err; } @@ -363,7 +363,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, int err; if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); + err = v4l2_prio_check(&dev->prio, fh->prio); if (0 != err) return err; } diff --git a/drivers/staging/cx25821/cx25821-video5.c b/drivers/staging/cx25821/cx25821-video5.c index 2019c5e3ea1..59370337b07 100644 --- a/drivers/staging/cx25821/cx25821-video5.c +++ b/drivers/staging/cx25821/cx25821-video5.c @@ -219,7 +219,7 @@ static int video_release(struct file *file) videobuf_mmap_free(&fh->vidq); - v4l2_prio_close(&dev->prio, &fh->prio); + v4l2_prio_close(&dev->prio, fh->prio); file->private_data = NULL; kfree(fh); @@ -274,7 +274,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, int pix_format = 0; if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); + err = v4l2_prio_check(&dev->prio, fh->prio); if (0 != err) return err; } @@ -363,7 +363,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, int err; if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); + err = v4l2_prio_check(&dev->prio, fh->prio); if (0 != err) return err; } diff --git a/drivers/staging/cx25821/cx25821-video6.c b/drivers/staging/cx25821/cx25821-video6.c index d19c786e5a5..4db2eb83d35 100644 --- a/drivers/staging/cx25821/cx25821-video6.c +++ b/drivers/staging/cx25821/cx25821-video6.c @@ -218,7 +218,7 @@ static int video_release(struct file *file) videobuf_mmap_free(&fh->vidq); - v4l2_prio_close(&dev->prio, &fh->prio); + v4l2_prio_close(&dev->prio, fh->prio); file->private_data = NULL; kfree(fh); @@ -273,7 +273,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, int pix_format = 0; if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); + err = v4l2_prio_check(&dev->prio, fh->prio); if (0 != err) return err; } @@ -363,7 +363,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, int err; if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); + err = v4l2_prio_check(&dev->prio, fh->prio); if (0 != err) return err; } diff --git a/drivers/staging/cx25821/cx25821-video7.c b/drivers/staging/cx25821/cx25821-video7.c index 8a7c854a0fc..5e4a769bada 100644 --- a/drivers/staging/cx25821/cx25821-video7.c +++ b/drivers/staging/cx25821/cx25821-video7.c @@ -218,7 +218,7 @@ static int video_release(struct file *file) videobuf_mmap_free(&fh->vidq); - v4l2_prio_close(&dev->prio, &fh->prio); + v4l2_prio_close(&dev->prio, fh->prio); file->private_data = NULL; kfree(fh); @@ -273,7 +273,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, int pix_format = 0; if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); + err = v4l2_prio_check(&dev->prio, fh->prio); if (0 != err) return err; } @@ -362,7 +362,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, int err; if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); + err = v4l2_prio_check(&dev->prio, fh->prio); if (0 != err) return err; } diff --git a/drivers/staging/cx25821/cx25821-videoioctl.c b/drivers/staging/cx25821/cx25821-videoioctl.c index 840714a9415..d16807d88be 100644 --- a/drivers/staging/cx25821/cx25821-videoioctl.c +++ b/drivers/staging/cx25821/cx25821-videoioctl.c @@ -201,7 +201,7 @@ static int video_release(struct file *file) videobuf_mmap_free(&fh->vidq); - v4l2_prio_close(&dev->prio, &fh->prio); + v4l2_prio_close(&dev->prio, fh->prio); file->private_data = NULL; kfree(fh); @@ -256,7 +256,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, int err; if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); + err = v4l2_prio_check(&dev->prio, fh->prio); if (0 != err) return err; } @@ -409,7 +409,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, int err; if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); + err = v4l2_prio_check(&dev->prio, fh->prio); if (0 != err) return err; } diff --git a/drivers/staging/cx25821/cx25821-vidups10.c b/drivers/staging/cx25821/cx25821-vidups10.c index 89c8592e5f0..c746a17ccbd 100644 --- a/drivers/staging/cx25821/cx25821-vidups10.c +++ b/drivers/staging/cx25821/cx25821-vidups10.c @@ -201,7 +201,7 @@ static int video_release(struct file *file) videobuf_mmap_free(&fh->vidq); - v4l2_prio_close(&dev->prio, &fh->prio); + v4l2_prio_close(&dev->prio, fh->prio); file->private_data = NULL; kfree(fh); @@ -299,7 +299,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, int err; if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); + err = v4l2_prio_check(&dev->prio, fh->prio); if (0 != err) return err; } @@ -347,7 +347,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, int err; if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); + err = v4l2_prio_check(&dev->prio, fh->prio); if (0 != err) return err; } diff --git a/drivers/staging/cx25821/cx25821-vidups9.c b/drivers/staging/cx25821/cx25821-vidups9.c index c8e8083c793..466e0f34ae3 100644 --- a/drivers/staging/cx25821/cx25821-vidups9.c +++ b/drivers/staging/cx25821/cx25821-vidups9.c @@ -201,7 +201,7 @@ static int video_release(struct file *file) videobuf_mmap_free(&fh->vidq); - v4l2_prio_close(&dev->prio, &fh->prio); + v4l2_prio_close(&dev->prio, fh->prio); file->private_data = NULL; kfree(fh); @@ -299,7 +299,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, int err; if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); + err = v4l2_prio_check(&dev->prio, fh->prio); if (0 != err) return err; } @@ -345,7 +345,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, struct cx25821_fh *fh = priv; int err; if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); + err = v4l2_prio_check(&dev->prio, fh->prio); if (0 != err) return err; } diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index 3b2efdc6d06..98b32645e5a 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h @@ -85,13 +85,13 @@ struct v4l2_prio_state { atomic_t prios[4]; }; -int v4l2_prio_init(struct v4l2_prio_state *global); +void v4l2_prio_init(struct v4l2_prio_state *global); int v4l2_prio_change(struct v4l2_prio_state *global, enum v4l2_priority *local, enum v4l2_priority new); -int v4l2_prio_open(struct v4l2_prio_state *global, enum v4l2_priority *local); -int v4l2_prio_close(struct v4l2_prio_state *global, enum v4l2_priority *local); +void v4l2_prio_open(struct v4l2_prio_state *global, enum v4l2_priority *local); +void v4l2_prio_close(struct v4l2_prio_state *global, enum v4l2_priority local); enum v4l2_priority v4l2_prio_max(struct v4l2_prio_state *global); -int v4l2_prio_check(struct v4l2_prio_state *global, enum v4l2_priority *local); +int v4l2_prio_check(struct v4l2_prio_state *global, enum v4l2_priority local); /* ------------------------------------------------------------------------- */ -- cgit v1.2.3-70-g09d2 From cf19cd3d8a043b1c5784218709a85e358e0d78fb Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 1 May 2010 08:23:07 -0300 Subject: V4L/DVB: tvp7002: fix query_dv_preset If no signal or valid format is detected, then VIDIOC_QUERY_DV_PRESET must return 0 and set the preset to V4L2_DV_INVALID. This driver returned an error instead. Also simplified the kernel messages a bit: change v4l2_err to v4l2_dbg (not detecting a signal/valid format is not an error, so only print this info when debug == 1) and do not call v4l_fill_dv_preset_info: it's overkill to do this just for a debug message. Thanks to Mats Randgaard for bringing this to my attention. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvp7002.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/tvp7002.c b/drivers/media/video/tvp7002.c index 4a69bcc738f..f650f0d125e 100644 --- a/drivers/media/video/tvp7002.c +++ b/drivers/media/video/tvp7002.c @@ -785,7 +785,6 @@ static int tvp7002_query_dv_preset(struct v4l2_subdev *sd, struct v4l2_dv_preset *qpreset) { const struct tvp7002_preset_definition *presets = tvp7002_presets; - struct v4l2_dv_enum_preset e_preset; struct tvp7002 *device; u8 progressive; u32 lpfr; @@ -828,20 +827,18 @@ static int tvp7002_query_dv_preset(struct v4l2_subdev *sd, } if (index == NUM_PRESETS) { - v4l2_err(sd, "querystd error, lpf = %x, cpl = %x\n", + v4l2_dbg(1, debug, sd, "detection failed: lpf = %x, cpl = %x\n", lpfr, cpln); - return -EINVAL; + /* Could not detect a signal, so return the 'invalid' preset */ + qpreset->preset = V4L2_DV_INVALID; + return 0; } - if (v4l_fill_dv_preset_info(presets->preset, &e_preset)) - return -EINVAL; - /* Set values in found preset */ qpreset->preset = presets->preset; /* Update lines per frame and clocks per line info */ - v4l2_dbg(1, debug, sd, "Current preset: %d %d", - e_preset.width, e_preset.height); + v4l2_dbg(1, debug, sd, "detected preset: %d\n", presets->preset); return 0; } -- cgit v1.2.3-70-g09d2 From 0eed42e48a6292ebc96606c6a7105c69b37666d0 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 1 May 2010 18:06:50 -0300 Subject: V4L/DVB: em28xx: g_tuner must set type field The 'type' field was undefined but should be set to ANALOG_TV. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-video.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 8565fb3ff94..20090e34173 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -1500,6 +1500,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, return -EINVAL; strcpy(t->name, "Tuner"); + t->type = V4L2_TUNER_ANALOG_TV; mutex_lock(&dev->lock); v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t); -- cgit v1.2.3-70-g09d2 From dd0daf2a6fb6bec436a3ef68bd585ea09a2a54b7 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 2 May 2010 05:11:32 -0300 Subject: V4L/DVB: v4l2-dev: remove unnecessary lock around atomic clear_bit No need to lock when unregistering the device: clear_bit is already an atomic operation. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-dev.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 65a7b30524c..0ca7ec9ca90 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c @@ -600,9 +600,7 @@ void video_unregister_device(struct video_device *vdev) if (!vdev || !video_is_registered(vdev)) return; - mutex_lock(&videodev_lock); clear_bit(V4L2_FL_REGISTERED, &vdev->flags); - mutex_unlock(&videodev_lock); device_unregister(&vdev->dev); } EXPORT_SYMBOL(video_unregister_device); -- cgit v1.2.3-70-g09d2 From f2b305cd6711b7b3ce30db93b50bc5d6312950c8 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 2 May 2010 08:01:04 -0300 Subject: V4L/DVB: hdpvr: fix disconnect sequence Disconnecting the HDPVR caused a kernel oops if lockdep was enabled. In addition, if an app still had video0 open and attempted to call ioctl when the device was already disconnected the system would crash. Move the freeing and cleanup code to the release function: that is the right place for it since you know when you get there that nobody is using the device. Also removed usb_set_intfdata: v4l2_device_register sets this already to v4l2_dev. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/hdpvr/hdpvr-core.c | 33 +++++---------------------------- drivers/media/video/hdpvr/hdpvr-video.c | 18 ++++++++++++++++++ drivers/media/video/hdpvr/hdpvr.h | 5 +++++ 3 files changed, 28 insertions(+), 28 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/hdpvr/hdpvr-core.c b/drivers/media/video/hdpvr/hdpvr-core.c index 2fc9865fd48..830d47b05e1 100644 --- a/drivers/media/video/hdpvr/hdpvr-core.c +++ b/drivers/media/video/hdpvr/hdpvr-core.c @@ -373,9 +373,6 @@ static int hdpvr_probe(struct usb_interface *interface, } #endif /* CONFIG_I2C */ - /* save our data pointer in this interface device */ - usb_set_intfdata(interface, dev); - /* let the user know what node this device is now attached to */ v4l2_info(&dev->v4l2_dev, "device now attached to %s\n", video_device_node_name(dev->video_dev)); @@ -391,44 +388,24 @@ error: static void hdpvr_disconnect(struct usb_interface *interface) { - struct hdpvr_device *dev; - - dev = usb_get_intfdata(interface); - usb_set_intfdata(interface, NULL); + struct hdpvr_device *dev = to_hdpvr_dev(usb_get_intfdata(interface)); + v4l2_info(&dev->v4l2_dev, "device %s disconnected\n", + video_device_node_name(dev->video_dev)); /* prevent more I/O from starting and stop any ongoing */ mutex_lock(&dev->io_mutex); dev->status = STATUS_DISCONNECTED; - v4l2_device_disconnect(&dev->v4l2_dev); - video_unregister_device(dev->video_dev); wake_up_interruptible(&dev->wait_data); wake_up_interruptible(&dev->wait_buffer); mutex_unlock(&dev->io_mutex); + v4l2_device_disconnect(&dev->v4l2_dev); msleep(100); flush_workqueue(dev->workqueue); mutex_lock(&dev->io_mutex); hdpvr_cancel_queue(dev); - destroy_workqueue(dev->workqueue); mutex_unlock(&dev->io_mutex); - - /* deregister I2C adapter */ -#ifdef CONFIG_I2C - mutex_lock(&dev->i2c_mutex); - if (dev->i2c_adapter) - i2c_del_adapter(dev->i2c_adapter); - kfree(dev->i2c_adapter); - dev->i2c_adapter = NULL; - mutex_unlock(&dev->i2c_mutex); -#endif /* CONFIG_I2C */ - + video_unregister_device(dev->video_dev); atomic_dec(&dev_nr); - - v4l2_info(&dev->v4l2_dev, "device %s disconnected\n", - video_device_node_name(dev->video_dev)); - - v4l2_device_unregister(&dev->v4l2_dev); - kfree(dev->usbc_buf); - kfree(dev); } diff --git a/drivers/media/video/hdpvr/hdpvr-video.c b/drivers/media/video/hdpvr/hdpvr-video.c index 196f82de48f..d2f0ee29737 100644 --- a/drivers/media/video/hdpvr/hdpvr-video.c +++ b/drivers/media/video/hdpvr/hdpvr-video.c @@ -1214,6 +1214,24 @@ static void hdpvr_device_release(struct video_device *vdev) struct hdpvr_device *dev = video_get_drvdata(vdev); hdpvr_delete(dev); + mutex_lock(&dev->io_mutex); + destroy_workqueue(dev->workqueue); + mutex_unlock(&dev->io_mutex); + + v4l2_device_unregister(&dev->v4l2_dev); + + /* deregister I2C adapter */ +#ifdef CONFIG_I2C + mutex_lock(&dev->i2c_mutex); + if (dev->i2c_adapter) + i2c_del_adapter(dev->i2c_adapter); + kfree(dev->i2c_adapter); + dev->i2c_adapter = NULL; + mutex_unlock(&dev->i2c_mutex); +#endif /* CONFIG_I2C */ + + kfree(dev->usbc_buf); + kfree(dev); } static const struct video_device hdpvr_video_template = { diff --git a/drivers/media/video/hdpvr/hdpvr.h b/drivers/media/video/hdpvr/hdpvr.h index 49ae25d83d1..b0f046df3cd 100644 --- a/drivers/media/video/hdpvr/hdpvr.h +++ b/drivers/media/video/hdpvr/hdpvr.h @@ -111,6 +111,11 @@ struct hdpvr_device { u8 *usbc_buf; }; +static inline struct hdpvr_device *to_hdpvr_dev(struct v4l2_device *v4l2_dev) +{ + return container_of(v4l2_dev, struct hdpvr_device, v4l2_dev); +} + /* buffer one bulk urb of data */ struct hdpvr_buffer { -- cgit v1.2.3-70-g09d2 From aeb506aaaa08bc1910650666463843a73c34b139 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 2 May 2010 09:00:13 -0300 Subject: V4L/DVB: usbvision: don't use usb_set_intfdata, let v4l2_device_register handle this v4l2_device_register already sets intfdata, no need to do this again. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/usbvision/usbvision-video.c | 5 +---- drivers/media/video/usbvision/usbvision.h | 5 +++++ 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index d91f0166807..6248a639ba2 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c @@ -1649,8 +1649,6 @@ static int __devinit usbvision_probe(struct usb_interface *intf, usbvision_configure_video(usbvision); mutex_unlock(&usbvision->lock); - - usb_set_intfdata (intf, usbvision); usbvision_create_sysfs(usbvision->vdev); PDEBUG(DBG_PROBE, "success"); @@ -1668,7 +1666,7 @@ static int __devinit usbvision_probe(struct usb_interface *intf, */ static void __devexit usbvision_disconnect(struct usb_interface *intf) { - struct usb_usbvision *usbvision = usb_get_intfdata(intf); + struct usb_usbvision *usbvision = to_usbvision(usb_get_intfdata(intf)); PDEBUG(DBG_PROBE, ""); @@ -1677,7 +1675,6 @@ static void __devexit usbvision_disconnect(struct usb_interface *intf) "%s: usb_get_intfdata() failed\n", __func__); return; } - usb_set_intfdata (intf, NULL); mutex_lock(&usbvision->lock); diff --git a/drivers/media/video/usbvision/usbvision.h b/drivers/media/video/usbvision/usbvision.h index 5ab936e252f..d1b3cc0cd87 100644 --- a/drivers/media/video/usbvision/usbvision.h +++ b/drivers/media/video/usbvision/usbvision.h @@ -462,6 +462,11 @@ struct usb_usbvision { int ComprBlockTypes[4]; }; +static inline struct usb_usbvision *to_usbvision(struct v4l2_device *v4l2_dev) +{ + return container_of(v4l2_dev, struct usb_usbvision, v4l2_dev); +} + #define call_all(usbvision, o, f, args...) \ v4l2_device_call_all(&usbvision->v4l2_dev, 0, o, f, ##args) -- cgit v1.2.3-70-g09d2 From 4d6c871ac338a8d804a1139dade2a463614d3e34 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 2 May 2010 09:29:27 -0300 Subject: V4L/DVB: usbvision: add delay before detecting the saa711x The detection of the saa711x often failed. Adding a small delay before attempting to detect it fixed this. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/usbvision/usbvision-i2c.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c index 083765238a6..42ba2878575 100644 --- a/drivers/media/video/usbvision/usbvision-i2c.c +++ b/drivers/media/video/usbvision/usbvision-i2c.c @@ -244,6 +244,9 @@ int usbvision_i2c_register(struct usb_usbvision *usbvision) switch (usbvision_device_data[usbvision->DevModel].Codec) { case CODEC_SAA7113: case CODEC_SAA7111: + /* Without this delay the detection of the saa711x is + hit-and-miss. */ + mdelay(10); v4l2_i2c_new_subdev(&usbvision->v4l2_dev, &usbvision->i2c_adap, "saa7115", "saa7115_auto", 0, saa711x_addrs); -- cgit v1.2.3-70-g09d2 From 3e56b0f09c5b6ac277322c8bbd04b65094197106 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 2 May 2010 11:11:40 -0300 Subject: V4L/DVB: ivtv: fix VIDIOC_S_PRIORITY handling VIDIOC_S_PRIORITY is also part of the ioctls that need to check the access priority. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtv-ioctl.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index 6573764f506..fa9f0d958f9 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c @@ -1850,6 +1850,7 @@ static long ivtv_serialized_ioctl(struct ivtv *itv, struct file *filp, case VIDIOC_S_AUDOUT: case VIDIOC_S_EXT_CTRLS: case VIDIOC_S_FBUF: + case VIDIOC_S_PRIORITY: case VIDIOC_OVERLAY: ret = v4l2_prio_check(&itv->prio, id->prio); if (ret) -- cgit v1.2.3-70-g09d2 From e077f86bacb1795f2d434c6b3e6655769b5ce17c Mon Sep 17 00:00:00 2001 From: Brian Johnson Date: Mon, 5 Apr 2010 20:52:52 -0300 Subject: V4L/DVB: gspca - sn9c20x: Add another laptop to upsidedown device list Signed-off-by: Brian Johnson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sn9c20x.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c index 4069f72ac3a..c5f6ff3f70b 100644 --- a/drivers/media/video/gspca/sn9c20x.c +++ b/drivers/media/video/gspca/sn9c20x.c @@ -146,6 +146,13 @@ static const struct dmi_system_id flip_dmi_table[] = { DMI_MATCH(DMI_BOARD_NAME, "MS-1632") } }, + { + .ident = "ASUSTeK W7J", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc."), + DMI_MATCH(DMI_BOARD_NAME, "W7J ") + } + }, {} }; -- cgit v1.2.3-70-g09d2 From 5d26ed9102404dec1b9ae3ea3ad3832fe6330f0f Mon Sep 17 00:00:00 2001 From: Brian Johnson Date: Sat, 10 Apr 2010 02:12:46 -0300 Subject: V4L/DVB: gspca - sn9c20x: Add another MSI laptop to upsidedown device list Signed-off-by: Brian Johnson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sn9c20x.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c index c5f6ff3f70b..ccc34fd7619 100644 --- a/drivers/media/video/gspca/sn9c20x.c +++ b/drivers/media/video/gspca/sn9c20x.c @@ -146,6 +146,13 @@ static const struct dmi_system_id flip_dmi_table[] = { DMI_MATCH(DMI_BOARD_NAME, "MS-1632") } }, + { + .ident = "MSI MS-1635X", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "MSI"), + DMI_MATCH(DMI_BOARD_NAME, "MS-1635X") + } + }, { .ident = "ASUSTeK W7J", .matches = { -- cgit v1.2.3-70-g09d2 From 33ddc16f1003fc13d57ebe5061b29e16e6f84848 Mon Sep 17 00:00:00 2001 From: Brian Johnson Date: Sun, 18 Apr 2010 21:42:40 -0300 Subject: V4L/DVB: gspca - sn9c20x: HAS_BUTTON flag -> HAS_NO_BUTTON flag Reverse HAS_BUTTON logic since most webcams either have a button or if they don't don't bother to send any interrupts. However I have at least one model that appears to leave the button GPIO floating and can send a bogus interrupt. Signed-off-by: Brian Johnson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sn9c20x.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c index ccc34fd7619..dad5ddeb7ff 100644 --- a/drivers/media/video/gspca/sn9c20x.c +++ b/drivers/media/video/gspca/sn9c20x.c @@ -55,7 +55,7 @@ MODULE_LICENSE("GPL"); #define SENSOR_MT9VPRB 20 /* camera flags */ -#define HAS_BUTTON 0x1 +#define HAS_NO_BUTTON 0x1 #define LED_REVERSE 0x2 /* some cameras unset gpio to turn on leds */ #define FLIP_DETECT 0x4 @@ -2340,7 +2340,7 @@ static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, { struct sd *sd = (struct sd *) gspca_dev; int ret = -EINVAL; - if (sd->flags & HAS_BUTTON && len == 1) { + if (!(sd->flags & HAS_NO_BUTTON) && len == 1) { input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); input_sync(gspca_dev->input_dev); input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); @@ -2438,9 +2438,9 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x0c45, 0x6242), SN9C20X(MT9M111, 0x5d, 0)}, {USB_DEVICE(0x0c45, 0x6248), SN9C20X(OV9655, 0x30, 0)}, {USB_DEVICE(0x0c45, 0x624c), SN9C20X(MT9M112, 0x5d, 0)}, - {USB_DEVICE(0x0c45, 0x624e), SN9C20X(SOI968, 0x30, - (HAS_BUTTON | LED_REVERSE))}, - {USB_DEVICE(0x0c45, 0x624f), SN9C20X(OV9650, 0x30, FLIP_DETECT)}, + {USB_DEVICE(0x0c45, 0x624e), SN9C20X(SOI968, 0x30, LED_REVERSE)}, + {USB_DEVICE(0x0c45, 0x624f), SN9C20X(OV9650, 0x30, + (FLIP_DETECT | HAS_NO_BUTTON))}, {USB_DEVICE(0x0c45, 0x6251), SN9C20X(OV9650, 0x30, 0)}, {USB_DEVICE(0x0c45, 0x6253), SN9C20X(OV9650, 0x30, 0)}, {USB_DEVICE(0x0c45, 0x6260), SN9C20X(OV7670, 0x21, 0)}, @@ -2450,14 +2450,14 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x0c45, 0x627f), SN9C20X(OV9650, 0x30, 0)}, {USB_DEVICE(0x0c45, 0x6280), SN9C20X(MT9M001, 0x5d, 0)}, {USB_DEVICE(0x0c45, 0x6282), SN9C20X(MT9M111, 0x5d, 0)}, - {USB_DEVICE(0x0c45, 0x6288), SN9C20X(OV9655, 0x30, HAS_BUTTON)}, + {USB_DEVICE(0x0c45, 0x6288), SN9C20X(OV9655, 0x30, 0)}, {USB_DEVICE(0x0c45, 0x628c), SN9C20X(MT9M112, 0x5d, 0)}, {USB_DEVICE(0x0c45, 0x628e), SN9C20X(SOI968, 0x30, 0)}, {USB_DEVICE(0x0c45, 0x628f), SN9C20X(OV9650, 0x30, 0)}, {USB_DEVICE(0x0c45, 0x62a0), SN9C20X(OV7670, 0x21, 0)}, {USB_DEVICE(0x0c45, 0x62b0), SN9C20X(MT9VPRB, 0x00, 0)}, {USB_DEVICE(0x0c45, 0x62b3), SN9C20X(OV9655, 0x30, 0)}, - {USB_DEVICE(0x0c45, 0x62bb), SN9C20X(OV7660, 0x21, HAS_BUTTON)}, + {USB_DEVICE(0x0c45, 0x62bb), SN9C20X(OV7660, 0x21, 0)}, {USB_DEVICE(0x0c45, 0x62bc), SN9C20X(HV7131R, 0x11, 0)}, {USB_DEVICE(0x045e, 0x00f4), SN9C20X(OV9650, 0x30, 0)}, {USB_DEVICE(0x145f, 0x013d), SN9C20X(OV7660, 0x21, 0)}, @@ -2468,7 +2468,7 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0xa168, 0x0611), SN9C20X(HV7131R, 0x11, 0)}, {USB_DEVICE(0xa168, 0x0613), SN9C20X(HV7131R, 0x11, 0)}, {USB_DEVICE(0xa168, 0x0618), SN9C20X(HV7131R, 0x11, 0)}, - {USB_DEVICE(0xa168, 0x0614), SN9C20X(MT9M111, 0x5d, HAS_BUTTON)}, + {USB_DEVICE(0xa168, 0x0614), SN9C20X(MT9M111, 0x5d, 0)}, {USB_DEVICE(0xa168, 0x0615), SN9C20X(MT9M111, 0x5d, 0)}, {USB_DEVICE(0xa168, 0x0617), SN9C20X(MT9M111, 0x5d, 0)}, {} -- cgit v1.2.3-70-g09d2 From 6ea23bd0bbeeaf67bd57f2195d8d97af96072ea3 Mon Sep 17 00:00:00 2001 From: Brian Johnson Date: Wed, 5 May 2010 13:22:45 -0300 Subject: V4L/DVB: gspca - sn9c20x: Fix non working mt9v111 sensor Signed-off-by: Brian Johnson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sn9c20x.c | 32 +++++++------------------------- 1 file changed, 7 insertions(+), 25 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c index dad5ddeb7ff..644a7fd4701 100644 --- a/drivers/media/video/gspca/sn9c20x.c +++ b/drivers/media/video/gspca/sn9c20x.c @@ -996,29 +996,12 @@ static struct i2c_reg_u16 mt9v112_init[] = { static struct i2c_reg_u16 mt9v111_init[] = { {0x01, 0x0004}, {0x0d, 0x0001}, {0x0d, 0x0000}, - {0x01, 0x0001}, {0x02, 0x0016}, {0x03, 0x01e1}, - {0x04, 0x0281}, {0x05, 0x0004}, {0x07, 0x3002}, - {0x21, 0x0000}, {0x25, 0x4024}, {0x26, 0xff03}, - {0x27, 0xff10}, {0x2b, 0x7828}, {0x2c, 0xb43c}, - {0x2d, 0xf0a0}, {0x2e, 0x0c64}, {0x2f, 0x0064}, - {0x67, 0x4010}, {0x06, 0x301e}, {0x08, 0x0480}, - {0x01, 0x0004}, {0x02, 0x0016}, {0x03, 0x01e6}, - {0x04, 0x0286}, {0x05, 0x0004}, {0x06, 0x0000}, - {0x07, 0x3002}, {0x08, 0x0008}, {0x0c, 0x0000}, - {0x0d, 0x0000}, {0x0e, 0x0000}, {0x0f, 0x0000}, - {0x10, 0x0000}, {0x11, 0x0000}, {0x12, 0x00b0}, - {0x13, 0x007c}, {0x14, 0x0000}, {0x15, 0x0000}, - {0x16, 0x0000}, {0x17, 0x0000}, {0x18, 0x0000}, - {0x19, 0x0000}, {0x1a, 0x0000}, {0x1b, 0x0000}, - {0x1c, 0x0000}, {0x1d, 0x0000}, {0x30, 0x0000}, - {0x30, 0x0005}, {0x31, 0x0000}, {0x02, 0x0016}, - {0x03, 0x01e1}, {0x04, 0x0281}, {0x05, 0x0004}, - {0x06, 0x0000}, {0x07, 0x3002}, {0x06, 0x002d}, - {0x05, 0x0004}, {0x09, 0x0064}, {0x2b, 0x00a0}, - {0x2c, 0x00a0}, {0x2d, 0x00a0}, {0x2e, 0x00a0}, - {0x02, 0x0016}, {0x03, 0x01e1}, {0x04, 0x0281}, - {0x05, 0x0004}, {0x06, 0x002d}, {0x07, 0x3002}, - {0x0e, 0x0008}, {0x06, 0x002d}, {0x05, 0x0004}, + {0x01, 0x0001}, {0x05, 0x0004}, {0x2d, 0xe0a0}, + {0x2e, 0x0c64}, {0x2f, 0x0064}, {0x06, 0x600e}, + {0x08, 0x0480}, {0x01, 0x0004}, {0x02, 0x0016}, + {0x03, 0x01e7}, {0x04, 0x0287}, {0x05, 0x0004}, + {0x06, 0x002d}, {0x07, 0x3002}, {0x08, 0x0008}, + {0x0e, 0x0008}, {0x20, 0x0000} }; static struct i2c_reg_u16 mt9v011_init[] = { @@ -1369,6 +1352,7 @@ static int mt9v_init_sensor(struct gspca_dev *gspca_dev) return -ENODEV; } } + gspca_dev->ctrl_dis = (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX) | (1 << GAIN_IDX); sd->hstart = 2; sd->vstart = 2; sd->sensor = SENSOR_MT9V111; @@ -1623,7 +1607,6 @@ static int set_exposure(struct gspca_dev *gspca_dev) break; case SENSOR_MT9M001: case SENSOR_MT9V112: - case SENSOR_MT9V111: case SENSOR_MT9V011: exp[0] |= (3 << 4); exp[2] = 0x09; @@ -1658,7 +1641,6 @@ static int set_gain(struct gspca_dev *gspca_dev) gain[3] = ov_gain[sd->gain]; break; case SENSOR_MT9V011: - case SENSOR_MT9V111: gain[0] |= (3 << 4); gain[2] = 0x35; gain[3] = micron1_gain[sd->gain] >> 8; -- cgit v1.2.3-70-g09d2 From 37eb446499fe447c4b827ff7ba87106ced3782dd Mon Sep 17 00:00:00 2001 From: Mats Randgaard Date: Wed, 5 May 2010 05:21:24 -0300 Subject: V4L/DVB: tvp7002.c: Add support for enum_dv_presets Implement enum_dv_presets in tvp7002. Signed-off-by: Mats Randgaard Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvp7002.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/tvp7002.c b/drivers/media/video/tvp7002.c index f650f0d125e..6ebbf175918 100644 --- a/drivers/media/video/tvp7002.c +++ b/drivers/media/video/tvp7002.c @@ -991,6 +991,23 @@ static int tvp7002_log_status(struct v4l2_subdev *sd) return 0; } +/* + * tvp7002_enum_dv_presets() - Enum supported digital video formats + * @sd: pointer to standard V4L2 sub-device structure + * @preset: pointer to format struct + * + * Enumerate supported digital video formats. + */ +static int tvp7002_enum_dv_presets(struct v4l2_subdev *sd, + struct v4l2_dv_enum_preset *preset) +{ + /* Check requested format index is within range */ + if (preset->index >= NUM_PRESETS) + return -EINVAL; + + return v4l_fill_dv_preset_info(tvp7002_presets[preset->index].preset, preset); +} + /* V4L2 core operation handlers */ static const struct v4l2_subdev_core_ops tvp7002_core_ops = { .g_chip_ident = tvp7002_g_chip_ident, @@ -1006,6 +1023,7 @@ static const struct v4l2_subdev_core_ops tvp7002_core_ops = { /* Specific video subsystem operation handlers */ static const struct v4l2_subdev_video_ops tvp7002_video_ops = { + .enum_dv_presets = tvp7002_enum_dv_presets, .s_dv_preset = tvp7002_s_dv_preset, .query_dv_preset = tvp7002_query_dv_preset, .s_stream = tvp7002_s_stream, -- cgit v1.2.3-70-g09d2 From 6fa7dac4b89af2839b69ea1f772fa73b03efdd6c Mon Sep 17 00:00:00 2001 From: Mats Randgaard Date: Wed, 5 May 2010 07:50:38 -0300 Subject: V4L/DVB: tvp7002.c: fix some copy-paste errors in the comments Signed-off-by: Mats Randgaard Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvp7002.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/tvp7002.c b/drivers/media/video/tvp7002.c index 6ebbf175918..8085ac39244 100644 --- a/drivers/media/video/tvp7002.c +++ b/drivers/media/video/tvp7002.c @@ -458,7 +458,7 @@ static inline struct tvp7002 *to_tvp7002(struct v4l2_subdev *sd) /* * tvp7002_read - Read a value from a register in an TVP7002 * @sd: ptr to v4l2_subdev struct - * @reg: TVP7002 register address + * @addr: TVP7002 register address * @dst: pointer to 8-bit destination * * Returns value read if successful, or non-zero (-1) otherwise. @@ -488,7 +488,7 @@ static int tvp7002_read(struct v4l2_subdev *sd, u8 addr, u8 *dst) * @sd: pointer to standard V4L2 sub-device structure * @reg: destination register * @val: value to be read - * @error: pointer to error value + * @err: pointer to error value * * Read a value in a register and save error value in pointer. * Also update the register table if successful @@ -535,7 +535,7 @@ static int tvp7002_write(struct v4l2_subdev *sd, u8 addr, u8 value) * @sd: pointer to standard V4L2 sub-device structure * @reg: destination register * @val: value to be written - * @error: pointer to error value + * @err: pointer to error value * * Write a value in a register and save error value in pointer. * Also update the register table if successful @@ -596,7 +596,7 @@ static int tvp7002_write_inittab(struct v4l2_subdev *sd, /* * tvp7002_s_dv_preset() - Set digital video preset * @sd: ptr to v4l2_subdev struct - * @std: ptr to v4l2_dv_preset struct + * @dv_preset: ptr to v4l2_dv_preset struct * * Set the digital video preset for a TVP7002 decoder device. * Returns zero when successful or -EINVAL if register access fails. @@ -676,7 +676,7 @@ static int tvp7002_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) /* * tvp7002_queryctrl() - Query a control * @sd: ptr to v4l2_subdev struct - * @ctrl: ptr to v4l2_queryctrl struct + * @qc: ptr to v4l2_queryctrl struct * * Query a control of a TVP7002 decoder device. * Returns zero when successful or -EINVAL if register read fails. @@ -776,7 +776,7 @@ static int tvp7002_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) /* * tvp7002_query_dv_preset() - query DV preset * @sd: pointer to standard V4L2 sub-device structure - * @std_id: standard V4L2 v4l2_dv_preset + * @qpreset: standard V4L2 v4l2_dv_preset structure * * Returns the current DV preset by TVP7002. If no active input is * detected, returns -EINVAL @@ -846,7 +846,7 @@ static int tvp7002_query_dv_preset(struct v4l2_subdev *sd, /* * tvp7002_g_register() - Get the value of a register * @sd: ptr to v4l2_subdev struct - * @vreg: ptr to v4l2_dbg_register struct + * @reg: ptr to v4l2_dbg_register struct * * Get the value of a TVP7002 decoder device register. * Returns zero when successful, -EINVAL if register read fails or @@ -873,7 +873,7 @@ static int tvp7002_g_register(struct v4l2_subdev *sd, /* * tvp7002_s_register() - set a control * @sd: ptr to v4l2_subdev struct - * @ctrl: ptr to v4l2_control struct + * @reg: ptr to v4l2_dbg_register struct * * Get the value of a TVP7002 decoder device register. * Returns zero when successful, -EINVAL if register read fails or @@ -896,7 +896,7 @@ static int tvp7002_s_register(struct v4l2_subdev *sd, /* * tvp7002_enum_fmt() - Enum supported formats * @sd: pointer to standard V4L2 sub-device structure - * @enable: pointer to format struct + * @fmtdesc: pointer to format struct * * Enumerate supported formats. */ @@ -1057,8 +1057,8 @@ static struct tvp7002 tvp7002_dev = { /* * tvp7002_probe - Probe a TVP7002 device - * @sd: ptr to v4l2_subdev struct - * @ctrl: ptr to i2c_device_id struct + * @c: ptr to i2c_client struct + * @id: ptr to i2c_device_id struct * * Initialize the TVP7002 device * Returns zero when successful, -EINVAL if register read fails or -- cgit v1.2.3-70-g09d2 From 16ee9bb100340f9f775ab334acb645f54642f312 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 5 May 2010 02:58:57 -0300 Subject: V4L/DVB: media/mem2mem: dereferencing free memory We dereferenced "ctx" on the error path. Signed-off-by: Dan Carpenter Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/mem2mem_testdev.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/mem2mem_testdev.c b/drivers/media/video/mem2mem_testdev.c index baf211b9f6c..b161d26b0dd 100644 --- a/drivers/media/video/mem2mem_testdev.c +++ b/drivers/media/video/mem2mem_testdev.c @@ -871,8 +871,10 @@ static int m2mtest_open(struct file *file) ctx->m2m_ctx = v4l2_m2m_ctx_init(ctx, dev->m2m_dev, queue_init); if (IS_ERR(ctx->m2m_ctx)) { + int ret = PTR_ERR(ctx->m2m_ctx); + kfree(ctx); - return PTR_ERR(ctx->m2m_ctx); + return ret; } atomic_inc(&dev->num_inst); -- cgit v1.2.3-70-g09d2 From b9245d80c375b93db79475ca231276e1fa5a7649 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 5 May 2010 02:59:48 -0300 Subject: V4L/DVB: ov511: cleanup: remove unneeded null check We dereference "ov" unconditionally throughout the function so there is no way it can be NULL here. This code has been around for ages so if it were possible for "ov" to be NULL someone would have complained. Signed-off-by: Dan Carpenter Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ov511.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/ov511.c b/drivers/media/video/ov511.c index 6085d558255..a10912097b7 100644 --- a/drivers/media/video/ov511.c +++ b/drivers/media/video/ov511.c @@ -5940,7 +5940,7 @@ ov51x_disconnect(struct usb_interface *intf) ov->dev = NULL; /* Free the memory */ - if (ov && !ov->user) { + if (!ov->user) { mutex_lock(&ov->cbuf_lock); kfree(ov->cbuf); ov->cbuf = NULL; -- cgit v1.2.3-70-g09d2 From aab9796f5580a988c46c130a727cdc398a05317b Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 5 May 2010 03:01:30 -0300 Subject: V4L/DVB: s2255drv: return if vdev not found The original code didn't handle the case where vdev was not found so I added a check for that. Signed-off-by: Dan Carpenter Cc: linux-dev@sensoray.com Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s2255drv.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index ac9c40cf583..1f9a49e054a 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c @@ -1716,11 +1716,15 @@ static int s2255_open(struct file *file) dprintk(1, "s2255: open called (dev=%s)\n", video_device_node_name(vdev)); - for (i = 0; i < MAX_CHANNELS; i++) + for (i = 0; i < MAX_CHANNELS; i++) { if (&dev->vdev[i] == vdev) { cur_channel = i; break; } + } + if (i == MAX_CHANNELS) + return -ENODEV; + /* * open lock necessary to prevent multiple instances * of v4l-conf (or other programs) from simultaneously -- cgit v1.2.3-70-g09d2 From 8b661b508b3a4c8d9fc7a4b10507d3f1172947c3 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 5 May 2010 03:00:47 -0300 Subject: V4L/DVB: s2255drv: remove dead code My concern initially was we dereference "dev" in the parameter list to s2255_dev_err() but it turns out that code path is never used. The s2255_stop_readpipe() is only called from one place and "dev" is never null. So this patch just removes the whole condition here. Signed-off-by: Dan Carpenter Cc: linux-dev@sensoray.com Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s2255drv.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index 1f9a49e054a..3c7a79f3812 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c @@ -2528,10 +2528,7 @@ static int s2255_stop_acquire(struct s2255_dev *dev, unsigned long chn) static void s2255_stop_readpipe(struct s2255_dev *dev) { struct s2255_pipeinfo *pipe = &dev->pipe; - if (dev == NULL) { - s2255_dev_err(&dev->udev->dev, "invalid device\n"); - return; - } + pipe->state = 0; if (pipe->stream_urb) { /* cancel urb */ -- cgit v1.2.3-70-g09d2 From 6b46c3977cdb34a199bbca20ef67b1e13335c43d Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 7 May 2010 15:22:26 -0300 Subject: V4L/DVB: vivi and mem2mem_testdev need slab.h to build Fix vivi and mem2mem_testdev build errors: need to #include : drivers/media/video/vivi.c:1144: error: implicit declaration of function 'kfree' drivers/media/video/vivi.c:1156: error: implicit declaration of function 'kzalloc' drivers/media/video/vivi.c:1156: warning: assignment makes pointer from integer without a cast drivers/media/video/mem2mem_testdev.c:862: error: implicit declaration of function 'kzalloc' drivers/media/video/mem2mem_testdev.c:862: warning: assignment makes pointer from integer without a cast drivers/media/video/mem2mem_testdev.c:874: error: implicit declaration of function 'kfree' drivers/media/video/mem2mem_testdev.c:944: warning: assignment makes pointer from integer without a cast Signed-off-by: Randy Dunlap Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/mem2mem_testdev.c | 1 + drivers/media/video/vivi.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/mem2mem_testdev.c b/drivers/media/video/mem2mem_testdev.c index b161d26b0dd..554eaf14012 100644 --- a/drivers/media/video/mem2mem_testdev.c +++ b/drivers/media/video/mem2mem_testdev.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index d5e30b85c55..e17b6fee046 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3-70-g09d2 From 997ea58eb92f9970b8af7aae48800d0ef43b9423 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Mon, 12 Apr 2010 13:17:25 +0200 Subject: USB: rename usb_buffer_alloc() and usb_buffer_free() users For more clearance what the functions actually do, usb_buffer_alloc() is renamed to usb_alloc_coherent() usb_buffer_free() is renamed to usb_free_coherent() They should only be used in code which really needs DMA coherency. All call sites have been changed accordingly, except for staging drivers. Signed-off-by: Daniel Mack Cc: Alan Stern Cc: Pedro Ribeiro Signed-off-by: Greg Kroah-Hartman --- Documentation/DocBook/writing_usb_driver.tmpl | 2 +- Documentation/usb/dma.txt | 4 +-- drivers/hid/usbhid/hid-core.c | 12 ++++---- drivers/hid/usbhid/usbkbd.c | 8 +++--- drivers/hid/usbhid/usbmouse.c | 6 ++-- drivers/input/joystick/xpad.c | 16 +++++------ drivers/input/misc/ati_remote.c | 12 ++++---- drivers/input/misc/ati_remote2.c | 4 +-- drivers/input/misc/cm109.c | 16 +++++------ drivers/input/misc/keyspan_remote.c | 6 ++-- drivers/input/misc/powermate.c | 8 +++--- drivers/input/misc/yealink.c | 14 ++++------ drivers/input/mouse/appletouch.c | 12 ++++---- drivers/input/mouse/bcm5974.c | 24 ++++++++-------- drivers/input/tablet/acecad.c | 6 ++-- drivers/input/tablet/aiptek.c | 14 +++++----- drivers/input/tablet/gtco.c | 12 ++++---- drivers/input/tablet/kbtab.c | 6 ++-- drivers/input/tablet/wacom_sys.c | 10 +++---- drivers/input/touchscreen/usbtouchscreen.c | 8 +++--- drivers/media/dvb/dvb-usb/usb-urb.c | 7 +++-- drivers/media/dvb/ttusb-dec/ttusb_dec.c | 6 ++-- drivers/media/video/au0828/au0828-video.c | 4 +-- drivers/media/video/cx231xx/cx231xx-core.c | 14 +++++----- drivers/media/video/em28xx/em28xx-core.c | 4 +-- drivers/media/video/gspca/benq.c | 4 +-- drivers/media/video/gspca/gspca.c | 30 ++++++++++---------- drivers/media/video/hdpvr/hdpvr-video.c | 8 +++--- drivers/media/video/tlg2300/pd-video.c | 14 +++++----- drivers/media/video/usbvision/usbvision-core.c | 16 +++++------ drivers/media/video/uvc/uvc_video.c | 4 +-- drivers/net/can/usb/ems_usb.c | 18 ++++++------ drivers/net/usb/ipheth.c | 24 +++++++--------- drivers/net/usb/kaweth.c | 12 ++++---- drivers/net/wireless/ath/ar9170/usb.c | 8 +++--- drivers/net/wireless/zd1211rw/zd_usb.c | 10 +++---- drivers/usb/class/cdc-acm.c | 22 +++++++-------- drivers/usb/class/cdc-wdm.c | 38 +++++++++++++------------- drivers/usb/class/usblp.c | 2 +- drivers/usb/misc/appledisplay.c | 6 ++-- drivers/usb/misc/ftdi-elan.c | 18 ++++++------ drivers/usb/misc/iowarrior.c | 12 ++++---- drivers/usb/misc/usblcd.c | 8 +++--- drivers/usb/misc/usbtest.c | 8 +++--- drivers/usb/storage/onetouch.c | 12 ++++---- drivers/usb/storage/usb.c | 4 +-- drivers/usb/usb-skeleton.c | 10 +++---- drivers/watchdog/pcwd_usb.c | 6 ++-- sound/usb/ua101.c | 16 +++++------ sound/usb/usbaudio.c | 18 ++++++------ sound/usb/usbmidi.c | 14 +++++----- 51 files changed, 286 insertions(+), 291 deletions(-) (limited to 'drivers/media/video') diff --git a/Documentation/DocBook/writing_usb_driver.tmpl b/Documentation/DocBook/writing_usb_driver.tmpl index eeff19ca831..bd97a13fa5a 100644 --- a/Documentation/DocBook/writing_usb_driver.tmpl +++ b/Documentation/DocBook/writing_usb_driver.tmpl @@ -342,7 +342,7 @@ static inline void skel_delete (struct usb_skel *dev) { kfree (dev->bulk_in_buffer); if (dev->bulk_out_buffer != NULL) - usb_buffer_free (dev->udev, dev->bulk_out_size, + usb_free_coherent (dev->udev, dev->bulk_out_size, dev->bulk_out_buffer, dev->write_urb->transfer_dma); usb_free_urb (dev->write_urb); diff --git a/Documentation/usb/dma.txt b/Documentation/usb/dma.txt index cfdcd16e3ab..a37e59cf278 100644 --- a/Documentation/usb/dma.txt +++ b/Documentation/usb/dma.txt @@ -43,10 +43,10 @@ and effects like cache-trashing can impose subtle penalties. kind of addresses to store in urb->transfer_buffer and urb->transfer_dma. You'd also set URB_NO_TRANSFER_DMA_MAP in urb->transfer_flags: - void *usb_buffer_alloc (struct usb_device *dev, size_t size, + void *usb_alloc_coherent (struct usb_device *dev, size_t size, int mem_flags, dma_addr_t *dma); - void usb_buffer_free (struct usb_device *dev, size_t size, + void usb_free_coherent (struct usb_device *dev, size_t size, void *addr, dma_addr_t dma); Most drivers should *NOT* be using these primitives; they don't need diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 6a510c9675f..df619756b7a 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -783,12 +783,12 @@ static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid) { struct usbhid_device *usbhid = hid->driver_data; - usbhid->inbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_KERNEL, + usbhid->inbuf = usb_alloc_coherent(dev, usbhid->bufsize, GFP_KERNEL, &usbhid->inbuf_dma); - usbhid->outbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_KERNEL, + usbhid->outbuf = usb_alloc_coherent(dev, usbhid->bufsize, GFP_KERNEL, &usbhid->outbuf_dma); usbhid->cr = kmalloc(sizeof(*usbhid->cr), GFP_KERNEL); - usbhid->ctrlbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_KERNEL, + usbhid->ctrlbuf = usb_alloc_coherent(dev, usbhid->bufsize, GFP_KERNEL, &usbhid->ctrlbuf_dma); if (!usbhid->inbuf || !usbhid->outbuf || !usbhid->cr || !usbhid->ctrlbuf) @@ -843,10 +843,10 @@ static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid) { struct usbhid_device *usbhid = hid->driver_data; - usb_buffer_free(dev, usbhid->bufsize, usbhid->inbuf, usbhid->inbuf_dma); - usb_buffer_free(dev, usbhid->bufsize, usbhid->outbuf, usbhid->outbuf_dma); + usb_free_coherent(dev, usbhid->bufsize, usbhid->inbuf, usbhid->inbuf_dma); + usb_free_coherent(dev, usbhid->bufsize, usbhid->outbuf, usbhid->outbuf_dma); kfree(usbhid->cr); - usb_buffer_free(dev, usbhid->bufsize, usbhid->ctrlbuf, usbhid->ctrlbuf_dma); + usb_free_coherent(dev, usbhid->bufsize, usbhid->ctrlbuf, usbhid->ctrlbuf_dma); } static int usbhid_parse(struct hid_device *hid) diff --git a/drivers/hid/usbhid/usbkbd.c b/drivers/hid/usbhid/usbkbd.c index bdc7b09e867..bb14c8270af 100644 --- a/drivers/hid/usbhid/usbkbd.c +++ b/drivers/hid/usbhid/usbkbd.c @@ -196,11 +196,11 @@ static int usb_kbd_alloc_mem(struct usb_device *dev, struct usb_kbd *kbd) return -1; if (!(kbd->led = usb_alloc_urb(0, GFP_KERNEL))) return -1; - if (!(kbd->new = usb_buffer_alloc(dev, 8, GFP_ATOMIC, &kbd->new_dma))) + if (!(kbd->new = usb_alloc_coherent(dev, 8, GFP_ATOMIC, &kbd->new_dma))) return -1; if (!(kbd->cr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL))) return -1; - if (!(kbd->leds = usb_buffer_alloc(dev, 1, GFP_ATOMIC, &kbd->leds_dma))) + if (!(kbd->leds = usb_alloc_coherent(dev, 1, GFP_ATOMIC, &kbd->leds_dma))) return -1; return 0; @@ -210,9 +210,9 @@ static void usb_kbd_free_mem(struct usb_device *dev, struct usb_kbd *kbd) { usb_free_urb(kbd->irq); usb_free_urb(kbd->led); - usb_buffer_free(dev, 8, kbd->new, kbd->new_dma); + usb_free_coherent(dev, 8, kbd->new, kbd->new_dma); kfree(kbd->cr); - usb_buffer_free(dev, 1, kbd->leds, kbd->leds_dma); + usb_free_coherent(dev, 1, kbd->leds, kbd->leds_dma); } static int usb_kbd_probe(struct usb_interface *iface, diff --git a/drivers/hid/usbhid/usbmouse.c b/drivers/hid/usbhid/usbmouse.c index 72ab4b26809..79b2bf81a05 100644 --- a/drivers/hid/usbhid/usbmouse.c +++ b/drivers/hid/usbhid/usbmouse.c @@ -142,7 +142,7 @@ static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_i if (!mouse || !input_dev) goto fail1; - mouse->data = usb_buffer_alloc(dev, 8, GFP_ATOMIC, &mouse->data_dma); + mouse->data = usb_alloc_coherent(dev, 8, GFP_ATOMIC, &mouse->data_dma); if (!mouse->data) goto fail1; @@ -205,7 +205,7 @@ static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_i fail3: usb_free_urb(mouse->irq); fail2: - usb_buffer_free(dev, 8, mouse->data, mouse->data_dma); + usb_free_coherent(dev, 8, mouse->data, mouse->data_dma); fail1: input_free_device(input_dev); kfree(mouse); @@ -221,7 +221,7 @@ static void usb_mouse_disconnect(struct usb_interface *intf) usb_kill_urb(mouse->irq); input_unregister_device(mouse->dev); usb_free_urb(mouse->irq); - usb_buffer_free(interface_to_usbdev(intf), 8, mouse->data, mouse->data_dma); + usb_free_coherent(interface_to_usbdev(intf), 8, mouse->data, mouse->data_dma); kfree(mouse); } } diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 9b3353b404d..c1087ce4cef 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -533,8 +533,8 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != XTYPE_XBOX) return 0; - xpad->odata = usb_buffer_alloc(xpad->udev, XPAD_PKT_LEN, - GFP_KERNEL, &xpad->odata_dma); + xpad->odata = usb_alloc_coherent(xpad->udev, XPAD_PKT_LEN, + GFP_KERNEL, &xpad->odata_dma); if (!xpad->odata) goto fail1; @@ -554,7 +554,7 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) return 0; - fail2: usb_buffer_free(xpad->udev, XPAD_PKT_LEN, xpad->odata, xpad->odata_dma); + fail2: usb_free_coherent(xpad->udev, XPAD_PKT_LEN, xpad->odata, xpad->odata_dma); fail1: return error; } @@ -568,7 +568,7 @@ static void xpad_deinit_output(struct usb_xpad *xpad) { if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX) { usb_free_urb(xpad->irq_out); - usb_buffer_free(xpad->udev, XPAD_PKT_LEN, + usb_free_coherent(xpad->udev, XPAD_PKT_LEN, xpad->odata, xpad->odata_dma); } } @@ -788,8 +788,8 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id if (!xpad || !input_dev) goto fail1; - xpad->idata = usb_buffer_alloc(udev, XPAD_PKT_LEN, - GFP_KERNEL, &xpad->idata_dma); + xpad->idata = usb_alloc_coherent(udev, XPAD_PKT_LEN, + GFP_KERNEL, &xpad->idata_dma); if (!xpad->idata) goto fail1; @@ -942,7 +942,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id fail5: usb_kill_urb(xpad->irq_in); fail4: usb_free_urb(xpad->irq_in); fail3: xpad_deinit_output(xpad); - fail2: usb_buffer_free(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma); + fail2: usb_free_coherent(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma); fail1: input_free_device(input_dev); kfree(xpad); return error; @@ -964,7 +964,7 @@ static void xpad_disconnect(struct usb_interface *intf) usb_kill_urb(xpad->irq_in); } usb_free_urb(xpad->irq_in); - usb_buffer_free(xpad->udev, XPAD_PKT_LEN, + usb_free_coherent(xpad->udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma); kfree(xpad); } diff --git a/drivers/input/misc/ati_remote.c b/drivers/input/misc/ati_remote.c index e8bbc619f6d..bce57129afb 100644 --- a/drivers/input/misc/ati_remote.c +++ b/drivers/input/misc/ati_remote.c @@ -624,13 +624,13 @@ static void ati_remote_irq_in(struct urb *urb) static int ati_remote_alloc_buffers(struct usb_device *udev, struct ati_remote *ati_remote) { - ati_remote->inbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, GFP_ATOMIC, - &ati_remote->inbuf_dma); + ati_remote->inbuf = usb_alloc_coherent(udev, DATA_BUFSIZE, GFP_ATOMIC, + &ati_remote->inbuf_dma); if (!ati_remote->inbuf) return -1; - ati_remote->outbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, GFP_ATOMIC, - &ati_remote->outbuf_dma); + ati_remote->outbuf = usb_alloc_coherent(udev, DATA_BUFSIZE, GFP_ATOMIC, + &ati_remote->outbuf_dma); if (!ati_remote->outbuf) return -1; @@ -653,10 +653,10 @@ static void ati_remote_free_buffers(struct ati_remote *ati_remote) usb_free_urb(ati_remote->irq_urb); usb_free_urb(ati_remote->out_urb); - usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, + usb_free_coherent(ati_remote->udev, DATA_BUFSIZE, ati_remote->inbuf, ati_remote->inbuf_dma); - usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, + usb_free_coherent(ati_remote->udev, DATA_BUFSIZE, ati_remote->outbuf, ati_remote->outbuf_dma); } diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c index 2124b99378b..e148749b585 100644 --- a/drivers/input/misc/ati_remote2.c +++ b/drivers/input/misc/ati_remote2.c @@ -589,7 +589,7 @@ static int ati_remote2_urb_init(struct ati_remote2 *ar2) int i, pipe, maxp; for (i = 0; i < 2; i++) { - ar2->buf[i] = usb_buffer_alloc(udev, 4, GFP_KERNEL, &ar2->buf_dma[i]); + ar2->buf[i] = usb_alloc_coherent(udev, 4, GFP_KERNEL, &ar2->buf_dma[i]); if (!ar2->buf[i]) return -ENOMEM; @@ -617,7 +617,7 @@ static void ati_remote2_urb_cleanup(struct ati_remote2 *ar2) for (i = 0; i < 2; i++) { usb_free_urb(ar2->urb[i]); - usb_buffer_free(ar2->udev, 4, ar2->buf[i], ar2->buf_dma[i]); + usb_free_coherent(ar2->udev, 4, ar2->buf[i], ar2->buf_dma[i]); } } diff --git a/drivers/input/misc/cm109.c b/drivers/input/misc/cm109.c index 8d2d291ee50..2b0eba6619b 100644 --- a/drivers/input/misc/cm109.c +++ b/drivers/input/misc/cm109.c @@ -630,11 +630,11 @@ static void cm109_usb_cleanup(struct cm109_dev *dev) { kfree(dev->ctl_req); if (dev->ctl_data) - usb_buffer_free(dev->udev, USB_PKT_LEN, - dev->ctl_data, dev->ctl_dma); + usb_free_coherent(dev->udev, USB_PKT_LEN, + dev->ctl_data, dev->ctl_dma); if (dev->irq_data) - usb_buffer_free(dev->udev, USB_PKT_LEN, - dev->irq_data, dev->irq_dma); + usb_free_coherent(dev->udev, USB_PKT_LEN, + dev->irq_data, dev->irq_dma); usb_free_urb(dev->urb_irq); /* parameter validation in core/urb */ usb_free_urb(dev->urb_ctl); /* parameter validation in core/urb */ @@ -683,13 +683,13 @@ static int cm109_usb_probe(struct usb_interface *intf, goto err_out; /* allocate usb buffers */ - dev->irq_data = usb_buffer_alloc(udev, USB_PKT_LEN, - GFP_KERNEL, &dev->irq_dma); + dev->irq_data = usb_alloc_coherent(udev, USB_PKT_LEN, + GFP_KERNEL, &dev->irq_dma); if (!dev->irq_data) goto err_out; - dev->ctl_data = usb_buffer_alloc(udev, USB_PKT_LEN, - GFP_KERNEL, &dev->ctl_dma); + dev->ctl_data = usb_alloc_coherent(udev, USB_PKT_LEN, + GFP_KERNEL, &dev->ctl_dma); if (!dev->ctl_data) goto err_out; diff --git a/drivers/input/misc/keyspan_remote.c b/drivers/input/misc/keyspan_remote.c index 86afdd1fdf9..a93c525475c 100644 --- a/drivers/input/misc/keyspan_remote.c +++ b/drivers/input/misc/keyspan_remote.c @@ -464,7 +464,7 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic remote->in_endpoint = endpoint; remote->toggle = -1; /* Set to -1 so we will always not match the toggle from the first remote message. */ - remote->in_buffer = usb_buffer_alloc(udev, RECV_SIZE, GFP_ATOMIC, &remote->in_dma); + remote->in_buffer = usb_alloc_coherent(udev, RECV_SIZE, GFP_ATOMIC, &remote->in_dma); if (!remote->in_buffer) { error = -ENOMEM; goto fail1; @@ -543,7 +543,7 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic return 0; fail3: usb_free_urb(remote->irq_urb); - fail2: usb_buffer_free(udev, RECV_SIZE, remote->in_buffer, remote->in_dma); + fail2: usb_free_coherent(udev, RECV_SIZE, remote->in_buffer, remote->in_dma); fail1: kfree(remote); input_free_device(input_dev); @@ -564,7 +564,7 @@ static void keyspan_disconnect(struct usb_interface *interface) input_unregister_device(remote->input); usb_kill_urb(remote->irq_urb); usb_free_urb(remote->irq_urb); - usb_buffer_free(remote->udev, RECV_SIZE, remote->in_buffer, remote->in_dma); + usb_free_coherent(remote->udev, RECV_SIZE, remote->in_buffer, remote->in_dma); kfree(remote); } } diff --git a/drivers/input/misc/powermate.c b/drivers/input/misc/powermate.c index 7ba4b5f53fc..bf170f6b442 100644 --- a/drivers/input/misc/powermate.c +++ b/drivers/input/misc/powermate.c @@ -273,8 +273,8 @@ static int powermate_input_event(struct input_dev *dev, unsigned int type, unsig static int powermate_alloc_buffers(struct usb_device *udev, struct powermate_device *pm) { - pm->data = usb_buffer_alloc(udev, POWERMATE_PAYLOAD_SIZE_MAX, - GFP_ATOMIC, &pm->data_dma); + pm->data = usb_alloc_coherent(udev, POWERMATE_PAYLOAD_SIZE_MAX, + GFP_ATOMIC, &pm->data_dma); if (!pm->data) return -1; @@ -287,8 +287,8 @@ static int powermate_alloc_buffers(struct usb_device *udev, struct powermate_dev static void powermate_free_buffers(struct usb_device *udev, struct powermate_device *pm) { - usb_buffer_free(udev, POWERMATE_PAYLOAD_SIZE_MAX, - pm->data, pm->data_dma); + usb_free_coherent(udev, POWERMATE_PAYLOAD_SIZE_MAX, + pm->data, pm->data_dma); kfree(pm->configcr); } diff --git a/drivers/input/misc/yealink.c b/drivers/input/misc/yealink.c index 2828328e9dd..41201c6b5e6 100644 --- a/drivers/input/misc/yealink.c +++ b/drivers/input/misc/yealink.c @@ -836,10 +836,8 @@ static int usb_cleanup(struct yealink_dev *yld, int err) usb_free_urb(yld->urb_ctl); kfree(yld->ctl_req); - usb_buffer_free(yld->udev, USB_PKT_LEN, - yld->ctl_data, yld->ctl_dma); - usb_buffer_free(yld->udev, USB_PKT_LEN, - yld->irq_data, yld->irq_dma); + usb_free_coherent(yld->udev, USB_PKT_LEN, yld->ctl_data, yld->ctl_dma); + usb_free_coherent(yld->udev, USB_PKT_LEN, yld->irq_data, yld->irq_dma); kfree(yld); return err; @@ -884,13 +882,13 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id) return usb_cleanup(yld, -ENOMEM); /* allocate usb buffers */ - yld->irq_data = usb_buffer_alloc(udev, USB_PKT_LEN, - GFP_ATOMIC, &yld->irq_dma); + yld->irq_data = usb_alloc_coherent(udev, USB_PKT_LEN, + GFP_ATOMIC, &yld->irq_dma); if (yld->irq_data == NULL) return usb_cleanup(yld, -ENOMEM); - yld->ctl_data = usb_buffer_alloc(udev, USB_PKT_LEN, - GFP_ATOMIC, &yld->ctl_dma); + yld->ctl_data = usb_alloc_coherent(udev, USB_PKT_LEN, + GFP_ATOMIC, &yld->ctl_dma); if (!yld->ctl_data) return usb_cleanup(yld, -ENOMEM); diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c index 53ec7ddd182..05edd75abca 100644 --- a/drivers/input/mouse/appletouch.c +++ b/drivers/input/mouse/appletouch.c @@ -806,8 +806,8 @@ static int atp_probe(struct usb_interface *iface, if (!dev->urb) goto err_free_devs; - dev->data = usb_buffer_alloc(dev->udev, dev->info->datalen, GFP_KERNEL, - &dev->urb->transfer_dma); + dev->data = usb_alloc_coherent(dev->udev, dev->info->datalen, GFP_KERNEL, + &dev->urb->transfer_dma); if (!dev->data) goto err_free_urb; @@ -862,8 +862,8 @@ static int atp_probe(struct usb_interface *iface, return 0; err_free_buffer: - usb_buffer_free(dev->udev, dev->info->datalen, - dev->data, dev->urb->transfer_dma); + usb_free_coherent(dev->udev, dev->info->datalen, + dev->data, dev->urb->transfer_dma); err_free_urb: usb_free_urb(dev->urb); err_free_devs: @@ -881,8 +881,8 @@ static void atp_disconnect(struct usb_interface *iface) if (dev) { usb_kill_urb(dev->urb); input_unregister_device(dev->input); - usb_buffer_free(dev->udev, dev->info->datalen, - dev->data, dev->urb->transfer_dma); + usb_free_coherent(dev->udev, dev->info->datalen, + dev->data, dev->urb->transfer_dma); usb_free_urb(dev->urb); kfree(dev); } diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index b89879bd860..6dedded2722 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c @@ -715,15 +715,15 @@ static int bcm5974_probe(struct usb_interface *iface, if (!dev->tp_urb) goto err_free_bt_urb; - dev->bt_data = usb_buffer_alloc(dev->udev, - dev->cfg.bt_datalen, GFP_KERNEL, - &dev->bt_urb->transfer_dma); + dev->bt_data = usb_alloc_coherent(dev->udev, + dev->cfg.bt_datalen, GFP_KERNEL, + &dev->bt_urb->transfer_dma); if (!dev->bt_data) goto err_free_urb; - dev->tp_data = usb_buffer_alloc(dev->udev, - dev->cfg.tp_datalen, GFP_KERNEL, - &dev->tp_urb->transfer_dma); + dev->tp_data = usb_alloc_coherent(dev->udev, + dev->cfg.tp_datalen, GFP_KERNEL, + &dev->tp_urb->transfer_dma); if (!dev->tp_data) goto err_free_bt_buffer; @@ -765,10 +765,10 @@ static int bcm5974_probe(struct usb_interface *iface, return 0; err_free_buffer: - usb_buffer_free(dev->udev, dev->cfg.tp_datalen, + usb_free_coherent(dev->udev, dev->cfg.tp_datalen, dev->tp_data, dev->tp_urb->transfer_dma); err_free_bt_buffer: - usb_buffer_free(dev->udev, dev->cfg.bt_datalen, + usb_free_coherent(dev->udev, dev->cfg.bt_datalen, dev->bt_data, dev->bt_urb->transfer_dma); err_free_urb: usb_free_urb(dev->tp_urb); @@ -788,10 +788,10 @@ static void bcm5974_disconnect(struct usb_interface *iface) usb_set_intfdata(iface, NULL); input_unregister_device(dev->input); - usb_buffer_free(dev->udev, dev->cfg.tp_datalen, - dev->tp_data, dev->tp_urb->transfer_dma); - usb_buffer_free(dev->udev, dev->cfg.bt_datalen, - dev->bt_data, dev->bt_urb->transfer_dma); + usb_free_coherent(dev->udev, dev->cfg.tp_datalen, + dev->tp_data, dev->tp_urb->transfer_dma); + usb_free_coherent(dev->udev, dev->cfg.bt_datalen, + dev->bt_data, dev->bt_urb->transfer_dma); usb_free_urb(dev->tp_urb); usb_free_urb(dev->bt_urb); kfree(dev); diff --git a/drivers/input/tablet/acecad.c b/drivers/input/tablet/acecad.c index 670c61c5a51..c0470163dc6 100644 --- a/drivers/input/tablet/acecad.c +++ b/drivers/input/tablet/acecad.c @@ -155,7 +155,7 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_ goto fail1; } - acecad->data = usb_buffer_alloc(dev, 8, GFP_KERNEL, &acecad->data_dma); + acecad->data = usb_alloc_coherent(dev, 8, GFP_KERNEL, &acecad->data_dma); if (!acecad->data) { err= -ENOMEM; goto fail1; @@ -241,7 +241,7 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_ return 0; - fail2: usb_buffer_free(dev, 8, acecad->data, acecad->data_dma); + fail2: usb_free_coherent(dev, 8, acecad->data, acecad->data_dma); fail1: input_free_device(input_dev); kfree(acecad); return err; @@ -256,7 +256,7 @@ static void usb_acecad_disconnect(struct usb_interface *intf) usb_kill_urb(acecad->irq); input_unregister_device(acecad->input); usb_free_urb(acecad->irq); - usb_buffer_free(interface_to_usbdev(intf), 10, acecad->data, acecad->data_dma); + usb_free_coherent(interface_to_usbdev(intf), 10, acecad->data, acecad->data_dma); kfree(acecad); } } diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c index 4be039d7dca..51b80b08d46 100644 --- a/drivers/input/tablet/aiptek.c +++ b/drivers/input/tablet/aiptek.c @@ -1711,8 +1711,8 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) goto fail1; } - aiptek->data = usb_buffer_alloc(usbdev, AIPTEK_PACKET_LENGTH, - GFP_ATOMIC, &aiptek->data_dma); + aiptek->data = usb_alloc_coherent(usbdev, AIPTEK_PACKET_LENGTH, + GFP_ATOMIC, &aiptek->data_dma); if (!aiptek->data) { dev_warn(&intf->dev, "cannot allocate usb buffer\n"); goto fail1; @@ -1884,8 +1884,8 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) fail4: sysfs_remove_group(&intf->dev.kobj, &aiptek_attribute_group); fail3: usb_free_urb(aiptek->urb); - fail2: usb_buffer_free(usbdev, AIPTEK_PACKET_LENGTH, aiptek->data, - aiptek->data_dma); + fail2: usb_free_coherent(usbdev, AIPTEK_PACKET_LENGTH, aiptek->data, + aiptek->data_dma); fail1: usb_set_intfdata(intf, NULL); input_free_device(inputdev); kfree(aiptek); @@ -1909,9 +1909,9 @@ static void aiptek_disconnect(struct usb_interface *intf) input_unregister_device(aiptek->inputdev); sysfs_remove_group(&intf->dev.kobj, &aiptek_attribute_group); usb_free_urb(aiptek->urb); - usb_buffer_free(interface_to_usbdev(intf), - AIPTEK_PACKET_LENGTH, - aiptek->data, aiptek->data_dma); + usb_free_coherent(interface_to_usbdev(intf), + AIPTEK_PACKET_LENGTH, + aiptek->data, aiptek->data_dma); kfree(aiptek); } } diff --git a/drivers/input/tablet/gtco.c b/drivers/input/tablet/gtco.c index 866a9ee1af1..8ea6afe2e99 100644 --- a/drivers/input/tablet/gtco.c +++ b/drivers/input/tablet/gtco.c @@ -850,8 +850,8 @@ static int gtco_probe(struct usb_interface *usbinterface, gtco->usbdev = usb_get_dev(interface_to_usbdev(usbinterface)); /* Allocate some data for incoming reports */ - gtco->buffer = usb_buffer_alloc(gtco->usbdev, REPORT_MAX_SIZE, - GFP_KERNEL, >co->buf_dma); + gtco->buffer = usb_alloc_coherent(gtco->usbdev, REPORT_MAX_SIZE, + GFP_KERNEL, >co->buf_dma); if (!gtco->buffer) { err("No more memory for us buffers"); error = -ENOMEM; @@ -982,8 +982,8 @@ static int gtco_probe(struct usb_interface *usbinterface, err_free_urb: usb_free_urb(gtco->urbinfo); err_free_buf: - usb_buffer_free(gtco->usbdev, REPORT_MAX_SIZE, - gtco->buffer, gtco->buf_dma); + usb_free_coherent(gtco->usbdev, REPORT_MAX_SIZE, + gtco->buffer, gtco->buf_dma); err_free_devs: input_free_device(input_dev); kfree(gtco); @@ -1005,8 +1005,8 @@ static void gtco_disconnect(struct usb_interface *interface) input_unregister_device(gtco->inputdevice); usb_kill_urb(gtco->urbinfo); usb_free_urb(gtco->urbinfo); - usb_buffer_free(gtco->usbdev, REPORT_MAX_SIZE, - gtco->buffer, gtco->buf_dma); + usb_free_coherent(gtco->usbdev, REPORT_MAX_SIZE, + gtco->buffer, gtco->buf_dma); kfree(gtco); } diff --git a/drivers/input/tablet/kbtab.c b/drivers/input/tablet/kbtab.c index 6682b17bf84..d31b9c79355 100644 --- a/drivers/input/tablet/kbtab.c +++ b/drivers/input/tablet/kbtab.c @@ -129,7 +129,7 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i if (!kbtab || !input_dev) goto fail1; - kbtab->data = usb_buffer_alloc(dev, 8, GFP_KERNEL, &kbtab->data_dma); + kbtab->data = usb_alloc_coherent(dev, 8, GFP_KERNEL, &kbtab->data_dma); if (!kbtab->data) goto fail1; @@ -182,7 +182,7 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i return 0; fail3: usb_free_urb(kbtab->irq); - fail2: usb_buffer_free(dev, 10, kbtab->data, kbtab->data_dma); + fail2: usb_free_coherent(dev, 10, kbtab->data, kbtab->data_dma); fail1: input_free_device(input_dev); kfree(kbtab); return error; @@ -197,7 +197,7 @@ static void kbtab_disconnect(struct usb_interface *intf) usb_kill_urb(kbtab->irq); input_unregister_device(kbtab->dev); usb_free_urb(kbtab->irq); - usb_buffer_free(interface_to_usbdev(intf), 10, kbtab->data, kbtab->data_dma); + usb_free_coherent(interface_to_usbdev(intf), 10, kbtab->data, kbtab->data_dma); kfree(kbtab); } } diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index f46502589e4..191197cd83e 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -556,8 +556,8 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i goto fail1; } - wacom_wac->data = usb_buffer_alloc(dev, WACOM_PKGLEN_MAX, - GFP_KERNEL, &wacom->data_dma); + wacom_wac->data = usb_alloc_coherent(dev, WACOM_PKGLEN_MAX, + GFP_KERNEL, &wacom->data_dma); if (!wacom_wac->data) { error = -ENOMEM; goto fail1; @@ -633,7 +633,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i return 0; fail3: usb_free_urb(wacom->irq); - fail2: usb_buffer_free(dev, WACOM_PKGLEN_MAX, wacom_wac->data, wacom->data_dma); + fail2: usb_free_coherent(dev, WACOM_PKGLEN_MAX, wacom_wac->data, wacom->data_dma); fail1: input_free_device(input_dev); kfree(wacom); kfree(wacom_wac); @@ -649,8 +649,8 @@ static void wacom_disconnect(struct usb_interface *intf) usb_kill_urb(wacom->irq); input_unregister_device(wacom->dev); usb_free_urb(wacom->irq); - usb_buffer_free(interface_to_usbdev(intf), WACOM_PKGLEN_MAX, - wacom->wacom_wac->data, wacom->data_dma); + usb_free_coherent(interface_to_usbdev(intf), WACOM_PKGLEN_MAX, + wacom->wacom_wac->data, wacom->data_dma); kfree(wacom->wacom_wac); kfree(wacom); } diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index 99330bbdbac..ea41a851ddf 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c @@ -1291,8 +1291,8 @@ static void usbtouch_close(struct input_dev *input) static void usbtouch_free_buffers(struct usb_device *udev, struct usbtouch_usb *usbtouch) { - usb_buffer_free(udev, usbtouch->type->rept_size, - usbtouch->data, usbtouch->data_dma); + usb_free_coherent(udev, usbtouch->type->rept_size, + usbtouch->data, usbtouch->data_dma); kfree(usbtouch->buffer); } @@ -1336,8 +1336,8 @@ static int usbtouch_probe(struct usb_interface *intf, if (!type->process_pkt) type->process_pkt = usbtouch_process_pkt; - usbtouch->data = usb_buffer_alloc(udev, type->rept_size, - GFP_KERNEL, &usbtouch->data_dma); + usbtouch->data = usb_alloc_coherent(udev, type->rept_size, + GFP_KERNEL, &usbtouch->data_dma); if (!usbtouch->data) goto out_free; diff --git a/drivers/media/dvb/dvb-usb/usb-urb.c b/drivers/media/dvb/dvb-usb/usb-urb.c index f9702e3756b..86d68933b6b 100644 --- a/drivers/media/dvb/dvb-usb/usb-urb.c +++ b/drivers/media/dvb/dvb-usb/usb-urb.c @@ -96,8 +96,9 @@ static int usb_free_stream_buffers(struct usb_data_stream *stream) while (stream->buf_num) { stream->buf_num--; deb_mem("freeing buffer %d\n",stream->buf_num); - usb_buffer_free(stream->udev, stream->buf_size, - stream->buf_list[stream->buf_num], stream->dma_addr[stream->buf_num]); + usb_free_coherent(stream->udev, stream->buf_size, + stream->buf_list[stream->buf_num], + stream->dma_addr[stream->buf_num]); } } @@ -116,7 +117,7 @@ static int usb_allocate_stream_buffers(struct usb_data_stream *stream, int num, for (stream->buf_num = 0; stream->buf_num < num; stream->buf_num++) { deb_mem("allocating buffer %d\n",stream->buf_num); if (( stream->buf_list[stream->buf_num] = - usb_buffer_alloc(stream->udev, size, GFP_ATOMIC, + usb_alloc_coherent(stream->udev, size, GFP_ATOMIC, &stream->dma_addr[stream->buf_num]) ) == NULL) { deb_mem("not enough memory for urb-buffer allocation.\n"); usb_free_stream_buffers(stream); diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c index 53baccbab17..fe1b8037b24 100644 --- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c +++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c @@ -1257,7 +1257,7 @@ static int ttusb_dec_init_usb(struct ttusb_dec *dec) if(!dec->irq_urb) { return -ENOMEM; } - dec->irq_buffer = usb_buffer_alloc(dec->udev,IRQ_PACKET_SIZE, + dec->irq_buffer = usb_alloc_coherent(dec->udev,IRQ_PACKET_SIZE, GFP_ATOMIC, &dec->irq_dma_handle); if(!dec->irq_buffer) { usb_free_urb(dec->irq_urb); @@ -1550,8 +1550,8 @@ static void ttusb_dec_exit_rc(struct ttusb_dec *dec) usb_free_urb(dec->irq_urb); - usb_buffer_free(dec->udev,IRQ_PACKET_SIZE, - dec->irq_buffer, dec->irq_dma_handle); + usb_free_coherent(dec->udev,IRQ_PACKET_SIZE, + dec->irq_buffer, dec->irq_dma_handle); if (dec->rc_input_dev) { input_unregister_device(dec->rc_input_dev); diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c index 8c140c01c5e..a2a0f79a84f 100644 --- a/drivers/media/video/au0828/au0828-video.c +++ b/drivers/media/video/au0828/au0828-video.c @@ -177,7 +177,7 @@ void au0828_uninit_isoc(struct au0828_dev *dev) usb_unlink_urb(urb); if (dev->isoc_ctl.transfer_buffer[i]) { - usb_buffer_free(dev->usbdev, + usb_free_coherent(dev->usbdev, urb->transfer_buffer_length, dev->isoc_ctl.transfer_buffer[i], urb->transfer_dma); @@ -247,7 +247,7 @@ int au0828_init_isoc(struct au0828_dev *dev, int max_packets, } dev->isoc_ctl.urb[i] = urb; - dev->isoc_ctl.transfer_buffer[i] = usb_buffer_alloc(dev->usbdev, + dev->isoc_ctl.transfer_buffer[i] = usb_alloc_coherent(dev->usbdev, sb_size, GFP_KERNEL, &urb->transfer_dma); if (!dev->isoc_ctl.transfer_buffer[i]) { printk("unable to allocate %i bytes for transfer" diff --git a/drivers/media/video/cx231xx/cx231xx-core.c b/drivers/media/video/cx231xx/cx231xx-core.c index b24eee115e7..6ccd87d5fb9 100644 --- a/drivers/media/video/cx231xx/cx231xx-core.c +++ b/drivers/media/video/cx231xx/cx231xx-core.c @@ -679,11 +679,11 @@ void cx231xx_uninit_isoc(struct cx231xx *dev) usb_unlink_urb(urb); if (dev->video_mode.isoc_ctl.transfer_buffer[i]) { - usb_buffer_free(dev->udev, - urb->transfer_buffer_length, - dev->video_mode.isoc_ctl. - transfer_buffer[i], - urb->transfer_dma); + usb_free_coherent(dev->udev, + urb->transfer_buffer_length, + dev->video_mode.isoc_ctl. + transfer_buffer[i], + urb->transfer_dma); } usb_free_urb(urb); dev->video_mode.isoc_ctl.urb[i] = NULL; @@ -770,8 +770,8 @@ int cx231xx_init_isoc(struct cx231xx *dev, int max_packets, dev->video_mode.isoc_ctl.urb[i] = urb; dev->video_mode.isoc_ctl.transfer_buffer[i] = - usb_buffer_alloc(dev->udev, sb_size, GFP_KERNEL, - &urb->transfer_dma); + usb_alloc_coherent(dev->udev, sb_size, GFP_KERNEL, + &urb->transfer_dma); if (!dev->video_mode.isoc_ctl.transfer_buffer[i]) { cx231xx_err("unable to allocate %i bytes for transfer" " buffer %i%s\n", diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index a41cc556677..d4a95546504 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -966,7 +966,7 @@ void em28xx_uninit_isoc(struct em28xx *dev) usb_unlink_urb(urb); if (dev->isoc_ctl.transfer_buffer[i]) { - usb_buffer_free(dev->udev, + usb_free_coherent(dev->udev, urb->transfer_buffer_length, dev->isoc_ctl.transfer_buffer[i], urb->transfer_dma); @@ -1041,7 +1041,7 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets, } dev->isoc_ctl.urb[i] = urb; - dev->isoc_ctl.transfer_buffer[i] = usb_buffer_alloc(dev->udev, + dev->isoc_ctl.transfer_buffer[i] = usb_alloc_coherent(dev->udev, sb_size, GFP_KERNEL, &urb->transfer_dma); if (!dev->isoc_ctl.transfer_buffer[i]) { em28xx_err("unable to allocate %i bytes for transfer" diff --git a/drivers/media/video/gspca/benq.c b/drivers/media/video/gspca/benq.c index 43ac4af8d3e..fce8d949264 100644 --- a/drivers/media/video/gspca/benq.c +++ b/drivers/media/video/gspca/benq.c @@ -117,13 +117,13 @@ static int sd_start(struct gspca_dev *gspca_dev) return -ENOMEM; } gspca_dev->urb[n] = urb; - urb->transfer_buffer = usb_buffer_alloc(gspca_dev->dev, + urb->transfer_buffer = usb_alloc_coherent(gspca_dev->dev, SD_PKT_SZ * SD_NPKT, GFP_KERNEL, &urb->transfer_dma); if (urb->transfer_buffer == NULL) { - err("usb_buffer_alloc failed"); + err("usb_alloc_coherent failed"); return -ENOMEM; } urb->dev = gspca_dev->dev; diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 222af479150..00713f81d1e 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -213,7 +213,7 @@ static int alloc_and_submit_int_urb(struct gspca_dev *gspca_dev, goto error; } - buffer = usb_buffer_alloc(dev, ep->wMaxPacketSize, + buffer = usb_alloc_coherent(dev, ep->wMaxPacketSize, GFP_KERNEL, &urb->transfer_dma); if (!buffer) { ret = -ENOMEM; @@ -232,10 +232,10 @@ static int alloc_and_submit_int_urb(struct gspca_dev *gspca_dev, return ret; error_submit: - usb_buffer_free(dev, - urb->transfer_buffer_length, - urb->transfer_buffer, - urb->transfer_dma); + usb_free_coherent(dev, + urb->transfer_buffer_length, + urb->transfer_buffer, + urb->transfer_dma); error_buffer: usb_free_urb(urb); error: @@ -272,10 +272,10 @@ static void gspca_input_destroy_urb(struct gspca_dev *gspca_dev) if (urb) { gspca_dev->int_urb = NULL; usb_kill_urb(urb); - usb_buffer_free(gspca_dev->dev, - urb->transfer_buffer_length, - urb->transfer_buffer, - urb->transfer_dma); + usb_free_coherent(gspca_dev->dev, + urb->transfer_buffer_length, + urb->transfer_buffer, + urb->transfer_dma); usb_free_urb(urb); } } @@ -597,10 +597,10 @@ static void destroy_urbs(struct gspca_dev *gspca_dev) gspca_dev->urb[i] = NULL; usb_kill_urb(urb); if (urb->transfer_buffer != NULL) - usb_buffer_free(gspca_dev->dev, - urb->transfer_buffer_length, - urb->transfer_buffer, - urb->transfer_dma); + usb_free_coherent(gspca_dev->dev, + urb->transfer_buffer_length, + urb->transfer_buffer, + urb->transfer_dma); usb_free_urb(urb); } } @@ -721,13 +721,13 @@ static int create_urbs(struct gspca_dev *gspca_dev, return -ENOMEM; } gspca_dev->urb[n] = urb; - urb->transfer_buffer = usb_buffer_alloc(gspca_dev->dev, + urb->transfer_buffer = usb_alloc_coherent(gspca_dev->dev, bsize, GFP_KERNEL, &urb->transfer_dma); if (urb->transfer_buffer == NULL) { - err("usb_buffer_alloc failed"); + err("usb_alloc_coherent failed"); return -ENOMEM; } urb->dev = gspca_dev->dev; diff --git a/drivers/media/video/hdpvr/hdpvr-video.c b/drivers/media/video/hdpvr/hdpvr-video.c index 196f82de48f..b65efe25b31 100644 --- a/drivers/media/video/hdpvr/hdpvr-video.c +++ b/drivers/media/video/hdpvr/hdpvr-video.c @@ -92,8 +92,8 @@ static int hdpvr_free_queue(struct list_head *q) buf = list_entry(p, struct hdpvr_buffer, buff_list); urb = buf->urb; - usb_buffer_free(urb->dev, urb->transfer_buffer_length, - urb->transfer_buffer, urb->transfer_dma); + usb_free_coherent(urb->dev, urb->transfer_buffer_length, + urb->transfer_buffer, urb->transfer_dma); usb_free_urb(urb); tmp = p->next; list_del(p); @@ -143,8 +143,8 @@ int hdpvr_alloc_buffers(struct hdpvr_device *dev, uint count) } buf->urb = urb; - mem = usb_buffer_alloc(dev->udev, dev->bulk_in_size, GFP_KERNEL, - &urb->transfer_dma); + mem = usb_alloc_coherent(dev->udev, dev->bulk_in_size, GFP_KERNEL, + &urb->transfer_dma); if (!mem) { v4l2_err(&dev->v4l2_dev, "cannot allocate usb transfer buffer\n"); diff --git a/drivers/media/video/tlg2300/pd-video.c b/drivers/media/video/tlg2300/pd-video.c index cf8f18c007e..7bc29065e1a 100644 --- a/drivers/media/video/tlg2300/pd-video.c +++ b/drivers/media/video/tlg2300/pd-video.c @@ -476,10 +476,10 @@ static int prepare_iso_urb(struct video_data *video) goto out; video->urb_array[i] = urb; - mem = usb_buffer_alloc(udev, - ISO_PKT_SIZE * PK_PER_URB, - GFP_KERNEL, - &urb->transfer_dma); + mem = usb_alloc_coherent(udev, + ISO_PKT_SIZE * PK_PER_URB, + GFP_KERNEL, + &urb->transfer_dma); urb->complete = urb_complete_iso; /* handler */ urb->dev = udev; @@ -519,8 +519,8 @@ int alloc_bulk_urbs_generic(struct urb **urb_array, int num, if (urb == NULL) return i; - mem = usb_buffer_alloc(udev, buf_size, gfp_flags, - &urb->transfer_dma); + mem = usb_alloc_coherent(udev, buf_size, gfp_flags, + &urb->transfer_dma); if (mem == NULL) return i; @@ -540,7 +540,7 @@ void free_all_urb_generic(struct urb **urb_array, int num) for (i = 0; i < num; i++) { urb = urb_array[i]; if (urb) { - usb_buffer_free(urb->dev, + usb_free_coherent(urb->dev, urb->transfer_buffer_length, urb->transfer_buffer, urb->transfer_dma); diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c index f7aae229375..b9dd74fde21 100644 --- a/drivers/media/video/usbvision/usbvision-core.c +++ b/drivers/media/video/usbvision/usbvision-core.c @@ -2493,10 +2493,10 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision) } usbvision->sbuf[bufIdx].urb = urb; usbvision->sbuf[bufIdx].data = - usb_buffer_alloc(usbvision->dev, - sb_size, - GFP_KERNEL, - &urb->transfer_dma); + usb_alloc_coherent(usbvision->dev, + sb_size, + GFP_KERNEL, + &urb->transfer_dma); urb->dev = dev; urb->context = usbvision; urb->pipe = usb_rcvisocpipe(dev, usbvision->video_endp); @@ -2552,10 +2552,10 @@ void usbvision_stop_isoc(struct usb_usbvision *usbvision) for (bufIdx = 0; bufIdx < USBVISION_NUMSBUF; bufIdx++) { usb_kill_urb(usbvision->sbuf[bufIdx].urb); if (usbvision->sbuf[bufIdx].data){ - usb_buffer_free(usbvision->dev, - sb_size, - usbvision->sbuf[bufIdx].data, - usbvision->sbuf[bufIdx].urb->transfer_dma); + usb_free_coherent(usbvision->dev, + sb_size, + usbvision->sbuf[bufIdx].data, + usbvision->sbuf[bufIdx].urb->transfer_dma); } usb_free_urb(usbvision->sbuf[bufIdx].urb); usbvision->sbuf[bufIdx].urb = NULL; diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index 821a9969b7b..53f3ef4635e 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c @@ -739,7 +739,7 @@ static void uvc_free_urb_buffers(struct uvc_streaming *stream) for (i = 0; i < UVC_URBS; ++i) { if (stream->urb_buffer[i]) { - usb_buffer_free(stream->dev->udev, stream->urb_size, + usb_free_coherent(stream->dev->udev, stream->urb_size, stream->urb_buffer[i], stream->urb_dma[i]); stream->urb_buffer[i] = NULL; } @@ -780,7 +780,7 @@ static int uvc_alloc_urb_buffers(struct uvc_streaming *stream, for (; npackets > 1; npackets /= 2) { for (i = 0; i < UVC_URBS; ++i) { stream->urb_size = psize * npackets; - stream->urb_buffer[i] = usb_buffer_alloc( + stream->urb_buffer[i] = usb_alloc_coherent( stream->dev->udev, stream->urb_size, gfp_flags | __GFP_NOWARN, &stream->urb_dma[i]); if (!stream->urb_buffer[i]) { diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c index d800b598ae3..25a5c7eea94 100644 --- a/drivers/net/can/usb/ems_usb.c +++ b/drivers/net/can/usb/ems_usb.c @@ -516,8 +516,8 @@ static void ems_usb_write_bulk_callback(struct urb *urb) netdev = dev->netdev; /* free up our allocated buffer */ - usb_buffer_free(urb->dev, urb->transfer_buffer_length, - urb->transfer_buffer, urb->transfer_dma); + usb_free_coherent(urb->dev, urb->transfer_buffer_length, + urb->transfer_buffer, urb->transfer_dma); atomic_dec(&dev->active_tx_urbs); @@ -614,8 +614,8 @@ static int ems_usb_start(struct ems_usb *dev) return -ENOMEM; } - buf = usb_buffer_alloc(dev->udev, RX_BUFFER_SIZE, GFP_KERNEL, - &urb->transfer_dma); + buf = usb_alloc_coherent(dev->udev, RX_BUFFER_SIZE, GFP_KERNEL, + &urb->transfer_dma); if (!buf) { dev_err(netdev->dev.parent, "No memory left for USB buffer\n"); @@ -635,8 +635,8 @@ static int ems_usb_start(struct ems_usb *dev) netif_device_detach(dev->netdev); usb_unanchor_urb(urb); - usb_buffer_free(dev->udev, RX_BUFFER_SIZE, buf, - urb->transfer_dma); + usb_free_coherent(dev->udev, RX_BUFFER_SIZE, buf, + urb->transfer_dma); break; } @@ -777,7 +777,7 @@ static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *ne goto nomem; } - buf = usb_buffer_alloc(dev->udev, size, GFP_ATOMIC, &urb->transfer_dma); + buf = usb_alloc_coherent(dev->udev, size, GFP_ATOMIC, &urb->transfer_dma); if (!buf) { dev_err(netdev->dev.parent, "No memory left for USB buffer\n"); usb_free_urb(urb); @@ -820,7 +820,7 @@ static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *ne */ if (!context) { usb_unanchor_urb(urb); - usb_buffer_free(dev->udev, size, buf, urb->transfer_dma); + usb_free_coherent(dev->udev, size, buf, urb->transfer_dma); dev_warn(netdev->dev.parent, "couldn't find free context\n"); @@ -845,7 +845,7 @@ static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *ne can_free_echo_skb(netdev, context->echo_index); usb_unanchor_urb(urb); - usb_buffer_free(dev->udev, size, buf, urb->transfer_dma); + usb_free_coherent(dev->udev, size, buf, urb->transfer_dma); dev_kfree_skb(skb); atomic_dec(&dev->active_tx_urbs); diff --git a/drivers/net/usb/ipheth.c b/drivers/net/usb/ipheth.c index 418825d26f9..197c352c47f 100644 --- a/drivers/net/usb/ipheth.c +++ b/drivers/net/usb/ipheth.c @@ -128,17 +128,13 @@ static int ipheth_alloc_urbs(struct ipheth_device *iphone) if (rx_urb == NULL) goto free_tx_urb; - tx_buf = usb_buffer_alloc(iphone->udev, - IPHETH_BUF_SIZE, - GFP_KERNEL, - &tx_urb->transfer_dma); + tx_buf = usb_alloc_coherent(iphone->udev, IPHETH_BUF_SIZE, + GFP_KERNEL, &tx_urb->transfer_dma); if (tx_buf == NULL) goto free_rx_urb; - rx_buf = usb_buffer_alloc(iphone->udev, - IPHETH_BUF_SIZE, - GFP_KERNEL, - &rx_urb->transfer_dma); + rx_buf = usb_alloc_coherent(iphone->udev, IPHETH_BUF_SIZE, + GFP_KERNEL, &rx_urb->transfer_dma); if (rx_buf == NULL) goto free_tx_buf; @@ -150,8 +146,8 @@ static int ipheth_alloc_urbs(struct ipheth_device *iphone) return 0; free_tx_buf: - usb_buffer_free(iphone->udev, IPHETH_BUF_SIZE, tx_buf, - tx_urb->transfer_dma); + usb_free_coherent(iphone->udev, IPHETH_BUF_SIZE, tx_buf, + tx_urb->transfer_dma); free_rx_urb: usb_free_urb(rx_urb); free_tx_urb: @@ -162,10 +158,10 @@ error_nomem: static void ipheth_free_urbs(struct ipheth_device *iphone) { - usb_buffer_free(iphone->udev, IPHETH_BUF_SIZE, iphone->rx_buf, - iphone->rx_urb->transfer_dma); - usb_buffer_free(iphone->udev, IPHETH_BUF_SIZE, iphone->tx_buf, - iphone->tx_urb->transfer_dma); + usb_free_coherent(iphone->udev, IPHETH_BUF_SIZE, iphone->rx_buf, + iphone->rx_urb->transfer_dma); + usb_free_coherent(iphone->udev, IPHETH_BUF_SIZE, iphone->tx_buf, + iphone->tx_urb->transfer_dma); usb_free_urb(iphone->rx_urb); usb_free_urb(iphone->tx_urb); } diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c index c4c334d9770..a3eb7be51d5 100644 --- a/drivers/net/usb/kaweth.c +++ b/drivers/net/usb/kaweth.c @@ -1156,13 +1156,13 @@ err_fw: if (!kaweth->irq_urb) goto err_tx_and_rx; - kaweth->intbuffer = usb_buffer_alloc( kaweth->dev, + kaweth->intbuffer = usb_alloc_coherent( kaweth->dev, INTBUFFERSIZE, GFP_KERNEL, &kaweth->intbufferhandle); if (!kaweth->intbuffer) goto err_tx_and_rx_and_irq; - kaweth->rx_buf = usb_buffer_alloc( kaweth->dev, + kaweth->rx_buf = usb_alloc_coherent( kaweth->dev, KAWETH_BUF_SIZE, GFP_KERNEL, &kaweth->rxbufferhandle); @@ -1203,9 +1203,9 @@ err_fw: err_intfdata: usb_set_intfdata(intf, NULL); - usb_buffer_free(kaweth->dev, KAWETH_BUF_SIZE, (void *)kaweth->rx_buf, kaweth->rxbufferhandle); + usb_free_coherent(kaweth->dev, KAWETH_BUF_SIZE, (void *)kaweth->rx_buf, kaweth->rxbufferhandle); err_all_but_rxbuf: - usb_buffer_free(kaweth->dev, INTBUFFERSIZE, (void *)kaweth->intbuffer, kaweth->intbufferhandle); + usb_free_coherent(kaweth->dev, INTBUFFERSIZE, (void *)kaweth->intbuffer, kaweth->intbufferhandle); err_tx_and_rx_and_irq: usb_free_urb(kaweth->irq_urb); err_tx_and_rx: @@ -1242,8 +1242,8 @@ static void kaweth_disconnect(struct usb_interface *intf) usb_free_urb(kaweth->tx_urb); usb_free_urb(kaweth->irq_urb); - usb_buffer_free(kaweth->dev, KAWETH_BUF_SIZE, (void *)kaweth->rx_buf, kaweth->rxbufferhandle); - usb_buffer_free(kaweth->dev, INTBUFFERSIZE, (void *)kaweth->intbuffer, kaweth->intbufferhandle); + usb_free_coherent(kaweth->dev, KAWETH_BUF_SIZE, (void *)kaweth->rx_buf, kaweth->rxbufferhandle); + usb_free_coherent(kaweth->dev, INTBUFFERSIZE, (void *)kaweth->intbuffer, kaweth->intbufferhandle); free_netdev(netdev); } diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c index e1c2fcaa8be..a1f5444f7cc 100644 --- a/drivers/net/wireless/ath/ar9170/usb.c +++ b/drivers/net/wireless/ath/ar9170/usb.c @@ -202,7 +202,7 @@ resubmit: return; free: - usb_buffer_free(aru->udev, 64, urb->transfer_buffer, urb->transfer_dma); + usb_free_coherent(aru->udev, 64, urb->transfer_buffer, urb->transfer_dma); } static void ar9170_usb_rx_completed(struct urb *urb) @@ -283,7 +283,7 @@ static int ar9170_usb_alloc_rx_irq_urb(struct ar9170_usb *aru) if (!urb) goto out; - ibuf = usb_buffer_alloc(aru->udev, 64, GFP_KERNEL, &urb->transfer_dma); + ibuf = usb_alloc_coherent(aru->udev, 64, GFP_KERNEL, &urb->transfer_dma); if (!ibuf) goto out; @@ -296,8 +296,8 @@ static int ar9170_usb_alloc_rx_irq_urb(struct ar9170_usb *aru) err = usb_submit_urb(urb, GFP_KERNEL); if (err) { usb_unanchor_urb(urb); - usb_buffer_free(aru->udev, 64, urb->transfer_buffer, - urb->transfer_dma); + usb_free_coherent(aru->udev, 64, urb->transfer_buffer, + urb->transfer_dma); } out: diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index d91ad1a612a..c257940b71b 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c @@ -664,15 +664,15 @@ static struct urb *alloc_rx_urb(struct zd_usb *usb) urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) return NULL; - buffer = usb_buffer_alloc(udev, USB_MAX_RX_SIZE, GFP_KERNEL, - &urb->transfer_dma); + buffer = usb_alloc_coherent(udev, USB_MAX_RX_SIZE, GFP_KERNEL, + &urb->transfer_dma); if (!buffer) { usb_free_urb(urb); return NULL; } usb_fill_bulk_urb(urb, udev, usb_rcvbulkpipe(udev, EP_DATA_IN), - buffer, USB_MAX_RX_SIZE, + buffer, USB_MAX_RX_SIZE, rx_urb_complete, usb); urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; @@ -683,8 +683,8 @@ static void free_rx_urb(struct urb *urb) { if (!urb) return; - usb_buffer_free(urb->dev, urb->transfer_buffer_length, - urb->transfer_buffer, urb->transfer_dma); + usb_free_coherent(urb->dev, urb->transfer_buffer_length, + urb->transfer_buffer, urb->transfer_dma); usb_free_urb(urb); } diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 5e1a253b08a..0c2f14ff969 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -892,7 +892,7 @@ static void acm_write_buffers_free(struct acm *acm) struct usb_device *usb_dev = interface_to_usbdev(acm->control); for (wb = &acm->wb[0], i = 0; i < ACM_NW; i++, wb++) - usb_buffer_free(usb_dev, acm->writesize, wb->buf, wb->dmah); + usb_free_coherent(usb_dev, acm->writesize, wb->buf, wb->dmah); } static void acm_read_buffers_free(struct acm *acm) @@ -901,8 +901,8 @@ static void acm_read_buffers_free(struct acm *acm) int i, n = acm->rx_buflimit; for (i = 0; i < n; i++) - usb_buffer_free(usb_dev, acm->readsize, - acm->rb[i].base, acm->rb[i].dma); + usb_free_coherent(usb_dev, acm->readsize, + acm->rb[i].base, acm->rb[i].dma); } /* Little helper: write buffers allocate */ @@ -912,13 +912,13 @@ static int acm_write_buffers_alloc(struct acm *acm) struct acm_wb *wb; for (wb = &acm->wb[0], i = 0; i < ACM_NW; i++, wb++) { - wb->buf = usb_buffer_alloc(acm->dev, acm->writesize, GFP_KERNEL, + wb->buf = usb_alloc_coherent(acm->dev, acm->writesize, GFP_KERNEL, &wb->dmah); if (!wb->buf) { while (i != 0) { --i; --wb; - usb_buffer_free(acm->dev, acm->writesize, + usb_free_coherent(acm->dev, acm->writesize, wb->buf, wb->dmah); } return -ENOMEM; @@ -1177,7 +1177,7 @@ made_compressed_probe: tty_port_init(&acm->port); acm->port.ops = &acm_port_ops; - buf = usb_buffer_alloc(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma); + buf = usb_alloc_coherent(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma); if (!buf) { dev_dbg(&intf->dev, "out of memory (ctrl buffer alloc)\n"); goto alloc_fail2; @@ -1210,11 +1210,11 @@ made_compressed_probe: for (i = 0; i < num_rx_buf; i++) { struct acm_rb *rb = &(acm->rb[i]); - rb->base = usb_buffer_alloc(acm->dev, readsize, + rb->base = usb_alloc_coherent(acm->dev, readsize, GFP_KERNEL, &rb->dma); if (!rb->base) { dev_dbg(&intf->dev, - "out of memory (read bufs usb_buffer_alloc)\n"); + "out of memory (read bufs usb_alloc_coherent)\n"); goto alloc_fail7; } } @@ -1306,7 +1306,7 @@ alloc_fail7: alloc_fail5: acm_write_buffers_free(acm); alloc_fail4: - usb_buffer_free(usb_dev, ctrlsize, acm->ctrl_buffer, acm->ctrl_dma); + usb_free_coherent(usb_dev, ctrlsize, acm->ctrl_buffer, acm->ctrl_dma); alloc_fail2: kfree(acm); alloc_fail: @@ -1356,8 +1356,8 @@ static void acm_disconnect(struct usb_interface *intf) stop_data_traffic(acm); acm_write_buffers_free(acm); - usb_buffer_free(usb_dev, acm->ctrlsize, acm->ctrl_buffer, - acm->ctrl_dma); + usb_free_coherent(usb_dev, acm->ctrlsize, acm->ctrl_buffer, + acm->ctrl_dma); acm_read_buffers_free(acm); if (!acm->combined_interfaces) diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 189141ca4e0..094c76b5de1 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -276,14 +276,14 @@ static void free_urbs(struct wdm_device *desc) static void cleanup(struct wdm_device *desc) { - usb_buffer_free(interface_to_usbdev(desc->intf), - desc->wMaxPacketSize, - desc->sbuf, - desc->validity->transfer_dma); - usb_buffer_free(interface_to_usbdev(desc->intf), - desc->wMaxCommand, - desc->inbuf, - desc->response->transfer_dma); + usb_free_coherent(interface_to_usbdev(desc->intf), + desc->wMaxPacketSize, + desc->sbuf, + desc->validity->transfer_dma); + usb_free_coherent(interface_to_usbdev(desc->intf), + desc->wMaxCommand, + desc->inbuf, + desc->response->transfer_dma); kfree(desc->orq); kfree(desc->irq); kfree(desc->ubuf); @@ -705,17 +705,17 @@ next_desc: if (!desc->ubuf) goto err; - desc->sbuf = usb_buffer_alloc(interface_to_usbdev(intf), + desc->sbuf = usb_alloc_coherent(interface_to_usbdev(intf), desc->wMaxPacketSize, GFP_KERNEL, &desc->validity->transfer_dma); if (!desc->sbuf) goto err; - desc->inbuf = usb_buffer_alloc(interface_to_usbdev(intf), - desc->bMaxPacketSize0, - GFP_KERNEL, - &desc->response->transfer_dma); + desc->inbuf = usb_alloc_coherent(interface_to_usbdev(intf), + desc->bMaxPacketSize0, + GFP_KERNEL, + &desc->response->transfer_dma); if (!desc->inbuf) goto err2; @@ -742,15 +742,15 @@ out: return rv; err3: usb_set_intfdata(intf, NULL); - usb_buffer_free(interface_to_usbdev(desc->intf), - desc->bMaxPacketSize0, + usb_free_coherent(interface_to_usbdev(desc->intf), + desc->bMaxPacketSize0, desc->inbuf, desc->response->transfer_dma); err2: - usb_buffer_free(interface_to_usbdev(desc->intf), - desc->wMaxPacketSize, - desc->sbuf, - desc->validity->transfer_dma); + usb_free_coherent(interface_to_usbdev(desc->intf), + desc->wMaxPacketSize, + desc->sbuf, + desc->validity->transfer_dma); err: free_urbs(desc); kfree(desc->ubuf); diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index 93b5f85d7ce..2250095db0a 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c @@ -27,7 +27,7 @@ * v0.11 - add proto_bias option (Pete Zaitcev) * v0.12 - add hpoj.sourceforge.net ioctls (David Paschal) * v0.13 - alloc space for statusbuf ( not on stack); - * use usb_buffer_alloc() for read buf & write buf; + * use usb_alloc_coherent() for read buf & write buf; * none - Maintained in Linux kernel after v0.13 */ diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c index 094f91cbc57..1fa6ce3e4a2 100644 --- a/drivers/usb/misc/appledisplay.c +++ b/drivers/usb/misc/appledisplay.c @@ -259,7 +259,7 @@ static int appledisplay_probe(struct usb_interface *iface, } /* Allocate buffer for interrupt data */ - pdata->urbdata = usb_buffer_alloc(pdata->udev, ACD_URB_BUFFER_LEN, + pdata->urbdata = usb_alloc_coherent(pdata->udev, ACD_URB_BUFFER_LEN, GFP_KERNEL, &pdata->urb->transfer_dma); if (!pdata->urbdata) { retval = -ENOMEM; @@ -316,7 +316,7 @@ error: if (pdata->urb) { usb_kill_urb(pdata->urb); if (pdata->urbdata) - usb_buffer_free(pdata->udev, ACD_URB_BUFFER_LEN, + usb_free_coherent(pdata->udev, ACD_URB_BUFFER_LEN, pdata->urbdata, pdata->urb->transfer_dma); usb_free_urb(pdata->urb); } @@ -337,7 +337,7 @@ static void appledisplay_disconnect(struct usb_interface *iface) usb_kill_urb(pdata->urb); cancel_delayed_work(&pdata->work); backlight_device_unregister(pdata->bd); - usb_buffer_free(pdata->udev, ACD_URB_BUFFER_LEN, + usb_free_coherent(pdata->udev, ACD_URB_BUFFER_LEN, pdata->urbdata, pdata->urb->transfer_dma); usb_free_urb(pdata->urb); kfree(pdata->msgdata); diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c index 2300a51d48b..82e16630a78 100644 --- a/drivers/usb/misc/ftdi-elan.c +++ b/drivers/usb/misc/ftdi-elan.c @@ -734,7 +734,7 @@ static void ftdi_elan_write_bulk_callback(struct urb *urb) dev_err(&ftdi->udev->dev, "urb=%p write bulk status received: %" "d\n", urb, status); } - usb_buffer_free(urb->dev, urb->transfer_buffer_length, + usb_free_coherent(urb->dev, urb->transfer_buffer_length, urb->transfer_buffer, urb->transfer_dma); } @@ -795,7 +795,7 @@ static int ftdi_elan_command_engine(struct usb_ftdi *ftdi) total_size); return -ENOMEM; } - buf = usb_buffer_alloc(ftdi->udev, total_size, GFP_KERNEL, + buf = usb_alloc_coherent(ftdi->udev, total_size, GFP_KERNEL, &urb->transfer_dma); if (!buf) { dev_err(&ftdi->udev->dev, "could not get a buffer to write %d c" @@ -829,7 +829,7 @@ static int ftdi_elan_command_engine(struct usb_ftdi *ftdi) dev_err(&ftdi->udev->dev, "failed %d to submit urb %p to write " "%d commands totaling %d bytes to the Uxxx\n", retval, urb, command_size, total_size); - usb_buffer_free(ftdi->udev, total_size, buf, urb->transfer_dma); + usb_free_coherent(ftdi->udev, total_size, buf, urb->transfer_dma); usb_free_urb(urb); return retval; } @@ -1167,7 +1167,7 @@ static ssize_t ftdi_elan_write(struct file *file, retval = -ENOMEM; goto error_1; } - buf = usb_buffer_alloc(ftdi->udev, count, GFP_KERNEL, + buf = usb_alloc_coherent(ftdi->udev, count, GFP_KERNEL, &urb->transfer_dma); if (!buf) { retval = -ENOMEM; @@ -1192,7 +1192,7 @@ static ssize_t ftdi_elan_write(struct file *file, exit: return count; error_3: - usb_buffer_free(ftdi->udev, count, buf, urb->transfer_dma); + usb_free_coherent(ftdi->udev, count, buf, urb->transfer_dma); error_2: usb_free_urb(urb); error_1: @@ -1968,7 +1968,7 @@ static int ftdi_elan_synchronize_flush(struct usb_ftdi *ftdi) "ence\n"); return -ENOMEM; } - buf = usb_buffer_alloc(ftdi->udev, I, GFP_KERNEL, &urb->transfer_dma); + buf = usb_alloc_coherent(ftdi->udev, I, GFP_KERNEL, &urb->transfer_dma); if (!buf) { dev_err(&ftdi->udev->dev, "could not get a buffer for flush seq" "uence\n"); @@ -1985,7 +1985,7 @@ static int ftdi_elan_synchronize_flush(struct usb_ftdi *ftdi) if (retval) { dev_err(&ftdi->udev->dev, "failed to submit urb containing the " "flush sequence\n"); - usb_buffer_free(ftdi->udev, i, buf, urb->transfer_dma); + usb_free_coherent(ftdi->udev, i, buf, urb->transfer_dma); usb_free_urb(urb); return -ENOMEM; } @@ -2011,7 +2011,7 @@ static int ftdi_elan_synchronize_reset(struct usb_ftdi *ftdi) "quence\n"); return -ENOMEM; } - buf = usb_buffer_alloc(ftdi->udev, I, GFP_KERNEL, &urb->transfer_dma); + buf = usb_alloc_coherent(ftdi->udev, I, GFP_KERNEL, &urb->transfer_dma); if (!buf) { dev_err(&ftdi->udev->dev, "could not get a buffer for the reset" " sequence\n"); @@ -2030,7 +2030,7 @@ static int ftdi_elan_synchronize_reset(struct usb_ftdi *ftdi) if (retval) { dev_err(&ftdi->udev->dev, "failed to submit urb containing the " "reset sequence\n"); - usb_buffer_free(ftdi->udev, i, buf, urb->transfer_dma); + usb_free_coherent(ftdi->udev, i, buf, urb->transfer_dma); usb_free_urb(urb); return -ENOMEM; } diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c index d3c85236388..7dc9d3c6998 100644 --- a/drivers/usb/misc/iowarrior.c +++ b/drivers/usb/misc/iowarrior.c @@ -239,8 +239,8 @@ static void iowarrior_write_callback(struct urb *urb) __func__, status); } /* free up our allocated buffer */ - usb_buffer_free(urb->dev, urb->transfer_buffer_length, - urb->transfer_buffer, urb->transfer_dma); + usb_free_coherent(urb->dev, urb->transfer_buffer_length, + urb->transfer_buffer, urb->transfer_dma); /* tell a waiting writer the interrupt-out-pipe is available again */ atomic_dec(&dev->write_busy); wake_up_interruptible(&dev->write_wait); @@ -421,8 +421,8 @@ static ssize_t iowarrior_write(struct file *file, dbg("%s Unable to allocate urb ", __func__); goto error_no_urb; } - buf = usb_buffer_alloc(dev->udev, dev->report_size, - GFP_KERNEL, &int_out_urb->transfer_dma); + buf = usb_alloc_coherent(dev->udev, dev->report_size, + GFP_KERNEL, &int_out_urb->transfer_dma); if (!buf) { retval = -ENOMEM; dbg("%s Unable to allocate buffer ", __func__); @@ -459,8 +459,8 @@ static ssize_t iowarrior_write(struct file *file, break; } error: - usb_buffer_free(dev->udev, dev->report_size, buf, - int_out_urb->transfer_dma); + usb_free_coherent(dev->udev, dev->report_size, buf, + int_out_urb->transfer_dma); error_no_buffer: usb_free_urb(int_out_urb); error_no_urb: diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c index 90aede90553..7828c764b32 100644 --- a/drivers/usb/misc/usblcd.c +++ b/drivers/usb/misc/usblcd.c @@ -205,8 +205,8 @@ static void lcd_write_bulk_callback(struct urb *urb) } /* free up our allocated buffer */ - usb_buffer_free(urb->dev, urb->transfer_buffer_length, - urb->transfer_buffer, urb->transfer_dma); + usb_free_coherent(urb->dev, urb->transfer_buffer_length, + urb->transfer_buffer, urb->transfer_dma); up(&dev->limit_sem); } @@ -234,7 +234,7 @@ static ssize_t lcd_write(struct file *file, const char __user * user_buffer, siz goto err_no_buf; } - buf = usb_buffer_alloc(dev->udev, count, GFP_KERNEL, &urb->transfer_dma); + buf = usb_alloc_coherent(dev->udev, count, GFP_KERNEL, &urb->transfer_dma); if (!buf) { retval = -ENOMEM; goto error; @@ -268,7 +268,7 @@ exit: error_unanchor: usb_unanchor_urb(urb); error: - usb_buffer_free(dev->udev, count, buf, urb->transfer_dma); + usb_free_coherent(dev->udev, count, buf, urb->transfer_dma); usb_free_urb(urb); err_no_buf: up(&dev->limit_sem); diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index 9dcc82337ce..16dffe99d9f 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -202,7 +202,7 @@ static struct urb *simple_alloc_urb ( urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; if (usb_pipein (pipe)) urb->transfer_flags |= URB_SHORT_NOT_OK; - urb->transfer_buffer = usb_buffer_alloc (udev, bytes, GFP_KERNEL, + urb->transfer_buffer = usb_alloc_coherent (udev, bytes, GFP_KERNEL, &urb->transfer_dma); if (!urb->transfer_buffer) { usb_free_urb (urb); @@ -272,8 +272,8 @@ static inline int simple_check_buf(struct usbtest_dev *tdev, struct urb *urb) static void simple_free_urb (struct urb *urb) { - usb_buffer_free (urb->dev, urb->transfer_buffer_length, - urb->transfer_buffer, urb->transfer_dma); + usb_free_coherent(urb->dev, urb->transfer_buffer_length, + urb->transfer_buffer, urb->transfer_dma); usb_free_urb (urb); } @@ -1416,7 +1416,7 @@ static struct urb *iso_alloc_urb ( urb->number_of_packets = packets; urb->transfer_buffer_length = bytes; - urb->transfer_buffer = usb_buffer_alloc (udev, bytes, GFP_KERNEL, + urb->transfer_buffer = usb_alloc_coherent (udev, bytes, GFP_KERNEL, &urb->transfer_dma); if (!urb->transfer_buffer) { usb_free_urb (urb); diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c index 198bb3ed95b..1943be5a291 100644 --- a/drivers/usb/storage/onetouch.c +++ b/drivers/usb/storage/onetouch.c @@ -201,8 +201,8 @@ static int onetouch_connect_input(struct us_data *ss) if (!onetouch || !input_dev) goto fail1; - onetouch->data = usb_buffer_alloc(udev, ONETOUCH_PKT_LEN, - GFP_KERNEL, &onetouch->data_dma); + onetouch->data = usb_alloc_coherent(udev, ONETOUCH_PKT_LEN, + GFP_KERNEL, &onetouch->data_dma); if (!onetouch->data) goto fail1; @@ -264,8 +264,8 @@ static int onetouch_connect_input(struct us_data *ss) return 0; fail3: usb_free_urb(onetouch->irq); - fail2: usb_buffer_free(udev, ONETOUCH_PKT_LEN, - onetouch->data, onetouch->data_dma); + fail2: usb_free_coherent(udev, ONETOUCH_PKT_LEN, + onetouch->data, onetouch->data_dma); fail1: kfree(onetouch); input_free_device(input_dev); return error; @@ -279,8 +279,8 @@ static void onetouch_release_input(void *onetouch_) usb_kill_urb(onetouch->irq); input_unregister_device(onetouch->dev); usb_free_urb(onetouch->irq); - usb_buffer_free(onetouch->udev, ONETOUCH_PKT_LEN, - onetouch->data, onetouch->data_dma); + usb_free_coherent(onetouch->udev, ONETOUCH_PKT_LEN, + onetouch->data, onetouch->data_dma); } } diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index c54a370c76c..e2798ef2dd1 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -414,7 +414,7 @@ static int associate_dev(struct us_data *us, struct usb_interface *intf) return -ENOMEM; } - us->iobuf = usb_buffer_alloc(us->pusb_dev, US_IOBUF_SIZE, + us->iobuf = usb_alloc_coherent(us->pusb_dev, US_IOBUF_SIZE, GFP_KERNEL, &us->iobuf_dma); if (!us->iobuf) { US_DEBUGP("I/O buffer allocation failed\n"); @@ -758,7 +758,7 @@ static void dissociate_dev(struct us_data *us) /* Free the buffers */ kfree(us->cr); - usb_buffer_free(us->pusb_dev, US_IOBUF_SIZE, us->iobuf, us->iobuf_dma); + usb_free_coherent(us->pusb_dev, US_IOBUF_SIZE, us->iobuf, us->iobuf_dma); /* Remove our private data from the interface */ usb_set_intfdata(us->pusb_intf, NULL); diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c index 61522787f39..d110588b56f 100644 --- a/drivers/usb/usb-skeleton.c +++ b/drivers/usb/usb-skeleton.c @@ -387,8 +387,8 @@ static void skel_write_bulk_callback(struct urb *urb) } /* free up our allocated buffer */ - usb_buffer_free(urb->dev, urb->transfer_buffer_length, - urb->transfer_buffer, urb->transfer_dma); + usb_free_coherent(urb->dev, urb->transfer_buffer_length, + urb->transfer_buffer, urb->transfer_dma); up(&dev->limit_sem); } @@ -442,8 +442,8 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, goto error; } - buf = usb_buffer_alloc(dev->udev, writesize, GFP_KERNEL, - &urb->transfer_dma); + buf = usb_alloc_coherent(dev->udev, writesize, GFP_KERNEL, + &urb->transfer_dma); if (!buf) { retval = -ENOMEM; goto error; @@ -491,7 +491,7 @@ error_unanchor: usb_unanchor_urb(urb); error: if (urb) { - usb_buffer_free(dev->udev, writesize, buf, urb->transfer_dma); + usb_free_coherent(dev->udev, writesize, buf, urb->transfer_dma); usb_free_urb(urb); } up(&dev->limit_sem); diff --git a/drivers/watchdog/pcwd_usb.c b/drivers/watchdog/pcwd_usb.c index 8e4eacc5bb5..748a74bd85e 100644 --- a/drivers/watchdog/pcwd_usb.c +++ b/drivers/watchdog/pcwd_usb.c @@ -600,8 +600,8 @@ static inline void usb_pcwd_delete(struct usb_pcwd_private *usb_pcwd) { usb_free_urb(usb_pcwd->intr_urb); if (usb_pcwd->intr_buffer != NULL) - usb_buffer_free(usb_pcwd->udev, usb_pcwd->intr_size, - usb_pcwd->intr_buffer, usb_pcwd->intr_dma); + usb_free_coherent(usb_pcwd->udev, usb_pcwd->intr_size, + usb_pcwd->intr_buffer, usb_pcwd->intr_dma); kfree(usb_pcwd); } @@ -671,7 +671,7 @@ static int usb_pcwd_probe(struct usb_interface *interface, le16_to_cpu(endpoint->wMaxPacketSize) : 8); /* set up the memory buffer's */ - usb_pcwd->intr_buffer = usb_buffer_alloc(udev, usb_pcwd->intr_size, + usb_pcwd->intr_buffer = usb_alloc_coherent(udev, usb_pcwd->intr_size, GFP_ATOMIC, &usb_pcwd->intr_dma); if (!usb_pcwd->intr_buffer) { printk(KERN_ERR PFX "Out of memory\n"); diff --git a/sound/usb/ua101.c b/sound/usb/ua101.c index 3d458d3b996..d700e32dee2 100644 --- a/sound/usb/ua101.c +++ b/sound/usb/ua101.c @@ -41,7 +41,7 @@ MODULE_SUPPORTED_DEVICE("{{Edirol,UA-101},{Edirol,UA-1000}}"); /* * This magic value optimizes memory usage efficiency for the UA-101's packet * sizes at all sample rates, taking into account the stupid cache pool sizes - * that usb_buffer_alloc() uses. + * that usb_alloc_coherent() uses. */ #define DEFAULT_QUEUE_LENGTH 21 @@ -1056,7 +1056,7 @@ static int alloc_stream_buffers(struct ua101 *ua, struct ua101_stream *stream) (unsigned int)MAX_QUEUE_LENGTH); /* - * The cache pool sizes used by usb_buffer_alloc() (128, 512, 2048) are + * The cache pool sizes used by usb_alloc_coherent() (128, 512, 2048) are * quite bad when used with the packet sizes of this device (e.g. 280, * 520, 624). Therefore, we allocate and subdivide entire pages, using * a smaller buffer only for the last chunk. @@ -1067,8 +1067,8 @@ static int alloc_stream_buffers(struct ua101 *ua, struct ua101_stream *stream) packets = min(remaining_packets, packets_per_page); size = packets * stream->max_packet_bytes; stream->buffers[i].addr = - usb_buffer_alloc(ua->dev, size, GFP_KERNEL, - &stream->buffers[i].dma); + usb_alloc_coherent(ua->dev, size, GFP_KERNEL, + &stream->buffers[i].dma); if (!stream->buffers[i].addr) return -ENOMEM; stream->buffers[i].size = size; @@ -1088,10 +1088,10 @@ static void free_stream_buffers(struct ua101 *ua, struct ua101_stream *stream) unsigned int i; for (i = 0; i < ARRAY_SIZE(stream->buffers); ++i) - usb_buffer_free(ua->dev, - stream->buffers[i].size, - stream->buffers[i].addr, - stream->buffers[i].dma); + usb_free_coherent(ua->dev, + stream->buffers[i].size, + stream->buffers[i].addr, + stream->buffers[i].dma); } static int alloc_stream_urbs(struct ua101 *ua, struct ua101_stream *stream, diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 11b0826b8fe..9d2274ce01d 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -985,9 +985,9 @@ static void release_urb_ctx(struct snd_urb_ctx *u) { if (u->urb) { if (u->buffer_size) - usb_buffer_free(u->subs->dev, u->buffer_size, - u->urb->transfer_buffer, - u->urb->transfer_dma); + usb_free_coherent(u->subs->dev, u->buffer_size, + u->urb->transfer_buffer, + u->urb->transfer_dma); usb_free_urb(u->urb); u->urb = NULL; } @@ -1008,8 +1008,8 @@ static void release_substream_urbs(struct snd_usb_substream *subs, int force) release_urb_ctx(&subs->dataurb[i]); for (i = 0; i < SYNC_URBS; i++) release_urb_ctx(&subs->syncurb[i]); - usb_buffer_free(subs->dev, SYNC_URBS * 4, - subs->syncbuf, subs->sync_dma); + usb_free_coherent(subs->dev, SYNC_URBS * 4, + subs->syncbuf, subs->sync_dma); subs->syncbuf = NULL; subs->nurbs = 0; } @@ -1113,8 +1113,8 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri if (!u->urb) goto out_of_memory; u->urb->transfer_buffer = - usb_buffer_alloc(subs->dev, u->buffer_size, GFP_KERNEL, - &u->urb->transfer_dma); + usb_alloc_coherent(subs->dev, u->buffer_size, GFP_KERNEL, + &u->urb->transfer_dma); if (!u->urb->transfer_buffer) goto out_of_memory; u->urb->pipe = subs->datapipe; @@ -1126,8 +1126,8 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri if (subs->syncpipe) { /* allocate and initialize sync urbs */ - subs->syncbuf = usb_buffer_alloc(subs->dev, SYNC_URBS * 4, - GFP_KERNEL, &subs->sync_dma); + subs->syncbuf = usb_alloc_coherent(subs->dev, SYNC_URBS * 4, + GFP_KERNEL, &subs->sync_dma); if (!subs->syncbuf) goto out_of_memory; for (i = 0; i < SYNC_URBS; i++) { diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c index 9e28b20cb2c..61b2d8fd033 100644 --- a/sound/usb/usbmidi.c +++ b/sound/usb/usbmidi.c @@ -1047,8 +1047,8 @@ static struct snd_rawmidi_ops snd_usbmidi_input_ops = { static void free_urb_and_buffer(struct snd_usb_midi *umidi, struct urb *urb, unsigned int buffer_length) { - usb_buffer_free(umidi->dev, buffer_length, - urb->transfer_buffer, urb->transfer_dma); + usb_free_coherent(umidi->dev, buffer_length, + urb->transfer_buffer, urb->transfer_dma); usb_free_urb(urb); } @@ -1099,8 +1099,8 @@ static int snd_usbmidi_in_endpoint_create(struct snd_usb_midi* umidi, pipe = usb_rcvbulkpipe(umidi->dev, ep_info->in_ep); length = usb_maxpacket(umidi->dev, pipe, 0); for (i = 0; i < INPUT_URBS; ++i) { - buffer = usb_buffer_alloc(umidi->dev, length, GFP_KERNEL, - &ep->urbs[i]->transfer_dma); + buffer = usb_alloc_coherent(umidi->dev, length, GFP_KERNEL, + &ep->urbs[i]->transfer_dma); if (!buffer) { snd_usbmidi_in_endpoint_delete(ep); return -ENOMEM; @@ -1190,9 +1190,9 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi* umidi, break; } for (i = 0; i < OUTPUT_URBS; ++i) { - buffer = usb_buffer_alloc(umidi->dev, - ep->max_transfer, GFP_KERNEL, - &ep->urbs[i].urb->transfer_dma); + buffer = usb_alloc_coherent(umidi->dev, + ep->max_transfer, GFP_KERNEL, + &ep->urbs[i].urb->transfer_dma); if (!buffer) { snd_usbmidi_out_endpoint_delete(ep); return -ENOMEM; -- cgit v1.2.3-70-g09d2 From beb7b04a09a9da8b12417f7b74fbcceedb087fc3 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 30 Apr 2010 12:14:04 -0400 Subject: USB: remove leftover references to udev->autosuspend_disabled This patch (as1373) fixes a couple of drivers outside the USB subtree. Devices are now disabled or enabled for autosuspend by calling a core function instead of setting a flag. Signed-off-by: Alan Stern Cc: Stephen Rothwell Signed-off-by: Greg Kroah-Hartman --- drivers/media/video/tlg2300/pd-main.c | 2 +- drivers/net/wimax/i2400m/usb.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/tlg2300/pd-main.c b/drivers/media/video/tlg2300/pd-main.c index 2cf0ebf9f28..a6400dad12a 100644 --- a/drivers/media/video/tlg2300/pd-main.c +++ b/drivers/media/video/tlg2300/pd-main.c @@ -455,8 +455,8 @@ static int poseidon_probe(struct usb_interface *interface, device_init_wakeup(&udev->dev, 1); #ifdef CONFIG_PM - pd->udev->autosuspend_disabled = 0; pd->udev->autosuspend_delay = HZ * PM_SUSPEND_DELAY; + usb_enable_autosuspend(pd->udev); if (in_hibernation(pd)) { INIT_WORK(&pd->pm_work, hibernation_resume); diff --git a/drivers/net/wimax/i2400m/usb.c b/drivers/net/wimax/i2400m/usb.c index d8c4d6497fd..d555e37a665 100644 --- a/drivers/net/wimax/i2400m/usb.c +++ b/drivers/net/wimax/i2400m/usb.c @@ -505,7 +505,7 @@ int i2400mu_probe(struct usb_interface *iface, iface->needs_remote_wakeup = 1; /* autosuspend (15s delay) */ device_init_wakeup(dev, 1); usb_dev->autosuspend_delay = 15 * HZ; - usb_dev->autosuspend_disabled = 0; + usb_enable_autosuspend(usb_dev); #endif result = i2400m_setup(i2400m, I2400M_BRI_MAC_REINIT); -- cgit v1.2.3-70-g09d2