diff options
author | Stephen Rothwell <sfr@canb.auug.org.au> | 2008-02-22 13:10:15 +1100 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2008-02-22 13:10:15 +1100 |
commit | c3b5bb895499e02213a2985e3ca49f16aabae528 (patch) | |
tree | 4a0bd1e86797b6d04356a48bad1d43ab9cc009f1 | |
parent | 06fabdfab168149d2141d6fa739ad17a5aa07485 (diff) | |
parent | 2cfe9395ef25b36cc88bd11bfee1d9fad4f3b047 (diff) |
Merge commit 'v4l-dvb/stable'
146 files changed, 5170 insertions, 708 deletions
diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 0424901ebc78..765a06b1f0f6 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -131,3 +131,6 @@ 130 -> Beholder BeholdTV M6 / BeholdTV M6 Extra [5ace:6190,5ace:6193] 131 -> Twinhan Hybrid DTV-DVB 3056 PCI [1822:0022] 132 -> Genius TVGO AM11MCE +133 -> NXP Snake DVB-S reference design +134 -> Medion/Creatix CTX953 Hybrid [16be:0010] +135 -> MSI TV@nywhere A/D v1.1 [1462:8625] diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c index bfccb80ac8ef..3838aabdf338 100644 --- a/arch/arm/mach-pxa/devices.c +++ b/arch/arm/mach-pxa/devices.c @@ -11,6 +11,7 @@ #include <asm/arch/irda.h> #include <asm/arch/i2c.h> #include <asm/arch/ohci.h> +#include <asm/arch/camera.h> #include "devices.h" @@ -540,6 +541,37 @@ struct platform_device pxa27x_device_ssp3 = { .resource = pxa27x_resource_ssp3, .num_resources = ARRAY_SIZE(pxa27x_resource_ssp3), }; + +static struct resource pxa27x_resource_camera[] = { + [0] = { + .start = 0x50000000, + .end = 0x50000fff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_CAMERA, + .end = IRQ_CAMERA, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 pxa27x_dma_mask_camera = DMA_BIT_MASK(32); + +static struct platform_device pxa27x_device_camera = { + .name = "pxa27x-camera", + .id = 0, /* This is used to put cameras on this interface */ + .dev = { + .dma_mask = &pxa27x_dma_mask_camera, + .coherent_dma_mask = 0xffffffff, + }, + .num_resources = ARRAY_SIZE(pxa27x_resource_camera), + .resource = pxa27x_resource_camera, +}; + +void __init pxa_set_camera_info(struct pxacamera_platform_data *info) +{ + pxa_register_device(&pxa27x_device_camera, info); +} #endif /* CONFIG_PXA27x || CONFIG_PXA3xx */ #ifdef CONFIG_PXA3xx diff --git a/arch/arm/mach-pxa/pcm990-baseboard.c b/arch/arm/mach-pxa/pcm990-baseboard.c index 3dda16a20049..07ac050f2b4e 100644 --- a/arch/arm/mach-pxa/pcm990-baseboard.c +++ b/arch/arm/mach-pxa/pcm990-baseboard.c @@ -23,6 +23,13 @@ #include <linux/irq.h> #include <linux/platform_device.h> #include <linux/ide.h> +#include <linux/i2c.h> + +#include <media/soc_camera.h> + +#include <asm/gpio.h> +#include <asm/arch/i2c.h> +#include <asm/arch/camera.h> #include <asm/mach/map.h> #include <asm/arch/pxa-regs.h> #include <asm/arch/mmc.h> @@ -258,6 +265,76 @@ static struct pxaohci_platform_data pcm990_ohci_platform_data = { }; /* + * PXA27x Camera specific stuff + */ +#if defined(CONFIG_VIDEO_PXA27x) || defined(CONFIG_VIDEO_PXA27x_MODULE) +static int pcm990_pxacamera_init(struct device *dev) +{ + pxa_gpio_mode(GPIO98_CIF_DD0_MD); + pxa_gpio_mode(GPIO105_CIF_DD1_MD); + pxa_gpio_mode(GPIO104_CIF_DD2_MD); + pxa_gpio_mode(GPIO103_CIF_DD3_MD); + pxa_gpio_mode(GPIO95_CIF_DD4_MD); + pxa_gpio_mode(GPIO94_CIF_DD5_MD); + pxa_gpio_mode(GPIO93_CIF_DD6_MD); + pxa_gpio_mode(GPIO108_CIF_DD7_MD); + pxa_gpio_mode(GPIO107_CIF_DD8_MD); + pxa_gpio_mode(GPIO106_CIF_DD9_MD); + pxa_gpio_mode(GPIO42_CIF_MCLK_MD); + pxa_gpio_mode(GPIO45_CIF_PCLK_MD); + pxa_gpio_mode(GPIO43_CIF_FV_MD); + pxa_gpio_mode(GPIO44_CIF_LV_MD); + + return 0; +} + +/* + * CICR4: PCLK_EN: Pixel clock is supplied by the sensor + * MCLK_EN: Master clock is generated by PXA + * PCP: Data sampled on the falling edge of pixel clock + */ +struct pxacamera_platform_data pcm990_pxacamera_platform_data = { + .init = pcm990_pxacamera_init, + .flags = PXA_CAMERA_MASTER | PXA_CAMERA_DATAWIDTH_8 | PXA_CAMERA_DATAWIDTH_10 | + PXA_CAMERA_PCLK_EN | PXA_CAMERA_MCLK_EN/* | PXA_CAMERA_PCP*/, + .mclk_10khz = 1000, +}; + +#include <linux/i2c/pca953x.h> + +static struct pca953x_platform_data pca9536_data = { + .gpio_base = NR_BUILTIN_GPIO + 1, +}; + +static struct soc_camera_link iclink[] = { + { + .bus_id = 0, /* Must match with the camera ID above */ + .gpio = NR_BUILTIN_GPIO + 1, + }, { + .bus_id = 0, /* Must match with the camera ID above */ + } +}; + +/* Board I2C devices. */ +static struct i2c_board_info __initdata pcm990_i2c_devices[] = { + { + /* Must initialize before the camera(s) */ + I2C_BOARD_INFO("pca953x", 0x41), + .type = "pca9536", + .platform_data = &pca9536_data, + }, { + I2C_BOARD_INFO("mt9v022", 0x48), + .type = "mt9v022", + .platform_data = &iclink[0], /* With extender */ + }, { + I2C_BOARD_INFO("mt9m001", 0x5d), + .type = "mt9m001", + .platform_data = &iclink[0], /* With extender */ + }, +}; +#endif /* CONFIG_VIDEO_PXA27x ||CONFIG_VIDEO_PXA27x_MODULE */ + +/* * AC97 support * Note: The connected AC97 mixer also reports interrupts at PCM990_AC97_IRQ */ @@ -326,5 +403,14 @@ void __init pcm990_baseboard_init(void) /* USB host */ pxa_set_ohci_info(&pcm990_ohci_platform_data); + pxa_set_i2c_info(NULL); + +#if defined(CONFIG_VIDEO_PXA27x) || defined(CONFIG_VIDEO_PXA27x_MODULE) + pxa_set_camera_info(&pcm990_pxacamera_platform_data); + + i2c_register_board_info(0, pcm990_i2c_devices, + ARRAY_SIZE(pcm990_i2c_devices)); +#endif + printk(KERN_INFO"PCM-990 Evaluation baseboard initialized\n"); } diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index 11950698a2e7..a86504587447 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig @@ -71,9 +71,13 @@ source "drivers/media/dvb/Kconfig" source "drivers/media/common/Kconfig" +config VIDEO_TUNER_TYPES + tristate + config VIDEO_TUNER tristate depends on I2C + select VIDEO_TUNER_TYPES select TUNER_XC2028 if !VIDEO_TUNER_CUSTOMIZE select TUNER_MT20XX if !VIDEO_TUNER_CUSTOMIZE select TUNER_TDA8290 if !VIDEO_TUNER_CUSTOMIZE @@ -136,6 +140,7 @@ config TUNER_TEA5767 config TUNER_SIMPLE tristate "Simple tuner support" depends on I2C + select VIDEO_TUNER_TYPES select TUNER_TDA9887 default m if VIDEO_TUNER_CUSTOMIZE help @@ -155,7 +160,7 @@ config VIDEOBUF_GEN tristate config VIDEOBUF_DMA_SG - depends on PCI + depends on PCI || ARCH_PXA select VIDEOBUF_GEN tristate diff --git a/drivers/media/common/ir-functions.c b/drivers/media/common/ir-functions.c index bb2a027b9483..266505207925 100644 --- a/drivers/media/common/ir-functions.c +++ b/drivers/media/common/ir-functions.c @@ -34,7 +34,7 @@ static int repeat = 1; module_param(repeat, int, 0444); MODULE_PARM_DESC(repeat,"auto-repeat for IR keys (default: on)"); -static int debug = 0; /* debug level (0,1,2) */ +static int debug; /* debug level (0,1,2) */ module_param(debug, int, 0644); #define dprintk(level, fmt, arg...) if (debug >= level) \ diff --git a/drivers/media/dvb/b2c2/flexcop-pci.c b/drivers/media/dvb/b2c2/flexcop-pci.c index 01af4d237eb1..5b30dfc7846b 100644 --- a/drivers/media/dvb/b2c2/flexcop-pci.c +++ b/drivers/media/dvb/b2c2/flexcop-pci.c @@ -32,7 +32,7 @@ MODULE_PARM_DESC(irq_chk_intv, "set the interval for IRQ watchdog (currently jus #define deb_irq(args...) dprintk(0x08,args) #define deb_chk(args...) dprintk(0x10,args) -static int debug = 0; +static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "set debug level (1=info,2=regs,4=TS,8=irqdma (|-able))." DEBSTATUS); diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c index ed3f8268ed11..ba4db890a77a 100644 --- a/drivers/media/dvb/dvb-core/dvb_net.c +++ b/drivers/media/dvb/dvb-core/dvb_net.c @@ -354,7 +354,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) #ifdef ULE_DEBUG /* The code inside ULE_DEBUG keeps a history of the last 100 TS cells processed. */ static unsigned char ule_hist[100*TS_SZ]; - static unsigned char *ule_where = ule_hist, ule_dump = 0; + static unsigned char *ule_where = ule_hist, ule_dump; #endif /* For all TS cells in current buffer. diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c index 18738faecbbc..ce5122e220f6 100644 --- a/drivers/media/dvb/dvb-core/dvbdev.c +++ b/drivers/media/dvb/dvb-core/dvbdev.c @@ -97,7 +97,7 @@ static int dvb_device_open(struct inode *inode, struct file *file) } -static struct file_operations dvb_device_fops = +static const struct file_operations dvb_device_fops = { .owner = THIS_MODULE, .open = dvb_device_open, diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 9ad86ce4a4e5..0209644f222a 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -379,6 +379,13 @@ config DVB_LNBP21 help An SEC control chip. +config DVB_ISL6405 + tristate "ISL6405 SEC controller" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + An SEC control chip. + config DVB_ISL6421 tristate "ISL6421 SEC controller" depends on DVB_CORE && I2C diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 16bd107ebd32..23304b3774b5 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -38,6 +38,7 @@ obj-$(CONFIG_DVB_S5H1420) += s5h1420.o obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o obj-$(CONFIG_DVB_CX24123) += cx24123.o obj-$(CONFIG_DVB_LNBP21) += lnbp21.o +obj-$(CONFIG_DVB_ISL6405) += isl6405.o obj-$(CONFIG_DVB_ISL6421) += isl6421.o obj-$(CONFIG_DVB_TDA10086) += tda10086.o obj-$(CONFIG_DVB_TDA826X) += tda826x.o diff --git a/drivers/media/dvb/frontends/cx22702.c b/drivers/media/dvb/frontends/cx22702.c index 1dc164d5488c..406c4cfa82bb 100644 --- a/drivers/media/dvb/frontends/cx22702.c +++ b/drivers/media/dvb/frontends/cx22702.c @@ -48,7 +48,7 @@ struct cx22702_state { u8 prevUCBlocks; }; -static int debug = 0; +static int debug; #define dprintk if (debug) printk /* Register values to initialise the demod */ diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index 8c8d7342d0b3..decf798994e9 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -44,7 +44,7 @@ struct dvb_pll_priv { static unsigned int dvb_pll_devcount; -static int debug = 0; +static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); diff --git a/drivers/media/dvb/frontends/isl6405.c b/drivers/media/dvb/frontends/isl6405.c new file mode 100644 index 000000000000..33d33f4d8867 --- /dev/null +++ b/drivers/media/dvb/frontends/isl6405.c @@ -0,0 +1,164 @@ +/* + * isl6405.c - driver for dual lnb supply and control ic ISL6405 + * + * Copyright (C) 2008 Hartmut Hackmann + * Copyright (C) 2006 Oliver Endriss + * + * 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. + * + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + * + * + * the project's page is at http://www.linuxtv.org + */ +#include <linux/delay.h> +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/string.h> +#include <linux/slab.h> + +#include "dvb_frontend.h" +#include "isl6405.h" + +struct isl6405 { + u8 config; + u8 override_or; + u8 override_and; + struct i2c_adapter *i2c; + u8 i2c_addr; +}; + +static int isl6405_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) +{ + struct isl6405 *isl6405 = (struct isl6405 *) fe->sec_priv; + struct i2c_msg msg = { .addr = isl6405->i2c_addr, .flags = 0, + .buf = &isl6405->config, + .len = sizeof(isl6405->config) }; + + if (isl6405->override_or & 0x80) { + isl6405->config &= ~(ISL6405_VSEL2 | ISL6405_EN2); + switch (voltage) { + case SEC_VOLTAGE_OFF: + break; + case SEC_VOLTAGE_13: + isl6405->config |= ISL6405_EN2; + break; + case SEC_VOLTAGE_18: + isl6405->config |= (ISL6405_EN2 | ISL6405_VSEL2); + break; + default: + return -EINVAL; + } + } else { + isl6405->config &= ~(ISL6405_VSEL1 | ISL6405_EN1); + switch (voltage) { + case SEC_VOLTAGE_OFF: + break; + case SEC_VOLTAGE_13: + isl6405->config |= ISL6405_EN1; + break; + case SEC_VOLTAGE_18: + isl6405->config |= (ISL6405_EN1 | ISL6405_VSEL1); + break; + default: + return -EINVAL; + }; + } + isl6405->config |= isl6405->override_or; + isl6405->config &= isl6405->override_and; + + return (i2c_transfer(isl6405->i2c, &msg, 1) == 1) ? 0 : -EIO; +} + +static int isl6405_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg) +{ + struct isl6405 *isl6405 = (struct isl6405 *) fe->sec_priv; + struct i2c_msg msg = { .addr = isl6405->i2c_addr, .flags = 0, + .buf = &isl6405->config, + .len = sizeof(isl6405->config) }; + + if (isl6405->override_or & 0x80) { + if (arg) + isl6405->config |= ISL6405_LLC2; + else + isl6405->config &= ~ISL6405_LLC2; + } else { + if (arg) + isl6405->config |= ISL6405_LLC1; + else + isl6405->config &= ~ISL6405_LLC1; + } + isl6405->config |= isl6405->override_or; + isl6405->config &= isl6405->override_and; + + return (i2c_transfer(isl6405->i2c, &msg, 1) == 1) ? 0 : -EIO; +} + +static void isl6405_release(struct dvb_frontend *fe) +{ + /* power off */ + isl6405_set_voltage(fe, SEC_VOLTAGE_OFF); + + /* free */ + kfree(fe->sec_priv); + fe->sec_priv = NULL; +} + +struct dvb_frontend *isl6405_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, + u8 i2c_addr, u8 override_set, u8 override_clear) +{ + struct isl6405 *isl6405 = kmalloc(sizeof(struct isl6405), GFP_KERNEL); + if (!isl6405) + return NULL; + + /* default configuration */ + if (override_set & 0x80) + isl6405->config = ISL6405_ISEL2; + else + isl6405->config = ISL6405_ISEL1; + isl6405->i2c = i2c; + isl6405->i2c_addr = i2c_addr; + fe->sec_priv = isl6405; + + /* bits which should be forced to '1' */ + isl6405->override_or = override_set; + + /* bits which should be forced to '0' */ + isl6405->override_and = ~override_clear; + + /* detect if it is present or not */ + if (isl6405_set_voltage(fe, SEC_VOLTAGE_OFF)) { + kfree(isl6405); + fe->sec_priv = NULL; + return NULL; + } + + /* install release callback */ + fe->ops.release_sec = isl6405_release; + + /* override frontend ops */ + fe->ops.set_voltage = isl6405_set_voltage; + fe->ops.enable_high_lnb_voltage = isl6405_enable_high_lnb_voltage; + + return fe; +} +EXPORT_SYMBOL(isl6405_attach); + +MODULE_DESCRIPTION("Driver for lnb supply and control ic isl6405"); +MODULE_AUTHOR("Hartmut Hackmann & Oliver Endriss"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/frontends/isl6405.h b/drivers/media/dvb/frontends/isl6405.h new file mode 100644 index 000000000000..9d4001a2237e --- /dev/null +++ b/drivers/media/dvb/frontends/isl6405.h @@ -0,0 +1,74 @@ +/* + * isl6405.h - driver for dual lnb supply and control ic ISL6405 + * + * Copyright (C) 2008 Hartmut Hackmann + * Copyright (C) 2006 Oliver Endriss + * + * 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. + * + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + * + * + * the project's page is at http://www.linuxtv.org + */ + +#ifndef _ISL6405_H +#define _ISL6405_H + +#include <linux/dvb/frontend.h> + +/* system register bits */ + +/* this bit selects register (control) 1 or 2 + note that the bit maps are different */ + +#define ISL6405_SR 0x80 + +/* SR = 0 */ +#define ISL6405_OLF1 0x01 +#define ISL6405_EN1 0x02 +#define ISL6405_VSEL1 0x04 +#define ISL6405_LLC1 0x08 +#define ISL6405_ENT1 0x10 +#define ISL6405_ISEL1 0x20 +#define ISL6405_DCL 0x40 + +/* SR = 1 */ +#define ISL6405_OLF2 0x01 +#define ISL6405_OTF 0x02 +#define ISL6405_EN2 0x04 +#define ISL6405_VSEL2 0x08 +#define ISL6405_LLC2 0x10 +#define ISL6405_ENT2 0x20 +#define ISL6405_ISEL2 0x40 + +#if defined(CONFIG_DVB_ISL6405) || (defined(CONFIG_DVB_ISL6405_MODULE) && defined(MODULE)) +/* override_set and override_clear control which system register bits (above) + * to always set & clear + */ +extern struct dvb_frontend *isl6405_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, + u8 i2c_addr, u8 override_set, u8 override_clear); +#else +static inline struct dvb_frontend *isl6405_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, u8 i2c_addr, + u8 override_set, u8 override_clear) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +#endif /* CONFIG_DVB_ISL6405 */ + +#endif diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c index bdc9fa88b86a..dc897a3903fc 100644 --- a/drivers/media/dvb/frontends/lgdt330x.c +++ b/drivers/media/dvb/frontends/lgdt330x.c @@ -49,7 +49,7 @@ /* Use Equalizer Mean Squared Error instead of Phaser Tracker MSE */ /* #define USE_EQMSE */ -static int debug = 0; +static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug,"Turn on/off lgdt330x frontend debugging (default:off)."); #define dprintk(args...) \ diff --git a/drivers/media/dvb/frontends/nxt6000.c b/drivers/media/dvb/frontends/nxt6000.c index d313d7dcf386..0eef22dbf8a0 100644 --- a/drivers/media/dvb/frontends/nxt6000.c +++ b/drivers/media/dvb/frontends/nxt6000.c @@ -38,7 +38,7 @@ struct nxt6000_state { struct dvb_frontend frontend; }; -static int debug = 0; +static int debug; #define dprintk if (debug) printk static int nxt6000_writereg(struct nxt6000_state* state, u8 reg, u8 data) diff --git a/drivers/media/dvb/frontends/s5h1409.c b/drivers/media/dvb/frontends/s5h1409.c index 819433485d3b..c5232e8ffc56 100644 --- a/drivers/media/dvb/frontends/s5h1409.c +++ b/drivers/media/dvb/frontends/s5h1409.c @@ -48,7 +48,7 @@ struct s5h1409_state { u32 qam_state; }; -static int debug = 0; +static int debug; #define dprintk if (debug) printk /* Register values to initialise the demod, this will set VSB by default */ diff --git a/drivers/media/dvb/frontends/s5h1420.c b/drivers/media/dvb/frontends/s5h1420.c index 2c2c344c4c64..7c64af91e5ac 100644 --- a/drivers/media/dvb/frontends/s5h1420.c +++ b/drivers/media/dvb/frontends/s5h1420.c @@ -53,7 +53,7 @@ static int s5h1420_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings); -static int debug = 0; +static int debug; #define dprintk if (debug) printk static int s5h1420_writereg (struct s5h1420_state* state, u8 reg, u8 data) diff --git a/drivers/media/dvb/frontends/sp8870.c b/drivers/media/dvb/frontends/sp8870.c index da876f7bfe32..f5b3bfc00436 100644 --- a/drivers/media/dvb/frontends/sp8870.c +++ b/drivers/media/dvb/frontends/sp8870.c @@ -449,15 +449,15 @@ static int sp8870_read_uncorrected_blocks (struct dvb_frontend* fe, u32* ublocks return 0; } -// number of trials to recover from lockup +/* number of trials to recover from lockup */ #define MAXTRIALS 5 -// maximum checks for data valid signal +/* maximum checks for data valid signal */ #define MAXCHECKS 100 -// only for debugging: counter for detected lockups -static int lockups = 0; -// only for debugging: counter for channel switches -static int switches = 0; +/* only for debugging: counter for detected lockups */ +static int lockups; +/* only for debugging: counter for channel switches */ +static int switches; static int sp8870_set_frontend (struct dvb_frontend* fe, struct dvb_frontend_parameters *p) { diff --git a/drivers/media/dvb/frontends/tda10086.c b/drivers/media/dvb/frontends/tda10086.c index 0d2b69a99ad4..143af96439b9 100644 --- a/drivers/media/dvb/frontends/tda10086.c +++ b/drivers/media/dvb/frontends/tda10086.c @@ -43,7 +43,7 @@ struct tda10086_state { bool has_lock; }; -static int debug = 0; +static int debug; #define dprintk(args...) \ do { \ if (debug) printk(KERN_DEBUG "tda10086: " args); \ diff --git a/drivers/media/dvb/frontends/tda18271-common.c b/drivers/media/dvb/frontends/tda18271-common.c index bca570990613..39496463ccf3 100644 --- a/drivers/media/dvb/frontends/tda18271-common.c +++ b/drivers/media/dvb/frontends/tda18271-common.c @@ -125,16 +125,16 @@ int tda18271_read_regs(struct dvb_frontend *fe) unsigned char buf = 0x00; int ret; struct i2c_msg msg[] = { - { .addr = priv->i2c_addr, .flags = 0, + { .addr = priv->i2c_props.addr, .flags = 0, .buf = &buf, .len = 1 }, - { .addr = priv->i2c_addr, .flags = I2C_M_RD, + { .addr = priv->i2c_props.addr, .flags = I2C_M_RD, .buf = regs, .len = 16 } }; tda18271_i2c_gate_ctrl(fe, 1); /* read all registers */ - ret = i2c_transfer(priv->i2c_adap, msg, 2); + ret = i2c_transfer(priv->i2c_props.adap, msg, 2); tda18271_i2c_gate_ctrl(fe, 0); @@ -155,16 +155,16 @@ int tda18271_read_extended(struct dvb_frontend *fe) unsigned char buf = 0x00; int ret, i; struct i2c_msg msg[] = { - { .addr = priv->i2c_addr, .flags = 0, + { .addr = priv->i2c_props.addr, .flags = 0, .buf = &buf, .len = 1 }, - { .addr = priv->i2c_addr, .flags = I2C_M_RD, + { .addr = priv->i2c_props.addr, .flags = I2C_M_RD, .buf = regdump, .len = TDA18271_NUM_REGS } }; tda18271_i2c_gate_ctrl(fe, 1); /* read all registers */ - ret = i2c_transfer(priv->i2c_adap, msg, 2); + ret = i2c_transfer(priv->i2c_props.adap, msg, 2); tda18271_i2c_gate_ctrl(fe, 0); @@ -192,7 +192,7 @@ int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len) struct tda18271_priv *priv = fe->tuner_priv; unsigned char *regs = priv->tda18271_regs; unsigned char buf[TDA18271_NUM_REGS + 1]; - struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0, + struct i2c_msg msg = { .addr = priv->i2c_props.addr, .flags = 0, .buf = buf, .len = len + 1 }; int i, ret; @@ -205,7 +205,7 @@ int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len) tda18271_i2c_gate_ctrl(fe, 1); /* write registers */ - ret = i2c_transfer(priv->i2c_adap, &msg, 1); + ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); tda18271_i2c_gate_ctrl(fe, 0); @@ -223,7 +223,8 @@ int tda18271_init_regs(struct dvb_frontend *fe) unsigned char *regs = priv->tda18271_regs; tda_dbg("initializing registers for device @ %d-%04x\n", - i2c_adapter_id(priv->i2c_adap), priv->i2c_addr); + i2c_adapter_id(priv->i2c_props.adap), + priv->i2c_props.addr); /* initialize registers */ switch (priv->id) { diff --git a/drivers/media/dvb/frontends/tda18271-fe.c b/drivers/media/dvb/frontends/tda18271-fe.c index dfe72aaec380..b5d69a8108d9 100644 --- a/drivers/media/dvb/frontends/tda18271-fe.c +++ b/drivers/media/dvb/frontends/tda18271-fe.c @@ -31,27 +31,11 @@ static int tda18271_cal_on_startup; module_param_named(cal, tda18271_cal_on_startup, int, 0644); MODULE_PARM_DESC(cal, "perform RF tracking filter calibration on startup"); -static LIST_HEAD(tda18271_list); static DEFINE_MUTEX(tda18271_list_mutex); +static LIST_HEAD(hybrid_tuner_instance_list); /*---------------------------------------------------------------------*/ -static int tda18271_ir_cal_init(struct dvb_frontend *fe) -{ - struct tda18271_priv *priv = fe->tuner_priv; - unsigned char *regs = priv->tda18271_regs; - - tda18271_read_regs(fe); - - /* test IR_CAL_OK to see if we need init */ - if ((regs[R_EP1] & 0x08) == 0) - tda18271_init_regs(fe); - - return 0; -} - -/* ------------------------------------------------------------------ */ - static int tda18271_channel_configuration(struct dvb_frontend *fe, u32 ifc, u32 freq, u32 bw, u8 std, int radio) @@ -195,8 +179,10 @@ static int tda18271_read_thermometer(struct dvb_frontend *fe) return tm; } -static int tda18271_rf_tracking_filters_correction(struct dvb_frontend *fe, - u32 freq) +/* ------------------------------------------------------------------ */ + +static int tda18271c2_rf_tracking_filters_correction(struct dvb_frontend *fe, + u32 freq) { struct tda18271_priv *priv = fe->tuner_priv; struct tda18271_rf_tracking_filter_cal *map = priv->rf_cal_state; @@ -587,7 +573,7 @@ static int tda18271_calc_rf_filter_curve(struct dvb_frontend *fe) /* ------------------------------------------------------------------ */ -static int tda18271_rf_cal_init(struct dvb_frontend *fe) +static int tda18271c2_rf_cal_init(struct dvb_frontend *fe) { struct tda18271_priv *priv = fe->tuner_priv; unsigned char *regs = priv->tda18271_regs; @@ -610,63 +596,13 @@ static int tda18271_rf_cal_init(struct dvb_frontend *fe) return 0; } -static int tda18271_init(struct dvb_frontend *fe) -{ - struct tda18271_priv *priv = fe->tuner_priv; - - mutex_lock(&priv->lock); - - /* power up */ - tda18271_set_standby_mode(fe, 0, 0, 0); - - /* initialization */ - tda18271_ir_cal_init(fe); - - if (priv->id == TDA18271HDC2) - tda18271_rf_cal_init(fe); - - mutex_unlock(&priv->lock); - - return 0; -} - -static int tda18271c2_tune(struct dvb_frontend *fe, - u32 ifc, u32 freq, u32 bw, u8 std, int radio) -{ - struct tda18271_priv *priv = fe->tuner_priv; - - tda_dbg("freq = %d, ifc = %d\n", freq, ifc); - - tda18271_init(fe); - - mutex_lock(&priv->lock); - - tda18271_rf_tracking_filters_correction(fe, freq); - - tda18271_channel_configuration(fe, ifc, freq, bw, std, radio); - - mutex_unlock(&priv->lock); - - return 0; -} - -/* ------------------------------------------------------------------ */ - -static int tda18271c1_tune(struct dvb_frontend *fe, - u32 ifc, u32 freq, u32 bw, u8 std, int radio) +static int tda18271c1_rf_tracking_filter_calibration(struct dvb_frontend *fe, + u32 freq, u32 bw) { struct tda18271_priv *priv = fe->tuner_priv; unsigned char *regs = priv->tda18271_regs; u32 N = 0; - tda18271_init(fe); - - mutex_lock(&priv->lock); - - tda_dbg("freq = %d, ifc = %d\n", freq, ifc); - - /* RF tracking filter calibration */ - /* calculate bp filter */ tda18271_calc_bp_filter(fe, &freq); tda18271_write_regs(fe, R_EP1, 1); @@ -737,7 +673,7 @@ static int tda18271c1_tune(struct dvb_frontend *fe, regs[R_EB7] = 0x40; tda18271_write_regs(fe, R_EB7, 1); - msleep(10); + msleep(10); /* pll locking */ regs[R_EB20] = 0xec; tda18271_write_regs(fe, R_EB20, 1); @@ -752,74 +688,70 @@ static int tda18271c1_tune(struct dvb_frontend *fe, if (0 == tda18271_calc_rf_cal(fe, &freq)) tda18271_write_regs(fe, R_EB14, 1); - /* Channel Configuration */ + return 0; +} - switch (priv->mode) { - case TDA18271_ANALOG: - regs[R_EB22] = 0x2c; - break; - case TDA18271_DIGITAL: - regs[R_EB22] = 0x37; - break; - } - tda18271_write_regs(fe, R_EB22, 1); +/* ------------------------------------------------------------------ */ - regs[R_EP1] |= 0x40; /* set dis power level on */ +static int tda18271_ir_cal_init(struct dvb_frontend *fe) +{ + struct tda18271_priv *priv = fe->tuner_priv; + unsigned char *regs = priv->tda18271_regs; - /* set standard */ - regs[R_EP3] &= ~0x1f; /* clear std bits */ + tda18271_read_regs(fe); - /* see table 22 */ - regs[R_EP3] |= std; + /* test IR_CAL_OK to see if we need init */ + if ((regs[R_EP1] & 0x08) == 0) + tda18271_init_regs(fe); - regs[R_EP4] &= ~0x03; /* set cal mode to normal */ + return 0; +} - regs[R_EP4] &= ~0x1c; /* clear if level bits */ - switch (priv->mode) { - case TDA18271_ANALOG: - regs[R_MPD] &= ~0x80; /* IF notch = 0 */ - break; - case TDA18271_DIGITAL: - regs[R_EP4] |= 0x04; - regs[R_MPD] |= 0x80; - break; - } +static int tda18271_init(struct dvb_frontend *fe) +{ + struct tda18271_priv *priv = fe->tuner_priv; - if (radio) - regs[R_EP4] |= 0x80; - else - regs[R_EP4] &= ~0x80; + mutex_lock(&priv->lock); - /* image rejection validity */ - tda18271_calc_ir_measure(fe, &freq); + /* power up */ + tda18271_set_standby_mode(fe, 0, 0, 0); - /* calculate MAIN PLL */ - N = freq + ifc; + /* initialization */ + tda18271_ir_cal_init(fe); - tda18271_calc_main_pll(fe, N); + if (priv->id == TDA18271HDC2) + tda18271c2_rf_cal_init(fe); - tda18271_write_regs(fe, R_TM, 15); - msleep(5); mutex_unlock(&priv->lock); return 0; } -static inline int tda18271_tune(struct dvb_frontend *fe, - u32 ifc, u32 freq, u32 bw, u8 std, int radio) +static int tda18271_tune(struct dvb_frontend *fe, + u32 ifc, u32 freq, u32 bw, u8 std, int radio) { struct tda18271_priv *priv = fe->tuner_priv; - int ret = -EINVAL; + + tda_dbg("freq = %d, ifc = %d, bw = %d, std = 0x%02x\n", + freq, ifc, bw, std); + + tda18271_init(fe); + + mutex_lock(&priv->lock); switch (priv->id) { case TDA18271HDC1: - ret = tda18271c1_tune(fe, ifc, freq, bw, std, radio); + tda18271c1_rf_tracking_filter_calibration(fe, freq, bw); break; case TDA18271HDC2: - ret = tda18271c2_tune(fe, ifc, freq, bw, std, radio); + tda18271c2_rf_tracking_filters_correction(fe, freq); break; } - return ret; + tda18271_channel_configuration(fe, ifc, freq, bw, std, radio); + + mutex_unlock(&priv->lock); + + return 0; } /* ------------------------------------------------------------------ */ @@ -986,16 +918,9 @@ static int tda18271_release(struct dvb_frontend *fe) mutex_lock(&tda18271_list_mutex); - priv->count--; - - if (!priv->count) { - tda_dbg("destroying instance @ %d-%04x\n", - i2c_adapter_id(priv->i2c_adap), - priv->i2c_addr); - list_del(&priv->tda18271_list); + if (priv) + hybrid_tuner_release_state(priv); - kfree(priv); - } mutex_unlock(&tda18271_list_mutex); fe->tuner_priv = NULL; @@ -1109,7 +1034,8 @@ static int tda18271_get_id(struct dvb_frontend *fe) } tda_info("%s detected @ %d-%04x%s\n", name, - i2c_adapter_id(priv->i2c_adap), priv->i2c_addr, + i2c_adapter_id(priv->i2c_props.adap), + priv->i2c_props.addr, (0 == ret) ? "" : ", device not supported."); return ret; @@ -1136,46 +1062,25 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, struct tda18271_config *cfg) { struct tda18271_priv *priv = NULL; - int state_found = 0; + int instance; mutex_lock(&tda18271_list_mutex); - list_for_each_entry(priv, &tda18271_list, tda18271_list) { - if ((i2c_adapter_id(priv->i2c_adap) == i2c_adapter_id(i2c)) && - (priv->i2c_addr == addr)) { - tda_dbg("attaching existing tuner @ %d-%04x\n", - i2c_adapter_id(priv->i2c_adap), - priv->i2c_addr); - priv->count++; - fe->tuner_priv = priv; - state_found = 1; - /* allow dvb driver to override i2c gate setting */ - if ((cfg) && (cfg->gate != TDA18271_GATE_ANALOG)) - priv->gate = cfg->gate; - break; - } - } - if (state_found == 0) { - tda_dbg("creating new tuner instance @ %d-%04x\n", - i2c_adapter_id(i2c), addr); - - priv = kzalloc(sizeof(struct tda18271_priv), GFP_KERNEL); - if (priv == NULL) { - mutex_unlock(&tda18271_list_mutex); - return NULL; - } - - priv->i2c_addr = addr; - priv->i2c_adap = i2c; + instance = hybrid_tuner_request_state(struct tda18271_priv, priv, + hybrid_tuner_instance_list, + i2c, addr, "tda18271"); + switch (instance) { + case 0: + goto fail; + break; + case 1: + /* new tuner instance */ priv->gate = (cfg) ? cfg->gate : TDA18271_GATE_AUTO; priv->cal_initialized = false; mutex_init(&priv->lock); - priv->count++; fe->tuner_priv = priv; - list_add_tail(&priv->tda18271_list, &tda18271_list); - if (tda18271_get_id(fe) < 0) goto fail; @@ -1186,9 +1091,18 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, tda18271_init_regs(fe); if ((tda18271_cal_on_startup) && (priv->id == TDA18271HDC2)) - tda18271_rf_cal_init(fe); + tda18271c2_rf_cal_init(fe); mutex_unlock(&priv->lock); + break; + default: + /* existing tuner instance */ + fe->tuner_priv = priv; + + /* allow dvb driver to override i2c gate setting */ + if ((cfg) && (cfg->gate != TDA18271_GATE_ANALOG)) + priv->gate = cfg->gate; + break; } /* override default std map with values in config struct */ diff --git a/drivers/media/dvb/frontends/tda18271-priv.h b/drivers/media/dvb/frontends/tda18271-priv.h index 7b939a5325fb..840b1803d171 100644 --- a/drivers/media/dvb/frontends/tda18271-priv.h +++ b/drivers/media/dvb/frontends/tda18271-priv.h @@ -24,6 +24,7 @@ #include <linux/kernel.h> #include <linux/types.h> #include <linux/mutex.h> +#include "tuner-i2c.h" #include "tda18271.h" #define R_ID 0x00 /* ID byte */ @@ -98,17 +99,15 @@ enum tda18271_ver { }; struct tda18271_priv { - u8 i2c_addr; - struct i2c_adapter *i2c_adap; unsigned char tda18271_regs[TDA18271_NUM_REGS]; - struct list_head tda18271_list; + struct list_head hybrid_tuner_instance_list; + struct tuner_i2c_props i2c_props; enum tda18271_mode mode; enum tda18271_i2c_gate gate; enum tda18271_ver id; - unsigned int count; unsigned int tm_rfcal; unsigned int cal_initialized:1; diff --git a/drivers/media/dvb/frontends/tda826x.c b/drivers/media/dvb/frontends/tda826x.c index bd3ebc284835..9a91eb0333d9 100644 --- a/drivers/media/dvb/frontends/tda826x.c +++ b/drivers/media/dvb/frontends/tda826x.c @@ -26,7 +26,7 @@ #include "tda826x.h" -static int debug = 0; +static int debug; #define dprintk(args...) \ do { \ if (debug) printk(KERN_DEBUG "tda826x: " args); \ diff --git a/drivers/media/dvb/frontends/tda827x.c b/drivers/media/dvb/frontends/tda827x.c index 229b11987a58..3190c8d0c17c 100644 --- a/drivers/media/dvb/frontends/tda827x.c +++ b/drivers/media/dvb/frontends/tda827x.c @@ -25,7 +25,7 @@ #include "tda827x.h" -static int debug = 0; +static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); diff --git a/drivers/media/dvb/frontends/ves1x93.c b/drivers/media/dvb/frontends/ves1x93.c index 23fd0303c91b..c041c81f9686 100644 --- a/drivers/media/dvb/frontends/ves1x93.c +++ b/drivers/media/dvb/frontends/ves1x93.c @@ -48,7 +48,7 @@ struct ves1x93_state { u8 demod_type; }; -static int debug = 0; +static int debug; #define dprintk if (debug) printk #define DEMOD_VES1893 0 diff --git a/drivers/media/dvb/frontends/xc5000.c b/drivers/media/dvb/frontends/xc5000.c index f642ca200b59..a5094b7f21fd 100644 --- a/drivers/media/dvb/frontends/xc5000.c +++ b/drivers/media/dvb/frontends/xc5000.c @@ -151,7 +151,7 @@ typedef struct { #define FM_Radio_INPUT2 21 #define FM_Radio_INPUT1 22 -XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = { +static XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = { {"M/N-NTSC/PAL-BTSC", 0x0400, 0x8020}, {"M/N-NTSC/PAL-A2", 0x0600, 0x8020}, {"M/N-NTSC/PAL-EIAJ", 0x0440, 0x8020}, diff --git a/drivers/media/dvb/frontends/zl10353.c b/drivers/media/dvb/frontends/zl10353.c index 276e3b631dc2..3d508ff4b292 100644 --- a/drivers/media/dvb/frontends/zl10353.c +++ b/drivers/media/dvb/frontends/zl10353.c @@ -46,7 +46,7 @@ static int debug; if (debug) printk(KERN_DEBUG "zl10353: " args); \ } while (0) -static int debug_regs = 0; +static int debug_regs; static int zl10353_single_write(struct dvb_frontend *fe, u8 reg, u8 val) { diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index 509349211d4f..0f476f75e03d 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -86,7 +86,7 @@ static int rc5_device = -1; module_param(rc5_device, int, 0644); MODULE_PARM_DESC(rc5_device, "only IR commands to given RC5 device (device = 0 - 31, any device = 255, default: autodetect)"); -static int ir_debug = 0; +static int ir_debug; module_param(ir_debug, int, 0644); MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding"); diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c index 7902ae1d9a18..1b3b6c1589f7 100644 --- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c +++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c @@ -542,7 +542,7 @@ static void ttusb_handle_sec_data(struct ttusb_channel *channel, const u8 * data, int len); #endif -static int numpkt = 0, numts, numstuff, numsec, numinvalid; +static int numpkt, numts, numstuff, numsec, numinvalid; static unsigned long lastj; static void ttusb_process_muxpack(struct ttusb *ttusb, const u8 * muxpack, @@ -1005,7 +1005,7 @@ static int stc_release(struct inode *inode, struct file *file) return 0; } -static struct file_operations stc_fops = { +static const struct file_operations stc_fops = { .owner = THIS_MODULE, .read = stc_read, .open = stc_open, diff --git a/drivers/media/radio/miropcm20-rds.c b/drivers/media/radio/miropcm20-rds.c index aed11477378b..06dfed9ef4c7 100644 --- a/drivers/media/radio/miropcm20-rds.c +++ b/drivers/media/radio/miropcm20-rds.c @@ -19,7 +19,7 @@ #include "miropcm20-rds-core.h" static char * text_buffer; -static int rds_users = 0; +static int rds_users; static int rds_f_open(struct inode *in, struct file *fi) diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c index 34e317ced5a3..cf68a7013fdf 100644 --- a/drivers/media/radio/radio-cadet.c +++ b/drivers/media/radio/radio-cadet.c @@ -69,13 +69,13 @@ static struct v4l2_queryctrl radio_qctrl[] = { static int io=-1; /* default to isapnp activation */ static int radio_nr = -1; -static int users=0; -static int curtuner=0; -static int tunestat=0; -static int sigstrength=0; +static int users; +static int curtuner; +static int tunestat; +static int sigstrength; static wait_queue_head_t read_queue; static struct timer_list readtimer; -static __u8 rdsin=0,rdsout=0,rdsstat=0; +static __u8 rdsin, rdsout, rdsstat; static unsigned char rdsbuf[RDS_BUFFER]; static spinlock_t cadet_io_lock; diff --git a/drivers/media/radio/radio-typhoon.c b/drivers/media/radio/radio-typhoon.c index 1366326474e5..02e3a2f05eee 100644 --- a/drivers/media/radio/radio-typhoon.c +++ b/drivers/media/radio/radio-typhoon.c @@ -404,7 +404,7 @@ MODULE_PARM_DESC(io, "I/O address of the Typhoon card (0x316 or 0x336)"); module_param(radio_nr, int, 0); #ifdef MODULE -static unsigned long mutefreq = 0; +static unsigned long mutefreq; module_param(mutefreq, ulong, 0); MODULE_PARM_DESC(mutefreq, "Frequency used when muting the card (in kHz)"); #endif diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 22729f56031b..35fc66ad9ffc 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -837,4 +837,49 @@ config USB_STKWEBCAM endif # V4L_USB_DRIVERS +config SOC_CAMERA + tristate "SoC camera support" + depends on VIDEO_V4L2 + select VIDEOBUF_DMA_SG + help + SoC Camera is a common API to several cameras, not connecting + over a bus like PCI or USB. For example some i2c camera connected + directly to the data bus of an SoC. + +config SOC_CAMERA_MT9M001 + tristate "mt9m001 support" + depends on SOC_CAMERA + select GPIO_PCA953X if MT9M001_PCA9536_SWITCH + help + This driver supports MT9M001 cameras from Micron, monochrome + and colour models. + +config MT9M001_PCA9536_SWITCH + bool "pca9536 datawidth switch for mt9m001" + depends on SOC_CAMERA_MT9M001 && GENERIC_GPIO + help + Select this if your MT9M001 camera uses a PCA9536 I2C GPIO + extender to switch between 8 and 10 bit datawidth modes + +config SOC_CAMERA_MT9V022 + tristate "mt9v022 support" + depends on SOC_CAMERA + select GPIO_PCA953X if MT9V022_PCA9536_SWITCH + help + This driver supports MT9V022 cameras from Micron + +config MT9V022_PCA9536_SWITCH + bool "pca9536 datawidth switch for mt9v022" + depends on SOC_CAMERA_MT9V022 && GENERIC_GPIO + help + Select this if your MT9V022 camera uses a PCA9536 I2C GPIO + extender to switch between 8 and 10 bit datawidth modes + +config VIDEO_PXA27x + tristate "PXA27x Quick Capture Interface driver" + depends on VIDEO_DEV && PXA27x + select SOC_CAMERA + ---help--- + This is a v4l2 driver for the PXA27x Quick Capture Interface + endif # VIDEO_CAPTURE_DRIVERS diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 0adb7b9fd54d..1ad09707f1af 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -4,7 +4,7 @@ zr36067-objs := zoran_procfs.o zoran_device.o \ zoran_driver.o zoran_card.o -tuner-objs := tuner-core.o tuner-types.o +tuner-objs := tuner-core.o msp3400-objs := msp3400-driver.o msp3400-kthreads.o @@ -84,6 +84,7 @@ obj-$(CONFIG_VIDEO_DPC) += dpc7146.o obj-$(CONFIG_TUNER_3036) += tuner-3036.o obj-$(CONFIG_VIDEO_TUNER) += tuner.o +obj-$(CONFIG_VIDEO_TUNER_TYPES) += tuner-types.o obj-$(CONFIG_TUNER_XC2028) += tuner-xc2028.o obj-$(CONFIG_TUNER_SIMPLE) += tuner-simple.o @@ -137,5 +138,10 @@ obj-$(CONFIG_VIDEO_IVTV) += ivtv/ obj-$(CONFIG_VIDEO_VIVI) += vivi.o obj-$(CONFIG_VIDEO_CX23885) += cx23885/ +obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o +obj-$(CONFIG_SOC_CAMERA) += soc_camera.o +obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o +obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o + EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core EXTRA_CFLAGS += -Idrivers/media/dvb/frontends diff --git a/drivers/media/video/adv7170.c b/drivers/media/video/adv7170.c index cbab53fc6243..92327fd8571b 100644 --- a/drivers/media/video/adv7170.c +++ b/drivers/media/video/adv7170.c @@ -56,7 +56,7 @@ MODULE_LICENSE("GPL"); #define I2C_NAME(x) (x)->name -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c index 0d0c554bfdf7..9ed4e5e89738 100644 --- a/drivers/media/video/adv7175.c +++ b/drivers/media/video/adv7175.c @@ -52,7 +52,7 @@ MODULE_LICENSE("GPL"); #define I2C_NAME(s) (s)->name -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c index c94a4d0f2804..e4d891b29f63 100644 --- a/drivers/media/video/arv.c +++ b/drivers/media/video/arv.c @@ -125,8 +125,8 @@ static unsigned char yuv[MAX_AR_FRAME_BYTES]; /* default frequency */ #define DEFAULT_FREQ 50 /* 50 or 75 (MHz) is available as BCLK */ static int freq = DEFAULT_FREQ; /* BCLK: available 50 or 70 (MHz) */ -static int vga = 0; /* default mode(0:QVGA mode, other:VGA mode) */ -static int vga_interlace = 0; /* 0 is normal mode for, else interlace mode */ +static int vga; /* default mode(0:QVGA mode, other:VGA mode) */ +static int vga_interlace; /* 0 is normal mode for, else interlace mode */ module_param(freq, int, 0); module_param(vga, int, 0); module_param(vga_interlace, int, 0); diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c index 12d1b9248be5..34d4383ffa75 100644 --- a/drivers/media/video/bt819.c +++ b/drivers/media/video/bt819.c @@ -57,7 +57,7 @@ MODULE_LICENSE("GPL"); #define I2C_NAME(s) (s)->name -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); diff --git a/drivers/media/video/bt856.c b/drivers/media/video/bt856.c index e1028a76c042..df0c41be6c98 100644 --- a/drivers/media/video/bt856.c +++ b/drivers/media/video/bt856.c @@ -56,7 +56,7 @@ MODULE_LICENSE("GPL"); #define I2C_NAME(s) (s)->name -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); diff --git a/drivers/media/video/bt8xx/bttv-vbi.c b/drivers/media/video/bt8xx/bttv-vbi.c index 75fa82c7c735..bfdbc469e30f 100644 --- a/drivers/media/video/bt8xx/bttv-vbi.c +++ b/drivers/media/video/bt8xx/bttv-vbi.c @@ -54,7 +54,7 @@ #define VBI_DEFLINES 16 static unsigned int vbibufs = 4; -static unsigned int vbi_debug = 0; +static unsigned int vbi_debug; module_param(vbibufs, int, 0444); module_param(vbi_debug, int, 0644); diff --git a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c index 032265383df2..40a8e92a01b9 100644 --- a/drivers/media/video/bw-qcam.c +++ b/drivers/media/video/bw-qcam.c @@ -523,7 +523,7 @@ static inline int qc_readbytes(struct qcam_device *q, char buffer[]) int ret=1; unsigned int hi, lo; unsigned int hi2, lo2; - static int state = 0; + static int state; if (buffer == NULL) { @@ -912,7 +912,7 @@ static struct video_device qcam_template= #define MAX_CAMS 4 static struct qcam_device *qcams[MAX_CAMS]; -static unsigned int num_cams = 0; +static unsigned int num_cams; static int init_bwqcam(struct parport *port) { diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c index cf1546b5a7f1..d4d5adfb0351 100644 --- a/drivers/media/video/c-qcam.c +++ b/drivers/media/video/c-qcam.c @@ -69,7 +69,7 @@ struct qcam_device { static int parport[MAX_CAMS] = { [1 ... MAX_CAMS-1] = -1 }; static int probe = 2; -static int force_rgb = 0; +static int force_rgb; static int video_nr = -1; static inline void qcam_set_ack(struct qcam_device *qcam, unsigned int i) @@ -741,7 +741,7 @@ static struct qcam_device *qcam_init(struct parport *port) } static struct qcam_device *qcams[MAX_CAMS]; -static unsigned int num_cams = 0; +static unsigned int num_cams; static int init_cqcam(struct parport *port) { diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c index 7ae499c9c54c..5195b1f3378a 100644 --- a/drivers/media/video/cafe_ccic.c +++ b/drivers/media/video/cafe_ccic.c @@ -65,7 +65,7 @@ MODULE_SUPPORTED_DEVICE("Video"); */ #define MAX_DMA_BUFS 3 -static int alloc_bufs_at_read = 0; +static int alloc_bufs_at_read; module_param(alloc_bufs_at_read, bool, 0444); MODULE_PARM_DESC(alloc_bufs_at_read, "Non-zero value causes DMA buffers to be allocated when the " @@ -99,7 +99,7 @@ MODULE_PARM_DESC(max_buffers, "will be allowed to allocate. These buffers are big and live " "in vmalloc space."); -static int flip = 0; +static int flip; module_param(flip, bool, 0444); MODULE_PARM_DESC(flip, "If set, the sensor will be instructed to flip the image " diff --git a/drivers/media/video/cpia2/cpia2_core.c b/drivers/media/video/cpia2/cpia2_core.c index a76bd786cf13..a439a56c3cc9 100644 --- a/drivers/media/video/cpia2/cpia2_core.c +++ b/drivers/media/video/cpia2/cpia2_core.c @@ -34,7 +34,7 @@ #include <linux/slab.h> #include <linux/vmalloc.h> -//#define _CPIA2_DEBUG_ +/* #define _CPIA2_DEBUG_ */ #include "cpia2patch.h" @@ -48,7 +48,7 @@ static const char *block_name[] = { }; #endif -static unsigned int debugs_on = 0;//DEBUG_REG; +static unsigned int debugs_on; /* default 0 - DEBUG_REG */ /****************************************************************************** diff --git a/drivers/media/video/cpia2/cpia2_usb.c b/drivers/media/video/cpia2/cpia2_usb.c index d8e929863a88..a4574740350d 100644 --- a/drivers/media/video/cpia2/cpia2_usb.c +++ b/drivers/media/video/cpia2/cpia2_usb.c @@ -84,7 +84,7 @@ static struct usb_driver cpia2_driver = { *****************************************************************************/ static void process_frame(struct camera_data *cam) { - static int frame_count = 0; + static int frame_count; unsigned char *inbuff = cam->workbuff->data; diff --git a/drivers/media/video/cx23885/cx23885-i2c.c b/drivers/media/video/cx23885/cx23885-i2c.c index 92fe0bd37c84..748c79a46549 100644 --- a/drivers/media/video/cx23885/cx23885-i2c.c +++ b/drivers/media/video/cx23885/cx23885-i2c.c @@ -33,7 +33,7 @@ static unsigned int i2c_debug; module_param(i2c_debug, int, 0644); MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); -static unsigned int i2c_scan = 0; +static unsigned int i2c_scan; module_param(i2c_scan, int, 0444); MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time"); diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index a99e9d5950aa..c37269074524 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -45,7 +45,7 @@ static unsigned int mpegbufs = 32; module_param(mpegbufs,int,0644); MODULE_PARM_DESC(mpegbufs,"number of mpeg buffers, range 2-32"); -static unsigned int debug = 0; +static unsigned int debug; module_param(debug,int,0644); MODULE_PARM_DESC(debug,"enable debug messages [blackbird]"); diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index 01e2ac98970b..12440b91e4b3 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c @@ -47,15 +47,15 @@ MODULE_LICENSE("GPL"); /* ------------------------------------------------------------------ */ -static unsigned int core_debug = 0; +static unsigned int core_debug; module_param(core_debug,int,0644); MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); -static unsigned int nicam = 0; +static unsigned int nicam; module_param(nicam,int,0644); MODULE_PARM_DESC(nicam,"tv audio is nicam"); -static unsigned int nocomb = 0; +static unsigned int nocomb; module_param(nocomb,int,0644); MODULE_PARM_DESC(nocomb,"disable comb filter"); diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index f7b41eb1bb5a..7586fe31f643 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -51,7 +51,7 @@ MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>"); MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); MODULE_LICENSE("GPL"); -static unsigned int debug = 0; +static unsigned int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug,"enable debug messages [dvb]"); diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c index 566b26af523e..c6b44732a082 100644 --- a/drivers/media/video/cx88/cx88-i2c.c +++ b/drivers/media/video/cx88/cx88-i2c.c @@ -35,11 +35,11 @@ #include "cx88.h" #include <media/v4l2-common.h> -static unsigned int i2c_debug = 0; +static unsigned int i2c_debug; module_param(i2c_debug, int, 0644); MODULE_PARM_DESC(i2c_debug,"enable debug messages [i2c]"); -static unsigned int i2c_scan = 0; +static unsigned int i2c_scan; module_param(i2c_scan, int, 0444); MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time"); diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index bb0911b4d2f6..d2e42c77b5a8 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -57,7 +57,7 @@ struct cx88_IR { u32 mask_keyup; }; -static int ir_debug = 0; +static int ir_debug; module_param(ir_debug, int, 0644); /* debug level [IR] */ MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]"); diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index e357f415db06..a02cabbab778 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/video/cx88/cx88-mpeg.c @@ -39,7 +39,7 @@ MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>"); MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); MODULE_LICENSE("GPL"); -static unsigned int debug = 0; +static unsigned int debug; module_param(debug,int,0644); MODULE_PARM_DESC(debug,"enable debug messages [mpeg]"); diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c index 76e5c78d8ae4..c574f450498f 100644 --- a/drivers/media/video/cx88/cx88-tvaudio.c +++ b/drivers/media/video/cx88/cx88-tvaudio.c @@ -53,15 +53,15 @@ #include "cx88.h" -static unsigned int audio_debug = 0; +static unsigned int audio_debug; module_param(audio_debug, int, 0644); MODULE_PARM_DESC(audio_debug, "enable debug messages [audio]"); -static unsigned int always_analog = 0; +static unsigned int always_analog; module_param(always_analog,int,0644); MODULE_PARM_DESC(always_analog,"force analog audio out"); -static unsigned int radio_deemphasis = 0; +static unsigned int radio_deemphasis; module_param(radio_deemphasis,int,0644); MODULE_PARM_DESC(radio_deemphasis, "Radio deemphasis time constant, " "0=None, 1=50us (elsewhere), 2=75us (USA)"); diff --git a/drivers/media/video/cx88/cx88-vbi.c b/drivers/media/video/cx88/cx88-vbi.c index d96ecfcf393a..0943060682bc 100644 --- a/drivers/media/video/cx88/cx88-vbi.c +++ b/drivers/media/video/cx88/cx88-vbi.c @@ -11,7 +11,7 @@ static unsigned int vbibufs = 4; module_param(vbibufs,int,0644); MODULE_PARM_DESC(vbibufs,"number of vbi buffers, range 2-32"); -static unsigned int vbi_debug = 0; +static unsigned int vbi_debug; module_param(vbi_debug,int,0644); MODULE_PARM_DESC(vbi_debug,"enable debug messages [vbi]"); diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 7f1931aed207..4f79dcd5115d 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -63,11 +63,11 @@ MODULE_PARM_DESC(video_nr,"video device numbers"); MODULE_PARM_DESC(vbi_nr,"vbi device numbers"); MODULE_PARM_DESC(radio_nr,"radio device numbers"); -static unsigned int video_debug = 0; +static unsigned int video_debug; module_param(video_debug,int,0644); MODULE_PARM_DESC(video_debug,"enable debug messages [video]"); -static unsigned int irq_debug = 0; +static unsigned int irq_debug; module_param(irq_debug,int,0644); MODULE_PARM_DESC(irq_debug,"enable debug messages [IRQ handler]"); diff --git a/drivers/media/video/dpc7146.c b/drivers/media/video/dpc7146.c index 566e479e2629..24ce5c3608ba 100644 --- a/drivers/media/video/dpc7146.c +++ b/drivers/media/video/dpc7146.c @@ -54,11 +54,11 @@ #define DPC_BOARD_CAN_DO_VBI(dev) (dev->revision != 0) -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "debug verbosity"); -static int dpc_num = 0; +static int dpc_num; #define DPC_INPUTS 2 static struct v4l2_input dpc_inputs[DPC_INPUTS] = { diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 7d1537cab867..bc06abde7a60 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -31,7 +31,7 @@ /* #define ENABLE_DEBUG_ISOC_FRAMES */ -static unsigned int core_debug = 0; +static unsigned int core_debug; module_param(core_debug,int,0644); MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); @@ -40,7 +40,7 @@ MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); printk(KERN_INFO "%s %s :"fmt, \ dev->name, __FUNCTION__ , ##arg); } while (0) -static unsigned int reg_debug = 0; +static unsigned int reg_debug; module_param(reg_debug,int,0644); MODULE_PARM_DESC(reg_debug,"enable debug messages [URB reg]"); @@ -49,7 +49,7 @@ MODULE_PARM_DESC(reg_debug,"enable debug messages [URB reg]"); printk(KERN_INFO "%s %s :"fmt, \ dev->name, __FUNCTION__ , ##arg); } while (0) -static unsigned int isoc_debug = 0; +static unsigned int isoc_debug; module_param(isoc_debug,int,0644); MODULE_PARM_DESC(isoc_debug,"enable debug messages [isoc transfers]"); diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index cacd04d46e99..c3d98d81c335 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c @@ -33,11 +33,11 @@ /* ----------------------------------------------------------- */ -static unsigned int i2c_scan = 0; +static unsigned int i2c_scan; module_param(i2c_scan, int, 0444); MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time"); -static unsigned int i2c_debug = 0; +static unsigned int i2c_debug; module_param(i2c_debug, int, 0644); MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 4abe6701a770..c8264f40aa0d 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -74,7 +74,7 @@ MODULE_PARM_DESC(video_nr, "video device numbers"); MODULE_PARM_DESC(vbi_nr, "vbi device numbers"); MODULE_PARM_DESC(radio_nr, "radio device numbers"); -static unsigned int video_debug = 0; +static unsigned int video_debug; module_param(video_debug,int,0644); MODULE_PARM_DESC(video_debug,"enable debug messages [video]"); diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c index 06b6a3ae06c4..32ebb71097b5 100644 --- a/drivers/media/video/et61x251/et61x251_core.c +++ b/drivers/media/video/et61x251/et61x251_core.c @@ -2538,7 +2538,7 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) { struct usb_device *udev = interface_to_usbdev(intf); struct et61x251_device* cam; - static unsigned int dev_nr = 0; + static unsigned int dev_nr; unsigned int i; int err = 0; diff --git a/drivers/media/video/hexium_gemini.c b/drivers/media/video/hexium_gemini.c index c7fed3405655..352f84d440fb 100644 --- a/drivers/media/video/hexium_gemini.c +++ b/drivers/media/video/hexium_gemini.c @@ -25,12 +25,12 @@ #include <media/saa7146_vv.h> -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "debug verbosity"); /* global variables */ -static int hexium_num = 0; +static int hexium_num; #define HEXIUM_GEMINI 4 #define HEXIUM_GEMINI_DUAL 5 diff --git a/drivers/media/video/hexium_orion.c b/drivers/media/video/hexium_orion.c index 137c4736da04..8d3c1482e7ea 100644 --- a/drivers/media/video/hexium_orion.c +++ b/drivers/media/video/hexium_orion.c @@ -25,12 +25,12 @@ #include <media/saa7146_vv.h> -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "debug verbosity"); /* global variables */ -static int hexium_num = 0; +static int hexium_num; #define HEXIUM_HV_PCI6_ORION 1 #define HEXIUM_ORION_1SVHS_3BNC 2 diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index 9851987b95fb..5084db22bbd3 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -51,7 +51,7 @@ static int debug; module_param(debug, int, 0644); /* debug level (0,1,2) */ -static int hauppauge = 0; +static int hauppauge; module_param(hauppauge, int, 0644); /* Choose Hauppauge remote */ MODULE_PARM_DESC(hauppauge, "Specify Hauppauge remote: 0=black, 1=grey (defaults to 0)"); diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index d42f120354e5..d24db8477cf2 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c @@ -127,11 +127,11 @@ static int dec_mpg_buffers = IVTV_DEFAULT_DEC_MPG_BUFFERS; static int dec_yuv_buffers = IVTV_DEFAULT_DEC_YUV_BUFFERS; static int dec_vbi_buffers = IVTV_DEFAULT_DEC_VBI_BUFFERS; -static int ivtv_yuv_mode = 0; -static int ivtv_yuv_threshold=-1; +static int ivtv_yuv_mode; +static int ivtv_yuv_threshold = -1; static int ivtv_pci_latency = 1; -int ivtv_debug = 0; +int ivtv_debug; static int newi2c = -1; diff --git a/drivers/media/video/ivtv/ivtv-yuv.c b/drivers/media/video/ivtv/ivtv-yuv.c index 85183480a225..8fdd67cef74c 100644 --- a/drivers/media/video/ivtv/ivtv-yuv.c +++ b/drivers/media/video/ivtv/ivtv-yuv.c @@ -914,7 +914,7 @@ static void ivtv_yuv_init(struct ivtv *itv) } /* Get next available yuv buffer on PVR350 */ -void ivtv_yuv_next_free(struct ivtv *itv) +static void ivtv_yuv_next_free(struct ivtv *itv) { int draw, display; struct yuv_playback_info *yi = &itv->yuv_info; @@ -937,7 +937,7 @@ void ivtv_yuv_next_free(struct ivtv *itv) } /* Set up frame according to ivtv_dma_frame parameters */ -void ivtv_yuv_setup_frame(struct ivtv *itv, struct ivtv_dma_frame *args) +static void ivtv_yuv_setup_frame(struct ivtv *itv, struct ivtv_dma_frame *args) { struct yuv_playback_info *yi = &itv->yuv_info; u8 frame = yi->draw_frame; @@ -1042,7 +1042,7 @@ void ivtv_yuv_frame_complete(struct ivtv *itv) (itv->yuv_info.draw_frame + 1) % IVTV_YUV_BUFFERS); } -int ivtv_yuv_udma_frame(struct ivtv *itv, struct ivtv_dma_frame *args) +static int ivtv_yuv_udma_frame(struct ivtv *itv, struct ivtv_dma_frame *args) { DEFINE_WAIT(wait); int rc = 0; diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c index 3d51fa0a52b6..caa9a7ac6184 100644 --- a/drivers/media/video/meye.c +++ b/drivers/media/video/meye.c @@ -789,7 +789,7 @@ static irqreturn_t meye_irq(int irq, void *dev_id) { u32 v; int reqnr; - static int sequence = 0; + static int sequence; v = mchip_read(MCHIP_MM_INTA); @@ -1239,6 +1239,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, c->default_value = 48; c->flags = 0; break; + case V4L2_CID_MEYE_SHARPNESS: case V4L2_CID_SHARPNESS: c->type = V4L2_CTRL_TYPE_INTEGER; strcpy(c->name, "Sharpness"); @@ -1246,7 +1247,12 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, c->maximum = 63; c->step = 1; c->default_value = 32; - c->flags = 0; + + /* Continue to report legacy private SHARPNESS ctrl but + * say it is disabled in preference to ctrl in the spec + */ + c->flags = (c->id == V4L2_CID_SHARPNESS) ? 0 : + V4L2_CTRL_FLAG_DISABLED; break; case V4L2_CID_PICTURE: c->type = V4L2_CTRL_TYPE_INTEGER; @@ -1312,6 +1318,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, meye.params.agc = c->value; break; case V4L2_CID_SHARPNESS: + case V4L2_CID_MEYE_SHARPNESS: sony_pic_camera_command( SONY_PIC_COMMAND_SETCAMERASHARPNESS, c->value); meye.params.sharpness = c->value; @@ -1356,6 +1363,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, c->value = meye.params.agc; break; case V4L2_CID_SHARPNESS: + case V4L2_CID_MEYE_SHARPNESS: c->value = meye.params.sharpness; break; case V4L2_CID_PICTURE: diff --git a/drivers/media/video/mt20xx.c b/drivers/media/video/mt20xx.c index 58bab653330f..fdfebc22e533 100644 --- a/drivers/media/video/mt20xx.c +++ b/drivers/media/video/mt20xx.c @@ -10,12 +10,10 @@ #include "tuner-i2c.h" #include "mt20xx.h" -static int debug = 0; +static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); -#define PREFIX "mt20xx" - /* ---------------------------------------------------------------------- */ static unsigned int optimize_vco = 1; @@ -24,7 +22,7 @@ module_param(optimize_vco, int, 0644); static unsigned int tv_antenna = 1; module_param(tv_antenna, int, 0644); -static unsigned int radio_antenna = 0; +static unsigned int radio_antenna; module_param(radio_antenna, int, 0644); /* ---------------------------------------------------------------------- */ @@ -611,6 +609,7 @@ struct dvb_frontend *microtune_attach(struct dvb_frontend *fe, priv->i2c_props.addr = i2c_addr; priv->i2c_props.adap = i2c_adap; + priv->i2c_props.name = "mt20xx"; //priv->radio_if2 = 10700 * 1000; /* 10.7MHz - FM radio */ diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c new file mode 100644 index 000000000000..e3afc82050af --- /dev/null +++ b/drivers/media/video/mt9m001.c @@ -0,0 +1,692 @@ +/* + * Driver for MT9M001 CMOS Image Sensor from Micron + * + * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de> + * + * 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 <linux/videodev2.h> +#include <linux/slab.h> +#include <linux/i2c.h> +#include <linux/log2.h> + +#include <media/v4l2-common.h> +#include <media/v4l2-chip-ident.h> +#include <media/soc_camera.h> + +#ifdef CONFIG_MT9M001_PCA9536_SWITCH +#include <asm/gpio.h> +#endif + +/* mt9m001 i2c address 0x5d + * The platform has to define i2c_board_info + * and call i2c_register_board_info() */ + +/* mt9m001 selected register addresses */ +#define MT9M001_CHIP_VERSION 0x00 +#define MT9M001_ROW_START 0x01 +#define MT9M001_COLUMN_START 0x02 +#define MT9M001_WINDOW_HEIGHT 0x03 +#define MT9M001_WINDOW_WIDTH 0x04 +#define MT9M001_HORIZONTAL_BLANKING 0x05 +#define MT9M001_VERTICAL_BLANKING 0x06 +#define MT9M001_OUTPUT_CONTROL 0x07 +#define MT9M001_SHUTTER_WIDTH 0x09 +#define MT9M001_FRAME_RESTART 0x0b +#define MT9M001_SHUTTER_DELAY 0x0c +#define MT9M001_RESET 0x0d +#define MT9M001_READ_OPTIONS1 0x1e +#define MT9M001_READ_OPTIONS2 0x20 +#define MT9M001_GLOBAL_GAIN 0x35 +#define MT9M001_CHIP_ENABLE 0xF1 + +static const struct soc_camera_data_format mt9m001_colour_formats[] = { + { + .name = "RGB Bayer (sRGB)", + .depth = 16, + .fourcc = V4L2_PIX_FMT_SBGGR8, + .colorspace = V4L2_COLORSPACE_SRGB, + } +}; + +static const struct soc_camera_data_format mt9m001_monochrome_formats[] = { + { + .name = "Monochrome 10 bit", + .depth = 10, + .fourcc = V4L2_PIX_FMT_Y16, + }, { + .name = "Monochrome 8 bit", + .depth = 8, + .fourcc = V4L2_PIX_FMT_GREY, + }, +}; + +struct mt9m001 { + struct i2c_client *client; + struct soc_camera_device icd; + int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */ + int switch_gpio; + unsigned char autoexposure; + unsigned char datawidth; +}; + +static int reg_read(struct soc_camera_device *icd, const u8 reg) +{ + struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + struct i2c_client *client = mt9m001->client; + s32 data = i2c_smbus_read_word_data(client, reg); + return data < 0 ? data : swab16(data); +} + +static int reg_write(struct soc_camera_device *icd, const u8 reg, + const u16 data) +{ + struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + return i2c_smbus_write_word_data(mt9m001->client, reg, swab16(data)); +} + +static int reg_set(struct soc_camera_device *icd, const u8 reg, + const u16 data) +{ + int ret; + + ret = reg_read(icd, reg); + if (ret < 0) + return ret; + return reg_write(icd, reg, ret | data); +} + +static int reg_clear(struct soc_camera_device *icd, const u8 reg, + const u16 data) +{ + int ret; + + ret = reg_read(icd, reg); + if (ret < 0) + return ret; + return reg_write(icd, reg, ret & ~data); +} + +static int mt9m001_init(struct soc_camera_device *icd) +{ + int ret; + + /* Disable chip, synchronous option update */ + dev_dbg(icd->vdev->dev, "%s\n", __FUNCTION__); + + ret = reg_write(icd, MT9M001_RESET, 1); + if (ret >= 0) + ret = reg_write(icd, MT9M001_RESET, 0); + if (ret >= 0) + ret = reg_write(icd, MT9M001_OUTPUT_CONTROL, 0); + + return ret >= 0 ? 0 : -EIO; +} + +static int mt9m001_release(struct soc_camera_device *icd) +{ + /* Disable the chip */ + reg_write(icd, MT9M001_OUTPUT_CONTROL, 0); + return 0; +} + +static int mt9m001_start_capture(struct soc_camera_device *icd) +{ + /* Switch to master "normal" mode */ + if (reg_write(icd, MT9M001_OUTPUT_CONTROL, 2) < 0) + return -EIO; + return 0; +} + +static int mt9m001_stop_capture(struct soc_camera_device *icd) +{ + /* Stop sensor readout */ + if (reg_write(icd, MT9M001_OUTPUT_CONTROL, 0) < 0) + return -EIO; + return 0; +} + +static int bus_switch_request(struct mt9m001 *mt9m001, + struct soc_camera_link *icl) +{ +#ifdef CONFIG_MT9M001_PCA9536_SWITCH + int ret; + unsigned int gpio = icl->gpio; + + if (gpio_is_valid(gpio)) { + /* We have a data bus switch. */ + ret = gpio_request(gpio, "mt9m001"); + if (ret < 0) { + dev_err(&mt9m001->client->dev, "Cannot get GPIO %u\n", + gpio); + return ret; + } + + ret = gpio_direction_output(gpio, 0); + if (ret < 0) { + dev_err(&mt9m001->client->dev, + "Cannot set GPIO %u to output\n", gpio); + gpio_free(gpio); + return ret; + } + } + + mt9m001->switch_gpio = gpio; +#else + mt9m001->switch_gpio = -EINVAL; +#endif + return 0; +} + +static void bus_switch_release(struct mt9m001 *mt9m001) +{ +#ifdef CONFIG_MT9M001_PCA9536_SWITCH + if (gpio_is_valid(mt9m001->switch_gpio)) + gpio_free(mt9m001->switch_gpio); +#endif +} + +static int bus_switch_act(struct mt9m001 *mt9m001, int go8bit) +{ +#ifdef CONFIG_MT9M001_PCA9536_SWITCH + if (!gpio_is_valid(mt9m001->switch_gpio)) + return -ENODEV; + + gpio_set_value_cansleep(mt9m001->switch_gpio, go8bit); + return 0; +#else + return -ENODEV; +#endif +} + +static int mt9m001_set_capture_format(struct soc_camera_device *icd, + __u32 pixfmt, struct v4l2_rect *rect, unsigned int flags) +{ + struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + unsigned int width_flag = flags & (IS_DATAWIDTH_10 | IS_DATAWIDTH_9 | + IS_DATAWIDTH_8); + int ret; + const u16 hblank = 9, vblank = 25; + + /* MT9M001 has all capture_format parameters fixed */ + if (!(flags & IS_MASTER) || + !(flags & IS_PCLK_SAMPLE_RISING) || + !(flags & IS_HSYNC_ACTIVE_HIGH) || + !(flags & IS_VSYNC_ACTIVE_HIGH)) + return -EINVAL; + + /* Only one width bit may be set */ + if (!is_power_of_2(width_flag)) + return -EINVAL; + + if ((mt9m001->datawidth != 10 && (width_flag == IS_DATAWIDTH_10)) || + (mt9m001->datawidth != 9 && (width_flag == IS_DATAWIDTH_9)) || + (mt9m001->datawidth != 8 && (width_flag == IS_DATAWIDTH_8))) { + /* Well, we actually only can do 10 or 8 bits... */ + if (width_flag == IS_DATAWIDTH_9) + return -EINVAL; + ret = bus_switch_act(mt9m001, + width_flag == IS_DATAWIDTH_8); + if (ret < 0) + return ret; + + mt9m001->datawidth = width_flag == IS_DATAWIDTH_8 ? 8 : 10; + } + + /* Blanking and start values - default... */ + ret = reg_write(icd, MT9M001_HORIZONTAL_BLANKING, hblank); + if (ret >= 0) + ret = reg_write(icd, MT9M001_VERTICAL_BLANKING, vblank); + + /* The caller provides a supported format, as verified per + * call to icd->try_fmt_cap() */ + if (ret >= 0) + ret = reg_write(icd, MT9M001_COLUMN_START, rect->left); + if (ret >= 0) + ret = reg_write(icd, MT9M001_ROW_START, rect->top); + if (ret >= 0) + ret = reg_write(icd, MT9M001_WINDOW_WIDTH, rect->width - 1); + if (ret >= 0) + ret = reg_write(icd, MT9M001_WINDOW_HEIGHT, + rect->height + icd->y_skip_top - 1); + if (ret >= 0 && mt9m001->autoexposure) { + ret = reg_write(icd, MT9M001_SHUTTER_WIDTH, + rect->height + icd->y_skip_top + vblank); + if (ret >= 0) { + const struct v4l2_queryctrl *qctrl = + soc_camera_find_qctrl(icd->ops, + V4L2_CID_EXPOSURE); + icd->exposure = (524 + (rect->height + icd->y_skip_top + + vblank - 1) * + (qctrl->maximum - qctrl->minimum)) / + 1048 + qctrl->minimum; + } + } + + return ret < 0 ? ret : 0; +} + +static int mt9m001_try_fmt_cap(struct soc_camera_device *icd, + struct v4l2_format *f) +{ + if (f->fmt.pix.height < 32 + icd->y_skip_top) + f->fmt.pix.height = 32 + icd->y_skip_top; + if (f->fmt.pix.height > 1024 + icd->y_skip_top) + f->fmt.pix.height = 1024 + icd->y_skip_top; + if (f->fmt.pix.width < 48) + f->fmt.pix.width = 48; + if (f->fmt.pix.width > 1280) + f->fmt.pix.width = 1280; + f->fmt.pix.width &= ~0x01; /* has to be even, unsure why was ~3 */ + + return 0; +} + +static int mt9m001_get_chip_id(struct soc_camera_device *icd, + struct v4l2_chip_ident *id) +{ + struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + + if (id->match_type != V4L2_CHIP_MATCH_I2C_ADDR) + return -EINVAL; + + if (id->match_chip != mt9m001->client->addr) + return -ENODEV; + + id->ident = mt9m001->model; + id->revision = 0; + + return 0; +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int mt9m001_get_register(struct soc_camera_device *icd, + struct v4l2_register *reg) +{ + struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + + if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) + return -EINVAL; + + if (reg->match_chip != mt9m001->client->addr) + return -ENODEV; + + reg->val = reg_read(icd, reg->reg); + + if (reg->val > 0xffff) + return -EIO; + + return 0; +} + +static int mt9m001_set_register(struct soc_camera_device *icd, + struct v4l2_register *reg) +{ + struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + + if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) + return -EINVAL; + + if (reg->match_chip != mt9m001->client->addr) + return -ENODEV; + + if (reg_write(icd, reg->reg, reg->val) < 0) + return -EIO; + + return 0; +} +#endif + +static unsigned int mt9m001_get_datawidth(struct soc_camera_device *icd) +{ + struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + return mt9m001->datawidth; +} + +const struct v4l2_queryctrl mt9m001_controls[] = { + { + .id = V4L2_CID_VFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Flip Vertically", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + }, { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Gain", + .minimum = 0, + .maximum = 127, + .step = 1, + .default_value = 64, + .flags = V4L2_CTRL_FLAG_SLIDER, + }, { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Exposure", + .minimum = 1, + .maximum = 255, + .step = 1, + .default_value = 255, + .flags = V4L2_CTRL_FLAG_SLIDER, + }, { + .id = V4L2_CID_EXPOSURE_AUTO, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Automatic Exposure", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 1, + } +}; + +static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl); +static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl); + +static struct soc_camera_ops mt9m001_ops = { + .owner = THIS_MODULE, + .init = mt9m001_init, + .release = mt9m001_release, + .start_capture = mt9m001_start_capture, + .stop_capture = mt9m001_stop_capture, + .set_capture_format = mt9m001_set_capture_format, + .try_fmt_cap = mt9m001_try_fmt_cap, + .formats = NULL, /* Filled in later depending on the */ + .num_formats = 0, /* camera type and data widths */ + .get_datawidth = mt9m001_get_datawidth, + .controls = mt9m001_controls, + .num_controls = ARRAY_SIZE(mt9m001_controls), + .get_control = mt9m001_get_control, + .set_control = mt9m001_set_control, + .get_chip_id = mt9m001_get_chip_id, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .get_register = mt9m001_get_register, + .set_register = mt9m001_set_register, +#endif +}; + +static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) +{ + struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + int data; + + switch (ctrl->id) { + case V4L2_CID_VFLIP: + data = reg_read(icd, MT9M001_READ_OPTIONS2); + if (data < 0) + return -EIO; + ctrl->value = !!(data & 0x8000); + break; + case V4L2_CID_EXPOSURE_AUTO: + ctrl->value = mt9m001->autoexposure; + break; + } + return 0; +} + +static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) +{ + struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + const struct v4l2_queryctrl *qctrl; + int data; + + qctrl = soc_camera_find_qctrl(&mt9m001_ops, ctrl->id); + + if (!qctrl) + return -EINVAL; + + switch (ctrl->id) { + case V4L2_CID_VFLIP: + if (ctrl->value) + data = reg_set(icd, MT9M001_READ_OPTIONS2, 0x8000); + else + data = reg_clear(icd, MT9M001_READ_OPTIONS2, 0x8000); + if (data < 0) + return -EIO; + break; + case V4L2_CID_GAIN: + if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum) + return -EINVAL; + /* See Datasheet Table 7, Gain settings. */ + if (ctrl->value <= qctrl->default_value) { + /* Pack it into 0..1 step 0.125, register values 0..8 */ + unsigned long range = qctrl->default_value - qctrl->minimum; + data = ((ctrl->value - qctrl->minimum) * 8 + range / 2) / range; + + dev_dbg(&icd->dev, "Setting gain %d\n", data); + data = reg_write(icd, MT9M001_GLOBAL_GAIN, data); + if (data < 0) + return -EIO; + } else { + /* Pack it into 1.125..15 variable step, register values 9..67 */ + /* We assume qctrl->maximum - qctrl->default_value - 1 > 0 */ + unsigned long range = qctrl->maximum - qctrl->default_value - 1; + unsigned long gain = ((ctrl->value - qctrl->default_value - 1) * + 111 + range / 2) / range + 9; + + if (gain <= 32) + data = gain; + else if (gain <= 64) + data = ((gain - 32) * 16 + 16) / 32 + 80; + else + data = ((gain - 64) * 7 + 28) / 56 + 96; + + dev_dbg(&icd->dev, "Setting gain from %d to %d\n", + reg_read(icd, MT9M001_GLOBAL_GAIN), data); + data = reg_write(icd, MT9M001_GLOBAL_GAIN, data); + if (data < 0) + return -EIO; + } + + /* Success */ + icd->gain = ctrl->value; + break; + case V4L2_CID_EXPOSURE: + /* mt9m001 has maximum == default */ + if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum) + return -EINVAL; + else { + unsigned long range = qctrl->maximum - qctrl->minimum; + unsigned long shutter = ((ctrl->value - qctrl->minimum) * 1048 + + range / 2) / range + 1; + + dev_dbg(&icd->dev, "Setting shutter width from %d to %lu\n", + reg_read(icd, MT9M001_SHUTTER_WIDTH), shutter); + if (reg_write(icd, MT9M001_SHUTTER_WIDTH, shutter) < 0) + return -EIO; + icd->exposure = ctrl->value; + mt9m001->autoexposure = 0; + } + break; + case V4L2_CID_EXPOSURE_AUTO: + if (ctrl->value) { + const u16 vblank = 25; + if (reg_write(icd, MT9M001_SHUTTER_WIDTH, icd->height + + icd->y_skip_top + vblank) < 0) + return -EIO; + qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); + icd->exposure = (524 + (icd->height + icd->y_skip_top + vblank - 1) * + (qctrl->maximum - qctrl->minimum)) / + 1048 + qctrl->minimum; + mt9m001->autoexposure = 1; + } else + mt9m001->autoexposure = 0; + break; + } + return 0; +} + +/* 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 */ +static int mt9m001_video_probe(struct soc_camera_device *icd) +{ + struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + s32 data; + int ret; + + /* We must have a parent by now. And it cannot be a wrong one. + * So this entire test is completely redundant. */ + if (!icd->dev.parent || + to_soc_camera_host(icd->dev.parent)->nr != icd->iface) + return -ENODEV; + + /* Enable the chip */ + data = reg_write(&mt9m001->icd, MT9M001_CHIP_ENABLE, 1); + dev_dbg(&icd->dev, "write: %d\n", data); + + /* Read out the chip version register */ + data = reg_read(icd, MT9M001_CHIP_VERSION); + + /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */ + switch (data) { + case 0x8411: + case 0x8421: + mt9m001->model = V4L2_IDENT_MT9M001C12ST; + mt9m001_ops.formats = mt9m001_colour_formats; + mt9m001_ops.num_formats = ARRAY_SIZE(mt9m001_colour_formats); + break; + case 0x8431: + mt9m001->model = V4L2_IDENT_MT9M001C12STM; + mt9m001_ops.formats = mt9m001_monochrome_formats; + if (mt9m001->client->dev.platform_data) + mt9m001_ops.num_formats = ARRAY_SIZE(mt9m001_monochrome_formats); + else + mt9m001_ops.num_formats = 1; + break; + default: + ret = -ENODEV; + dev_err(&icd->dev, + "No MT9M001 chip detected, register read %x\n", data); + goto ei2c; + } + + dev_info(&icd->dev, "Detected a MT9M001 chip ID %x (%s)\n", data, + data == 0x8431 ? "C12STM" : "C12ST"); + + /* Now that we know the model, we can start video */ + ret = soc_camera_video_start(icd); + if (ret) + goto eisis; + + return 0; + +eisis: +ei2c: + return ret; +} + +static void mt9m001_video_remove(struct soc_camera_device *icd) +{ + struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + + dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9m001->client->addr, + mt9m001->icd.dev.parent, mt9m001->icd.vdev); + soc_camera_video_stop(&mt9m001->icd); +} + +static int mt9m001_probe(struct i2c_client *client) +{ + struct mt9m001 *mt9m001; + struct soc_camera_device *icd; + struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); + struct soc_camera_link *icl = client->dev.platform_data; + int ret; + + if (!icl) { + dev_err(&client->dev, "MT9M001 driver needs platform data\n"); + return -EINVAL; + } + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) { + dev_warn(&adapter->dev, + "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n"); + return -EIO; + } + + mt9m001 = kzalloc(sizeof(struct mt9m001), GFP_KERNEL); + if (!mt9m001) + return -ENOMEM; + + mt9m001->client = client; + i2c_set_clientdata(client, mt9m001); + + /* Second stage probe - when a capture adapter is there */ + icd = &mt9m001->icd; + icd->probe = mt9m001_video_probe; + icd->remove = mt9m001_video_remove; + icd->ops = &mt9m001_ops; + icd->control = &client->dev; + icd->x_min = 20; + icd->y_min = 12; + icd->x_current = 20; + icd->y_current = 12; + icd->width_min = 48; + icd->width_max = 1280; + icd->height_min = 32; + icd->height_max = 1024; + icd->y_skip_top = 1; + icd->iface = icl->bus_id; + /* Default datawidth - this is the only width this camera (normally) + * supports. It is only with extra logic that it can support + * other widths. Therefore it seems to be a sensible default. */ + mt9m001->datawidth = 10; + /* Simulated autoexposure. If enabled, we calculate shutter width + * ourselves in the driver based on vertical blanking and frame width */ + mt9m001->autoexposure = 1; + + ret = bus_switch_request(mt9m001, icl); + if (ret) + goto eswinit; + + ret = soc_camera_device_register(icd); + if (ret) + goto eisdr; + + return 0; + +eisdr: + bus_switch_release(mt9m001); +eswinit: + kfree(mt9m001); + return ret; +} + +static int mt9m001_remove(struct i2c_client *client) +{ + struct mt9m001 *mt9m001 = i2c_get_clientdata(client); + + soc_camera_device_unregister(&mt9m001->icd); + bus_switch_release(mt9m001); + kfree(mt9m001); + + return 0; +} + +static struct i2c_driver mt9m001_i2c_driver = { + .driver = { + .name = "mt9m001", + }, + .probe = mt9m001_probe, + .remove = mt9m001_remove, +}; + +static int __init mt9m001_mod_init(void) +{ + return i2c_add_driver(&mt9m001_i2c_driver); +} + +static void __exit mt9m001_mod_exit(void) +{ + i2c_del_driver(&mt9m001_i2c_driver); +} + +module_init(mt9m001_mod_init); +module_exit(mt9m001_mod_exit); + +MODULE_DESCRIPTION("Micron MT9M001 Camera driver"); +MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c new file mode 100644 index 000000000000..468333946d57 --- /dev/null +++ b/drivers/media/video/mt9v022.c @@ -0,0 +1,802 @@ +/* + * Driver for MT9V022 CMOS Image Sensor from Micron + * + * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de> + * + * 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 <linux/videodev2.h> +#include <linux/slab.h> +#include <linux/i2c.h> +#include <linux/delay.h> +#include <linux/log2.h> + +#include <media/v4l2-common.h> +#include <media/v4l2-chip-ident.h> +#include <media/soc_camera.h> + +#ifdef CONFIG_MT9M001_PCA9536_SWITCH +#include <asm/gpio.h> +#endif + +/* mt9v022 i2c address 0x48, 0x4c, 0x58, 0x5c + * The platform has to define i2c_board_info + * and call i2c_register_board_info() */ + +static char *sensor_type; +module_param(sensor_type, charp, S_IRUGO); +MODULE_PARM_DESC(sensor_type, "Sensor type: \"colour\" or \"monochrome\"\n"); + +/* mt9v022 selected register addresses */ +#define MT9V022_CHIP_VERSION 0x00 +#define MT9V022_COLUMN_START 0x01 +#define MT9V022_ROW_START 0x02 +#define MT9V022_WINDOW_HEIGHT 0x03 +#define MT9V022_WINDOW_WIDTH 0x04 +#define MT9V022_HORIZONTAL_BLANKING 0x05 +#define MT9V022_VERTICAL_BLANKING 0x06 +#define MT9V022_CHIP_CONTROL 0x07 +#define MT9V022_SHUTTER_WIDTH1 0x08 +#define MT9V022_SHUTTER_WIDTH2 0x09 +#define MT9V022_SHUTTER_WIDTH_CTRL 0x0a +#define MT9V022_TOTAL_SHUTTER_WIDTH 0x0b +#define MT9V022_RESET 0x0c +#define MT9V022_READ_MODE 0x0d +#define MT9V022_MONITOR_MODE 0x0e +#define MT9V022_PIXEL_OPERATION_MODE 0x0f +#define MT9V022_LED_OUT_CONTROL 0x1b +#define MT9V022_ADC_MODE_CONTROL 0x1c +#define MT9V022_ANALOG_GAIN 0x34 +#define MT9V022_BLACK_LEVEL_CALIB_CTRL 0x47 +#define MT9V022_PIXCLK_FV_LV 0x74 +#define MT9V022_DIGITAL_TEST_PATTERN 0x7f +#define MT9V022_AEC_AGC_ENABLE 0xAF +#define MT9V022_MAX_TOTAL_SHUTTER_WIDTH 0xBD + +/* Progressive scan, master, defaults */ +#define MT9V022_CHIP_CONTROL_DEFAULT 0x188 + +static const struct soc_camera_data_format mt9v022_formats[] = { + { + .name = "RGB Bayer (sRGB)", + .depth = 8, + .fourcc = V4L2_PIX_FMT_SBGGR8, + .colorspace = V4L2_COLORSPACE_SRGB, + }, { + .name = "RGB Bayer (sRGB)", + .depth = 10, + .fourcc = V4L2_PIX_FMT_SBGGR16, + .colorspace = V4L2_COLORSPACE_SRGB, + }, { + .name = "Monochrome 10 bit", + .depth = 10, + .fourcc = V4L2_PIX_FMT_Y16, + }, { + .name = "Monochrome 8 bit", + .depth = 8, + .fourcc = V4L2_PIX_FMT_GREY, + }, +}; + +struct mt9v022 { + struct i2c_client *client; + struct soc_camera_device icd; + int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */ + int switch_gpio; + u16 chip_control; + unsigned char datawidth; +}; + +static int reg_read(struct soc_camera_device *icd, const u8 reg) +{ + struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + struct i2c_client *client = mt9v022->client; + s32 data = i2c_smbus_read_word_data(client, reg); + return data < 0 ? data : swab16(data); +} + +static int reg_write(struct soc_camera_device *icd, const u8 reg, + const u16 data) +{ + struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + return i2c_smbus_write_word_data(mt9v022->client, reg, swab16(data)); +} + +static int reg_set(struct soc_camera_device *icd, const u8 reg, + const u16 data) +{ + int ret; + + ret = reg_read(icd, reg); + if (ret < 0) + return ret; + return reg_write(icd, reg, ret | data); +} + +static int reg_clear(struct soc_camera_device *icd, const u8 reg, + const u16 data) +{ + int ret; + + ret = reg_read(icd, reg); + if (ret < 0) + return ret; + return reg_write(icd, reg, ret & ~data); +} + +static int mt9v022_init(struct soc_camera_device *icd) +{ + struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + int ret; + + /* Almost the default mode: master, parallel, simultaneous, and an + * undocumented bit 0x200, which is present in table 7, but not in 8, + * plus snapshot mode to disable scan for now */ + mt9v022->chip_control |= 0x10; + ret = reg_write(icd, MT9V022_CHIP_CONTROL, mt9v022->chip_control); + if (ret >= 0) + reg_write(icd, MT9V022_READ_MODE, 0x300); + + /* All defaults */ + if (ret >= 0) + /* AEC, AGC on */ + ret = reg_set(icd, MT9V022_AEC_AGC_ENABLE, 0x3); + if (ret >= 0) + ret = reg_write(icd, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, 480); + if (ret >= 0) + /* default - auto */ + ret = reg_clear(icd, MT9V022_BLACK_LEVEL_CALIB_CTRL, 1); + if (ret >= 0) + ret = reg_write(icd, MT9V022_DIGITAL_TEST_PATTERN, 0); + + return ret >= 0 ? 0 : -EIO; +} + +static int mt9v022_release(struct soc_camera_device *icd) +{ + /* Nothing? */ + return 0; +} + +static int mt9v022_start_capture(struct soc_camera_device *icd) +{ + struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + /* Switch to master "normal" mode */ + mt9v022->chip_control &= ~0x10; + if (reg_write(icd, MT9V022_CHIP_CONTROL, + mt9v022->chip_control) < 0) + return -EIO; + return 0; +} + +static int mt9v022_stop_capture(struct soc_camera_device *icd) +{ + struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + /* Switch to snapshot mode */ + mt9v022->chip_control |= 0x10; + if (reg_write(icd, MT9V022_CHIP_CONTROL, + mt9v022->chip_control) < 0) + return -EIO; + return 0; +} + +static int bus_switch_request(struct mt9v022 *mt9v022, struct soc_camera_link *icl) +{ +#ifdef CONFIG_MT9V022_PCA9536_SWITCH + int ret; + unsigned int gpio = icl->gpio; + + if (gpio_is_valid(gpio)) { + /* We have a data bus switch. */ + ret = gpio_request(gpio, "mt9v022"); + if (ret < 0) { + dev_err(&mt9v022->client->dev, "Cannot get GPIO %u\n", gpio); + return ret; + } + + ret = gpio_direction_output(gpio, 0); + if (ret < 0) { + dev_err(&mt9v022->client->dev, + "Cannot set GPIO %u to output\n", gpio); + gpio_free(gpio); + return ret; + } + } + + mt9v022->switch_gpio = gpio; +#else + mt9v022->switch_gpio = -EINVAL; +#endif + return 0; +} + +static void bus_switch_release(struct mt9v022 *mt9v022) +{ +#ifdef CONFIG_MT9V022_PCA9536_SWITCH + if (gpio_is_valid(mt9v022->switch_gpio)) + gpio_free(mt9v022->switch_gpio); +#endif +} + +static int bus_switch_act(struct mt9v022 *mt9v022, int go8bit) +{ +#ifdef CONFIG_MT9V022_PCA9536_SWITCH + if (!gpio_is_valid(mt9v022->switch_gpio)) + return -ENODEV; + + gpio_set_value_cansleep(mt9v022->switch_gpio, go8bit); + return 0; +#else + return -ENODEV; +#endif +} + +static int mt9v022_set_capture_format(struct soc_camera_device *icd, + __u32 pixfmt, struct v4l2_rect *rect, unsigned int flags) +{ + struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + unsigned int width_flag = flags & (IS_DATAWIDTH_10 | IS_DATAWIDTH_9 | + IS_DATAWIDTH_8); + u16 pixclk = 0; + int ret; + + /* Only one width bit may be set */ + if (!is_power_of_2(width_flag)) + return -EINVAL; + + /* The caller provides a supported format, as verified per call to + * icd->try_fmt_cap(), datawidth is from our supported format list */ + switch (pixfmt) { + case V4L2_PIX_FMT_GREY: + case V4L2_PIX_FMT_Y16: + if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATM) + return -EINVAL; + break; + case V4L2_PIX_FMT_SBGGR8: + case V4L2_PIX_FMT_SBGGR16: + if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATC) + return -EINVAL; + break; + case 0: + /* No format change, only geometry */ + break; + default: + return -EINVAL; + } + + /* Like in example app. Contradicts the datasheet though */ + ret = reg_read(icd, MT9V022_AEC_AGC_ENABLE); + if (ret >= 0) { + if (ret & 1) /* Autoexposure */ + ret = reg_write(icd, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, + rect->height + icd->y_skip_top + 43); + else + ret = reg_write(icd, MT9V022_TOTAL_SHUTTER_WIDTH, + rect->height + icd->y_skip_top + 43); + } + /* Setup frame format: defaults apart from width and height */ + if (ret >= 0) + ret = reg_write(icd, MT9V022_COLUMN_START, rect->left); + if (ret >= 0) + ret = reg_write(icd, MT9V022_ROW_START, rect->top); + if (ret >= 0) + /* Default 94, Phytec driver says: + * "width + horizontal blank >= 660" */ + ret = reg_write(icd, MT9V022_HORIZONTAL_BLANKING, + rect->width > 660 - 43 ? 43 : + 660 - rect->width); + if (ret >= 0) + ret = reg_write(icd, MT9V022_VERTICAL_BLANKING, 45); + if (ret >= 0) + ret = reg_write(icd, MT9V022_WINDOW_WIDTH, rect->width); + if (ret >= 0) + ret = reg_write(icd, MT9V022_WINDOW_HEIGHT, + rect->height + icd->y_skip_top); + + if (ret < 0) + return ret; + + dev_dbg(&icd->dev, "Frame %ux%u pixel\n", rect->width, rect->height); + + if ((mt9v022->datawidth != 10 && (width_flag == IS_DATAWIDTH_10)) || + (mt9v022->datawidth != 9 && (width_flag == IS_DATAWIDTH_9)) || + (mt9v022->datawidth != 8 && (width_flag == IS_DATAWIDTH_8))) { + /* Well, we actually only can do 10 or 8 bits... */ + if (width_flag == IS_DATAWIDTH_9) + return -EINVAL; + + ret = bus_switch_act(mt9v022, + width_flag == IS_DATAWIDTH_8); + if (ret < 0) + return ret; + + mt9v022->datawidth = width_flag == IS_DATAWIDTH_8 ? 8 : 10; + } + + if (flags & IS_PCLK_SAMPLE_RISING) + pixclk |= 0x10; + + if (!(flags & IS_HSYNC_ACTIVE_HIGH)) + pixclk |= 0x1; + + if (!(flags & IS_VSYNC_ACTIVE_HIGH)) + pixclk |= 0x2; + + ret = reg_write(icd, MT9V022_PIXCLK_FV_LV, pixclk); + if (ret < 0) + return ret; + + if (!(flags & IS_MASTER)) + mt9v022->chip_control &= ~0x8; + + ret = reg_write(icd, MT9V022_CHIP_CONTROL, mt9v022->chip_control); + if (ret < 0) + return ret; + + dev_dbg(&icd->dev, "Calculated pixclk 0x%x, chip control 0x%x\n", + pixclk, mt9v022->chip_control); + + return 0; +} + +static int mt9v022_try_fmt_cap(struct soc_camera_device *icd, + struct v4l2_format *f) +{ + if (f->fmt.pix.height < 32 + icd->y_skip_top) + f->fmt.pix.height = 32 + icd->y_skip_top; + if (f->fmt.pix.height > 480 + icd->y_skip_top) + f->fmt.pix.height = 480 + icd->y_skip_top; + if (f->fmt.pix.width < 48) + f->fmt.pix.width = 48; + if (f->fmt.pix.width > 752) + f->fmt.pix.width = 752; + f->fmt.pix.width &= ~0x03; /* ? */ + + return 0; +} + +static int mt9v022_get_chip_id(struct soc_camera_device *icd, + struct v4l2_chip_ident *id) +{ + struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + + if (id->match_type != V4L2_CHIP_MATCH_I2C_ADDR) + return -EINVAL; + + if (id->match_chip != mt9v022->client->addr) + return -ENODEV; + + id->ident = mt9v022->model; + id->revision = 0; + + return 0; +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int mt9v022_get_register(struct soc_camera_device *icd, + struct v4l2_register *reg) +{ + struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + + if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) + return -EINVAL; + + if (reg->match_chip != mt9v022->client->addr) + return -ENODEV; + + reg->val = reg_read(icd, reg->reg); + + if (reg->val > 0xffff) + return -EIO; + + return 0; +} + +static int mt9v022_set_register(struct soc_camera_device *icd, + struct v4l2_register *reg) +{ + struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + + if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) + return -EINVAL; + + if (reg->match_chip != mt9v022->client->addr) + return -ENODEV; + + if (reg_write(icd, reg->reg, reg->val) < 0) + return -EIO; + + return 0; +} +#endif + +static unsigned int mt9v022_get_datawidth(struct soc_camera_device *icd) +{ + struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + return mt9v022->datawidth; +} + +const struct v4l2_queryctrl mt9v022_controls[] = { + { + .id = V4L2_CID_VFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Flip Vertically", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + }, { + .id = V4L2_CID_HFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Flip Horizontally", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + }, { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Analog Gain", + .minimum = 64, + .maximum = 127, + .step = 1, + .default_value = 64, + .flags = V4L2_CTRL_FLAG_SLIDER, + }, { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Exposure", + .minimum = 1, + .maximum = 255, + .step = 1, + .default_value = 255, + .flags = V4L2_CTRL_FLAG_SLIDER, + }, { + .id = V4L2_CID_AUTOGAIN, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Automatic Gain", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 1, + }, { + .id = V4L2_CID_EXPOSURE_AUTO, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Automatic Exposure", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 1, + } +}; + +static int mt9v022_get_control(struct soc_camera_device *icd, + struct v4l2_control *ctrl); +static int mt9v022_set_control(struct soc_camera_device *icd, + struct v4l2_control *ctrl); + +static struct soc_camera_ops mt9v022_ops = { + .owner = THIS_MODULE, + .init = mt9v022_init, + .release = mt9v022_release, + .start_capture = mt9v022_start_capture, + .stop_capture = mt9v022_stop_capture, + .set_capture_format = mt9v022_set_capture_format, + .try_fmt_cap = mt9v022_try_fmt_cap, + .formats = mt9v022_formats, + .num_formats = ARRAY_SIZE(mt9v022_formats), + .get_datawidth = mt9v022_get_datawidth, + .controls = mt9v022_controls, + .num_controls = ARRAY_SIZE(mt9v022_controls), + .get_control = mt9v022_get_control, + .set_control = mt9v022_set_control, + .get_chip_id = mt9v022_get_chip_id, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .get_register = mt9v022_get_register, + .set_register = mt9v022_set_register, +#endif +}; + +static int mt9v022_get_control(struct soc_camera_device *icd, + struct v4l2_control *ctrl) +{ + int data; + + switch (ctrl->id) { + case V4L2_CID_VFLIP: + data = reg_read(icd, MT9V022_READ_MODE); + if (data < 0) + return -EIO; + ctrl->value = !!(data & 0x10); + break; + case V4L2_CID_HFLIP: + data = reg_read(icd, MT9V022_READ_MODE); + if (data < 0) + return -EIO; + ctrl->value = !!(data & 0x20); + break; + case V4L2_CID_EXPOSURE_AUTO: + data = reg_read(icd, MT9V022_AEC_AGC_ENABLE); + if (data < 0) + return -EIO; + ctrl->value = !!(data & 0x1); + break; + case V4L2_CID_AUTOGAIN: + data = reg_read(icd, MT9V022_AEC_AGC_ENABLE); + if (data < 0) + return -EIO; + ctrl->value = !!(data & 0x2); + break; + } + return 0; +} + +static int mt9v022_set_control(struct soc_camera_device *icd, + struct v4l2_control *ctrl) +{ + int data; + const struct v4l2_queryctrl *qctrl; + + qctrl = soc_camera_find_qctrl(&mt9v022_ops, ctrl->id); + + if (!qctrl) + return -EINVAL; + + switch (ctrl->id) { + case V4L2_CID_VFLIP: + if (ctrl->value) + data = reg_set(icd, MT9V022_READ_MODE, 0x10); + else + data = reg_clear(icd, MT9V022_READ_MODE, 0x10); + if (data < 0) + return -EIO; + break; + case V4L2_CID_HFLIP: + if (ctrl->value) + data = reg_set(icd, MT9V022_READ_MODE, 0x20); + else + data = reg_clear(icd, MT9V022_READ_MODE, 0x20); + if (data < 0) + return -EIO; + break; + case V4L2_CID_GAIN: + /* mt9v022 has minimum == default */ + if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum) + return -EINVAL; + else { + unsigned long range = qctrl->maximum - qctrl->minimum; + /* Datasheet says 16 to 64. autogain only works properly + * after setting gain to maximum 14. Larger values + * produce "white fly" noise effect. On the whole, + * manually setting analog gain does no good. */ + unsigned long gain = ((ctrl->value - qctrl->minimum) * + 10 + range / 2) / range + 4; + if (gain >= 32) + gain &= ~1; + /* The user wants to set gain manually, hope, she + * knows, what she's doing... Switch AGC off. */ + + if (reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x2) < 0) + return -EIO; + + dev_info(&icd->dev, "Setting gain from %d to %lu\n", + reg_read(icd, MT9V022_ANALOG_GAIN), gain); + if (reg_write(icd, MT9V022_ANALOG_GAIN, gain) < 0) + return -EIO; + icd->gain = ctrl->value; + } + break; + case V4L2_CID_EXPOSURE: + /* mt9v022 has maximum == default */ + if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum) + return -EINVAL; + else { + unsigned long range = qctrl->maximum - qctrl->minimum; + unsigned long shutter = ((ctrl->value - qctrl->minimum) * + 479 + range / 2) / range + 1; + /* The user wants to set shutter width manually, hope, + * she knows, what she's doing... Switch AEC off. */ + + if (reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x1) < 0) + return -EIO; + + dev_dbg(&icd->dev, "Shutter width from %d to %lu\n", + reg_read(icd, MT9V022_TOTAL_SHUTTER_WIDTH), + shutter); + if (reg_write(icd, MT9V022_TOTAL_SHUTTER_WIDTH, + shutter) < 0) + return -EIO; + icd->exposure = ctrl->value; + } + break; + case V4L2_CID_AUTOGAIN: + if (ctrl->value) + data = reg_set(icd, MT9V022_AEC_AGC_ENABLE, 0x2); + else + data = reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x2); + if (data < 0) + return -EIO; + break; + case V4L2_CID_EXPOSURE_AUTO: + if (ctrl->value) + data = reg_set(icd, MT9V022_AEC_AGC_ENABLE, 0x1); + else + data = reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x1); + if (data < 0) + return -EIO; + break; + } + return 0; +} + +/* 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 */ +static int mt9v022_video_probe(struct soc_camera_device *icd) +{ + struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + s32 data; + int ret; + + if (!icd->dev.parent || + to_soc_camera_host(icd->dev.parent)->nr != icd->iface) + return -ENODEV; + + /* Read out the chip version register */ + data = reg_read(icd, MT9V022_CHIP_VERSION); + + /* must be 0x1311 or 0x1313 */ + if (data != 0x1311 && data != 0x1313) { + ret = -ENODEV; + dev_info(&icd->dev, "No MT9V022 detected, ID register 0x%x\n", + data); + goto ei2c; + } + + /* Soft reset */ + ret = reg_write(icd, MT9V022_RESET, 1); + if (ret < 0) + goto ei2c; + /* 15 clock cycles */ + udelay(200); + if (reg_read(icd, MT9V022_RESET)) { + dev_err(&icd->dev, "Resetting MT9V022 failed!\n"); + goto ei2c; + } + + /* Set monochrome or colour sensor type */ + if (sensor_type && (!strcmp("colour", sensor_type) || + !strcmp("color", sensor_type))) { + ret = reg_write(icd, MT9V022_PIXEL_OPERATION_MODE, 4 | 0x11); + mt9v022->model = V4L2_IDENT_MT9V022IX7ATC; + } else { + ret = reg_write(icd, MT9V022_PIXEL_OPERATION_MODE, 0x11); + mt9v022->model = V4L2_IDENT_MT9V022IX7ATM; + } + + if (ret >= 0) + ret = soc_camera_video_start(icd); + if (ret < 0) + goto eisis; + + dev_info(&icd->dev, "Detected a MT9V022 chip ID %x, %s sensor\n", + data, mt9v022->model == V4L2_IDENT_MT9V022IX7ATM ? + "monochrome" : "colour"); + + return 0; + +eisis: +ei2c: + return ret; +} + +static void mt9v022_video_remove(struct soc_camera_device *icd) +{ + struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + + dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9v022->client->addr, + mt9v022->icd.dev.parent, mt9v022->icd.vdev); + soc_camera_video_stop(&mt9v022->icd); +} + +static int mt9v022_probe(struct i2c_client *client) +{ + struct mt9v022 *mt9v022; + struct soc_camera_device *icd; + struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); + struct soc_camera_link *icl = client->dev.platform_data; + int ret; + + if (!icl) { + dev_err(&client->dev, "MT9V022 driver needs platform data\n"); + return -EINVAL; + } + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) { + dev_warn(&adapter->dev, + "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n"); + return -EIO; + } + + mt9v022 = kzalloc(sizeof(struct mt9v022), GFP_KERNEL); + if (!mt9v022) + return -ENOMEM; + + mt9v022->chip_control = MT9V022_CHIP_CONTROL_DEFAULT; + mt9v022->client = client; + i2c_set_clientdata(client, mt9v022); + + icd = &mt9v022->icd; + icd->probe = mt9v022_video_probe; + icd->remove = mt9v022_video_remove; + icd->ops = &mt9v022_ops; + icd->control = &client->dev; + icd->x_min = 1; + icd->y_min = 4; + icd->x_current = 1; + icd->y_current = 4; + icd->width_min = 48; + icd->width_max = 752; + icd->height_min = 32; + icd->height_max = 480; + icd->y_skip_top = 1; + icd->iface = icl->bus_id; + /* Default datawidth - this is the only width this camera (normally) + * supports. It is only with extra logic that it can support + * other widths. Therefore it seems to be a sensible default. */ + mt9v022->datawidth = 10; + + ret = bus_switch_request(mt9v022, icl); + if (ret) + goto eswinit; + + ret = soc_camera_device_register(icd); + if (ret) + goto eisdr; + + return 0; + +eisdr: + bus_switch_release(mt9v022); +eswinit: + kfree(mt9v022); + return ret; +} + +static int mt9v022_remove(struct i2c_client *client) +{ + struct mt9v022 *mt9v022 = i2c_get_clientdata(client); + + soc_camera_device_unregister(&mt9v022->icd); + bus_switch_release(mt9v022); + kfree(mt9v022); + + return 0; +} + +static struct i2c_driver mt9v022_i2c_driver = { + .driver = { + .name = "mt9v022", + }, + .probe = mt9v022_probe, + .remove = mt9v022_remove, +}; + +static int __init mt9v022_mod_init(void) +{ + return i2c_add_driver(&mt9v022_i2c_driver); +} + +static void __exit mt9v022_mod_exit(void) +{ + i2c_del_driver(&mt9v022_i2c_driver); +} + +module_init(mt9v022_mod_init); +module_exit(mt9v022_mod_exit); + +MODULE_DESCRIPTION("Micron MT9V022 Camera driver"); +MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c index add6d0d680be..41207ec0c951 100644 --- a/drivers/media/video/mxb.c +++ b/drivers/media/video/mxb.c @@ -38,7 +38,7 @@ #define MXB_BOARD_CAN_DO_VBI(dev) (dev->revision != 0) /* global variable */ -static int mxb_num = 0; +static int mxb_num; /* initial frequence the tuner will be tuned to. in verden (lower saxony, germany) 4148 is a @@ -47,7 +47,7 @@ static int freq = 4148; module_param(freq, int, 0644); MODULE_PARM_DESC(freq, "initial frequency the tuner will be tuned to while setup"); -static int debug = 0; +static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off)."); diff --git a/drivers/media/video/pms.c b/drivers/media/video/pms.c index 6820c2aabd30..4a6c5723f7cc 100644 --- a/drivers/media/video/pms.c +++ b/drivers/media/video/pms.c @@ -57,11 +57,11 @@ struct i2c_info u8 hits; }; -static int i2c_count = 0; +static int i2c_count; static struct i2c_info i2cinfo[64]; static int decoder = PHILIPS2; -static int standard = 0; /* 0 - auto 1 - ntsc 2 - pal 3 - secam */ +static int standard; /* 0 - auto 1 - ntsc 2 - pal 3 - secam */ /* * I/O ports and Shared Memory diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 41ae980405ed..24c4e31294a5 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -44,13 +44,13 @@ static struct pvr2_hdw *unit_pointers[PVR_NUM] = {[ 0 ... PVR_NUM-1 ] = NULL}; static DEFINE_MUTEX(pvr2_unit_mtx); -static int ctlchg = 0; +static int ctlchg; static int initusbreset = 1; -static int procreload = 0; +static int procreload; static int tuner[PVR_NUM] = { [0 ... PVR_NUM-1] = -1 }; static int tolerance[PVR_NUM] = { [0 ... PVR_NUM-1] = 0 }; static int video_std[PVR_NUM] = { [0 ... PVR_NUM-1] = 0 }; -static int init_pause_msec = 0; +static int init_pause_msec; module_param(ctlchg, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(ctlchg, "0=optimize ctl change 1=always accept new ctl value"); diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c index 62867fa3517a..793c89a8d672 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c @@ -35,7 +35,7 @@ */ -static unsigned int i2c_scan = 0; +static unsigned int i2c_scan; module_param(i2c_scan, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time"); diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index f991d72fe108..b4146f89efb0 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c @@ -130,8 +130,8 @@ static int default_fbufs = 3; /* Default number of frame buffers */ #ifdef CONFIG_USB_PWC_DEBUG int pwc_trace = PWC_DEBUG_LEVEL; #endif -static int power_save = 0; -static int led_on = 100, led_off = 0; /* defaults to LED that is on while in use */ +static int power_save; +static int led_on = 100, led_off; /* defaults to LED that is on while in use */ static int pwc_preferred_compression = 1; /* 0..3 = uncompressed..high */ static struct { int type; @@ -786,8 +786,8 @@ static void pwc_isoc_handler(struct urb *urb) } /* ..status == 0 */ else { /* This is normally not interesting to the user, unless - * you are really debugging something */ - static int iso_error = 0; + * you are really debugging something, default = 0 */ + static int iso_error; iso_error++; if (iso_error < 20) PWC_DEBUG_FLOW("Iso frame %d of USB has error %d\n", i, fst); diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c new file mode 100644 index 000000000000..11aecad769cc --- /dev/null +++ b/drivers/media/video/pxa_camera.c @@ -0,0 +1,937 @@ +/* + * V4L2 Driver for PXA camera host + * + * Copyright (C) 2006, Sascha Hauer, Pengutronix + * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de> + * + * 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 <asm/io.h> + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/delay.h> +#include <linux/dma-mapping.h> +#include <linux/errno.h> +#include <linux/fs.h> +#include <linux/interrupt.h> +#include <linux/kernel.h> +#include <linux/mm.h> +#include <linux/moduleparam.h> +#include <linux/time.h> +#include <linux/version.h> +#include <linux/device.h> +#include <linux/platform_device.h> +#include <linux/mutex.h> +#include <linux/clk.h> + +#include <media/v4l2-common.h> +#include <media/v4l2-dev.h> +#include <media/soc_camera.h> + +#include <linux/videodev2.h> + +#include <asm/dma.h> +#include <asm/arch/pxa-regs.h> +#include <asm/arch/camera.h> + +#define PXA_CAM_VERSION_CODE KERNEL_VERSION(0, 0, 5) +#define PXA_CAM_DRV_NAME "pxa27x-camera" + +#define CICR0_IRQ_MASK (CICR0_TOM | CICR0_RDAVM | CICR0_FEM | CICR0_EOLM | \ + CICR0_PERRM | CICR0_QDM | CICR0_CDM | CICR0_SOFM | \ + CICR0_EOFM | CICR0_FOM) + +static DEFINE_MUTEX(camera_lock); + +/* + * Structures + */ + +/* buffer for one video frame */ +struct pxa_buffer { + /* common v4l buffer stuff -- must be first */ + struct videobuf_buffer vb; + + const struct soc_camera_data_format *fmt; + + /* our descriptor list needed for the PXA DMA engine */ + dma_addr_t sg_dma; + struct pxa_dma_desc *sg_cpu; + size_t sg_size; + int inwork; +}; + +struct pxa_framebuffer_queue { + dma_addr_t sg_last_dma; + struct pxa_dma_desc *sg_last_cpu; +}; + +struct pxa_camera_dev { + struct device *dev; + /* PXA27x is only supposed to handle one camera on its Quick Capture + * interface. If anyone ever builds hardware to enable more than + * one camera, they will have to modify this driver too */ + struct soc_camera_device *icd; + struct clk *clk; + + unsigned int irq; + void __iomem *base; + unsigned int dma_chan_y; + + enum v4l2_buf_type type; + + struct pxacamera_platform_data *pdata; + struct resource *res; + unsigned long platform_flags; + unsigned long platform_mclk_10khz; + + struct list_head capture; + + spinlock_t lock; + + int dma_running; + + struct pxa_buffer *active; +}; + +static const char *pxa_cam_driver_description = "PXA_Camera"; + +static unsigned int vid_limit = 16; /* Video memory limit, in Mb */ + +/* + * Videobuf operations + */ +static int +pxa_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, + unsigned int *size) +{ + struct soc_camera_device *icd = vq->priv_data; + + dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size); + + *size = icd->width * icd->height * ((icd->current_fmt->depth + 7) >> 3); + + if (0 == *count) + *count = 32; + while (*size * *count > vid_limit * 1024 * 1024) + (*count)--; + + return 0; +} + +static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf) +{ + struct soc_camera_device *icd = vq->priv_data; + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + struct pxa_camera_dev *pcdev = ici->priv; + struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb); + + BUG_ON(in_interrupt()); + + dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __FUNCTION__, + &buf->vb, buf->vb.baddr, buf->vb.bsize); + + /* This waits until this buffer is out of danger, i.e., until it is no + * longer in STATE_QUEUED or STATE_ACTIVE */ + videobuf_waiton(&buf->vb, 0, 0); + videobuf_dma_unmap(vq, dma); + videobuf_dma_free(dma); + + if (buf->sg_cpu) + dma_free_coherent(pcdev->dev, buf->sg_size, buf->sg_cpu, + buf->sg_dma); + buf->sg_cpu = NULL; + + buf->vb.state = VIDEOBUF_NEEDS_INIT; +} + +static int +pxa_videobuf_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, + enum v4l2_field field) +{ + struct soc_camera_device *icd = vq->priv_data; + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + struct pxa_camera_dev *pcdev = ici->priv; + struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb); + int i, ret; + + dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __FUNCTION__, + vb, vb->baddr, vb->bsize); + + /* Added list head initialization on alloc */ + WARN_ON(!list_empty(&vb->queue)); + +#ifdef DEBUG + /* This can be useful if you want to see if we actually fill + * the buffer with something */ + memset((void *)vb->baddr, 0xaa, vb->bsize); +#endif + + BUG_ON(NULL == icd->current_fmt); + + /* I think, in buf_prepare you only have to protect global data, + * the actual buffer is yours */ + buf->inwork = 1; + + if (buf->fmt != icd->current_fmt || + vb->width != icd->width || + vb->height != icd->height || + vb->field != field) { + buf->fmt = icd->current_fmt; + vb->width = icd->width; + vb->height = icd->height; + vb->field = field; + vb->state = VIDEOBUF_NEEDS_INIT; + } + + vb->size = vb->width * vb->height * ((buf->fmt->depth + 7) >> 3); + if (0 != vb->baddr && vb->bsize < vb->size) { + ret = -EINVAL; + goto out; + } + + if (vb->state == VIDEOBUF_NEEDS_INIT) { + unsigned int size = vb->size; + struct videobuf_dmabuf *dma = videobuf_to_dma(vb); + + ret = videobuf_iolock(vq, vb, NULL); + if (ret) + goto fail; + + if (buf->sg_cpu) + dma_free_coherent(pcdev->dev, buf->sg_size, buf->sg_cpu, + buf->sg_dma); + + buf->sg_size = (dma->sglen + 1) * sizeof(struct pxa_dma_desc); + buf->sg_cpu = dma_alloc_coherent(pcdev->dev, buf->sg_size, + &buf->sg_dma, GFP_KERNEL); + if (!buf->sg_cpu) { + ret = -ENOMEM; + goto fail; + } + + dev_dbg(&icd->dev, "nents=%d size: %d sg=0x%p\n", + dma->sglen, size, dma->sglist); + for (i = 0; i < dma->sglen; i++) { + struct scatterlist *sg = dma->sglist; + unsigned int dma_len = sg_dma_len(&sg[i]), xfer_len; + + /* CIBR0 */ + buf->sg_cpu[i].dsadr = pcdev->res->start + 0x28; + buf->sg_cpu[i].dtadr = sg_dma_address(&sg[i]); + /* PXA270 Developer's Manual 27.4.4.1: + * round up to 8 bytes */ + xfer_len = (min(dma_len, size) + 7) & ~7; + if (xfer_len & 7) + dev_err(&icd->dev, "Unaligned buffer: " + "dma_len %u, size %u\n", dma_len, size); + buf->sg_cpu[i].dcmd = DCMD_FLOWSRC | DCMD_BURST8 | + DCMD_INCTRGADDR | xfer_len; + size -= dma_len; + buf->sg_cpu[i].ddadr = buf->sg_dma + (i + 1) * + sizeof(struct pxa_dma_desc); + } + buf->sg_cpu[dma->sglen - 1].ddadr = DDADR_STOP; + buf->sg_cpu[dma->sglen - 1].dcmd |= DCMD_ENDIRQEN; + + vb->state = VIDEOBUF_PREPARED; + } + + buf->inwork = 0; + + return 0; + +fail: + free_buffer(vq, buf); +out: + buf->inwork = 0; + return ret; +} + +static void +pxa_videobuf_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) +{ + struct soc_camera_device *icd = vq->priv_data; + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + struct pxa_camera_dev *pcdev = ici->priv; + struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb); + struct pxa_buffer *active = pcdev->active; + struct videobuf_dmabuf *dma = videobuf_to_dma(vb); + int nents = dma->sglen; + unsigned long flags; + + dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __FUNCTION__, + vb, vb->baddr, vb->bsize); + spin_lock_irqsave(&pcdev->lock, flags); + + list_add_tail(&vb->queue, &pcdev->capture); + + vb->state = VIDEOBUF_ACTIVE; + + if (!pcdev->active) { + CIFR |= CIFR_RESET_F; + DDADR(pcdev->dma_chan_y) = buf->sg_dma; + DCSR(pcdev->dma_chan_y) = DCSR_RUN; + pcdev->active = buf; + CICR0 |= CICR0_ENB; + } else { + struct videobuf_dmabuf *active_dma = + videobuf_to_dma(&active->vb); + /* Stop DMA engine */ + DCSR(pcdev->dma_chan_y) = 0; + + /* Add the descriptors we just initialized to the currently + * running chain + */ + active->sg_cpu[active_dma->sglen - 1].ddadr = buf->sg_dma; + + /* Setup a dummy descriptor with the DMA engines current + * state + */ + /* CIBR0 */ + buf->sg_cpu[nents].dsadr = pcdev->res->start + 0x28; + buf->sg_cpu[nents].dtadr = DTADR(pcdev->dma_chan_y); + buf->sg_cpu[nents].dcmd = DCMD(pcdev->dma_chan_y); + + if (DDADR(pcdev->dma_chan_y) == DDADR_STOP) { + /* The DMA engine is on the last descriptor, set the + * next descriptors address to the descriptors + * we just initialized + */ + buf->sg_cpu[nents].ddadr = buf->sg_dma; + } else { + buf->sg_cpu[nents].ddadr = DDADR(pcdev->dma_chan_y); + } + + /* The next descriptor is the dummy descriptor */ + DDADR(pcdev->dma_chan_y) = buf->sg_dma + nents * + sizeof(struct pxa_dma_desc); + +#ifdef DEBUG + if (CISR & CISR_IFO_0) { + dev_warn(pcdev->dev, "FIFO overrun\n"); + DDADR(pcdev->dma_chan_y) = pcdev->active->sg_dma; + + CICR0 &= ~CICR0_ENB; + CIFR |= CIFR_RESET_F; + DCSR(pcdev->dma_chan_y) = DCSR_RUN; + CICR0 |= CICR0_ENB; + } else +#endif + DCSR(pcdev->dma_chan_y) = DCSR_RUN; + } + + spin_unlock_irqrestore(&pcdev->lock, flags); + +} + +static void pxa_videobuf_release(struct videobuf_queue *vq, + struct videobuf_buffer *vb) +{ + struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb); +#ifdef DEBUG + struct soc_camera_device *icd = vq->priv_data; + + dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __FUNCTION__, + vb, vb->baddr, vb->bsize); + + switch (vb->state) { + case VIDEOBUF_ACTIVE: + dev_dbg(&icd->dev, "%s (active)\n", __FUNCTION__); + break; + case VIDEOBUF_QUEUED: + dev_dbg(&icd->dev, "%s (queued)\n", __FUNCTION__); + break; + case VIDEOBUF_PREPARED: + dev_dbg(&icd->dev, "%s (prepared)\n", __FUNCTION__); + break; + default: + dev_dbg(&icd->dev, "%s (unknown)\n", __FUNCTION__); + break; + } +#endif + + free_buffer(vq, buf); +} + +static void pxa_camera_dma_irq_y(int channel, void *data) +{ + struct pxa_camera_dev *pcdev = data; + struct pxa_buffer *buf; + unsigned long flags; + unsigned int status; + struct videobuf_buffer *vb; + + spin_lock_irqsave(&pcdev->lock, flags); + + status = DCSR(pcdev->dma_chan_y); + if (status & DCSR_BUSERR) { + dev_err(pcdev->dev, "%s: Bus Error\n", __FUNCTION__); + DCSR(pcdev->dma_chan_y) |= DCSR_BUSERR; + goto out; + } + + if (!(status & DCSR_ENDINTR)) { + dev_err(pcdev->dev, "%s: unknown dma interrupt source. " + "status: 0x%08x\n", __FUNCTION__, status); + goto out; + } + + DCSR(pcdev->dma_chan_y) |= DCSR_ENDINTR; + + if (!pcdev->active) { + dev_err(pcdev->dev, "%s: no active buf\n", __FUNCTION__); + goto out; + } + + vb = &pcdev->active->vb; + buf = container_of(vb, struct pxa_buffer, vb); + WARN_ON(buf->inwork || list_empty(&vb->queue)); + dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __FUNCTION__, + vb, vb->baddr, vb->bsize); + + /* _init is used to debug races, see comment in pxa_is_reqbufs() */ + list_del_init(&vb->queue); + vb->state = VIDEOBUF_DONE; + do_gettimeofday(&vb->ts); + vb->field_count++; + wake_up(&vb->done); + + if (list_empty(&pcdev->capture)) { + pcdev->active = NULL; + DCSR(pcdev->dma_chan_y) = 0; + CICR0 &= ~CICR0_ENB; + goto out; + } + + pcdev->active = list_entry(pcdev->capture.next, struct pxa_buffer, + vb.queue); + +out: + spin_unlock_irqrestore(&pcdev->lock, flags); +} + +static struct videobuf_queue_ops pxa_video_ops = { + .buf_setup = pxa_videobuf_setup, + .buf_prepare = pxa_videobuf_prepare, + .buf_queue = pxa_videobuf_queue, + .buf_release = pxa_videobuf_release, +}; + +static int mclk_get_divisor(struct pxa_camera_dev *pcdev) +{ + unsigned int mclk_10khz = pcdev->platform_mclk_10khz; + unsigned long div; + unsigned long lcdclk; + + lcdclk = clk_get_rate(pcdev->clk) / 10000; + + /* We verify platform_mclk_10khz != 0, so if anyone breaks it, here + * they get a nice Oops */ + div = (lcdclk + 2 * mclk_10khz - 1) / (2 * mclk_10khz) - 1; + + dev_dbg(pcdev->dev, "LCD clock %lukHz, target freq %dkHz, " + "divisor %lu\n", lcdclk * 10, mclk_10khz * 10, div); + + return div; +} + +static void pxa_is_activate(struct pxa_camera_dev *pcdev) +{ + struct pxacamera_platform_data *pdata = pcdev->pdata; + u32 cicr4 = 0; + + dev_dbg(pcdev->dev, "Registered platform device at %p data %p\n", + pcdev, pdata); + + if (pdata && pdata->init) { + dev_dbg(pcdev->dev, "%s: Init gpios\n", __FUNCTION__); + pdata->init(pcdev->dev); + } + + if (pdata && pdata->power) { + dev_dbg(pcdev->dev, "%s: Power on camera\n", __FUNCTION__); + pdata->power(pcdev->dev, 1); + } + + if (pdata && pdata->reset) { + dev_dbg(pcdev->dev, "%s: Releasing camera reset\n", + __FUNCTION__); + pdata->reset(pcdev->dev, 1); + } + + CICR0 = 0x3FF; /* disable all interrupts */ + + if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN) + cicr4 |= CICR4_PCLK_EN; + if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN) + cicr4 |= CICR4_MCLK_EN; + if (pcdev->platform_flags & PXA_CAMERA_PCP) + cicr4 |= CICR4_PCP; + if (pcdev->platform_flags & PXA_CAMERA_HSP) + cicr4 |= CICR4_HSP; + if (pcdev->platform_flags & PXA_CAMERA_VSP) + cicr4 |= CICR4_VSP; + + CICR4 = mclk_get_divisor(pcdev) | cicr4; + + clk_enable(pcdev->clk); +} + +static void pxa_is_deactivate(struct pxa_camera_dev *pcdev) +{ + struct pxacamera_platform_data *board = pcdev->pdata; + + clk_disable(pcdev->clk); + + if (board && board->reset) { + dev_dbg(pcdev->dev, "%s: Asserting camera reset\n", + __FUNCTION__); + board->reset(pcdev->dev, 0); + } + + if (board && board->power) { + dev_dbg(pcdev->dev, "%s: Power off camera\n", __FUNCTION__); + board->power(pcdev->dev, 0); + } +} + +static irqreturn_t pxa_camera_irq(int irq, void *data) +{ + struct pxa_camera_dev *pcdev = data; + unsigned int status = CISR; + + dev_dbg(pcdev->dev, "Camera interrupt status 0x%x\n", status); + + CISR = status; + + return IRQ_HANDLED; +} + +/* The following two functions absolutely depend on the fact, that + * there can be only one camera on PXA quick capture interface */ +static int pxa_is_add_device(struct soc_camera_device *icd) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct pxa_camera_dev *pcdev = ici->priv; + int ret; + + mutex_lock(&camera_lock); + + if (pcdev->icd) { + ret = -EBUSY; + goto ebusy; + } + + dev_info(&icd->dev, "PXA Camera driver attached to camera %d\n", + icd->devnum); + + pxa_is_activate(pcdev); + ret = icd->ops->init(icd); + + if (!ret) + pcdev->icd = icd; + +ebusy: + mutex_unlock(&camera_lock); + + return ret; +} + +static void pxa_is_remove_device(struct soc_camera_device *icd) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct pxa_camera_dev *pcdev = ici->priv; + + BUG_ON(icd != pcdev->icd); + + dev_info(&icd->dev, "PXA Camera driver detached from camera %d\n", + icd->devnum); + + /* disable capture, disable interrupts */ + CICR0 = 0x3ff; + /* Stop DMA engine */ + DCSR(pcdev->dma_chan_y) = 0; + + icd->ops->release(icd); + + pxa_is_deactivate(pcdev); + + pcdev->icd = NULL; +} + +static int pxa_is_set_capture_format(struct soc_camera_device *icd, + __u32 pixfmt, struct v4l2_rect *rect) +{ + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + struct pxa_camera_dev *pcdev = ici->priv; + unsigned int datawidth = 0, dw, bpp; + u32 cicr0, cicr4 = 0; + int ret; + + /* If requested data width is supported by the platform, use it */ + switch (icd->cached_datawidth) { + case 10: + if (pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_10) + datawidth = IS_DATAWIDTH_10; + break; + case 9: + if (pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_9) + datawidth = IS_DATAWIDTH_9; + break; + case 8: + if (pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_8) + datawidth = IS_DATAWIDTH_8; + } + if (!datawidth) + return -EINVAL; + + ret = icd->ops->set_capture_format(icd, pixfmt, rect, + datawidth | + (pcdev->platform_flags & PXA_CAMERA_MASTER ? + IS_MASTER : 0) | + (pcdev->platform_flags & PXA_CAMERA_HSP ? + 0 : IS_HSYNC_ACTIVE_HIGH) | + (pcdev->platform_flags & PXA_CAMERA_VSP ? + 0 : IS_VSYNC_ACTIVE_HIGH) | + (pcdev->platform_flags & PXA_CAMERA_PCP ? + 0 : IS_PCLK_SAMPLE_RISING)); + if (ret < 0) + return ret; + + /* Datawidth is now guaranteed to be equal to one of the three values. + * We fix bit-per-pixel equal to data-width... */ + switch (datawidth) { + case IS_DATAWIDTH_10: + icd->cached_datawidth = 10; + dw = 4; + bpp = 0x40; + break; + case IS_DATAWIDTH_9: + icd->cached_datawidth = 9; + dw = 3; + bpp = 0x20; + break; + default: + /* Actually it can only be 8 now, + * default is just to silence compiler warnings */ + case IS_DATAWIDTH_8: + icd->cached_datawidth = 8; + dw = 2; + bpp = 0; + } + + if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN) + cicr4 |= CICR4_PCLK_EN; + if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN) + cicr4 |= CICR4_MCLK_EN; + if (pcdev->platform_flags & PXA_CAMERA_PCP) + cicr4 |= CICR4_PCP; + if (pcdev->platform_flags & PXA_CAMERA_HSP) + cicr4 |= CICR4_HSP; + if (pcdev->platform_flags & PXA_CAMERA_VSP) + cicr4 |= CICR4_VSP; + + cicr0 = CICR0; + if (cicr0 & CICR0_ENB) + CICR0 = cicr0 & ~CICR0_ENB; + CICR1 = CICR1_PPL_VAL(rect->width - 1) | bpp | dw; + CICR2 = 0; + CICR3 = CICR3_LPF_VAL(rect->height - 1) | + CICR3_BFW_VAL(min((unsigned short)255, icd->y_skip_top)); + CICR4 = mclk_get_divisor(pcdev) | cicr4; + + /* CIF interrupts are not used, only DMA */ + CICR0 = (pcdev->platform_flags & PXA_CAMERA_MASTER ? + 0 : (CICR0_SL_CAP_EN | CICR0_SIM_SP)) | + CICR0_DMAEN | CICR0_IRQ_MASK | (cicr0 & CICR0_ENB); + + return 0; +} + +static int pxa_is_try_fmt_cap(struct soc_camera_host *ici, + struct v4l2_format *f) +{ + /* limit to pxa hardware capabilities */ + if (f->fmt.pix.height < 32) + f->fmt.pix.height = 32; + if (f->fmt.pix.height > 2048) + f->fmt.pix.height = 2048; + if (f->fmt.pix.width < 48) + f->fmt.pix.width = 48; + if (f->fmt.pix.width > 2048) + f->fmt.pix.width = 2048; + f->fmt.pix.width &= ~0x01; + + return 0; +} + +static int pxa_is_reqbufs(struct soc_camera_file *icf, + struct v4l2_requestbuffers *p) +{ + int i; + + /* This is for locking debugging only. I removed spinlocks and now I + * check whether .prepare is ever called on a linked buffer, or whether + * a dma IRQ can occur for an in-work or unlinked buffer. Until now + * it hadn't triggered */ + for (i = 0; i < p->count; i++) { + struct pxa_buffer *buf = container_of(icf->vb_vidq.bufs[i], + struct pxa_buffer, vb); + buf->inwork = 0; + INIT_LIST_HEAD(&buf->vb.queue); + } + + return 0; +} + +static unsigned int pxa_is_poll(struct file *file, poll_table *pt) +{ + struct soc_camera_file *icf = file->private_data; + struct pxa_buffer *buf; + + buf = list_entry(icf->vb_vidq.stream.next, struct pxa_buffer, + vb.stream); + + poll_wait(file, &buf->vb.done, pt); + + if (buf->vb.state == VIDEOBUF_DONE || + buf->vb.state == VIDEOBUF_ERROR) + return POLLIN|POLLRDNORM; + + return 0; +} + +static int pxa_is_querycap(struct soc_camera_host *ici, + struct v4l2_capability *cap) +{ + /* cap->name is set by the firendly caller:-> */ + strlcpy(cap->card, pxa_cam_driver_description, sizeof(cap->card)); + cap->version = PXA_CAM_VERSION_CODE; + cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; + + return 0; +} + +/* Should beallocated dynamically too, but we have only one. */ +static struct soc_camera_host pxa_soc_camera_host = { + .drv_name = PXA_CAM_DRV_NAME, + .vbq_ops = &pxa_video_ops, + .add = pxa_is_add_device, + .remove = pxa_is_remove_device, + .msize = sizeof(struct pxa_buffer), + .set_capture_format = pxa_is_set_capture_format, + .try_fmt_cap = pxa_is_try_fmt_cap, + .reqbufs = pxa_is_reqbufs, + .poll = pxa_is_poll, + .querycap = pxa_is_querycap, +}; + +static int pxa_camera_probe(struct platform_device *pdev) +{ + struct pxa_camera_dev *pcdev; + struct resource *res; + void __iomem *base; + unsigned int irq; + int err = 0; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + irq = platform_get_irq(pdev, 0); + if (!res || !irq) { + err = -ENODEV; + goto exit; + } + + pcdev = kzalloc(sizeof(*pcdev), GFP_KERNEL); + if (!pcdev) { + dev_err(&pdev->dev, "%s: Could not allocate pcdev\n", + __FUNCTION__); + err = -ENOMEM; + goto exit; + } + + pcdev->clk = clk_get(&pdev->dev, "CAMCLK"); + if (IS_ERR(pcdev->clk)) { + err = PTR_ERR(pcdev->clk); + goto exit_kfree; + } + + dev_set_drvdata(&pdev->dev, pcdev); + pcdev->res = res; + + pcdev->pdata = pdev->dev.platform_data; + pcdev->platform_flags = pcdev->pdata->flags; + if (!pcdev->platform_flags & (PXA_CAMERA_DATAWIDTH_8 | + PXA_CAMERA_DATAWIDTH_9 | PXA_CAMERA_DATAWIDTH_10)) { + /* Platform hasn't set available data widths. This is bad. + * Warn and use a default. */ + dev_warn(&pdev->dev, "WARNING! Platform hasn't set available " + "data widths, using default 10 bit\n"); + pcdev->platform_flags |= PXA_CAMERA_DATAWIDTH_10; + } + pcdev->platform_mclk_10khz = pcdev->pdata->mclk_10khz; + if (!pcdev->platform_mclk_10khz) { + dev_warn(&pdev->dev, + "mclk_10khz == 0! Please, fix your platform data. " + "Using default 20MHz\n"); + pcdev->platform_mclk_10khz = 2000; + } + + INIT_LIST_HEAD(&pcdev->capture); + spin_lock_init(&pcdev->lock); + + /* + * Request the regions. + */ + if (!request_mem_region(res->start, res->end - res->start + 1, + PXA_CAM_DRV_NAME)) { + err = -EBUSY; + goto exit_clk; + } + + base = ioremap(res->start, res->end - res->start + 1); + if (!base) { + err = -ENOMEM; + goto exit_release; + } + pcdev->irq = irq; + pcdev->base = base; + pcdev->dev = &pdev->dev; + + /* request dma */ + pcdev->dma_chan_y = pxa_request_dma("CI_Y", DMA_PRIO_HIGH, + pxa_camera_dma_irq_y, pcdev); + if (pcdev->dma_chan_y < 0) { + dev_err(pcdev->dev, "Can't request DMA for Y\n"); + err = -ENOMEM; + goto exit_iounmap; + } + dev_dbg(pcdev->dev, "got DMA channel %d\n", pcdev->dma_chan_y); + + DRCMR68 = pcdev->dma_chan_y | DRCMR_MAPVLD; + + /* request irq */ + err = request_irq(pcdev->irq, pxa_camera_irq, 0, PXA_CAM_DRV_NAME, + pcdev); + if (err) { + dev_err(pcdev->dev, "Camera interrupt register failed \n"); + goto exit_free_dma; + } + + pxa_soc_camera_host.priv = pcdev; + pxa_soc_camera_host.dev.parent = &pdev->dev; + pxa_soc_camera_host.nr = pdev->id; + err = soc_camera_host_register(&pxa_soc_camera_host, THIS_MODULE); + if (err) + goto exit_free_irq; + + return 0; + +exit_free_irq: + free_irq(pcdev->irq, pcdev); +exit_free_dma: + pxa_free_dma(pcdev->dma_chan_y); +exit_iounmap: + iounmap(base); +exit_release: + release_mem_region(res->start, res->end - res->start + 1); +exit_clk: + clk_put(pcdev->clk); +exit_kfree: + kfree(pcdev); +exit: + return err; +} + +static int __devexit pxa_camera_remove(struct platform_device *pdev) +{ + struct pxa_camera_dev *pcdev = platform_get_drvdata(pdev); + struct resource *res; + + clk_put(pcdev->clk); + + pxa_free_dma(pcdev->dma_chan_y); + free_irq(pcdev->irq, pcdev); + + soc_camera_host_unregister(&pxa_soc_camera_host); + + iounmap(pcdev->base); + + res = pcdev->res; + release_mem_region(res->start, res->end - res->start + 1); + + kfree(pcdev); + + dev_info(&pdev->dev, "%s: PXA Camera driver unloaded\n", __FUNCTION__); + + return 0; +} + +/* + * Suspend the Camera Module. + */ +static int pxa_camera_suspend(struct platform_device *pdev, pm_message_t level) +{ + struct pxa_camera_dev *pcdev = platform_get_drvdata(pdev); + + dev_info(&pdev->dev, "camera suspend\n"); + disable_irq(pcdev->irq); + return 0; +} + +/* + * Resume the Camera Module. + */ +static int pxa_camera_resume(struct platform_device *pdev) +{ + struct pxa_camera_dev *pcdev = platform_get_drvdata(pdev); + + dev_info(&pdev->dev, "camera resume\n"); + enable_irq(pcdev->irq); + +/* if (pcdev) { */ /* FIXME: dev in use? */ +/* DRCMR68 = pcdev->dma_chan_y | DRCMR_MAPVLD; */ +/* DRCMR69 = pcdev->dma_chan_cb | DRCMR_MAPVLD; */ +/* DRCMR70 = pcdev->dma_chan_cr | DRCMR_MAPVLD; */ +/* } */ + + return 0; +} + + +static struct platform_driver pxa_camera_driver = { + .driver = { + .name = PXA_CAM_DRV_NAME, + }, + .probe = pxa_camera_probe, + .remove = __exit_p(pxa_camera_remove), + .suspend = pxa_camera_suspend, + .resume = pxa_camera_resume, +}; + + +static int __devinit pxa_camera_init(void) +{ + return platform_driver_register(&pxa_camera_driver); +} + +static void __exit pxa_camera_exit(void) +{ + return platform_driver_unregister(&pxa_camera_driver); +} + +module_init(pxa_camera_init); +module_exit(pxa_camera_exit); + +MODULE_DESCRIPTION("PXA27x SoC Camera Host driver"); +MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c index 72e344a12c79..716ee7f64df3 100644 --- a/drivers/media/video/saa6588.c +++ b/drivers/media/video/saa6588.c @@ -44,10 +44,10 @@ static unsigned short normal_i2c[] = { I2C_CLIENT_INSMOD; /* insmod options */ -static unsigned int debug = 0; -static unsigned int xtal = 0; -static unsigned int rbds = 0; -static unsigned int plvl = 0; +static unsigned int debug; +static unsigned int xtal; +static unsigned int rbds; +static unsigned int plvl; static unsigned int bufblocks = 100; module_param(debug, int, 0644); diff --git a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c index 061134a7ba9f..a8993000662d 100644 --- a/drivers/media/video/saa7110.c +++ b/drivers/media/video/saa7110.c @@ -46,7 +46,7 @@ MODULE_LICENSE("GPL"); #include <media/v4l2-common.h> #include <linux/video_decoder.h> -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); diff --git a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c index 7ae2d646d000..17a0f5f06f96 100644 --- a/drivers/media/video/saa7111.c +++ b/drivers/media/video/saa7111.c @@ -55,7 +55,7 @@ MODULE_LICENSE("GPL"); #define I2C_NAME(s) (s)->name -static int debug = 0; +static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Debug level (0-1)"); diff --git a/drivers/media/video/saa7114.c b/drivers/media/video/saa7114.c index 677df51de1a9..77e2d1e1fc49 100644 --- a/drivers/media/video/saa7114.c +++ b/drivers/media/video/saa7114.c @@ -56,7 +56,7 @@ MODULE_LICENSE("GPL"); #define I2C_NAME(x) (x)->name -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index 41e5e518a47e..aaec17f9d4eb 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -57,7 +57,7 @@ MODULE_AUTHOR( "Maxim Yevtyushkin, Kevin Thayer, Chris Kennedy, " "Hans Verkuil, Mauro Carvalho Chehab"); MODULE_LICENSE("GPL"); -static int debug = 0; +static int debug; module_param(debug, bool, 0644); MODULE_PARM_DESC(debug, "Debug level (0-1)"); diff --git a/drivers/media/video/saa711x.c b/drivers/media/video/saa711x.c index 80bf91187856..cedb988574bd 100644 --- a/drivers/media/video/saa711x.c +++ b/drivers/media/video/saa711x.c @@ -48,7 +48,7 @@ MODULE_LICENSE("GPL"); #include <linux/video_decoder.h> -static int debug = 0; +static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, " Set the default Debug level. Default: 0 (Off) - (0-1)"); diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index 047add8f3010..505bc0a478af 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c @@ -31,7 +31,7 @@ #include "saa7134.h" #include "saa7134-reg.h" -static unsigned int debug = 0; +static unsigned int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug,"enable debug messages [alsa]"); diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 262830da08c8..f9c85b7cba1a 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2484,27 +2484,28 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .gpiomask = 0x080200000, - .inputs = {{ - .name = name_tv, - .vmux = 4, - .amux = TV, - .tv = 1, - },{ - .name = name_comp1, - .vmux = 1, - .amux = LINE2, - },{ - .name = name_comp2, - .vmux = 0, - .amux = LINE2, - },{ - .name = name_svideo, - .vmux = 8, - .amux = LINE2, - }}, + .inputs = { { + .name = name_tv, + .vmux = 4, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 1, + .amux = LINE2, + }, { + .name = name_comp2, + .vmux = 0, + .amux = LINE2, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE2, + } }, .radio = { - .name = name_radio, - .amux = LINE1, + .name = name_radio, + .amux = TV, + .gpio = 0x0200000, }, }, [SAA7134_BOARD_ASUSTeK_P7131_DUAL] = { @@ -3991,6 +3992,78 @@ struct saa7134_board saa7134_boards[] = { .gpio = 0x6000, }, }, + [SAA7134_BOARD_PHILIPS_SNAKE] = { + .name = "NXP Snake DVB-S reference design", + .audio_clock = 0x00200000, + .tuner_type = TUNER_ABSENT, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .mpeg = SAA7134_MPEG_DVB, + .inputs = {{ + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + }, + [SAA7134_BOARD_CREATIX_CTX953] = { + .name = "Medion/Creatix CTX953 Hybrid", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_TDA8290, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tuner_config = 0, + .mpeg = SAA7134_MPEG_DVB, + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 0, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + }, + [SAA7134_BOARD_MSI_TVANYWHERE_AD11] = { + .name = "MSI TV@nywhere A/D v1.1", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_TDA8290, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tuner_config = 2, + .mpeg = SAA7134_MPEG_DVB, + .gpiomask = 0x0200000, + .inputs = { { + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + .radio = { + .name = name_radio, + .amux = TV, + .gpio = 0x0200000, + }, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -4941,6 +5014,18 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x1822, /*Twinhan Technology Co. Ltd*/ .subdevice = 0x0022, .driver_data = SAA7134_BOARD_TWINHAN_DTV_DVB_3056, + }, { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x16be, + .subdevice = 0x0010, /* Medion version CTX953_V.1.4.3 */ + .driver_data = SAA7134_BOARD_CREATIX_CTX953, + }, { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x1462, /* MSI */ + .subdevice = 0x8625, /* TV@nywhere A/D v1.1 */ + .driver_data = SAA7134_BOARD_MSI_TVANYWHERE_AD11, },{ /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, @@ -5282,6 +5367,14 @@ int saa7134_board_init2(struct saa7134_dev *dev) } break; case SAA7134_BOARD_PHILIPS_EUROPA: + if (dev->autodetected && (dev->eedata[0x41] == 0x1c)) { + /* Reconfigure board as Snake reference design */ + dev->board = SAA7134_BOARD_PHILIPS_SNAKE; + dev->tuner_type = saa7134_boards[dev->board].tuner_type; + printk(KERN_INFO "%s: Reconfigured board as %s\n", + dev->name, saa7134_boards[dev->board].name); + break; + } case SAA7134_BOARD_VIDEOMATE_DVBT_300: case SAA7134_BOARD_ASUS_EUROPA2_HYBRID: /* The Philips EUROPA based hybrid boards have the tuner connected through @@ -5332,6 +5425,7 @@ int saa7134_board_init2(struct saa7134_dev *dev) case SAA7134_BOARD_MEDION_MD8800_QUADRO: case SAA7134_BOARD_AVERMEDIA_SUPER_007: case SAA7134_BOARD_TWINHAN_DTV_DVB_3056: + case SAA7134_BOARD_CREATIX_CTX953: /* this is a hybrid board, initialize to analog mode * and configure firmware eeprom address */ diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 52baa4f7f7dd..a5ed2522331b 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -42,23 +42,23 @@ MODULE_LICENSE("GPL"); /* ------------------------------------------------------------------ */ -static unsigned int irq_debug = 0; +static unsigned int irq_debug; module_param(irq_debug, int, 0644); MODULE_PARM_DESC(irq_debug,"enable debug messages [IRQ handler]"); -static unsigned int core_debug = 0; +static unsigned int core_debug; module_param(core_debug, int, 0644); MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); -static unsigned int gpio_tracking = 0; +static unsigned int gpio_tracking; module_param(gpio_tracking, int, 0644); MODULE_PARM_DESC(gpio_tracking,"enable debug messages [gpio]"); -static unsigned int alsa = 0; +static unsigned int alsa; module_param(alsa, int, 0644); MODULE_PARM_DESC(alsa,"enable ALSA DMA sound [dmasound]"); -static unsigned int oss = 0; +static unsigned int oss; module_param(oss, int, 0644); MODULE_PARM_DESC(oss,"enable OSS DMA sound [dmasound]"); diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index ea2be9eceeb8..b55df4877aff 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -43,20 +43,22 @@ #include "tda826x.h" #include "tda827x.h" #include "isl6421.h" +#include "isl6405.h" +#include "lnbp21.h" MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); MODULE_LICENSE("GPL"); -static unsigned int antenna_pwr = 0; +static unsigned int antenna_pwr; module_param(antenna_pwr, int, 0444); MODULE_PARM_DESC(antenna_pwr,"enable antenna power (Pinnacle 300i)"); -static int use_frontend = 0; +static int use_frontend; module_param(use_frontend, int, 0644); MODULE_PARM_DESC(use_frontend,"for cards with multiple frontends (0: terrestrial, 1: satellite)"); -static int debug = 0; +static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off module debugging (default:off)."); @@ -844,6 +846,36 @@ static struct tda10086_config flydvbs = { .diseqc_tone = 0, }; +/* ------------------------------------------------------------------ + * special case: lnb supply is connected to the gated i2c + */ + +static int md8800_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) +{ + int res = -EIO; + struct saa7134_dev *dev = fe->dvb->priv; + if (fe->ops.i2c_gate_ctrl) { + fe->ops.i2c_gate_ctrl(fe, 1); + if (dev->original_set_voltage) + res = dev->original_set_voltage(fe, voltage); + fe->ops.i2c_gate_ctrl(fe, 0); + } + return res; +}; + +static int md8800_set_high_voltage(struct dvb_frontend *fe, long arg) +{ + int res = -EIO; + struct saa7134_dev *dev = fe->dvb->priv; + if (fe->ops.i2c_gate_ctrl) { + fe->ops.i2c_gate_ctrl(fe, 1); + if (dev->original_set_high_voltage) + res = dev->original_set_high_voltage(fe, arg); + fe->ops.i2c_gate_ctrl(fe, 0); + } + return res; +}; + /* ================================================================== * nxt200x based ATSC cards, helper functions */ @@ -990,7 +1022,35 @@ static int dvb_init(struct saa7134_dev *dev) configure_tda827x_fe(dev, &tevion_dvbt220rf_config); break; case SAA7134_BOARD_MEDION_MD8800_QUADRO: - configure_tda827x_fe(dev, &md8800_dvbt_config); + if (!use_frontend) { /* terrestrial */ + configure_tda827x_fe(dev, &md8800_dvbt_config); + } else { /* satellite */ + dev->dvb.frontend = dvb_attach(tda10086_attach, + &flydvbs, &dev->i2c_adap); + if (dev->dvb.frontend) { + struct dvb_frontend *fe; + if (dvb_attach(tda826x_attach, dev->dvb.frontend, + 0x60, &dev->i2c_adap, 0) == NULL) + wprintk("%s: Medion Quadro, no tda826x " + "found !\n", __FUNCTION__); + /* Note 10.2. Hac + * up to here. configuration for ctx948 and and one branch + * of md8800 should be identical + */ + /* we need to open the i2c gate (we know it exists) */ + fe = dev->dvb.frontend; + fe->ops.i2c_gate_ctrl(fe, 1); + if (dvb_attach(isl6405_attach, fe, + &dev->i2c_adap, 0x08, 0, 0) == NULL) + wprintk("%s: Medion Quadro, no ISL6405 " + "found !\n", __FUNCTION__); + fe->ops.i2c_gate_ctrl(fe, 0); + dev->original_set_voltage = fe->ops.set_voltage; + fe->ops.set_voltage = md8800_set_voltage; + dev->original_set_high_voltage = fe->ops.enable_high_lnb_voltage; + fe->ops.enable_high_lnb_voltage = md8800_set_high_voltage; + } + } break; case SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180: dev->dvb.frontend = dvb_attach(nxt200x_attach, &avertvhda180, @@ -1064,6 +1124,24 @@ static int dvb_init(struct saa7134_dev *dev) case SAA7134_BOARD_TWINHAN_DTV_DVB_3056: configure_tda827x_fe(dev, &twinhan_dtv_dvb_3056_config); break; + case SAA7134_BOARD_PHILIPS_SNAKE: + dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, + &dev->i2c_adap); + if (dev->dvb.frontend) { + if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x60, + &dev->i2c_adap, 0) == NULL) + wprintk("%s: No tda826x found!\n", __FUNCTION__); + if (dvb_attach(lnbp21_attach, dev->dvb.frontend, + &dev->i2c_adap, 0, 0) == NULL) + wprintk("%s: No lnbp21 found!\n", __FUNCTION__); + } + break; + case SAA7134_BOARD_CREATIX_CTX953: + configure_tda827x_fe(dev, &md8800_dvbt_config); + break; + case SAA7134_BOARD_MSI_TVANYWHERE_AD11: + configure_tda827x_fe(dev, &philips_tiger_s_config); + break; default: wprintk("Huh? unknown DVB card?\n"); break; diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index 3d2ec30de227..40d4a66b77f5 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c @@ -40,7 +40,7 @@ static unsigned int empress_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; module_param_array(empress_nr, int, NULL, 0444); MODULE_PARM_DESC(empress_nr,"ts device number"); -static unsigned int debug = 0; +static unsigned int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug,"enable debug messages"); diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c index d3322c3018f2..ba71dd0040be 100644 --- a/drivers/media/video/saa7134/saa7134-i2c.c +++ b/drivers/media/video/saa7134/saa7134-i2c.c @@ -33,11 +33,11 @@ /* ----------------------------------------------------------- */ -static unsigned int i2c_debug = 0; +static unsigned int i2c_debug; module_param(i2c_debug, int, 0644); MODULE_PARM_DESC(i2c_debug,"enable debug messages [i2c]"); -static unsigned int i2c_scan = 0; +static unsigned int i2c_scan; module_param(i2c_scan, int, 0444); MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time"); diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index b4188819782f..65f8e594d6fb 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -27,15 +27,15 @@ #include "saa7134-reg.h" #include "saa7134.h" -static unsigned int disable_ir = 0; +static unsigned int disable_ir; module_param(disable_ir, int, 0444); MODULE_PARM_DESC(disable_ir,"disable infrared remote support"); -static unsigned int ir_debug = 0; +static unsigned int ir_debug; module_param(ir_debug, int, 0644); MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]"); -static int pinnacle_remote = 0; +static int pinnacle_remote; module_param(pinnacle_remote, int, 0644); /* Choose Pinnacle PCTV remote */ MODULE_PARM_DESC(pinnacle_remote, "Specify Pinnacle PCTV remote: 0=coloured, 1=grey (defaults to 0)"); diff --git a/drivers/media/video/saa7134/saa7134-ts.c b/drivers/media/video/saa7134/saa7134-ts.c index f1b8fcaeb43a..eae72fd60cec 100644 --- a/drivers/media/video/saa7134/saa7134-ts.c +++ b/drivers/media/video/saa7134/saa7134-ts.c @@ -32,7 +32,7 @@ /* ------------------------------------------------------------------ */ -static unsigned int ts_debug = 0; +static unsigned int ts_debug; module_param(ts_debug, int, 0644); MODULE_PARM_DESC(ts_debug,"enable debug messages [ts]"); diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c index 4e9810469ae3..b90c55c0536e 100644 --- a/drivers/media/video/saa7134/saa7134-tvaudio.c +++ b/drivers/media/video/saa7134/saa7134-tvaudio.c @@ -35,18 +35,18 @@ /* ------------------------------------------------------------------ */ -static unsigned int audio_debug = 0; +static unsigned int audio_debug; module_param(audio_debug, int, 0644); MODULE_PARM_DESC(audio_debug,"enable debug messages [tv audio]"); -static unsigned int audio_ddep = 0; +static unsigned int audio_ddep; module_param(audio_ddep, int, 0644); MODULE_PARM_DESC(audio_ddep,"audio ddep overwrite"); static int audio_clock_override = UNSET; module_param(audio_clock_override, int, 0644); -static int audio_clock_tweak = 0; +static int audio_clock_tweak; module_param(audio_clock_tweak, int, 0644); MODULE_PARM_DESC(audio_clock_tweak, "Audio clock tick fine tuning for cards with audio crystal that's slightly off (range [-1024 .. 1024])"); diff --git a/drivers/media/video/saa7134/saa7134-vbi.c b/drivers/media/video/saa7134/saa7134-vbi.c index f0d5ed9c2b06..cb0304298a96 100644 --- a/drivers/media/video/saa7134/saa7134-vbi.c +++ b/drivers/media/video/saa7134/saa7134-vbi.c @@ -31,7 +31,7 @@ /* ------------------------------------------------------------------ */ -static unsigned int vbi_debug = 0; +static unsigned int vbi_debug; module_param(vbi_debug, int, 0644); MODULE_PARM_DESC(vbi_debug,"enable debug messages [vbi]"); diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index 39c41ad97d0e..5385026a85ef 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -40,7 +40,7 @@ unsigned int video_debug; static unsigned int gbuffers = 8; -static unsigned int noninterlaced = 0; +static unsigned int noninterlaced; /* 0 */ static unsigned int gbufsize = 720*576*4; static unsigned int gbufsize_max = 720*576*4; static char secam[] = "--"; diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index f940d0254798..d7e0781fe8a1 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -253,7 +253,10 @@ struct saa7134_format { #define SAA7134_BOARD_BEHOLD_607_9FM 129 #define SAA7134_BOARD_BEHOLD_M6 130 #define SAA7134_BOARD_TWINHAN_DTV_DVB_3056 131 -#define SAA7134_BOARD_GENIUS_TVGO_A11MCE 132 +#define SAA7134_BOARD_GENIUS_TVGO_A11MCE 132 +#define SAA7134_BOARD_PHILIPS_SNAKE 133 +#define SAA7134_BOARD_CREATIX_CTX953 134 +#define SAA7134_BOARD_MSI_TVANYWHERE_AD11 135 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 @@ -556,7 +559,9 @@ struct saa7134_dev { #if defined(CONFIG_VIDEO_SAA7134_DVB) || defined(CONFIG_VIDEO_SAA7134_DVB_MODULE) /* SAA7134_MPEG_DVB only */ struct videobuf_dvb dvb; - int (*original_demod_sleep)(struct dvb_frontend* fe); + int (*original_demod_sleep)(struct dvb_frontend *fe); + int (*original_set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage); + int (*original_set_high_voltage)(struct dvb_frontend *fe, long arg); #endif }; diff --git a/drivers/media/video/saa7185.c b/drivers/media/video/saa7185.c index 66cc92c0ea66..14d9ee290afc 100644 --- a/drivers/media/video/saa7185.c +++ b/drivers/media/video/saa7185.c @@ -52,7 +52,7 @@ MODULE_LICENSE("GPL"); #define I2C_NAME(s) (s)->name -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); diff --git a/drivers/media/video/se401.c b/drivers/media/video/se401.c index d5d7d6cf734a..312a01a1f095 100644 --- a/drivers/media/video/se401.c +++ b/drivers/media/video/se401.c @@ -35,7 +35,7 @@ static const char version[] = "0.24"; #include <linux/usb.h> #include "se401.h" -static int flickerless=0; +static int flickerless; static int video_nr = -1; static struct usb_device_id device_table [] = { diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c index c40ba3adab21..94f393eebd51 100644 --- a/drivers/media/video/sn9c102/sn9c102_core.c +++ b/drivers/media/video/sn9c102/sn9c102_core.c @@ -528,7 +528,7 @@ sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len) /* Search for the SOF marker (fixed part) in the header */ for (j = 0, b=cam->sof.bytesread; j+b < sizeof(marker); j++) { - if (unlikely(i+j) == len) + if (unlikely(i+j == len)) return NULL; if (*(m+i+j) == marker[cam->sof.bytesread]) { cam->sof.header[cam->sof.bytesread] = *(m+i+j); @@ -3239,7 +3239,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) { struct usb_device *udev = interface_to_usbdev(intf); struct sn9c102_device* cam; - static unsigned int dev_nr = 0; + static unsigned int dev_nr; unsigned int i; int err = 0, r; diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c new file mode 100644 index 000000000000..904e9dfc1a89 --- /dev/null +++ b/drivers/media/video/soc_camera.c @@ -0,0 +1,973 @@ +/* + * camera image capture (abstract) bus driver + * + * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de> + * + * This driver provides an interface between platform-specific camera + * busses and camera devices. It should be used if the camera is + * connected not over a "proper" bus like PCI or USB, but over a + * special bus, like, for example, the Quick Capture interface on PXA270 + * SoCs. Later it should also be used for i.MX31 SoCs from Freescale. + * It can handle multiple cameras and / or multiple busses, which can + * be used, e.g., in stereo-vision applications. + * + * 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 <linux/module.h> +#include <linux/init.h> +#include <linux/device.h> +#include <linux/list.h> +#include <linux/err.h> +#include <linux/mutex.h> +#include <linux/vmalloc.h> + +#include <media/v4l2-common.h> +#include <media/v4l2-dev.h> +#include <media/soc_camera.h> + +static LIST_HEAD(hosts); +static LIST_HEAD(devices); +static DEFINE_MUTEX(list_lock); +static DEFINE_MUTEX(video_lock); + +const static struct soc_camera_data_format* +format_by_fourcc(struct soc_camera_device *icd, unsigned int fourcc) +{ + unsigned int i; + + for (i = 0; i < icd->ops->num_formats; i++) + if (icd->ops->formats[i].fourcc == fourcc) + return icd->ops->formats + i; + return NULL; +} + +static int soc_camera_try_fmt_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + enum v4l2_field field; + const struct soc_camera_data_format *fmt; + int ret; + + WARN_ON(priv != file->private_data); + + fmt = format_by_fourcc(icd, f->fmt.pix.pixelformat); + if (!fmt) { + dev_dbg(&icd->dev, "invalid format 0x%08x\n", + f->fmt.pix.pixelformat); + return -EINVAL; + } + + dev_dbg(&icd->dev, "fmt: 0x%08x\n", fmt->fourcc); + + field = f->fmt.pix.field; + + if (field == V4L2_FIELD_ANY) { + field = V4L2_FIELD_NONE; + } else if (V4L2_FIELD_NONE != field) { + dev_err(&icd->dev, "Field type invalid.\n"); + return -EINVAL; + } + + /* limit to host capabilities */ + ret = ici->try_fmt_cap(ici, f); + + /* limit to sensor capabilities */ + if (!ret) + ret = icd->ops->try_fmt_cap(icd, f); + + /* calculate missing fields */ + 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; + + return ret; +} + +static int soc_camera_enum_input(struct file *file, void *priv, + struct v4l2_input *inp) +{ + if (inp->index != 0) + return -EINVAL; + + inp->type = V4L2_INPUT_TYPE_CAMERA; + inp->std = V4L2_STD_UNKNOWN; + strcpy(inp->name, "Camera"); + + return 0; +} + +static int soc_camera_g_input(struct file *file, void *priv, unsigned int *i) +{ + *i = 0; + + return 0; +} + +static int soc_camera_s_input(struct file *file, void *priv, unsigned int i) +{ + if (i > 0) + return -EINVAL; + + return 0; +} + +static int soc_camera_s_std(struct file *file, void *priv, v4l2_std_id *a) +{ + return 0; +} + +static int soc_camera_reqbufs(struct file *file, void *priv, + struct v4l2_requestbuffers *p) +{ + int ret; + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + + WARN_ON(priv != file->private_data); + + dev_dbg(&icd->dev, "%s: %d\n", __FUNCTION__, p->memory); + + ret = videobuf_reqbufs(&icf->vb_vidq, p); + if (ret < 0) + return ret; + + return ici->reqbufs(icf, p); + + return ret; +} + +static int soc_camera_querybuf(struct file *file, void *priv, + struct v4l2_buffer *p) +{ + struct soc_camera_file *icf = file->private_data; + + WARN_ON(priv != file->private_data); + + return videobuf_querybuf(&icf->vb_vidq, p); +} + +static int soc_camera_qbuf(struct file *file, void *priv, + struct v4l2_buffer *p) +{ + struct soc_camera_file *icf = file->private_data; + + WARN_ON(priv != file->private_data); + + return videobuf_qbuf(&icf->vb_vidq, p); +} + +static int soc_camera_dqbuf(struct file *file, void *priv, + struct v4l2_buffer *p) +{ + struct soc_camera_file *icf = file->private_data; + + WARN_ON(priv != file->private_data); + + return videobuf_dqbuf(&icf->vb_vidq, p, file->f_flags & O_NONBLOCK); +} + +static int soc_camera_open(struct inode *inode, struct file *file) +{ + struct video_device *vdev = video_devdata(file); + struct soc_camera_device *icd = container_of(vdev->dev, + struct soc_camera_device, dev); + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + struct soc_camera_file *icf; + int ret; + + icf = vmalloc(sizeof(*icf)); + if (!icf) + return -ENOMEM; + + icf->icd = icd; + + if (!try_module_get(icd->ops->owner)) { + dev_err(&icd->dev, "Couldn't lock sensor driver.\n"); + ret = -EINVAL; + goto emgd; + } + + if (!try_module_get(ici->owner)) { + dev_err(&icd->dev, "Couldn't lock capture bus driver.\n"); + ret = -EINVAL; + goto emgi; + } + + file->private_data = icf; + dev_dbg(&icd->dev, "camera device open\n"); + + /* We must pass NULL as dev pointer, then all pci_* dma operations + * transform to normal dma_* ones. Do we need an irqlock? */ + videobuf_queue_pci_init(&icf->vb_vidq, ici->vbq_ops, NULL, NULL, + V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, + ici->msize, icd); + + return 0; + +emgi: + module_put(icd->ops->owner); +emgd: + vfree(icf); + return ret; +} + +static int soc_camera_close(struct inode *inode, struct file *file) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct video_device *vdev = icd->vdev; + + module_put(icd->ops->owner); + module_put(ici->owner); + vfree(file->private_data); + + dev_dbg(vdev->dev, "camera device close\n"); + + return 0; +} + +static int soc_camera_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + struct video_device *vdev = icd->vdev; + int err = -EINVAL; + + dev_err(vdev->dev, "camera device read not implemented\n"); + + return err; +} + +static int soc_camera_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + int err; + + dev_dbg(&icd->dev, "mmap called, vma=0x%08lx\n", (unsigned long)vma); + + err = videobuf_mmap_mapper(&icf->vb_vidq, vma); + + dev_dbg(&icd->dev, "vma start=0x%08lx, size=%ld, ret=%d\n", + (unsigned long)vma->vm_start, + (unsigned long)vma->vm_end - (unsigned long)vma->vm_start, + err); + + return err; +} + +static unsigned int soc_camera_poll(struct file *file, poll_table *pt) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + + if (list_empty(&icf->vb_vidq.stream)) { + dev_err(&icd->dev, "Trying to poll with no queued buffers!\n"); + return POLLERR; + } + + return ici->poll(file, pt); +} + + +static struct file_operations soc_camera_fops = { + .owner = THIS_MODULE, + .open = soc_camera_open, + .release = soc_camera_close, + .ioctl = video_ioctl2, + .read = soc_camera_read, + .mmap = soc_camera_mmap, + .poll = soc_camera_poll, + .llseek = no_llseek, +}; + + +static int soc_camera_s_fmt_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + int ret; + struct v4l2_rect rect; + const static struct soc_camera_data_format *data_fmt; + + WARN_ON(priv != file->private_data); + + data_fmt = format_by_fourcc(icd, f->fmt.pix.pixelformat); + if (!data_fmt) + return -EINVAL; + + /* cached_datawidth may be further adjusted by the ici */ + icd->cached_datawidth = data_fmt->depth; + + ret = soc_camera_try_fmt_cap(file, icf, f); + if (ret < 0) + return ret; + + rect.left = icd->x_current; + rect.top = icd->y_current; + rect.width = f->fmt.pix.width; + rect.height = f->fmt.pix.height; + ret = ici->set_capture_format(icd, f->fmt.pix.pixelformat, &rect); + + if (!ret) { + icd->current_fmt = data_fmt; + icd->width = rect.width; + icd->height = rect.height; + icf->vb_vidq.field = f->fmt.pix.field; + if (V4L2_BUF_TYPE_VIDEO_CAPTURE != f->type) + dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n", + f->type); + + dev_dbg(&icd->dev, "set width: %d height: %d\n", + icd->width, icd->height); + } + + return ret; +} + +static int soc_camera_enum_fmt_cap(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + const struct soc_camera_data_format *format; + + WARN_ON(priv != file->private_data); + + if (f->index >= icd->ops->num_formats) + return -EINVAL; + + format = &icd->ops->formats[f->index]; + + strlcpy(f->description, format->name, sizeof(f->description)); + f->pixelformat = format->fourcc; + return 0; +} + +static int soc_camera_g_fmt_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + + WARN_ON(priv != file->private_data); + + f->fmt.pix.width = icd->width; + f->fmt.pix.height = icd->height; + f->fmt.pix.field = icf->vb_vidq.field; + f->fmt.pix.pixelformat = icd->current_fmt->fourcc; + f->fmt.pix.bytesperline = + (f->fmt.pix.width * icd->current_fmt->depth) >> 3; + f->fmt.pix.sizeimage = + f->fmt.pix.height * f->fmt.pix.bytesperline; + dev_dbg(&icd->dev, "current_fmt->fourcc: 0x%08x\n", + icd->current_fmt->fourcc); + return 0; +} + +static int soc_camera_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + + WARN_ON(priv != file->private_data); + + strlcpy(cap->driver, ici->drv_name, sizeof(cap->driver)); + return ici->querycap(ici, cap); +} + +static int soc_camera_streamon(struct file *file, void *priv, + enum v4l2_buf_type i) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + + WARN_ON(priv != file->private_data); + + dev_dbg(&icd->dev, "%s\n", __FUNCTION__); + + if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + icd->ops->start_capture(icd); + + /* This calls buf_queue from host driver's videobuf_queue_ops */ + return videobuf_streamon(&icf->vb_vidq); +} + +static int soc_camera_streamoff(struct file *file, void *priv, + enum v4l2_buf_type i) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + + WARN_ON(priv != file->private_data); + + dev_dbg(&icd->dev, "%s\n", __FUNCTION__); + + if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + /* This calls buf_release from host driver's videobuf_queue_ops for all + * remaining buffers. When the last buffer is freed, stop capture */ + videobuf_streamoff(&icf->vb_vidq); + + icd->ops->stop_capture(icd); + + return 0; +} + +static int soc_camera_queryctrl(struct file *file, void *priv, + struct v4l2_queryctrl *qc) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + int i; + + WARN_ON(priv != file->private_data); + + if (!qc->id) + return -EINVAL; + + for (i = 0; i < icd->ops->num_controls; i++) + if (qc->id == icd->ops->controls[i].id) { + memcpy(qc, &(icd->ops->controls[i]), + sizeof(*qc)); + return 0; + } + + return -EINVAL; +} + +static int soc_camera_g_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + + WARN_ON(priv != file->private_data); + + switch (ctrl->id) { + case V4L2_CID_GAIN: + if (icd->gain == (unsigned short)~0) + return -EINVAL; + ctrl->value = icd->gain; + return 0; + case V4L2_CID_EXPOSURE: + if (icd->exposure == (unsigned short)~0) + return -EINVAL; + ctrl->value = icd->exposure; + return 0; + } + + if (icd->ops->get_control) + return icd->ops->get_control(icd, ctrl); + return -EINVAL; +} + +static int soc_camera_s_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + + WARN_ON(priv != file->private_data); + + if (icd->ops->set_control) + return icd->ops->set_control(icd, ctrl); + return -EINVAL; +} + +static int soc_camera_cropcap(struct file *file, void *fh, + struct v4l2_cropcap *a) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + a->bounds.left = icd->x_min; + a->bounds.top = icd->y_min; + a->bounds.width = icd->width_max; + a->bounds.height = icd->height_max; + a->defrect.left = icd->x_min; + a->defrect.top = icd->y_min; + a->defrect.width = 640; + a->defrect.height = 480; + a->pixelaspect.numerator = 1; + a->pixelaspect.denominator = 1; + + return 0; +} + +static int soc_camera_g_crop(struct file *file, void *fh, + struct v4l2_crop *a) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + a->c.left = icd->x_current; + a->c.top = icd->y_current; + a->c.width = icd->width; + a->c.height = icd->height; + + return 0; +} + +static int soc_camera_s_crop(struct file *file, void *fh, + struct v4l2_crop *a) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + int ret; + + if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + ret = ici->set_capture_format(icd, 0, &a->c); + if (!ret) { + icd->width = a->c.width; + icd->height = a->c.height; + icd->x_current = a->c.left; + icd->y_current = a->c.top; + } + + return ret; +} + +static int soc_camera_g_chip_ident(struct file *file, void *fh, + struct v4l2_chip_ident *id) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + + if (!icd->ops->get_chip_id) + return -EINVAL; + + return icd->ops->get_chip_id(icd, id); +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int soc_camera_g_register(struct file *file, void *fh, + struct v4l2_register *reg) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + + if (!icd->ops->get_register) + return -EINVAL; + + return icd->ops->get_register(icd, reg); +} + +static int soc_camera_s_register(struct file *file, void *fh, + struct v4l2_register *reg) +{ + struct soc_camera_file *icf = file->private_data; + struct soc_camera_device *icd = icf->icd; + + if (!icd->ops->set_register) + return -EINVAL; + + return icd->ops->set_register(icd, reg); +} +#endif + +static int device_register_link(struct soc_camera_device *icd) +{ + int ret = device_register(&icd->dev); + + if (ret < 0) { + /* Prevent calling device_unregister() */ + icd->dev.parent = NULL; + dev_err(&icd->dev, "Cannot register device: %d\n", ret); + /* Even if probe() was unsuccessful for all registered drivers, + * device_register() returns 0, and we add the link, just to + * document this camera's control device */ + } else if (icd->control) + /* Have to sysfs_remove_link() before device_unregister()? */ + if (sysfs_create_link(&icd->dev.kobj, &icd->control->kobj, + "control")) + dev_warn(&icd->dev, + "Failed creating the control symlink\n"); + return ret; +} + +/* So far this function cannot fail */ +static void scan_add_host(struct soc_camera_host *ici) +{ + struct soc_camera_device *icd; + + mutex_lock(&list_lock); + + list_for_each_entry(icd, &devices, list) { + if (icd->iface == ici->nr) { + icd->dev.parent = &ici->dev; + device_register_link(icd); + } + } + + mutex_unlock(&list_lock); +} + +/* return: 0 if no match found or a match found and + * device_register() successful, error code otherwise */ +static int scan_add_device(struct soc_camera_device *icd) +{ + struct soc_camera_host *ici; + int ret = 0; + + mutex_lock(&list_lock); + + list_add_tail(&icd->list, &devices); + + /* Watch out for class_for_each_device / class_find_device API by + * Dave Young <hidave.darkstar@gmail.com> */ + list_for_each_entry(ici, &hosts, list) { + if (icd->iface == ici->nr) { + ret = 1; + icd->dev.parent = &ici->dev; + break; + } + } + + mutex_unlock(&list_lock); + + if (ret) + ret = device_register_link(icd); + + return ret; +} + +static int soc_camera_probe(struct device *dev) +{ + struct soc_camera_device *icd = to_soc_camera_dev(dev); + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + int ret; + + if (!icd->probe) + return -ENODEV; + + ret = ici->add(icd); + if (ret < 0) + return ret; + + ret = icd->probe(icd); + if (ret < 0) + ici->remove(icd); + else { + const struct v4l2_queryctrl *qctrl; + + qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_GAIN); + icd->gain = qctrl ? qctrl->default_value : (unsigned short)~0; + qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); + icd->exposure = qctrl ? qctrl->default_value : + (unsigned short)~0; + } + + return ret; +} + +/* This is called on device_unregister, which only means we have to disconnect + * from the host, but not remove ourselves from the device list */ +static int soc_camera_remove(struct device *dev) +{ + struct soc_camera_device *icd = to_soc_camera_dev(dev); + struct soc_camera_host *ici = + to_soc_camera_host(icd->dev.parent); + + if (icd->remove) + icd->remove(icd); + + ici->remove(icd); + + return 0; +} + +static struct bus_type soc_camera_bus_type = { + .name = "soc-camera", + .probe = soc_camera_probe, + .remove = soc_camera_remove, +}; + +static struct device_driver ic_drv = { + .name = "camera", + .bus = &soc_camera_bus_type, + .owner = THIS_MODULE, +}; + +/* + * Image capture host - this is a host device, not a bus device, so, + * no bus reference, no probing. + */ +static struct class soc_camera_host_class = { + .owner = THIS_MODULE, + .name = "camera_host", +}; + +static void dummy_release(struct device *dev) +{ +} + +int soc_camera_host_register(struct soc_camera_host *ici, struct module *owner) +{ + int ret; + struct soc_camera_host *ix; + + if (!ici->vbq_ops || !ici->add || !ici->remove || !owner) + return -EINVAL; + + /* Number might be equal to the platform device ID */ + sprintf(ici->dev.bus_id, "camera_host%d", ici->nr); + ici->dev.class = &soc_camera_host_class; + + mutex_lock(&list_lock); + list_for_each_entry(ix, &hosts, list) { + if (ix->nr == ici->nr) { + mutex_unlock(&list_lock); + return -EBUSY; + } + } + + list_add_tail(&ici->list, &hosts); + mutex_unlock(&list_lock); + + ici->owner = owner; + ici->dev.release = dummy_release; + + ret = device_register(&ici->dev); + + if (ret) + goto edevr; + + scan_add_host(ici); + + return 0; + +edevr: + mutex_lock(&list_lock); + list_del(&ici->list); + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(soc_camera_host_register); + +/* Unregister all clients! */ +void soc_camera_host_unregister(struct soc_camera_host *ici) +{ + struct soc_camera_device *icd; + + mutex_lock(&list_lock); + + list_del(&ici->list); + + list_for_each_entry(icd, &devices, list) { + if (icd->dev.parent == &ici->dev) { + device_unregister(&icd->dev); + /* Not before device_unregister(), .remove + * needs parent to call ici->remove() */ + icd->dev.parent = NULL; + memset(&icd->dev.kobj, 0, sizeof(icd->dev.kobj)); + } + } + + mutex_unlock(&list_lock); + + device_unregister(&ici->dev); +} +EXPORT_SYMBOL(soc_camera_host_unregister); + +/* Image capture device */ +int soc_camera_device_register(struct soc_camera_device *icd) +{ + struct soc_camera_device *ix; + int num = -1, i; + + if (!icd) + return -EINVAL; + + for (i = 0; i < 256 && num < 0; i++) { + num = i; + list_for_each_entry(ix, &devices, list) { + if (ix->iface == icd->iface && ix->devnum == i) { + num = -1; + break; + } + } + } + + if (num < 0) + /* ok, we have 256 cameras on this host... + * man, stay reasonable... */ + return -ENOMEM; + + icd->devnum = num; + icd->dev.bus = &soc_camera_bus_type; + snprintf(icd->dev.bus_id, sizeof(icd->dev.bus_id), + "%u-%u", icd->iface, icd->devnum); + + icd->dev.release = dummy_release; + + if (icd->ops->get_datawidth) + icd->cached_datawidth = icd->ops->get_datawidth(icd); + + return scan_add_device(icd); +} +EXPORT_SYMBOL(soc_camera_device_register); + +void soc_camera_device_unregister(struct soc_camera_device *icd) +{ + mutex_lock(&list_lock); + list_del(&icd->list); + + /* The bus->remove will be eventually called */ + if (icd->dev.parent) + device_unregister(&icd->dev); + mutex_unlock(&list_lock); +} +EXPORT_SYMBOL(soc_camera_device_unregister); + +int soc_camera_video_start(struct soc_camera_device *icd) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + int err = -ENOMEM; + struct video_device *vdev; + + if (!icd->dev.parent) + return -ENODEV; + + vdev = video_device_alloc(); + if (!vdev) + goto evidallocd; + dev_dbg(&ici->dev, "Allocated video_device %p\n", vdev); + + strlcpy(vdev->name, ici->drv_name, sizeof(vdev->name)); + /* Maybe better &ici->dev */ + vdev->dev = &icd->dev; + vdev->type = VID_TYPE_CAPTURE; + vdev->current_norm = V4L2_STD_UNKNOWN; + vdev->fops = &soc_camera_fops; + vdev->release = video_device_release; + vdev->minor = -1; + vdev->tvnorms = V4L2_STD_UNKNOWN, + vdev->vidioc_querycap = soc_camera_querycap; + vdev->vidioc_g_fmt_cap = soc_camera_g_fmt_cap; + vdev->vidioc_enum_fmt_cap = soc_camera_enum_fmt_cap; + vdev->vidioc_s_fmt_cap = soc_camera_s_fmt_cap; + vdev->vidioc_enum_input = soc_camera_enum_input; + vdev->vidioc_g_input = soc_camera_g_input; + vdev->vidioc_s_input = soc_camera_s_input; + vdev->vidioc_s_std = soc_camera_s_std; + vdev->vidioc_reqbufs = soc_camera_reqbufs; + vdev->vidioc_try_fmt_cap = soc_camera_try_fmt_cap; + vdev->vidioc_querybuf = soc_camera_querybuf; + vdev->vidioc_qbuf = soc_camera_qbuf; + vdev->vidioc_dqbuf = soc_camera_dqbuf; + vdev->vidioc_streamon = soc_camera_streamon; + vdev->vidioc_streamoff = soc_camera_streamoff; + vdev->vidioc_queryctrl = soc_camera_queryctrl; + vdev->vidioc_g_ctrl = soc_camera_g_ctrl; + vdev->vidioc_s_ctrl = soc_camera_s_ctrl; + vdev->vidioc_cropcap = soc_camera_cropcap; + vdev->vidioc_g_crop = soc_camera_g_crop; + vdev->vidioc_s_crop = soc_camera_s_crop; + vdev->vidioc_g_chip_ident = soc_camera_g_chip_ident; +#ifdef CONFIG_VIDEO_ADV_DEBUG + vdev->vidioc_g_register = soc_camera_g_register; + vdev->vidioc_s_register = soc_camera_s_register; +#endif + + icd->current_fmt = &icd->ops->formats[0]; + + err = video_register_device(vdev, VFL_TYPE_GRABBER, vdev->minor); + if (err < 0) { + dev_err(vdev->dev, "video_register_device failed\n"); + goto evidregd; + } + icd->vdev = vdev; + + return 0; + +evidregd: + video_device_release(vdev); +evidallocd: + return err; +} +EXPORT_SYMBOL(soc_camera_video_start); + +void soc_camera_video_stop(struct soc_camera_device *icd) +{ + struct video_device *vdev = icd->vdev; + + dev_dbg(&icd->dev, "%s\n", __FUNCTION__); + + if (!icd->dev.parent || !vdev) + return; + + mutex_lock(&video_lock); + video_unregister_device(vdev); + icd->vdev = NULL; + mutex_unlock(&video_lock); +} +EXPORT_SYMBOL(soc_camera_video_stop); + +static int __init soc_camera_init(void) +{ + int ret = bus_register(&soc_camera_bus_type); + if (ret) + return ret; + ret = driver_register(&ic_drv); + if (ret) + goto edrvr; + ret = class_register(&soc_camera_host_class); + if (ret) + goto eclr; + + return 0; + +eclr: + driver_unregister(&ic_drv); +edrvr: + bus_unregister(&soc_camera_bus_type); + return ret; +} + +static void __exit soc_camera_exit(void) +{ + class_unregister(&soc_camera_host_class); + driver_unregister(&ic_drv); + bus_unregister(&soc_camera_bus_type); +} + +module_init(soc_camera_init); +module_exit(soc_camera_exit); + +MODULE_DESCRIPTION("Image capture bus driver"); +MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c index 3fb85af5d1f2..3118dd322b24 100644 --- a/drivers/media/video/stradis.c +++ b/drivers/media/video/stradis.c @@ -58,7 +58,7 @@ static struct saa7146 saa7146s[SAA7146_MAX]; -static int saa_num = 0; /* number of SAA7146s in use */ +static int saa_num; /* number of SAA7146s in use */ static int video_nr = -1; module_param(video_nr, int, 0); @@ -248,7 +248,7 @@ static void I2CBusScan(struct saa7146 *saa) attach_inform(saa, i); } -static int debiwait_maxwait = 0; +static int debiwait_maxwait; static int wait_for_debi_done(struct saa7146 *saa) { diff --git a/drivers/media/video/stv680.c b/drivers/media/video/stv680.c index afc32aa56fde..1542797c048f 100644 --- a/drivers/media/video/stv680.c +++ b/drivers/media/video/stv680.c @@ -72,10 +72,13 @@ #include "stv680.h" static int video_nr = -1; -static int swapRGB = 0; /* default for auto sleect */ -static int swapRGB_on = 0; /* default to allow auto select; -1=swap never, +1= swap always */ -static unsigned int debug = 0; +static int swapRGB; /* 0 = default for auto select */ + +/* 0 = default to allow auto select; -1 = swap never, +1 = swap always */ +static int swapRGB_on; + +static unsigned int debug; #define PDEBUG(level, fmt, args...) \ do { \ diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index 55bc89a6f069..6f2449ab46a0 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -32,8 +32,6 @@ static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); -#define PREFIX "tda8290" - /* ---------------------------------------------------------------------- */ struct tda8290_priv { @@ -674,6 +672,7 @@ struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe, priv->i2c_props.addr = i2c_addr; priv->i2c_props.adap = i2c_adap; + priv->i2c_props.name = "tda829x"; if (cfg) { priv->cfg.config = cfg->lna_cfg; priv->cfg.tuner_callback = cfg->tuner_callback; diff --git a/drivers/media/video/tda9840.c b/drivers/media/video/tda9840.c index ef494febb5e4..845fc9009f5a 100644 --- a/drivers/media/video/tda9840.c +++ b/drivers/media/video/tda9840.c @@ -31,7 +31,7 @@ #include "tda9840.h" -static int debug = 0; /* insmod parameter */ +static int debug; /* insmod parameter */ module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off)."); #define dprintk(args...) \ diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index 106c93b8203f..75d08404d238 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c @@ -25,8 +25,6 @@ static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); -#define PREFIX "tda9887" - struct tda9887_priv { struct tuner_i2c_props i2c_props; @@ -673,6 +671,7 @@ struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe, priv->i2c_props.addr = i2c_addr; priv->i2c_props.adap = i2c_adap; + priv->i2c_props.name = "tda9887"; priv->mode = T_STANDBY; tuner_info("tda988[5/6/7] found\n"); diff --git a/drivers/media/video/tea5761.c b/drivers/media/video/tea5761.c index 5326eeceaacd..bd5ad549c1df 100644 --- a/drivers/media/video/tea5761.c +++ b/drivers/media/video/tea5761.c @@ -14,12 +14,10 @@ #include "tuner-i2c.h" #include "tea5761.h" -static int debug = 0; +static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); -#define PREFIX "tea5761" - struct tea5761_priv { struct tuner_i2c_props i2c_props; @@ -131,7 +129,7 @@ static void tea5761_status_dump(unsigned char *buffer) frq = 1000 * (div * 32768 / 1000 + FREQ_OFFSET + 225) / 4; /* Freq in KHz */ - printk(PREFIX "Frequency %d.%03d KHz (divider = 0x%04x)\n", + printk(KERN_INFO "tea5761: Frequency %d.%03d KHz (divider = 0x%04x)\n", frq / 1000, frq % 1000, div); } @@ -302,6 +300,7 @@ struct dvb_frontend *tea5761_attach(struct dvb_frontend *fe, priv->i2c_props.addr = i2c_addr; priv->i2c_props.adap = i2c_adap; + priv->i2c_props.name = "tea5761"; memcpy(&fe->ops.tuner_ops, &tea5761_tuner_ops, sizeof(struct dvb_tuner_ops)); diff --git a/drivers/media/video/tea5767.c b/drivers/media/video/tea5767.c index e1b48d87e7b7..833f2768958d 100644 --- a/drivers/media/video/tea5767.c +++ b/drivers/media/video/tea5767.c @@ -16,12 +16,10 @@ #include "tuner-i2c.h" #include "tea5767.h" -static int debug = 0; +static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); -#define PREFIX "tea5767" - /*****************************************************************************/ struct tea5767_priv { @@ -137,14 +135,14 @@ static void tea5767_status_dump(struct tea5767_priv *priv, unsigned int div, frq; if (TEA5767_READY_FLAG_MASK & buffer[0]) - printk(PREFIX "Ready Flag ON\n"); + tuner_info("Ready Flag ON\n"); else - printk(PREFIX "Ready Flag OFF\n"); + tuner_info("Ready Flag OFF\n"); if (TEA5767_BAND_LIMIT_MASK & buffer[0]) - printk(PREFIX "Tuner at band limit\n"); + tuner_info("Tuner at band limit\n"); else - printk(PREFIX "Tuner not at band limit\n"); + tuner_info("Tuner not at band limit\n"); div = ((buffer[0] & 0x3f) << 8) | buffer[1]; @@ -166,23 +164,23 @@ static void tea5767_status_dump(struct tea5767_priv *priv, buffer[0] = (div >> 8) & 0x3f; buffer[1] = div & 0xff; - printk(PREFIX "Frequency %d.%03d KHz (divider = 0x%04x)\n", - frq / 1000, frq % 1000, div); + tuner_info("Frequency %d.%03d KHz (divider = 0x%04x)\n", + frq / 1000, frq % 1000, div); if (TEA5767_STEREO_MASK & buffer[2]) - printk(PREFIX "Stereo\n"); + tuner_info("Stereo\n"); else - printk(PREFIX "Mono\n"); + tuner_info("Mono\n"); - printk(PREFIX "IF Counter = %d\n", buffer[2] & TEA5767_IF_CNTR_MASK); + tuner_info("IF Counter = %d\n", buffer[2] & TEA5767_IF_CNTR_MASK); - printk(PREFIX "ADC Level = %d\n", - (buffer[3] & TEA5767_ADC_LEVEL_MASK) >> 4); + tuner_info("ADC Level = %d\n", + (buffer[3] & TEA5767_ADC_LEVEL_MASK) >> 4); - printk(PREFIX "Chip ID = %d\n", (buffer[3] & TEA5767_CHIP_ID_MASK)); + tuner_info("Chip ID = %d\n", (buffer[3] & TEA5767_CHIP_ID_MASK)); - printk(PREFIX "Reserved = 0x%02x\n", - (buffer[4] & TEA5767_RESERVED_MASK)); + tuner_info("Reserved = 0x%02x\n", + (buffer[4] & TEA5767_RESERVED_MASK)); } /* Freq should be specifyed at 62.5 Hz */ @@ -456,6 +454,8 @@ struct dvb_frontend *tea5767_attach(struct dvb_frontend *fe, priv->i2c_props.addr = i2c_addr; priv->i2c_props.adap = i2c_adap; + priv->i2c_props.name = "tea5767"; + priv->ctrl.xtal_freq = TEA5767_HIGH_LO_32768; priv->ctrl.port1 = 1; priv->ctrl.port2 = 1; diff --git a/drivers/media/video/tea6415c.c b/drivers/media/video/tea6415c.c index 523df0b8cc63..32c0b48c3d11 100644 --- a/drivers/media/video/tea6415c.c +++ b/drivers/media/video/tea6415c.c @@ -33,7 +33,7 @@ #include "tea6415c.h" -static int debug = 0; /* insmod parameter */ +static int debug; /* insmod parameter */ module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off)."); #define dprintk(args...) \ diff --git a/drivers/media/video/tea6420.c b/drivers/media/video/tea6420.c index ca05cd655087..215b104afe26 100644 --- a/drivers/media/video/tea6420.c +++ b/drivers/media/video/tea6420.c @@ -33,7 +33,7 @@ #include "tea6420.h" -static int debug = 0; /* insmod parameter */ +static int debug; /* insmod parameter */ module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off)."); #define dprintk(args...) \ diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 78a09a2a4857..335a971298a3 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -68,9 +68,9 @@ static unsigned short normal_i2c[] = { I2C_CLIENT_INSMOD; /* insmod options used at init time => read/only */ -static unsigned int addr = 0; -static unsigned int no_autodetect = 0; -static unsigned int show_i2c = 0; +static unsigned int addr; +static unsigned int no_autodetect; +static unsigned int show_i2c; /* insmod options used at runtime => read/write */ static int tuner_debug; @@ -313,20 +313,10 @@ static void tuner_i2c_address_check(struct tuner *t) tuner_warn("output to v4l-dvb-maintainer@linuxtv.org\n"); tuner_warn("Please use subject line: \"obsolete tuner i2c address.\"\n"); tuner_warn("driver: %s, addr: 0x%02x, type: %d (%s)\n", - t->i2c->adapter->name, t->i2c->addr, t->type, - tuners[t->type].name); + t->i2c->adapter->name, t->i2c->addr, t->type, t->i2c->name); tuner_warn("====================== WARNING! ======================\n"); } -static void attach_simple_tuner(struct tuner *t) -{ - struct simple_tuner_config cfg = { - .type = t->type, - .tun = &tuners[t->type] - }; - simple_tuner_attach(&t->fe, t->i2c->adapter, t->i2c->addr, &cfg); -} - static void attach_tda829x(struct tuner *t) { struct tda829x_config cfg = { @@ -352,11 +342,6 @@ static void set_type(struct i2c_client *c, unsigned int type, return; } - if (type >= tuner_count) { - tuner_warn ("tuner 0x%02x: Tuner count greater than %d\n",c->addr,tuner_count); - return; - } - t->type = type; t->config = new_config; if (tuner_callback != NULL) { @@ -409,7 +394,12 @@ static void set_type(struct i2c_client *c, unsigned int type, buffer[2] = 0x86; buffer[3] = 0x54; i2c_master_send(c, buffer, 4); - attach_simple_tuner(t); + if (simple_tuner_attach(&t->fe, t->i2c->adapter, t->i2c->addr, + t->type) == NULL) { + t->type = TUNER_ABSENT; + t->mode_mask = T_UNINITIALIZED; + return; + } break; case TUNER_PHILIPS_TD1316: buffer[0] = 0x0b; @@ -417,7 +407,12 @@ static void set_type(struct i2c_client *c, unsigned int type, buffer[2] = 0x86; buffer[3] = 0xa4; i2c_master_send(c,buffer,4); - attach_simple_tuner(t); + if (simple_tuner_attach(&t->fe, t->i2c->adapter, + t->i2c->addr, t->type) == NULL) { + t->type = TUNER_ABSENT; + t->mode_mask = T_UNINITIALIZED; + return; + } break; case TUNER_XC2028: { @@ -455,7 +450,12 @@ static void set_type(struct i2c_client *c, unsigned int type, } break; default: - attach_simple_tuner(t); + if (simple_tuner_attach(&t->fe, t->i2c->adapter, + t->i2c->addr, t->type) == NULL) { + t->type = TUNER_ABSENT; + t->mode_mask = T_UNINITIALIZED; + return; + } break; } diff --git a/drivers/media/video/tuner-i2c.h b/drivers/media/video/tuner-i2c.h index de52e8ffd347..60ba794809fe 100644 --- a/drivers/media/video/tuner-i2c.h +++ b/drivers/media/video/tuner-i2c.h @@ -26,6 +26,10 @@ struct tuner_i2c_props { u8 addr; struct i2c_adapter *adap; + + /* used for tuner instance management */ + int count; + char *name; }; static inline int tuner_i2c_xfer_send(struct tuner_i2c_props *props, char *buf, int len) @@ -59,29 +63,111 @@ static inline int tuner_i2c_xfer_send_recv(struct tuner_i2c_props *props, return (ret == 2) ? ilen : ret; } -#define tuner_warn(fmt, arg...) do { \ - printk(KERN_WARNING "%s %d-%04x: " fmt, PREFIX, \ - i2c_adapter_id(priv->i2c_props.adap), \ - priv->i2c_props.addr, ##arg); \ +/* Callers must declare as a global for the module: + * + * static LIST_HEAD(hybrid_tuner_instance_list); + * + * hybrid_tuner_instance_list should be the third argument + * passed into hybrid_tuner_request_state(). + * + * state structure must contain the following: + * + * struct list_head hybrid_tuner_instance_list; + * struct tuner_i2c_props i2c_props; + * + * hybrid_tuner_instance_list (both within state structure and globally) + * is only required if the driver is using hybrid_tuner_request_state + * and hybrid_tuner_release_state to manage state sharing between + * multiple instances of hybrid tuners. + */ + +#define tuner_printk(kernlvl, i2cprops, fmt, arg...) do { \ + printk(kernlvl "%s %d-%04x: " fmt, i2cprops.name, \ + i2cprops.adap ? \ + i2c_adapter_id(i2cprops.adap) : -1, \ + i2cprops.addr, ##arg); \ } while (0) -#define tuner_info(fmt, arg...) do { \ - printk(KERN_INFO "%s %d-%04x: " fmt, PREFIX, \ - i2c_adapter_id(priv->i2c_props.adap), \ - priv->i2c_props.addr , ##arg); \ +/* TO DO: convert all callers of these macros to pass in + * struct tuner_i2c_props, then remove the macro wrappers */ + +#define __tuner_warn(i2cprops, fmt, arg...) do { \ + tuner_printk(KERN_WARNING, i2cprops, fmt, ##arg); \ } while (0) -#define tuner_err(fmt, arg...) do { \ - printk(KERN_ERR "%s %d-%04x: " fmt, PREFIX, \ - i2c_adapter_id(priv->i2c_props.adap), \ - priv->i2c_props.addr , ##arg); \ +#define __tuner_info(i2cprops, fmt, arg...) do { \ + tuner_printk(KERN_INFO, i2cprops, fmt, ##arg); \ } while (0) -#define tuner_dbg(fmt, arg...) do { \ +#define __tuner_err(i2cprops, fmt, arg...) do { \ + tuner_printk(KERN_ERR, i2cprops, fmt, ##arg); \ + } while (0) + +#define __tuner_dbg(i2cprops, fmt, arg...) do { \ if ((debug)) \ - printk(KERN_DEBUG "%s %d-%04x: " fmt, PREFIX, \ - i2c_adapter_id(priv->i2c_props.adap), \ - priv->i2c_props.addr , ##arg); \ + tuner_printk(KERN_DEBUG, i2cprops, fmt, ##arg); \ } while (0) +#define tuner_warn(fmt, arg...) __tuner_warn(priv->i2c_props, fmt, ##arg) +#define tuner_info(fmt, arg...) __tuner_info(priv->i2c_props, fmt, ##arg) +#define tuner_err(fmt, arg...) __tuner_err(priv->i2c_props, fmt, ##arg) +#define tuner_dbg(fmt, arg...) __tuner_dbg(priv->i2c_props, fmt, ##arg) + +/****************************************************************************/ + +/* The return value of hybrid_tuner_request_state indicates the number of + * instances using this tuner object. + * + * 0 - no instances, indicates an error - kzalloc must have failed + * + * 1 - one instance, indicates that the tuner object was created successfully + * + * 2 (or more) instances, indicates that an existing tuner object was found + */ + +#define hybrid_tuner_request_state(type, state, list, i2cadap, i2caddr, devname)\ +({ \ + int __ret = 0; \ + list_for_each_entry(state, &list, hybrid_tuner_instance_list) { \ + if ((state->i2c_props.addr == i2caddr) && \ + ((state->i2c_props.adap ? \ + i2c_adapter_id(state->i2c_props.adap) : -1) == \ + (i2cadap ? i2c_adapter_id(i2cadap) : -1))) { \ + __tuner_info(state->i2c_props, \ + "attaching existing instance\n"); \ + state->i2c_props.count++; \ + __ret = state->i2c_props.count; \ + break; \ + } \ + } \ + if (0 == __ret) { \ + state = kzalloc(sizeof(type), GFP_KERNEL); \ + if (NULL == state) \ + goto __fail; \ + state->i2c_props.addr = i2caddr; \ + state->i2c_props.adap = i2cadap; \ + state->i2c_props.name = devname; \ + __tuner_info(state->i2c_props, \ + "creating new instance\n"); \ + list_add_tail(&state->hybrid_tuner_instance_list, &list);\ + state->i2c_props.count++; \ + __ret = state->i2c_props.count; \ + } \ +__fail: \ + __ret; \ +}) + +#define hybrid_tuner_release_state(state) \ +({ \ + int __ret; \ + state->i2c_props.count--; \ + __ret = state->i2c_props.count; \ + if (!state->i2c_props.count) { \ + __tuner_info(state->i2c_props, "destroying instance\n");\ + list_del(&state->hybrid_tuner_instance_list); \ + kfree(state); \ + } \ + __ret; \ +}) + #endif /* __TUNER_I2C_H__ */ diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index c1db576696c6..dc2467159ece 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -13,15 +13,13 @@ #include "tuner-i2c.h" #include "tuner-simple.h" -static int debug = 0; +static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); -#define PREFIX "tuner-simple" - -static int offset = 0; +static int offset; module_param(offset, int, 0664); -MODULE_PARM_DESC(offset,"Allows to specify an offset for tuner"); +MODULE_PARM_DESC(offset, "Allows to specify an offset for tuner"); /* ---------------------------------------------------------------------- */ @@ -36,8 +34,8 @@ MODULE_PARM_DESC(offset,"Allows to specify an offset for tuner"); */ #define TEMIC_SET_PAL_I 0x05 #define TEMIC_SET_PAL_DK 0x09 -#define TEMIC_SET_PAL_L 0x0a // SECAM ? -#define TEMIC_SET_PAL_L2 0x0b // change IF ! +#define TEMIC_SET_PAL_L 0x0a /* SECAM ? */ +#define TEMIC_SET_PAL_L2 0x0b /* change IF ! */ #define TEMIC_SET_PAL_BG 0x0c /* tv tuner system standard selection for Philips FQ1216ME @@ -107,7 +105,7 @@ static int tuner_read_status(struct dvb_frontend *fe) struct tuner_simple_priv *priv = fe->tuner_priv; unsigned char byte; - if (1 != tuner_i2c_xfer_recv(&priv->i2c_props,&byte,1)) + if (1 != tuner_i2c_xfer_recv(&priv->i2c_props, &byte, 1)) return 0; return byte; @@ -121,13 +119,13 @@ static inline int tuner_signal(const int status) static inline int tuner_stereo(const int type, const int status) { switch (type) { - case TUNER_PHILIPS_FM1216ME_MK3: - case TUNER_PHILIPS_FM1236_MK3: - case TUNER_PHILIPS_FM1256_IH3: - case TUNER_LG_NTSC_TAPE: - return ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3); - default: - return status & TUNER_STEREO; + case TUNER_PHILIPS_FM1216ME_MK3: + case TUNER_PHILIPS_FM1236_MK3: + case TUNER_PHILIPS_FM1256_IH3: + case TUNER_LG_NTSC_TAPE: + return ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3); + default: + return status & TUNER_STEREO; } } @@ -173,129 +171,137 @@ static int simple_get_rf_strength(struct dvb_frontend *fe, u16 *strength) /* ---------------------------------------------------------------------- */ -static int simple_set_tv_freq(struct dvb_frontend *fe, - struct analog_parameters *params) +static inline char *tuner_param_name(enum param_type type) { - struct tuner_simple_priv *priv = fe->tuner_priv; - u8 config, cb, tuneraddr; - u16 div; - struct tunertype *tun; - u8 buffer[4]; - int rc, IFPCoff, i, j; - enum param_type desired_type; - struct tuner_params *t_params; + char *name; - tun = priv->tun; + switch (type) { + case TUNER_PARAM_TYPE_RADIO: + name = "radio"; + break; + case TUNER_PARAM_TYPE_PAL: + name = "pal"; + break; + case TUNER_PARAM_TYPE_SECAM: + name = "secam"; + break; + case TUNER_PARAM_TYPE_NTSC: + name = "ntsc"; + break; + default: + name = "unknown"; + break; + } + return name; +} - /* IFPCoff = Video Intermediate Frequency - Vif: - 940 =16*58.75 NTSC/J (Japan) - 732 =16*45.75 M/N STD - 704 =16*44 ATSC (at DVB code) - 632 =16*39.50 I U.K. - 622.4=16*38.90 B/G D/K I, L STD - 592 =16*37.00 D China - 590 =16.36.875 B Australia - 543.2=16*33.95 L' STD - 171.2=16*10.70 FM Radio (at set_radio_freq) - */ +static struct tuner_params *simple_tuner_params(struct dvb_frontend *fe, + enum param_type desired_type) +{ + struct tuner_simple_priv *priv = fe->tuner_priv; + struct tunertype *tun = priv->tun; + int i; - if (params->std == V4L2_STD_NTSC_M_JP) { - IFPCoff = 940; - desired_type = TUNER_PARAM_TYPE_NTSC; - } else if ((params->std & V4L2_STD_MN) && - !(params->std & ~V4L2_STD_MN)) { - IFPCoff = 732; - desired_type = TUNER_PARAM_TYPE_NTSC; - } else if (params->std == V4L2_STD_SECAM_LC) { - IFPCoff = 543; - desired_type = TUNER_PARAM_TYPE_SECAM; - } else { - IFPCoff = 623; - desired_type = TUNER_PARAM_TYPE_PAL; - } + for (i = 0; i < tun->count; i++) + if (desired_type == tun->params[i].type) + break; - for (j = 0; j < tun->count-1; j++) { - if (desired_type != tun->params[j].type) - continue; - break; - } - /* use default tuner_t_params if desired_type not available */ - if (desired_type != tun->params[j].type) { - tuner_dbg("IFPCoff = %d: tuner_t_params undefined for tuner %d\n", - IFPCoff, priv->type); - j = 0; + /* use default tuner params if desired_type not available */ + if (i == tun->count) { + tuner_dbg("desired params (%s) undefined for tuner %d\n", + tuner_param_name(desired_type), priv->type); + i = 0; } - t_params = &tun->params[j]; + + tuner_dbg("using tuner params #%d (%s)\n", i, + tuner_param_name(tun->params[i].type)); + + return &tun->params[i]; +} + +static int simple_config_lookup(struct dvb_frontend *fe, + struct tuner_params *t_params, + int *frequency, u8 *config, u8 *cb) +{ + struct tuner_simple_priv *priv = fe->tuner_priv; + int i; for (i = 0; i < t_params->count; i++) { - if (params->frequency > t_params->ranges[i].limit) + if (*frequency > t_params->ranges[i].limit) continue; break; } if (i == t_params->count) { - tuner_dbg("TV frequency out of range (%d > %d)", - params->frequency, t_params->ranges[i - 1].limit); - params->frequency = t_params->ranges[--i].limit; + tuner_dbg("frequency out of range (%d > %d)\n", + *frequency, t_params->ranges[i - 1].limit); + *frequency = t_params->ranges[--i].limit; } - config = t_params->ranges[i].config; - cb = t_params->ranges[i].cb; - /* i == 0 -> VHF_LO - * i == 1 -> VHF_HI - * i == 2 -> UHF */ - tuner_dbg("tv: param %d, range %d\n",j,i); + *config = t_params->ranges[i].config; + *cb = t_params->ranges[i].cb; + + tuner_dbg("freq = %d.%02d (%d), range = %d, " + "config = 0x%02x, cb = 0x%02x\n", + *frequency / 16, *frequency % 16 * 100 / 16, *frequency, + i, *config, *cb); + + return i; +} - div=params->frequency + IFPCoff + offset; +/* ---------------------------------------------------------------------- */ - tuner_dbg("Freq= %d.%02d MHz, V_IF=%d.%02d MHz, Offset=%d.%02d MHz, div=%0d\n", - params->frequency / 16, params->frequency % 16 * 100 / 16, - IFPCoff / 16, IFPCoff % 16 * 100 / 16, - offset / 16, offset % 16 * 100 / 16, - div); +static int simple_std_setup(struct dvb_frontend *fe, + struct analog_parameters *params, + u8 *buffer, u8 *config, u8 *cb) +{ + struct tuner_simple_priv *priv = fe->tuner_priv; + u8 tuneraddr; + int rc; /* tv norm specific stuff for multi-norm tuners */ switch (priv->type) { - case TUNER_PHILIPS_SECAM: // FI1216MF + case TUNER_PHILIPS_SECAM: /* FI1216MF */ /* 0x01 -> ??? no change ??? */ /* 0x02 -> PAL BDGHI / SECAM L */ /* 0x04 -> ??? PAL others / SECAM others ??? */ - cb &= ~0x03; - if (params->std & V4L2_STD_SECAM_L) //also valid for V4L2_STD_SECAM - cb |= PHILIPS_MF_SET_STD_L; + *cb &= ~0x03; + if (params->std & V4L2_STD_SECAM_L) + /* also valid for V4L2_STD_SECAM */ + *cb |= PHILIPS_MF_SET_STD_L; else if (params->std & V4L2_STD_SECAM_LC) - cb |= PHILIPS_MF_SET_STD_LC; + *cb |= PHILIPS_MF_SET_STD_LC; else /* V4L2_STD_B|V4L2_STD_GH */ - cb |= PHILIPS_MF_SET_STD_BG; + *cb |= PHILIPS_MF_SET_STD_BG; break; case TUNER_TEMIC_4046FM5: - cb &= ~0x0f; + *cb &= ~0x0f; if (params->std & V4L2_STD_PAL_BG) { - cb |= TEMIC_SET_PAL_BG; + *cb |= TEMIC_SET_PAL_BG; } else if (params->std & V4L2_STD_PAL_I) { - cb |= TEMIC_SET_PAL_I; + *cb |= TEMIC_SET_PAL_I; } else if (params->std & V4L2_STD_PAL_DK) { - cb |= TEMIC_SET_PAL_DK; + *cb |= TEMIC_SET_PAL_DK; } else if (params->std & V4L2_STD_SECAM_L) { - cb |= TEMIC_SET_PAL_L; + *cb |= TEMIC_SET_PAL_L; } break; case TUNER_PHILIPS_FQ1216ME: - cb &= ~0x0f; + *cb &= ~0x0f; if (params->std & (V4L2_STD_PAL_BG|V4L2_STD_PAL_DK)) { - cb |= PHILIPS_SET_PAL_BGDK; + *cb |= PHILIPS_SET_PAL_BGDK; } else if (params->std & V4L2_STD_PAL_I) { - cb |= PHILIPS_SET_PAL_I; + *cb |= PHILIPS_SET_PAL_I; } else if (params->std & V4L2_STD_SECAM_L) { - cb |= PHILIPS_SET_PAL_L; + *cb |= PHILIPS_SET_PAL_L; } break; @@ -305,15 +311,15 @@ static int simple_set_tv_freq(struct dvb_frontend *fe, /* 0x01 -> ATSC antenna input 2 */ /* 0x02 -> NTSC antenna input 1 */ /* 0x03 -> NTSC antenna input 2 */ - cb &= ~0x03; + *cb &= ~0x03; if (!(params->std & V4L2_STD_ATSC)) - cb |= 2; + *cb |= 2; /* FIXME: input */ break; case TUNER_MICROTUNE_4042FI5: /* Set the charge pump for fast tuning */ - config |= TUNER_CHARGE_PUMP; + *config |= TUNER_CHARGE_PUMP; break; case TUNER_PHILIPS_TUV1236D: @@ -325,23 +331,186 @@ static int simple_set_tv_freq(struct dvb_frontend *fe, buffer[1] = 0x00; buffer[2] = 0x17; buffer[3] = 0x00; - cb &= ~0x40; + *cb &= ~0x40; if (params->std & V4L2_STD_ATSC) { - cb |= 0x40; + *cb |= 0x40; buffer[1] = 0x04; } /* set to the correct mode (analog or digital) */ tuneraddr = priv->i2c_props.addr; priv->i2c_props.addr = 0x0a; - if (2 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,&buffer[0],2))) - tuner_warn("i2c i/o error: rc == %d (should be 2)\n",rc); - if (2 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,&buffer[2],2))) - tuner_warn("i2c i/o error: rc == %d (should be 2)\n",rc); + rc = tuner_i2c_xfer_send(&priv->i2c_props, &buffer[0], 2); + if (2 != rc) + tuner_warn("i2c i/o error: rc == %d " + "(should be 2)\n", rc); + rc = tuner_i2c_xfer_send(&priv->i2c_props, &buffer[2], 2); + if (2 != rc) + tuner_warn("i2c i/o error: rc == %d " + "(should be 2)\n", rc); priv->i2c_props.addr = tuneraddr; /* FIXME: input */ break; } + return 0; +} + +static int simple_post_tune(struct dvb_frontend *fe, u8 *buffer, + u16 div, u8 config, u8 cb) +{ + struct tuner_simple_priv *priv = fe->tuner_priv; + int rc; + + switch (priv->type) { + case TUNER_LG_TDVS_H06XF: + /* Set the Auxiliary Byte. */ + buffer[0] = buffer[2]; + buffer[0] &= ~0x20; + buffer[0] |= 0x18; + buffer[1] = 0x20; + tuner_dbg("tv 0x%02x 0x%02x\n", buffer[0], buffer[1]); + + rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 2); + if (2 != rc) + tuner_warn("i2c i/o error: rc == %d " + "(should be 2)\n", rc); + break; + case TUNER_MICROTUNE_4042FI5: + { + /* FIXME - this may also work for other tuners */ + unsigned long timeout = jiffies + msecs_to_jiffies(1); + u8 status_byte = 0; + + /* Wait until the PLL locks */ + for (;;) { + if (time_after(jiffies, timeout)) + return 0; + rc = tuner_i2c_xfer_recv(&priv->i2c_props, + &status_byte, 1); + if (1 != rc) { + tuner_warn("i2c i/o read error: rc == %d " + "(should be 1)\n", rc); + break; + } + if (status_byte & TUNER_PLL_LOCKED) + break; + udelay(10); + } + + /* Set the charge pump for optimized phase noise figure */ + config &= ~TUNER_CHARGE_PUMP; + buffer[0] = (div>>8) & 0x7f; + buffer[1] = div & 0xff; + buffer[2] = config; + buffer[3] = cb; + tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n", + buffer[0], buffer[1], buffer[2], buffer[3]); + + rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4); + if (4 != rc) + tuner_warn("i2c i/o error: rc == %d " + "(should be 4)\n", rc); + break; + } + } + + return 0; +} + +static int simple_radio_bandswitch(struct dvb_frontend *fe, u8 *buffer) +{ + struct tuner_simple_priv *priv = fe->tuner_priv; + + switch (priv->type) { + case TUNER_TENA_9533_DI: + case TUNER_YMEC_TVF_5533MF: + tuner_dbg("This tuner doesn't have FM. " + "Most cards have a TEA5767 for FM\n"); + return 0; + case TUNER_PHILIPS_FM1216ME_MK3: + case TUNER_PHILIPS_FM1236_MK3: + case TUNER_PHILIPS_FMD1216ME_MK3: + case TUNER_LG_NTSC_TAPE: + case TUNER_PHILIPS_FM1256_IH3: + buffer[3] = 0x19; + break; + case TUNER_TNF_5335MF: + buffer[3] = 0x11; + break; + case TUNER_LG_PAL_FM: + buffer[3] = 0xa5; + break; + case TUNER_THOMSON_DTT761X: + buffer[3] = 0x39; + break; + case TUNER_MICROTUNE_4049FM5: + default: + buffer[3] = 0xa4; + break; + } + + return 0; +} + +/* ---------------------------------------------------------------------- */ + +static int simple_set_tv_freq(struct dvb_frontend *fe, + struct analog_parameters *params) +{ + struct tuner_simple_priv *priv = fe->tuner_priv; + u8 config, cb; + u16 div; + struct tunertype *tun; + u8 buffer[4]; + int rc, IFPCoff, i; + enum param_type desired_type; + struct tuner_params *t_params; + + tun = priv->tun; + + /* IFPCoff = Video Intermediate Frequency - Vif: + 940 =16*58.75 NTSC/J (Japan) + 732 =16*45.75 M/N STD + 704 =16*44 ATSC (at DVB code) + 632 =16*39.50 I U.K. + 622.4=16*38.90 B/G D/K I, L STD + 592 =16*37.00 D China + 590 =16.36.875 B Australia + 543.2=16*33.95 L' STD + 171.2=16*10.70 FM Radio (at set_radio_freq) + */ + + if (params->std == V4L2_STD_NTSC_M_JP) { + IFPCoff = 940; + desired_type = TUNER_PARAM_TYPE_NTSC; + } else if ((params->std & V4L2_STD_MN) && + !(params->std & ~V4L2_STD_MN)) { + IFPCoff = 732; + desired_type = TUNER_PARAM_TYPE_NTSC; + } else if (params->std == V4L2_STD_SECAM_LC) { + IFPCoff = 543; + desired_type = TUNER_PARAM_TYPE_SECAM; + } else { + IFPCoff = 623; + desired_type = TUNER_PARAM_TYPE_PAL; + } + + t_params = simple_tuner_params(fe, desired_type); + + i = simple_config_lookup(fe, t_params, ¶ms->frequency, + &config, &cb); + + div = params->frequency + IFPCoff + offset; + + tuner_dbg("Freq= %d.%02d MHz, V_IF=%d.%02d MHz, " + "Offset=%d.%02d MHz, div=%0d\n", + params->frequency / 16, params->frequency % 16 * 100 / 16, + IFPCoff / 16, IFPCoff % 16 * 100 / 16, + offset / 16, offset % 16 * 100 / 16, div); + + /* tv norm specific stuff for multi-norm tuners */ + simple_std_setup(fe, params, &buffer[1], &config, &cb); + if (t_params->cb_first_if_lower_freq && div < priv->last_div) { buffer[0] = config; buffer[1] = cb; @@ -357,8 +526,10 @@ static int simple_set_tv_freq(struct dvb_frontend *fe, if (t_params->has_tda9887) { struct v4l2_priv_tun_config tda9887_cfg; int config = 0; - int is_secam_l = (params->std & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC)) && - !(params->std & ~(V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC)); + int is_secam_l = (params->std & (V4L2_STD_SECAM_L | + V4L2_STD_SECAM_LC)) && + !(params->std & ~(V4L2_STD_SECAM_L | + V4L2_STD_SECAM_LC)); tda9887_cfg.tuner = TUNER_TDA9887; tda9887_cfg.priv = &config; @@ -368,8 +539,7 @@ static int simple_set_tv_freq(struct dvb_frontend *fe, config |= TDA9887_PORT1_ACTIVE; if (t_params->port2_active ^ t_params->port2_invert_for_secam_lc) config |= TDA9887_PORT2_ACTIVE; - } - else { + } else { if (t_params->port1_active) config |= TDA9887_PORT1_ACTIVE; if (t_params->port2_active) @@ -384,8 +554,7 @@ static int simple_set_tv_freq(struct dvb_frontend *fe, config |= TDA9887_TOP(t_params->default_top_secam_mid); else if (t_params->default_top_secam_high) config |= TDA9887_TOP(t_params->default_top_secam_high); - } - else { + } else { if (i == 0 && t_params->default_top_low) config |= TDA9887_TOP(t_params->default_top_low); else if (i == 1 && t_params->default_top_mid) @@ -399,56 +568,14 @@ static int simple_set_tv_freq(struct dvb_frontend *fe, &tda9887_cfg); } tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n", - buffer[0],buffer[1],buffer[2],buffer[3]); - - if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,buffer,4))) - tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc); + buffer[0], buffer[1], buffer[2], buffer[3]); - switch (priv->type) { - case TUNER_LG_TDVS_H06XF: - /* Set the Auxiliary Byte. */ - buffer[0] = buffer[2]; - buffer[0] &= ~0x20; - buffer[0] |= 0x18; - buffer[1] = 0x20; - tuner_dbg("tv 0x%02x 0x%02x\n",buffer[0],buffer[1]); + rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4); + if (4 != rc) + tuner_warn("i2c i/o error: rc == %d (should be 4)\n", rc); - if (2 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,buffer,2))) - tuner_warn("i2c i/o error: rc == %d (should be 2)\n",rc); - break; - case TUNER_MICROTUNE_4042FI5: - { - // FIXME - this may also work for other tuners - unsigned long timeout = jiffies + msecs_to_jiffies(1); - u8 status_byte = 0; + simple_post_tune(fe, &buffer[0], div, config, cb); - /* Wait until the PLL locks */ - for (;;) { - if (time_after(jiffies,timeout)) - return 0; - if (1 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props,&status_byte,1))) { - tuner_warn("i2c i/o read error: rc == %d (should be 1)\n",rc); - break; - } - if (status_byte & TUNER_PLL_LOCKED) - break; - udelay(10); - } - - /* Set the charge pump for optimized phase noise figure */ - config &= ~TUNER_CHARGE_PUMP; - buffer[0] = (div>>8) & 0x7f; - buffer[1] = div & 0xff; - buffer[2] = config; - buffer[3] = cb; - tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n", - buffer[0],buffer[1],buffer[2],buffer[3]); - - if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,buffer,4))) - tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc); - break; - } - } return 0; } @@ -483,37 +610,13 @@ static int simple_set_radio_freq(struct dvb_frontend *fe, freq += (unsigned int)(41.3*16000); break; default: - tuner_warn("Unsupported radio_if value %d\n", t_params->radio_if); + tuner_warn("Unsupported radio_if value %d\n", + t_params->radio_if); return 0; } /* Bandswitch byte */ - switch (priv->type) { - case TUNER_TENA_9533_DI: - case TUNER_YMEC_TVF_5533MF: - tuner_dbg("This tuner doesn't have FM. Most cards have a TEA5767 for FM\n"); - return 0; - case TUNER_PHILIPS_FM1216ME_MK3: - case TUNER_PHILIPS_FM1236_MK3: - case TUNER_PHILIPS_FMD1216ME_MK3: - case TUNER_LG_NTSC_TAPE: - case TUNER_PHILIPS_FM1256_IH3: - buffer[3] = 0x19; - break; - case TUNER_TNF_5335MF: - buffer[3] = 0x11; - break; - case TUNER_LG_PAL_FM: - buffer[3] = 0xa5; - break; - case TUNER_THOMSON_DTT761X: - buffer[3] = 0x39; - break; - case TUNER_MICROTUNE_4049FM5: - default: - buffer[3] = 0xa4; - break; - } + simple_radio_bandswitch(fe, &buffer[0]); buffer[2] = (t_params->ranges[0].config & ~TUNER_RATIO_MASK) | TUNER_RATIO_SELECT_50; /* 50 kHz step */ @@ -534,7 +637,7 @@ static int simple_set_radio_freq(struct dvb_frontend *fe, } tuner_dbg("radio 0x%02x 0x%02x 0x%02x 0x%02x\n", - buffer[0],buffer[1],buffer[2],buffer[3]); + buffer[0], buffer[1], buffer[2], buffer[3]); priv->last_div = div; if (t_params->has_tda9887) { @@ -544,9 +647,11 @@ static int simple_set_radio_freq(struct dvb_frontend *fe, tda9887_cfg.tuner = TUNER_TDA9887; tda9887_cfg.priv = &config; - if (t_params->port1_active && !t_params->port1_fm_high_sensitivity) + if (t_params->port1_active && + !t_params->port1_fm_high_sensitivity) config |= TDA9887_PORT1_ACTIVE; - if (t_params->port2_active && !t_params->port2_fm_high_sensitivity) + if (t_params->port2_active && + !t_params->port2_fm_high_sensitivity) config |= TDA9887_PORT2_ACTIVE; if (t_params->intercarrier_mode) config |= TDA9887_INTERCARRIER; @@ -557,10 +662,11 @@ static int simple_set_radio_freq(struct dvb_frontend *fe, if (t_params->radio_if == 2) config |= TDA9887_RIF_41_3; i2c_clients_command(priv->i2c_props.adap, TUNER_SET_CONFIG, - &tda9887_cfg); + &tda9887_cfg); } - if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,buffer,4))) - tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc); + rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4); + if (4 != rc) + tuner_warn("i2c i/o error: rc == %d (should be 4)\n", rc); return 0; } @@ -613,10 +719,16 @@ static struct dvb_tuner_ops simple_tuner_ops = { struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c_adap, u8 i2c_addr, - struct simple_tuner_config *cfg) + unsigned int type) { struct tuner_simple_priv *priv = NULL; + if (type >= tuner_count) { + printk(KERN_WARNING "%s: invalid tuner type: %d (max: %d)\n", + __FUNCTION__, type, tuner_count-1); + return NULL; + } + priv = kzalloc(sizeof(struct tuner_simple_priv), GFP_KERNEL); if (priv == NULL) return NULL; @@ -624,19 +736,21 @@ struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe, priv->i2c_props.addr = i2c_addr; priv->i2c_props.adap = i2c_adap; - priv->type = cfg->type; - priv->tun = cfg->tun; + priv->i2c_props.name = "tuner-simple"; + + priv->type = type; + priv->tun = &tuners[type]; - memcpy(&fe->ops.tuner_ops, &simple_tuner_ops, sizeof(struct dvb_tuner_ops)); + memcpy(&fe->ops.tuner_ops, &simple_tuner_ops, + sizeof(struct dvb_tuner_ops)); - tuner_info("type set to %d (%s)\n", cfg->type, cfg->tun->name); + tuner_info("type set to %d (%s)\n", priv->type, priv->tun->name); - strlcpy(fe->ops.tuner_ops.info.name, cfg->tun->name, sizeof(fe->ops.tuner_ops.info.name)); + strlcpy(fe->ops.tuner_ops.info.name, priv->tun->name, + sizeof(fe->ops.tuner_ops.info.name)); return fe; } - - EXPORT_SYMBOL_GPL(simple_tuner_attach); MODULE_DESCRIPTION("Simple 4-control-bytes style tuner driver"); diff --git a/drivers/media/video/tuner-simple.h b/drivers/media/video/tuner-simple.h index 9089939a8c02..bf425f325f87 100644 --- a/drivers/media/video/tuner-simple.h +++ b/drivers/media/video/tuner-simple.h @@ -20,23 +20,16 @@ #include <linux/i2c.h> #include "dvb_frontend.h" -struct simple_tuner_config -{ - /* chip type */ - unsigned int type; - struct tunertype *tun; -}; - #if defined(CONFIG_TUNER_SIMPLE) || (defined(CONFIG_TUNER_SIMPLE_MODULE) && defined(MODULE)) extern struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c_adap, u8 i2c_addr, - struct simple_tuner_config *cfg); + unsigned int type); #else static inline struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c_adap, u8 i2c_addr, - struct simple_tuner_config *cfg) + unsigned int type) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); return NULL; diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index 883047f9c28c..9276ad33d03b 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c @@ -1480,5 +1480,11 @@ struct tunertype tuners[] = { /* see xc5000.c for details */ }, }; +EXPORT_SYMBOL(tuners); unsigned const int tuner_count = ARRAY_SIZE(tuners); +EXPORT_SYMBOL(tuner_count); + +MODULE_DESCRIPTION("Simple tuner device type database"); +MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c index 50cf876f020f..42dc2c6ccbbf 100644 --- a/drivers/media/video/tuner-xc2028.c +++ b/drivers/media/video/tuner-xc2028.c @@ -23,8 +23,6 @@ #include "dvb_frontend.h" -#define PREFIX "xc2028" - static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); @@ -145,7 +143,7 @@ static unsigned int xc2028_get_reg(struct xc2028_data *priv, u16 reg, u16 *val) } #define dump_firm_type(t) dump_firm_type_and_int_freq(t, 0) -void dump_firm_type_and_int_freq(unsigned int type, u16 int_freq) +static void dump_firm_type_and_int_freq(unsigned int type, u16 int_freq) { if (type & BASE) printk("BASE "); @@ -1153,13 +1151,13 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe, void *video_dev; if (debug) - printk(KERN_DEBUG PREFIX ": Xcv2028/3028 init called!\n"); + printk(KERN_DEBUG "xc2028: Xcv2028/3028 init called!\n"); if (NULL == cfg || NULL == cfg->video_dev) return NULL; if (!fe) { - printk(KERN_ERR PREFIX ": No frontend!\n"); + printk(KERN_ERR "xc2028: No frontend!\n"); return NULL; } @@ -1183,6 +1181,8 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe, priv->i2c_props.addr = cfg->i2c_addr; priv->i2c_props.adap = cfg->i2c_adap; + priv->i2c_props.name = "xc2028"; + priv->video_dev = video_dev; priv->tuner_callback = cfg->callback; priv->ctrl.max_len = 13; diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 01ebcec040c4..f29a2cd0f2f2 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -38,7 +38,7 @@ /* ---------------------------------------------------------------------- */ /* insmod args */ -static int debug = 0; /* insmod parameter */ +static int debug; /* insmod parameter */ module_param(debug, int, 0644); MODULE_DESCRIPTION("device driver for various i2c TV sound decoder / audiomux chips"); @@ -1235,11 +1235,11 @@ static int tda9850 = 1; static int tda9855 = 1; static int tda9873 = 1; static int tda9874a = 1; -static int tea6300 = 0; /* address clash with msp34xx */ -static int tea6320 = 0; /* address clash with msp34xx */ +static int tea6300; /* default 0 - address clash with msp34xx */ +static int tea6320; /* default 0 - address clash with msp34xx */ static int tea6420 = 1; static int pic16c54 = 1; -static int ta8874z = 0; /* address clash with tda9840 */ +static int ta8874z; /* default 0 - address clash with tda9840 */ module_param(tda8425, int, 0444); module_param(tda9840, int, 0444); diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index 445eba4174d7..d0bdf7d4c6e1 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c @@ -27,7 +27,7 @@ static unsigned short normal_i2c[] = { I2C_CLIENT_INSMOD; -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); diff --git a/drivers/media/video/usbvideo/ibmcam.c b/drivers/media/video/usbvideo/ibmcam.c index 14db95e10cfe..84ee6b1d9fd2 100644 --- a/drivers/media/video/usbvideo/ibmcam.c +++ b/drivers/media/video/usbvideo/ibmcam.c @@ -121,7 +121,7 @@ static int init_model2_yb = -1; /* 01.01.08 - Added for RCA video in support -LO */ /* Settings for camera model 3 */ -static int init_model3_input = 0; +static int init_model3_input; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)"); diff --git a/drivers/media/video/usbvideo/konicawc.c b/drivers/media/video/usbvideo/konicawc.c index 719b17ce83f8..97479609f97d 100644 --- a/drivers/media/video/usbvideo/konicawc.c +++ b/drivers/media/video/usbvideo/konicawc.c @@ -61,7 +61,7 @@ static int debug; } #else #define DEBUG(n, arg...) -static const int debug = 0; +static const int debug; #endif diff --git a/drivers/media/video/usbvideo/quickcam_messenger.c b/drivers/media/video/usbvideo/quickcam_messenger.c index a2acba0bcc47..e0ee6d8f2565 100644 --- a/drivers/media/video/usbvideo/quickcam_messenger.c +++ b/drivers/media/video/usbvideo/quickcam_messenger.c @@ -50,7 +50,7 @@ static int debug; } #else #define DEBUG(n, arg...) -static const int debug = 0; +static const int debug; #endif #define DRIVER_VERSION "v0.01" diff --git a/drivers/media/video/usbvideo/ultracam.c b/drivers/media/video/usbvideo/ultracam.c index 95453c108d40..9544e644bf0d 100644 --- a/drivers/media/video/usbvideo/ultracam.c +++ b/drivers/media/video/usbvideo/ultracam.c @@ -28,9 +28,9 @@ typedef struct { static struct usbvideo *cams = NULL; -static int debug = 0; +static int debug; -static int flags = 0; /* FLAGS_DISPLAY_HINTS | FLAGS_OVERLAY_STATS; */ +static int flags; /* FLAGS_DISPLAY_HINTS | FLAGS_OVERLAY_STATS; */ static const int min_canvasWidth = 8; static const int min_canvasHeight = 4; diff --git a/drivers/media/video/usbvideo/usbvideo.c b/drivers/media/video/usbvideo/usbvideo.c index fb434b5602a3..537bead590bd 100644 --- a/drivers/media/video/usbvideo/usbvideo.c +++ b/drivers/media/video/usbvideo/usbvideo.c @@ -522,7 +522,7 @@ void usbvideo_TestPattern(struct uvd *uvd, int fullframe, int pmode) struct usbvideo_frame *frame; int num_cell = 0; int scan_length = 0; - static int num_pass = 0; + static int num_pass; if (uvd == NULL) { err("%s: uvd == NULL", __FUNCTION__); diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c index 56775ab8b75d..47f64a031cad 100644 --- a/drivers/media/video/usbvision/usbvision-core.c +++ b/drivers/media/video/usbvision/usbvision-core.c @@ -53,19 +53,21 @@ #include "usbvision.h" -static unsigned int core_debug = 0; +static unsigned int core_debug; module_param(core_debug,int,0644); MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); -static unsigned int force_testpattern = 0; +static unsigned int force_testpattern; module_param(force_testpattern,int,0644); MODULE_PARM_DESC(force_testpattern,"enable test pattern display [core]"); -static int adjustCompression = 1; // Set the compression to be adaptive +static int adjustCompression = 1; /* Set the compression to be adaptive */ module_param(adjustCompression, int, 0444); MODULE_PARM_DESC(adjustCompression, " Set the ADPCM compression for the device. Default: 1 (On)"); -static int SwitchSVideoInput = 0; // To help people with Black and White output with using s-video input. Some cables and input device are wired differently. +/* To help people with Black and White output with using s-video input. + * Some cables and input device are wired differently. */ +static int SwitchSVideoInput; module_param(SwitchSVideoInput, int, 0444); MODULE_PARM_DESC(SwitchSVideoInput, " Set the S-Video input. Some cables and input device are wired differently. Default: 0 (Off)"); @@ -418,7 +420,7 @@ static void usbvision_testpattern(struct usb_usbvision *usbvision, unsigned char *f; int num_cell = 0; int scan_length = 0; - static int num_pass = 0; + static int num_pass; if (usbvision == NULL) { printk(KERN_ERR "%s: usbvision == NULL\n", proc); @@ -1430,7 +1432,7 @@ static int usbvision_compress_isochronous(struct usb_usbvision *usbvision, } #if ENABLE_HEXDUMP if (totlen > 0) { - static int foo = 0; + static int foo; if (foo < 1) { printk(KERN_DEBUG "+%d.\n", usbvision->scratchlen); usbvision_hexdump(data0, (totlen > 64) ? 64 : totlen); diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c index aabc42cae9c7..a7ed6f21f119 100644 --- a/drivers/media/video/usbvision/usbvision-i2c.c +++ b/drivers/media/video/usbvision/usbvision-i2c.c @@ -40,7 +40,7 @@ #define DBG_I2C 1<<0 -static int i2c_debug = 0; +static int i2c_debug; module_param (i2c_debug, int, 0644); // debug_i2c_usb mode of the device driver MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index df52f8a60215..2c2e10639564 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c @@ -115,7 +115,7 @@ USBVISION_DRIVER_VERSION_PATCHLEVEL) /* sequential number of usbvision device */ -static int usbvision_nr = 0; +static int usbvision_nr; static struct usbvision_v4l2_format_st usbvision_v4l2_format[] = { { 1, 1, 8, V4L2_PIX_FMT_GREY , "GREY" }, @@ -135,7 +135,7 @@ static void usbvision_release(struct usb_usbvision *usbvision); /* Set the default format for ISOC endpoint */ static int isocMode = ISOC_MODE_COMPRESS; /* Set the default Debug Mode of the device driver */ -static int video_debug = 0; +static int video_debug; /* Set the default device to power on at startup */ static int PowerOnAtOpen = 1; /* Sequential Number of Video Device */ diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c index dcf22a3b672a..b0de5ad2f753 100644 --- a/drivers/media/video/v4l1-compat.c +++ b/drivers/media/video/v4l1-compat.c @@ -39,7 +39,7 @@ #include <linux/kmod.h> #endif -static unsigned int debug = 0; +static unsigned int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug,"enable debug messages"); MODULE_AUTHOR("Bill Dirks"); diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c index 53fed4b74ce9..7008afabe92c 100644 --- a/drivers/media/video/videobuf-dma-sg.c +++ b/drivers/media/video/videobuf-dma-sg.c @@ -39,7 +39,7 @@ #define MAGIC_CHECK(is,should) if (unlikely((is) != (should))) \ { printk(KERN_ERR "magic mismatch: %x (expected %x)\n",is,should); BUG(); } -static int debug = 0; +static int debug; module_param(debug, int, 0644); MODULE_DESCRIPTION("helper module to manage video4linux pci dma sg buffers"); diff --git a/drivers/media/video/videobuf-dvb.c b/drivers/media/video/videobuf-dvb.c index b73aba65d21d..4ba8b7db7fda 100644 --- a/drivers/media/video/videobuf-dvb.c +++ b/drivers/media/video/videobuf-dvb.c @@ -30,7 +30,7 @@ MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); MODULE_LICENSE("GPL"); -static unsigned int debug = 0; +static unsigned int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug,"enable debug messages"); diff --git a/drivers/media/video/videobuf-vmalloc.c b/drivers/media/video/videobuf-vmalloc.c index 5266ecc91dab..3de3c8920175 100644 --- a/drivers/media/video/videobuf-vmalloc.c +++ b/drivers/media/video/videobuf-vmalloc.c @@ -33,7 +33,7 @@ #define MAGIC_CHECK(is,should) if (unlikely((is) != (should))) \ { printk(KERN_ERR "magic mismatch: %x (expected %x)\n",is,should); BUG(); } -static int debug = 0; +static int debug; module_param(debug, int, 0644); MODULE_DESCRIPTION("helper module to manage video4linux vmalloc buffers"); diff --git a/drivers/media/video/videocodec.c b/drivers/media/video/videocodec.c index 87951ec8254f..b30b6b2a9a85 100644 --- a/drivers/media/video/videocodec.c +++ b/drivers/media/video/videocodec.c @@ -44,7 +44,7 @@ #include "videocodec.h" -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-4)"); @@ -325,7 +325,7 @@ videocodec_unregister (const struct videocodec *codec) /* ============ */ static char *videocodec_buf = NULL; -static int videocodec_bufsize = 0; +static int videocodec_bufsize; static int videocodec_build_table (void) diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c index 5bb75294b5aa..d545c98dd5e7 100644 --- a/drivers/media/video/vino.c +++ b/drivers/media/video/vino.c @@ -333,7 +333,7 @@ struct vino_settings { * * Use non-zero value to enable conversion. */ -static int vino_pixel_conversion = 0; +static int vino_pixel_conversion; module_param_named(pixelconv, vino_pixel_conversion, int, 0); @@ -4370,8 +4370,8 @@ static int vino_ioctl(struct inode *inode, struct file *file, /* Initialization and cleanup */ -// __initdata -static int vino_init_stage = 0; +/* __initdata */ +static int vino_init_stage; static const struct file_operations vino_fops = { .owner = THIS_MODULE, @@ -4385,8 +4385,8 @@ static const struct file_operations vino_fops = { static struct video_device v4l_device_template = { .name = "NOT SET", - //.type = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE | - // VID_TYPE_CLIPPING | VID_TYPE_SCALES, VID_TYPE_OVERLAY + /*.type = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE | */ + /* VID_TYPE_CLIPPING | VID_TYPE_SCALES, VID_TYPE_OVERLAY */ .fops = &vino_fops, .minor = -1, }; diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c index a9133858e913..35293029da02 100644 --- a/drivers/media/video/vpx3220.c +++ b/drivers/media/video/vpx3220.c @@ -40,7 +40,7 @@ #define I2C_VPX3220 0x86 #define VPX3220_DEBUG KERN_DEBUG "vpx3220: " -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); diff --git a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c index 08aaae07c7e0..cc8c8246c30e 100644 --- a/drivers/media/video/w9966.c +++ b/drivers/media/video/w9966.c @@ -61,7 +61,7 @@ #include <media/v4l2-common.h> #include <linux/parport.h> -//#define DEBUG // Undef me for production +/*#define DEBUG*/ /* Undef me for production */ #ifdef DEBUG #define DPRINTF(x, a...) printk(KERN_DEBUG "W9966: %s(): "x, __FUNCTION__ , ##a) @@ -134,7 +134,7 @@ MODULE_PARM_DESC(pardev, "pardev: where to search for\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 = 0; +static int parmode; module_param(parmode, int, 0); MODULE_PARM_DESC(parmode, "parmode: transfer mode (0=auto, 1=ecp, 2=epp"); diff --git a/drivers/media/video/w9968cf.c b/drivers/media/video/w9968cf.c index 2ae1430f5f7d..cce23d24e6fc 100644 --- a/drivers/media/video/w9968cf.c +++ b/drivers/media/video/w9968cf.c @@ -3481,7 +3481,7 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) enum w9968cf_model_id mod_id; struct list_head* ptr; u8 sc = 0; /* number of simultaneous cameras */ - static unsigned short dev_nr = 0; /* we are handling device number n */ + static unsigned short dev_nr; /* 0 - we are handling device number n */ if (le16_to_cpu(udev->descriptor.idVendor) == winbond_id_table[0].idVendor && le16_to_cpu(udev->descriptor.idProduct) == winbond_id_table[0].idProduct) diff --git a/drivers/media/video/zc0301/zc0301_core.c b/drivers/media/video/zc0301/zc0301_core.c index 2c5665c82442..af357cbcb9bb 100644 --- a/drivers/media/video/zc0301/zc0301_core.c +++ b/drivers/media/video/zc0301/zc0301_core.c @@ -1939,7 +1939,7 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) { struct usb_device *udev = interface_to_usbdev(intf); struct zc0301_device* cam; - static unsigned int dev_nr = 0; + static unsigned int dev_nr; unsigned int i; int err = 0; diff --git a/drivers/media/video/zoran_card.c b/drivers/media/video/zoran_card.c index 690281bb59ee..006d48847e24 100644 --- a/drivers/media/video/zoran_card.c +++ b/drivers/media/video/zoran_card.c @@ -83,7 +83,7 @@ MODULE_PARM_DESC(decoder, "i2c TV decoder"); or set in in a VIDIOCSFBUF ioctl */ -static unsigned long vidmem = 0; /* Video memory base address */ +static unsigned long vidmem; /* default = 0 - Video memory base address */ module_param(vidmem, ulong, 0444); MODULE_PARM_DESC(vidmem, "Default video memory base address"); @@ -91,7 +91,7 @@ MODULE_PARM_DESC(vidmem, "Default video memory base address"); Default input and video norm at startup of the driver. */ -static unsigned int default_input = 0; /* 0=Composite, 1=S-Video */ +static unsigned int default_input; /* default 0 = Composite, 1 = S-Video */ module_param(default_input, uint, 0444); MODULE_PARM_DESC(default_input, "Default input (0=Composite, 1=S-Video, 2=Internal)"); @@ -101,7 +101,7 @@ module_param(default_mux, int, 0644); MODULE_PARM_DESC(default_mux, "Default 6 Eyes mux setting (Input selection)"); -static int default_norm = 0; /* 0=PAL, 1=NTSC 2=SECAM */ +static int default_norm; /* default 0 = PAL, 1 = NTSC 2 = SECAM */ module_param(default_norm, int, 0444); MODULE_PARM_DESC(default_norm, "Default norm (0=PAL, 1=NTSC, 2=SECAM)"); diff --git a/drivers/media/video/zoran_device.c b/drivers/media/video/zoran_device.c index f97c20692057..10686c68a65b 100644 --- a/drivers/media/video/zoran_device.c +++ b/drivers/media/video/zoran_device.c @@ -60,7 +60,8 @@ extern const struct zoran_format zoran_formats[]; -static int lml33dpath = 0; /* 1 will use digital path in capture +static int lml33dpath; /* default = 0 + * 1 will use digital path in capture * mode instead of analog. It can be * used for picture adjustments using * tool like xawtv while watching image @@ -987,7 +988,7 @@ void zr36057_enable_jpg (struct zoran *zr, enum zoran_codec_mode mode) { - static int zero = 0; + static int zero; static int one = 1; struct vfe_settings cap; int field_size = diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c index dd3d7d2c8b0e..36e7300d4972 100644 --- a/drivers/media/video/zoran_driver.c +++ b/drivers/media/video/zoran_driver.c @@ -205,7 +205,7 @@ extern int jpg_nbufs; extern int jpg_bufsize; extern int pass_through; -static int lock_norm = 0; /* 1=Don't change TV standard (norm) */ +static int lock_norm; /* 0 = default 1 = Don't change TV standard (norm) */ module_param(lock_norm, int, 0644); MODULE_PARM_DESC(lock_norm, "Prevent norm changes (1 = ignore, >1 = fail)"); diff --git a/drivers/media/video/zr36016.c b/drivers/media/video/zr36016.c index dd084555da8f..00d132bcd1e4 100644 --- a/drivers/media/video/zr36016.c +++ b/drivers/media/video/zr36016.c @@ -55,11 +55,10 @@ #define MAX_CODECS 20 /* amount of chips attached via this driver */ -static int zr36016_codecs = 0; +static int zr36016_codecs; /* debugging is available via module parameter */ - -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-4)"); diff --git a/drivers/media/video/zr36050.c b/drivers/media/video/zr36050.c index faae4ec3ea0b..cf8b271a1c8f 100644 --- a/drivers/media/video/zr36050.c +++ b/drivers/media/video/zr36050.c @@ -52,11 +52,10 @@ #define MAX_CODECS 20 /* amount of chips attached via this driver */ -static int zr36050_codecs = 0; +static int zr36050_codecs; /* debugging is available via module parameter */ - -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-4)"); diff --git a/drivers/media/video/zr36060.c b/drivers/media/video/zr36060.c index 7849b65969d0..8e74054d5ef1 100644 --- a/drivers/media/video/zr36060.c +++ b/drivers/media/video/zr36060.c @@ -52,14 +52,14 @@ #define MAX_CODECS 20 /* amount of chips attached via this driver */ -static int zr36060_codecs = 0; +static int zr36060_codecs; -static int low_bitrate = 0; +static int low_bitrate; module_param(low_bitrate, bool, 0); MODULE_PARM_DESC(low_bitrate, "Buz compatibility option, halves bitrate"); /* debugging is available via module parameter */ -static int debug = 0; +static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-4)"); diff --git a/drivers/media/video/zr364xx.c b/drivers/media/video/zr364xx.c index 1b44784d0efb..1cd63907f31b 100644 --- a/drivers/media/video/zr364xx.c +++ b/drivers/media/video/zr364xx.c @@ -62,8 +62,8 @@ /* Module parameters */ -static int debug = 0; -static int mode = 0; +static int debug; +static int mode; /* Module parameters interface */ diff --git a/include/asm-arm/arch-pxa/camera.h b/include/asm-arm/arch-pxa/camera.h new file mode 100644 index 000000000000..39516ced8b1f --- /dev/null +++ b/include/asm-arm/arch-pxa/camera.h @@ -0,0 +1,48 @@ +/* + camera.h - PXA camera driver header file + + Copyright (C) 2003, Intel Corporation + Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de> + + 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. + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __ASM_ARCH_CAMERA_H_ +#define __ASM_ARCH_CAMERA_H_ + +#define PXA_CAMERA_MASTER 1 +#define PXA_CAMERA_DATAWIDTH_4 2 +#define PXA_CAMERA_DATAWIDTH_5 4 +#define PXA_CAMERA_DATAWIDTH_8 8 +#define PXA_CAMERA_DATAWIDTH_9 0x10 +#define PXA_CAMERA_DATAWIDTH_10 0x20 +#define PXA_CAMERA_PCLK_EN 0x40 +#define PXA_CAMERA_MCLK_EN 0x80 +#define PXA_CAMERA_PCP 0x100 +#define PXA_CAMERA_HSP 0x200 +#define PXA_CAMERA_VSP 0x400 + +struct pxacamera_platform_data { + int (*init)(struct device *); + int (*power)(struct device *, int); + int (*reset)(struct device *, int); + + unsigned long flags; + unsigned long mclk_10khz; +}; + +extern void pxa_set_camera_info(struct pxacamera_platform_data *); + +#endif /* __ASM_ARCH_CAMERA_H_ */ diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h index ac175b4d10cb..9c1d3ed2dbf2 100644 --- a/include/asm-arm/arch-pxa/pxa-regs.h +++ b/include/asm-arm/arch-pxa/pxa-regs.h @@ -46,13 +46,13 @@ #define PCMCIA1AttrSp PCMCIAAttrSp /* PCMCIA 1 Attribute Space [byte] */ #define PCMCIA1MemSp PCMCIAMemSp /* PCMCIA 1 Memory Space [byte] */ -#define _PCMCIA(Nb) /* PCMCIA [0..1] */ \ - (0x20000000 + (Nb)*PCMCIASp) +#define _PCMCIA(Nb) /* PCMCIA [0..1] */ \ + (0x20000000 + (Nb)*PCMCIASp) #define _PCMCIAIO(Nb) _PCMCIA (Nb) /* PCMCIA I/O [0..1] */ -#define _PCMCIAAttr(Nb) /* PCMCIA Attribute [0..1] */ \ - (_PCMCIA (Nb) + 2*PCMCIAPrtSp) -#define _PCMCIAMem(Nb) /* PCMCIA Memory [0..1] */ \ - (_PCMCIA (Nb) + 3*PCMCIAPrtSp) +#define _PCMCIAAttr(Nb) /* PCMCIA Attribute [0..1] */ \ + (_PCMCIA (Nb) + 2*PCMCIAPrtSp) +#define _PCMCIAMem(Nb) /* PCMCIA Memory [0..1] */ \ + (_PCMCIA (Nb) + 3*PCMCIAPrtSp) #define _PCMCIA0 _PCMCIA (0) /* PCMCIA 0 */ #define _PCMCIA0IO _PCMCIAIO (0) /* PCMCIA 0 I/O */ @@ -1245,19 +1245,26 @@ #define GPIO10_RTCCLK 10 /* real time clock (1 Hz) */ #define GPIO11_3_6MHz 11 /* 3.6 MHz oscillator out */ #define GPIO12_32KHz 12 /* 32 kHz out */ +#define GPIO12_CIF_DD7 12 /* Capture Interface D7 (PXA27x) */ #define GPIO13_MBGNT 13 /* memory controller grant */ #define GPIO14_MBREQ 14 /* alternate bus master request */ #define GPIO15_nCS_1 15 /* chip select 1 */ #define GPIO16_PWM0 16 /* PWM0 output */ #define GPIO17_PWM1 17 /* PWM1 output */ +#define GPIO17_CIF_DD6 17 /* Capture Interface D6 (PXA27x) */ #define GPIO18_RDY 18 /* Ext. Bus Ready */ #define GPIO19_DREQ1 19 /* External DMA Request */ #define GPIO20_DREQ0 20 /* External DMA Request */ #define GPIO23_SCLK 23 /* SSP clock */ +#define GPIO23_CIF_MCLK 23 /* Capture Interface MCLK (PXA27x) */ #define GPIO24_SFRM 24 /* SSP Frame */ +#define GPIO24_CIF_FV 24 /* Capture Interface FV (PXA27x) */ #define GPIO25_STXD 25 /* SSP transmit */ +#define GPIO25_CIF_LV 25 /* Capture Interface LV (PXA27x) */ #define GPIO26_SRXD 26 /* SSP receive */ +#define GPIO26_CIF_PCLK 26 /* Capture Interface PCLK (PXA27x) */ #define GPIO27_SEXTCLK 27 /* SSP ext_clk */ +#define GPIO27_CIF_DD0 27 /* Capture Interface D0 (PXA27x) */ #define GPIO28_BITCLK 28 /* AC97/I2S bit_clk */ #define GPIO29_SDATA_IN 29 /* AC97 Sdata_in0 / I2S Sdata_in */ #define GPIO30_SDATA_OUT 30 /* AC97/I2S Sdata_out */ @@ -1278,28 +1285,40 @@ #define GPIO41_FFRTS 41 /* FFUART request to send */ #define GPIO42_BTRXD 42 /* BTUART receive data */ #define GPIO42_HWRXD 42 /* HWUART receive data */ +#define GPIO42_CIF_MCLK 42 /* Capture interface MCLK (PXA27x) */ #define GPIO43_BTTXD 43 /* BTUART transmit data */ #define GPIO43_HWTXD 43 /* HWUART transmit data */ +#define GPIO43_CIF_FV 43 /* Capture interface FV (PXA27x) */ #define GPIO44_BTCTS 44 /* BTUART clear to send */ #define GPIO44_HWCTS 44 /* HWUART clear to send */ +#define GPIO44_CIF_LV 44 /* Capture interface LV (PXA27x) */ #define GPIO45_BTRTS 45 /* BTUART request to send */ #define GPIO45_HWRTS 45 /* HWUART request to send */ #define GPIO45_AC97_SYSCLK 45 /* AC97 System Clock */ +#define GPIO45_CIF_PCLK 45 /* Capture interface PCLK (PXA27x) */ #define GPIO46_ICPRXD 46 /* ICP receive data */ #define GPIO46_STRXD 46 /* STD_UART receive data */ #define GPIO47_ICPTXD 47 /* ICP transmit data */ #define GPIO47_STTXD 47 /* STD_UART transmit data */ +#define GPIO47_CIF_DD0 47 /* Capture interface D0 (PXA27x) */ #define GPIO48_nPOE 48 /* Output Enable for Card Space */ +#define GPIO48_CIF_DD5 48 /* Capture interface D5 (PXA27x) */ #define GPIO49_nPWE 49 /* Write Enable for Card Space */ #define GPIO50_nPIOR 50 /* I/O Read for Card Space */ +#define GPIO50_CIF_DD3 50 /* Capture interface D3 (PXA27x) */ #define GPIO51_nPIOW 51 /* I/O Write for Card Space */ +#define GPIO51_CIF_DD2 51 /* Capture interface D2 (PXA27x) */ #define GPIO52_nPCE_1 52 /* Card Enable for Card Space */ +#define GPIO52_CIF_DD4 52 /* Capture interface D4 (PXA27x) */ #define GPIO53_nPCE_2 53 /* Card Enable for Card Space */ #define GPIO53_MMCCLK 53 /* MMC Clock */ +#define GPIO53_CIF_MCLK 53 /* Capture interface MCLK (PXA27x) */ #define GPIO54_MMCCLK 54 /* MMC Clock */ #define GPIO54_pSKTSEL 54 /* Socket Select for Card Space */ #define GPIO54_nPCE_2 54 /* Card Enable for Card Space (PXA27x) */ +#define GPIO54_CIF_PCLK 54 /* Capture interface PCLK (PXA27x) */ #define GPIO55_nPREG 55 /* Card Address bit 26 */ +#define GPIO55_CIF_DD1 55 /* Capture interface D1 (PXA27x) */ #define GPIO56_nPWAIT 56 /* Wait signal for Card Space */ #define GPIO57_nIOIS16 57 /* Bus Width select for I/O Card Space */ #define GPIO58_LDD_0 58 /* LCD data pin 0 */ @@ -1334,11 +1353,28 @@ #define GPIO79_nCS_3 79 /* chip select 3 */ #define GPIO80_nCS_4 80 /* chip select 4 */ #define GPIO81_NSCLK 81 /* NSSP clock */ +#define GPIO81_CIF_DD0 81 /* Capture Interface D0 (PXA27x) */ #define GPIO82_NSFRM 82 /* NSSP Frame */ +#define GPIO82_CIF_DD5 82 /* Capture Interface D5 (PXA27x) */ #define GPIO83_NSTXD 83 /* NSSP transmit */ +#define GPIO83_CIF_DD4 83 /* Capture Interface D4 (PXA27x) */ #define GPIO84_NSRXD 84 /* NSSP receive */ +#define GPIO84_CIF_FV 84 /* Capture Interface FV (PXA27x) */ #define GPIO85_nPCE_1 85 /* Card Enable for Card Space (PXA27x) */ +#define GPIO85_CIF_LV 85 /* Capture Interface LV (PXA27x) */ +#define GPIO90_CIF_DD4 90 /* Capture Interface DD4 (PXA27x) */ +#define GPIO91_CIF_DD5 91 /* Capture Interface DD5 (PXA27x) */ #define GPIO92_MMCDAT0 92 /* MMC DAT0 (PXA27x) */ +#define GPIO93_CIF_DD6 93 /* Capture interface D6 (PXA27x) */ +#define GPIO94_CIF_DD5 94 /* Capture interface D5 (PXA27x) */ +#define GPIO95_CIF_DD4 95 /* Capture interface D4 (PXA27x) */ +#define GPIO98_CIF_DD0 98 /* Capture interface D0 (PXA27x) */ +#define GPIO103_CIF_DD3 103 /* Capture interface D3 (PXA27x) */ +#define GPIO104_CIF_DD2 104 /* Capture interface D2 (PXA27x) */ +#define GPIO105_CIF_DD1 105 /* Capture interface D1 (PXA27x) */ +#define GPIO106_CIF_DD9 106 /* Capture interface D9 (PXA27x) */ +#define GPIO107_CIF_DD8 107 /* Capture interface D8 (PXA27x) */ +#define GPIO108_CIF_DD7 108 /* Capture interface D7 (PXA27x) */ #define GPIO102_nPCE_1 102 /* PCMCIA (PXA27x) */ #define GPIO109_MMCDAT1 109 /* MMC DAT1 (PXA27x) */ #define GPIO110_MMCDAT2 110 /* MMC DAT2 (PXA27x) */ @@ -1348,6 +1384,9 @@ #define GPIO112_MMCCMD 112 /* MMC CMD (PXA27x) */ #define GPIO113_I2S_SYSCLK 113 /* I2S System Clock (PXA27x) */ #define GPIO113_AC97_RESET_N 113 /* AC97 NRESET on (PXA27x) */ +#define GPIO114_CIF_DD1 114 /* Capture interface D1 (PXA27x) */ +#define GPIO115_CIF_DD3 115 /* Capture interface D3 (PXA27x) */ +#define GPIO116_CIF_DD2 116 /* Capture interface D2 (PXA27x) */ /* GPIO alternate function mode & direction */ @@ -1373,19 +1412,26 @@ #define GPIO10_RTCCLK_MD (10 | GPIO_ALT_FN_1_OUT) #define GPIO11_3_6MHz_MD (11 | GPIO_ALT_FN_1_OUT) #define GPIO12_32KHz_MD (12 | GPIO_ALT_FN_1_OUT) +#define GPIO12_CIF_DD7_MD (12 | GPIO_ALT_FN_2_IN) #define GPIO13_MBGNT_MD (13 | GPIO_ALT_FN_2_OUT) #define GPIO14_MBREQ_MD (14 | GPIO_ALT_FN_1_IN) #define GPIO15_nCS_1_MD (15 | GPIO_ALT_FN_2_OUT) #define GPIO16_PWM0_MD (16 | GPIO_ALT_FN_2_OUT) #define GPIO17_PWM1_MD (17 | GPIO_ALT_FN_2_OUT) +#define GPIO17_CIF_DD6_MD (17 | GPIO_ALT_FN_2_IN) #define GPIO18_RDY_MD (18 | GPIO_ALT_FN_1_IN) #define GPIO19_DREQ1_MD (19 | GPIO_ALT_FN_1_IN) #define GPIO20_DREQ0_MD (20 | GPIO_ALT_FN_1_IN) +#define GPIO23_CIF_MCLK_MD (23 | GPIO_ALT_FN_1_OUT) #define GPIO23_SCLK_MD (23 | GPIO_ALT_FN_2_OUT) +#define GPIO24_CIF_FV_MD (24 | GPIO_ALT_FN_1_OUT) #define GPIO24_SFRM_MD (24 | GPIO_ALT_FN_2_OUT) +#define GPIO25_CIF_LV_MD (25 | GPIO_ALT_FN_1_OUT) #define GPIO25_STXD_MD (25 | GPIO_ALT_FN_2_OUT) #define GPIO26_SRXD_MD (26 | GPIO_ALT_FN_1_IN) +#define GPIO26_CIF_PCLK_MD (26 | GPIO_ALT_FN_2_IN) #define GPIO27_SEXTCLK_MD (27 | GPIO_ALT_FN_1_IN) +#define GPIO27_CIF_DD0_MD (27 | GPIO_ALT_FN_3_IN) #define GPIO28_BITCLK_AC97_MD (28 | GPIO_ALT_FN_1_IN) #define GPIO28_BITCLK_IN_I2S_MD (28 | GPIO_ALT_FN_2_IN) #define GPIO28_BITCLK_OUT_I2S_MD (28 | GPIO_ALT_FN_1_OUT) @@ -1410,34 +1456,46 @@ #define GPIO40_FFDTR_MD (40 | GPIO_ALT_FN_2_OUT) #define GPIO41_FFRTS_MD (41 | GPIO_ALT_FN_2_OUT) #define GPIO42_BTRXD_MD (42 | GPIO_ALT_FN_1_IN) +#define GPIO42_CIF_MCLK_MD (42 | GPIO_ALT_FN_3_OUT) #define GPIO42_HWRXD_MD (42 | GPIO_ALT_FN_3_IN) #define GPIO43_BTTXD_MD (43 | GPIO_ALT_FN_2_OUT) +#define GPIO43_CIF_FV_MD (43 | GPIO_ALT_FN_3_OUT) #define GPIO43_HWTXD_MD (43 | GPIO_ALT_FN_3_OUT) #define GPIO44_BTCTS_MD (44 | GPIO_ALT_FN_1_IN) #define GPIO44_HWCTS_MD (44 | GPIO_ALT_FN_3_IN) +#define GPIO44_CIF_LV_MD (44 | GPIO_ALT_FN_3_OUT) #define GPIO45_BTRTS_MD (45 | GPIO_ALT_FN_2_OUT) #define GPIO45_HWRTS_MD (45 | GPIO_ALT_FN_3_OUT) #define GPIO45_SYSCLK_AC97_MD (45 | GPIO_ALT_FN_1_OUT) +#define GPIO45_CIF_PCLK_MD (45 | GPIO_ALT_FN_3_IN) #define GPIO46_ICPRXD_MD (46 | GPIO_ALT_FN_1_IN) #define GPIO46_STRXD_MD (46 | GPIO_ALT_FN_2_IN) #define GPIO47_ICPTXD_MD (47 | GPIO_ALT_FN_2_OUT) #define GPIO47_STTXD_MD (47 | GPIO_ALT_FN_1_OUT) +#define GPIO47_CIF_DD0_MD (47 | GPIO_ALT_FN_1_IN) #define GPIO48_nPOE_MD (48 | GPIO_ALT_FN_2_OUT) +#define GPIO48_CIF_DD5_MD (48 | GPIO_ALT_FN_1_IN) #define GPIO48_HWTXD_MD (48 | GPIO_ALT_FN_1_OUT) #define GPIO48_nPOE_MD (48 | GPIO_ALT_FN_2_OUT) #define GPIO49_HWRXD_MD (49 | GPIO_ALT_FN_1_IN) #define GPIO49_nPWE_MD (49 | GPIO_ALT_FN_2_OUT) #define GPIO50_nPIOR_MD (50 | GPIO_ALT_FN_2_OUT) +#define GPIO50_CIF_DD3_MD (50 | GPIO_ALT_FN_1_IN) #define GPIO50_HWCTS_MD (50 | GPIO_ALT_FN_1_IN) #define GPIO51_HWRTS_MD (51 | GPIO_ALT_FN_1_OUT) #define GPIO51_nPIOW_MD (51 | GPIO_ALT_FN_2_OUT) +#define GPIO51_CIF_DD2_MD (51 | GPIO_ALT_FN_1_IN) #define GPIO52_nPCE_1_MD (52 | GPIO_ALT_FN_2_OUT) +#define GPIO52_CIF_DD4_MD (52 | GPIO_ALT_FN_1_IN) #define GPIO53_nPCE_2_MD (53 | GPIO_ALT_FN_2_OUT) #define GPIO53_MMCCLK_MD (53 | GPIO_ALT_FN_1_OUT) +#define GPIO53_CIF_MCLK_MD (53 | GPIO_ALT_FN_2_OUT) #define GPIO54_MMCCLK_MD (54 | GPIO_ALT_FN_1_OUT) #define GPIO54_nPCE_2_MD (54 | GPIO_ALT_FN_2_OUT) #define GPIO54_pSKTSEL_MD (54 | GPIO_ALT_FN_2_OUT) +#define GPIO54_CIF_PCLK_MD (54 | GPIO_ALT_FN_3_IN) #define GPIO55_nPREG_MD (55 | GPIO_ALT_FN_2_OUT) +#define GPIO55_CIF_DD1_MD (55 | GPIO_ALT_FN_1_IN) #define GPIO56_nPWAIT_MD (56 | GPIO_ALT_FN_1_IN) #define GPIO57_nIOIS16_MD (57 | GPIO_ALT_FN_1_IN) #define GPIO58_LDD_0_MD (58 | GPIO_ALT_FN_2_OUT) @@ -1474,16 +1532,33 @@ #define GPIO80_nCS_4_MD (80 | GPIO_ALT_FN_2_OUT) #define GPIO81_NSSP_CLK_OUT (81 | GPIO_ALT_FN_1_OUT) #define GPIO81_NSSP_CLK_IN (81 | GPIO_ALT_FN_1_IN) +#define GPIO81_CIF_DD0_MD (81 | GPIO_ALT_FN_2_IN) #define GPIO82_NSSP_FRM_OUT (82 | GPIO_ALT_FN_1_OUT) #define GPIO82_NSSP_FRM_IN (82 | GPIO_ALT_FN_1_IN) +#define GPIO82_CIF_DD5_MD (82 | GPIO_ALT_FN_3_IN) #define GPIO83_NSSP_TX (83 | GPIO_ALT_FN_1_OUT) #define GPIO83_NSSP_RX (83 | GPIO_ALT_FN_2_IN) +#define GPIO83_CIF_DD4_MD (83 | GPIO_ALT_FN_3_IN) #define GPIO84_NSSP_TX (84 | GPIO_ALT_FN_1_OUT) #define GPIO84_NSSP_RX (84 | GPIO_ALT_FN_2_IN) +#define GPIO84_CIF_FV_MD (84 | GPIO_ALT_FN_3_OUT) #define GPIO85_nPCE_1_MD (85 | GPIO_ALT_FN_1_OUT) +#define GPIO85_CIF_LV_MD (85 | GPIO_ALT_FN_3_OUT) +#define GPIO90_CIF_DD4_MD (90 | GPIO_ALT_FN_3_IN) +#define GPIO91_CIF_DD5_MD (91 | GPIO_ALT_FN_3_IN) #define GPIO92_MMCDAT0_MD (92 | GPIO_ALT_FN_1_OUT) +#define GPIO93_CIF_DD6_MD (93 | GPIO_ALT_FN_2_IN) +#define GPIO94_CIF_DD5_MD (94 | GPIO_ALT_FN_2_IN) +#define GPIO95_CIF_DD4_MD (95 | GPIO_ALT_FN_2_IN) +#define GPIO98_CIF_DD0_MD (98 | GPIO_ALT_FN_2_IN) #define GPIO102_nPCE_1_MD (102 | GPIO_ALT_FN_1_OUT) +#define GPIO103_CIF_DD3_MD (103 | GPIO_ALT_FN_1_IN) #define GPIO104_pSKTSEL_MD (104 | GPIO_ALT_FN_1_OUT) +#define GPIO104_CIF_DD2_MD (104 | GPIO_ALT_FN_1_IN) +#define GPIO105_CIF_DD1_MD (105 | GPIO_ALT_FN_1_IN) +#define GPIO106_CIF_DD9_MD (106 | GPIO_ALT_FN_1_IN) +#define GPIO107_CIF_DD8_MD (107 | GPIO_ALT_FN_1_IN) +#define GPIO108_CIF_DD7_MD (108 | GPIO_ALT_FN_1_IN) #define GPIO109_MMCDAT1_MD (109 | GPIO_ALT_FN_1_OUT) #define GPIO110_MMCDAT2_MD (110 | GPIO_ALT_FN_1_OUT) #define GPIO110_MMCCS0_MD (110 | GPIO_ALT_FN_1_OUT) @@ -1712,7 +1787,7 @@ #define LCCR0_Color (LCCR0_CMS*0) /* Color display */ #define LCCR0_Mono (LCCR0_CMS*1) /* Monochrome display */ #define LCCR0_SDS (1 << 2) /* Single/Dual Panel Display */ - /* Select */ + /* Select */ #define LCCR0_Sngl (LCCR0_SDS*0) /* Single panel display */ #define LCCR0_Dual (LCCR0_SDS*1) /* Dual panel display */ @@ -1724,11 +1799,11 @@ #define LCCR0_Pas (LCCR0_PAS*0) /* Passive display (STN) */ #define LCCR0_Act (LCCR0_PAS*1) /* Active display (TFT) */ #define LCCR0_DPD (1 << 9) /* Double Pixel Data (monochrome */ - /* display mode) */ + /* display mode) */ #define LCCR0_4PixMono (LCCR0_DPD*0) /* 4-Pixel/clock Monochrome */ - /* display */ + /* display */ #define LCCR0_8PixMono (LCCR0_DPD*1) /* 8-Pixel/clock Monochrome */ - /* display */ + /* display */ #define LCCR0_DIS (1 << 10) /* LCD Disable */ #define LCCR0_QDM (1 << 11) /* LCD Quick Disable mask */ #define LCCR0_PDD (0xff << 12) /* Palette DMA request delay */ @@ -1743,47 +1818,47 @@ #define LCCR1_PPL Fld (10, 0) /* Pixels Per Line - 1 */ #define LCCR1_DisWdth(Pixel) /* Display Width [1..800 pix.] */ \ - (((Pixel) - 1) << FShft (LCCR1_PPL)) + (((Pixel) - 1) << FShft (LCCR1_PPL)) #define LCCR1_HSW Fld (6, 10) /* Horizontal Synchronization */ #define LCCR1_HorSnchWdth(Tpix) /* Horizontal Synchronization */ \ - /* pulse Width [1..64 Tpix] */ \ - (((Tpix) - 1) << FShft (LCCR1_HSW)) + /* pulse Width [1..64 Tpix] */ \ + (((Tpix) - 1) << FShft (LCCR1_HSW)) #define LCCR1_ELW Fld (8, 16) /* End-of-Line pixel clock Wait */ - /* count - 1 [Tpix] */ + /* count - 1 [Tpix] */ #define LCCR1_EndLnDel(Tpix) /* End-of-Line Delay */ \ - /* [1..256 Tpix] */ \ - (((Tpix) - 1) << FShft (LCCR1_ELW)) + /* [1..256 Tpix] */ \ + (((Tpix) - 1) << FShft (LCCR1_ELW)) #define LCCR1_BLW Fld (8, 24) /* Beginning-of-Line pixel clock */ - /* Wait count - 1 [Tpix] */ + /* Wait count - 1 [Tpix] */ #define LCCR1_BegLnDel(Tpix) /* Beginning-of-Line Delay */ \ - /* [1..256 Tpix] */ \ - (((Tpix) - 1) << FShft (LCCR1_BLW)) + /* [1..256 Tpix] */ \ + (((Tpix) - 1) << FShft (LCCR1_BLW)) #define LCCR2_LPP Fld (10, 0) /* Line Per Panel - 1 */ #define LCCR2_DisHght(Line) /* Display Height [1..1024 lines] */ \ - (((Line) - 1) << FShft (LCCR2_LPP)) + (((Line) - 1) << FShft (LCCR2_LPP)) #define LCCR2_VSW Fld (6, 10) /* Vertical Synchronization pulse */ - /* Width - 1 [Tln] (L_FCLK) */ + /* Width - 1 [Tln] (L_FCLK) */ #define LCCR2_VrtSnchWdth(Tln) /* Vertical Synchronization pulse */ \ - /* Width [1..64 Tln] */ \ - (((Tln) - 1) << FShft (LCCR2_VSW)) + /* Width [1..64 Tln] */ \ + (((Tln) - 1) << FShft (LCCR2_VSW)) #define LCCR2_EFW Fld (8, 16) /* End-of-Frame line clock Wait */ - /* count [Tln] */ + /* count [Tln] */ #define LCCR2_EndFrmDel(Tln) /* End-of-Frame Delay */ \ - /* [0..255 Tln] */ \ - ((Tln) << FShft (LCCR2_EFW)) + /* [0..255 Tln] */ \ + ((Tln) << FShft (LCCR2_EFW)) #define LCCR2_BFW Fld (8, 24) /* Beginning-of-Frame line clock */ - /* Wait count [Tln] */ + /* Wait count [Tln] */ #define LCCR2_BegFrmDel(Tln) /* Beginning-of-Frame Delay */ \ - /* [0..255 Tln] */ \ - ((Tln) << FShft (LCCR2_BFW)) + /* [0..255 Tln] */ \ + ((Tln) << FShft (LCCR2_BFW)) #if 0 #define LCCR3_PCD (0xff) /* Pixel clock divisor */ @@ -1800,7 +1875,7 @@ #define LCCR3_PixFlEdg (LCCR3_PCP*1) /* Pixel clock Falling-Edge */ #define LCCR3_OEP (1 << 23) /* Output Enable Polarity (L_BIAS, */ - /* active display mode) */ + /* active display mode) */ #define LCCR3_OutEnH (LCCR3_OEP*0) /* Output Enable active High */ #define LCCR3_OutEnL (LCCR3_OEP*1) /* Output Enable active Low */ @@ -1813,25 +1888,25 @@ #define LCCR3_PCD Fld (8, 0) /* Pixel Clock Divisor */ #define LCCR3_PixClkDiv(Div) /* Pixel Clock Divisor */ \ - (((Div) << FShft (LCCR3_PCD))) + (((Div) << FShft (LCCR3_PCD))) #define LCCR3_BPP Fld (3, 24) /* Bit Per Pixel */ #define LCCR3_Bpp(Bpp) /* Bit Per Pixel */ \ - (((Bpp) << FShft (LCCR3_BPP))) + (((Bpp) << FShft (LCCR3_BPP))) #define LCCR3_ACB Fld (8, 8) /* AC Bias */ #define LCCR3_Acb(Acb) /* BAC Bias */ \ - (((Acb) << FShft (LCCR3_ACB))) + (((Acb) << FShft (LCCR3_ACB))) #define LCCR3_HorSnchH (LCCR3_HSP*0) /* Horizontal Synchronization */ - /* pulse active High */ + /* pulse active High */ #define LCCR3_HorSnchL (LCCR3_HSP*1) /* Horizontal Synchronization */ #define LCCR3_VrtSnchH (LCCR3_VSP*0) /* Vertical Synchronization pulse */ - /* active High */ + /* active High */ #define LCCR3_VrtSnchL (LCCR3_VSP*1) /* Vertical Synchronization pulse */ - /* active Low */ + /* active Low */ #define LCSR_LDD (1 << 0) /* LCD Disable Done */ #define LCSR_SOF (1 << 1) /* Start of frame */ @@ -1938,6 +2013,11 @@ #define CICR0_ENB (1 << 28) /* Camera interface enable */ #define CICR0_DIS (1 << 27) /* Camera interface disable */ #define CICR0_SIM (0x7 << 24) /* Sensor interface mode mask */ +#define CICR0_SIM_MP (0 << 24) +#define CICR0_SIM_SP (1 << 24) +#define CICR0_SIM_MS (2 << 24) +#define CICR0_SIM_EP (3 << 24) +#define CICR0_SIM_ES (4 << 24) #define CICR0_TOM (1 << 9) /* Time-out mask */ #define CICR0_RDAVM (1 << 8) /* Receive-data-available mask */ #define CICR0_FEM (1 << 7) /* FIFO-empty mask */ @@ -1988,6 +2068,20 @@ #define CICR4_FR_RATE (0x7 << 8) /* Frame rate mask */ #define CICR4_DIV (0xff << 0) /* Clock divisor mask */ +#define CICR1_DW_VAL(x) ((x) & CICR1_DW) /* Data bus width */ +#define CICR1_PPL_VAL(x) (((x) << 15) & CICR1_PPL) /* Pixels per line */ + +#define CICR2_BLW_VAL(x) (((x) << 24) & CICR2_BLW) /* Beginning-of-line pixel clock wait count */ +#define CICR2_ELW_VAL(x) (((x) << 16) & CICR2_ELW) /* End-of-line pixel clock wait count */ +#define CICR2_HSW_VAL(x) (((x) << 10) & CICR2_HSW) /* Horizontal sync pulse width */ +#define CICR2_BFPW_VAL(x) (((x) << 3) & CICR2_BFPW) /* Beginning-of-frame pixel clock wait count */ +#define CICR2_FSW_VAL(x) (((x) << 0) & CICR2_FSW) /* Frame stabilization wait count */ + +#define CICR3_BFW_VAL(x) (((x) << 24) & CICR3_BFW) /* Beginning-of-frame line clock wait count */ +#define CICR3_EFW_VAL(x) (((x) << 16) & CICR3_EFW) /* End-of-frame line clock wait count */ +#define CICR3_VSW_VAL(x) (((x) << 11) & CICR3_VSW) /* Vertical sync pulse width */ +#define CICR3_LPF_VAL(x) (((x) << 0) & CICR3_LPF) /* Lines per frame */ + #define CISR_FTO (1 << 15) /* FIFO time-out */ #define CISR_RDAV_2 (1 << 14) /* Channel 2 receive data available */ #define CISR_RDAV_1 (1 << 13) /* Channel 1 receive data available */ diff --git a/include/linux/meye.h b/include/linux/meye.h index 39fd9c8ddd4b..12010ace1f04 100644 --- a/include/linux/meye.h +++ b/include/linux/meye.h @@ -58,7 +58,7 @@ struct meye_params { /* V4L2 private controls */ #define V4L2_CID_AGC V4L2_CID_PRIVATE_BASE -#define V4L2_CID_SHARPNESS (V4L2_CID_PRIVATE_BASE + 1) +#define V4L2_CID_MEYE_SHARPNESS (V4L2_CID_PRIVATE_BASE + 1) #define V4L2_CID_PICTURE (V4L2_CID_PRIVATE_BASE + 2) #define V4L2_CID_JPEGQUAL (V4L2_CID_PRIVATE_BASE + 3) #define V4L2_CID_FRAMERATE (V4L2_CID_PRIVATE_BASE + 4) diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 17a80177a674..50e6c35f8907 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -282,6 +282,7 @@ struct v4l2_pix_format #define V4L2_PIX_FMT_BGR32 v4l2_fourcc('B','G','R','4') /* 32 BGR-8-8-8-8 */ #define V4L2_PIX_FMT_RGB32 v4l2_fourcc('R','G','B','4') /* 32 RGB-8-8-8-8 */ #define V4L2_PIX_FMT_GREY v4l2_fourcc('G','R','E','Y') /* 8 Greyscale */ +#define V4L2_PIX_FMT_Y16 v4l2_fourcc('Y','1','6',' ') /* 16 Greyscale */ #define V4L2_PIX_FMT_PAL8 v4l2_fourcc('P','A','L','8') /* 8 8-bit palette */ #define V4L2_PIX_FMT_YVU410 v4l2_fourcc('Y','V','U','9') /* 9 YVU 4:1:0 */ #define V4L2_PIX_FMT_YVU420 v4l2_fourcc('Y','V','1','2') /* 12 YVU 4:2:0 */ @@ -308,6 +309,7 @@ struct v4l2_pix_format /* see http://www.siliconimaging.com/RGB%20Bayer.htm */ #define V4L2_PIX_FMT_SBGGR8 v4l2_fourcc('B','A','8','1') /* 8 BGBG.. GRGR.. */ +#define V4L2_PIX_FMT_SBGGR16 v4l2_fourcc('B','Y','R','2') /* 16 BGBG.. GRGR.. */ /* compressed formats */ #define V4L2_PIX_FMT_MJPEG v4l2_fourcc('M','J','P','G') /* Motion-JPEG */ @@ -793,6 +795,7 @@ struct v4l2_ext_controls /* Values for ctrl_class field */ #define V4L2_CTRL_CLASS_USER 0x00980000 /* Old-style 'user' controls */ #define V4L2_CTRL_CLASS_MPEG 0x00990000 /* MPEG-compression controls */ +#define V4L2_CTRL_CLASS_CAMERA 0x009a0000 /* Camera class controls */ #define V4L2_CTRL_ID_MASK (0x0fffffff) #define V4L2_CTRL_ID2CLASS(id) ((id) & 0x0fff0000UL) @@ -849,21 +852,34 @@ struct v4l2_querymenu #define V4L2_CID_AUDIO_TREBLE (V4L2_CID_BASE+8) #define V4L2_CID_AUDIO_MUTE (V4L2_CID_BASE+9) #define V4L2_CID_AUDIO_LOUDNESS (V4L2_CID_BASE+10) -#define V4L2_CID_BLACK_LEVEL (V4L2_CID_BASE+11) +#define V4L2_CID_BLACK_LEVEL (V4L2_CID_BASE+11) /* Deprecated */ #define V4L2_CID_AUTO_WHITE_BALANCE (V4L2_CID_BASE+12) #define V4L2_CID_DO_WHITE_BALANCE (V4L2_CID_BASE+13) #define V4L2_CID_RED_BALANCE (V4L2_CID_BASE+14) #define V4L2_CID_BLUE_BALANCE (V4L2_CID_BASE+15) #define V4L2_CID_GAMMA (V4L2_CID_BASE+16) -#define V4L2_CID_WHITENESS (V4L2_CID_GAMMA) /* ? Not sure */ +#define V4L2_CID_WHITENESS (V4L2_CID_GAMMA) /* Deprecated */ #define V4L2_CID_EXPOSURE (V4L2_CID_BASE+17) #define V4L2_CID_AUTOGAIN (V4L2_CID_BASE+18) #define V4L2_CID_GAIN (V4L2_CID_BASE+19) #define V4L2_CID_HFLIP (V4L2_CID_BASE+20) #define V4L2_CID_VFLIP (V4L2_CID_BASE+21) -#define V4L2_CID_HCENTER (V4L2_CID_BASE+22) -#define V4L2_CID_VCENTER (V4L2_CID_BASE+23) -#define V4L2_CID_LASTP1 (V4L2_CID_BASE+24) /* last CID + 1 */ + +/* Deprecated, use V4L2_CID_PAN_RESET and V4L2_CID_TILT_RESET */ +#define V4L2_CID_HCENTER_DEPRECATED (V4L2_CID_BASE+22) +#define V4L2_CID_VCENTER_DEPRECATED (V4L2_CID_BASE+23) + +#define V4L2_CID_POWER_LINE_FREQUENCY (V4L2_CID_BASE+24) +enum v4l2_power_line_frequency { + V4L2_CID_POWER_LINE_FREQUENCY_DISABLED = 0, + V4L2_CID_POWER_LINE_FREQUENCY_50HZ = 1, + V4L2_CID_POWER_LINE_FREQUENCY_60HZ = 2, +}; +#define V4L2_CID_HUE_AUTO (V4L2_CID_BASE+25) +#define V4L2_CID_WHITE_BALANCE_TEMPERATURE (V4L2_CID_BASE+26) +#define V4L2_CID_SHARPNESS (V4L2_CID_BASE+27) +#define V4L2_CID_BACKLIGHT_COMPENSATION (V4L2_CID_BASE+28) +#define V4L2_CID_LASTP1 (V4L2_CID_BASE+29) /* last CID + 1 */ /* MPEG-class control IDs defined by V4L2 */ #define V4L2_CID_MPEG_BASE (V4L2_CTRL_CLASS_MPEG | 0x900) @@ -1051,6 +1067,32 @@ enum v4l2_mpeg_cx2341x_video_median_filter_type { #define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP (V4L2_CID_MPEG_CX2341X_BASE+10) #define V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS (V4L2_CID_MPEG_CX2341X_BASE+11) +/* Camera class control IDs */ +#define V4L2_CID_CAMERA_CLASS_BASE (V4L2_CTRL_CLASS_CAMERA | 0x900) +#define V4L2_CID_CAMERA_CLASS (V4L2_CTRL_CLASS_CAMERA | 1) + +#define V4L2_CID_EXPOSURE_AUTO (V4L2_CID_CAMERA_CLASS_BASE+1) +enum v4l2_exposure_auto_type { + V4L2_EXPOSURE_AUTO = 0, + V4L2_EXPOSURE_MANUAL = 1, + V4L2_EXPOSURE_SHUTTER_PRIORITY = 2, + V4L2_EXPOSURE_APERTURE_PRIORITY = 3 +}; +#define V4L2_CID_EXPOSURE_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+2) +#define V4L2_CID_EXPOSURE_AUTO_PRIORITY (V4L2_CID_CAMERA_CLASS_BASE+3) + +#define V4L2_CID_PAN_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE+4) +#define V4L2_CID_TILT_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE+5) +#define V4L2_CID_PAN_RESET (V4L2_CID_CAMERA_CLASS_BASE+6) +#define V4L2_CID_TILT_RESET (V4L2_CID_CAMERA_CLASS_BASE+7) + +#define V4L2_CID_PAN_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+8) +#define V4L2_CID_TILT_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+9) + +#define V4L2_CID_FOCUS_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+10) +#define V4L2_CID_FOCUS_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE+11) +#define V4L2_CID_FOCUS_AUTO (V4L2_CID_CAMERA_CLASS_BASE+12) + /* * T U N I N G */ diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h new file mode 100644 index 000000000000..69aba7188e44 --- /dev/null +++ b/include/media/soc_camera.h @@ -0,0 +1,147 @@ +/* + * camera image capture (abstract) bus driver header + * + * Copyright (C) 2006, Sascha Hauer, Pengutronix + * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de> + * + * 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 SOC_CAMERA_H +#define SOC_CAMERA_H + +#include <linux/videodev2.h> +#include <media/videobuf-dma-sg.h> + +struct soc_camera_device { + struct list_head list; + struct device dev; + struct device *control; + unsigned short width; /* Current window */ + unsigned short height; /* sizes */ + unsigned short x_min; /* Camera capabilities */ + unsigned short y_min; + unsigned short x_current; /* Current window location */ + unsigned short y_current; + unsigned short width_min; + unsigned short width_max; + unsigned short height_min; + unsigned short height_max; + unsigned short y_skip_top; /* Lines to skip at the top */ + unsigned short gain; + unsigned short exposure; + unsigned char iface; /* Host number */ + unsigned char devnum; /* Device number per host */ + unsigned char cached_datawidth; /* See comment in .c */ + struct soc_camera_ops *ops; + struct video_device *vdev; + const struct soc_camera_data_format *current_fmt; + int (*probe)(struct soc_camera_device *icd); + void (*remove)(struct soc_camera_device *icd); + struct module *owner; +}; + +struct soc_camera_file { + struct soc_camera_device *icd; + struct videobuf_queue vb_vidq; +}; + +struct soc_camera_host { + struct list_head list; + struct device dev; + unsigned char nr; /* Host number */ + size_t msize; + struct videobuf_queue_ops *vbq_ops; + struct module *owner; + void *priv; + char *drv_name; + int (*add)(struct soc_camera_device *); + void (*remove)(struct soc_camera_device *); + int (*set_capture_format)(struct soc_camera_device *, __u32, + struct v4l2_rect *); + int (*try_fmt_cap)(struct soc_camera_host *, struct v4l2_format *); + int (*reqbufs)(struct soc_camera_file *, struct v4l2_requestbuffers *); + int (*querycap)(struct soc_camera_host *, struct v4l2_capability *); + unsigned int (*poll)(struct file *, poll_table *); +}; + +struct soc_camera_link { + /* Camera bus id, used to match a camera and a bus */ + int bus_id; + /* GPIO number to switch between 8 and 10 bit modes */ + unsigned int gpio; +}; + +static inline struct soc_camera_device *to_soc_camera_dev(struct device *dev) +{ + return container_of(dev, struct soc_camera_device, dev); +} + +static inline struct soc_camera_host *to_soc_camera_host(struct device *dev) +{ + return container_of(dev, struct soc_camera_host, dev); +} + +extern int soc_camera_host_register(struct soc_camera_host *ici, + struct module *owner); +extern void soc_camera_host_unregister(struct soc_camera_host *ici); +extern int soc_camera_device_register(struct soc_camera_device *icd); +extern void soc_camera_device_unregister(struct soc_camera_device *icd); + +extern int soc_camera_video_start(struct soc_camera_device *icd); +extern void soc_camera_video_stop(struct soc_camera_device *icd); + +struct soc_camera_data_format { + char *name; + unsigned int depth; + __u32 fourcc; + enum v4l2_colorspace colorspace; +}; + +struct soc_camera_ops { + struct module *owner; + int (*init)(struct soc_camera_device *); + int (*release)(struct soc_camera_device *); + int (*start_capture)(struct soc_camera_device *); + int (*stop_capture)(struct soc_camera_device *); + int (*set_capture_format)(struct soc_camera_device *, __u32, + struct v4l2_rect *, unsigned int); + int (*try_fmt_cap)(struct soc_camera_device *, struct v4l2_format *); + int (*get_chip_id)(struct soc_camera_device *, + struct v4l2_chip_ident *); +#ifdef CONFIG_VIDEO_ADV_DEBUG + int (*get_register)(struct soc_camera_device *, struct v4l2_register *); + int (*set_register)(struct soc_camera_device *, struct v4l2_register *); +#endif + const struct soc_camera_data_format *formats; + int num_formats; + int (*get_control)(struct soc_camera_device *, struct v4l2_control *); + int (*set_control)(struct soc_camera_device *, struct v4l2_control *); + const struct v4l2_queryctrl *controls; + int num_controls; + unsigned int(*get_datawidth)(struct soc_camera_device *icd); +}; + +static inline struct v4l2_queryctrl const *soc_camera_find_qctrl( + struct soc_camera_ops *ops, int id) +{ + int i; + + for (i = 0; i < ops->num_controls; i++) + if (ops->controls[i].id == id) + return &ops->controls[i]; + + return NULL; +} + +#define IS_MASTER (1<<0) +#define IS_HSYNC_ACTIVE_HIGH (1<<1) +#define IS_VSYNC_ACTIVE_HIGH (1<<2) +#define IS_DATAWIDTH_8 (1<<3) +#define IS_DATAWIDTH_9 (1<<4) +#define IS_DATAWIDTH_10 (1<<5) +#define IS_PCLK_SAMPLE_RISING (1<<6) + +#endif diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h index 032bb75f69c2..0ea0bd85c036 100644 --- a/include/media/v4l2-chip-ident.h +++ b/include/media/v4l2-chip-ident.h @@ -153,6 +153,12 @@ enum { V4L2_IDENT_MSP4428G = 44287, V4L2_IDENT_MSP4448G = 44487, V4L2_IDENT_MSP4458G = 44587, + + /* Micron CMOS sensor chips: 45000-45099 */ + V4L2_IDENT_MT9M001C12ST = 45000, + V4L2_IDENT_MT9M001C12STM = 45005, + V4L2_IDENT_MT9V022IX7ATC = 45010, /* No way to detect "normal" I77ATx */ + V4L2_IDENT_MT9V022IX7ATM = 45015, /* and "lead free" IA7ATx chips */ }; #endif |